Browse Source

Merge pull request #368 from libtom/fix/base16-api

Improve base16
Steffen Jaeckel 7 years ago
parent
commit
f4afa5d5bb
4 changed files with 37 additions and 21 deletions
  1. 3 3
      doc/crypt.tex
  2. 1 1
      src/headers/tomcrypt_misc.h
  3. 24 15
      src/misc/base16/base16_decode.c
  4. 9 2
      tests/base16_test.c

+ 3 - 3
doc/crypt.tex

@@ -6631,7 +6631,7 @@ The library provides functions to encode and decode a Base16 a.k.a Hex string.
 
 
 To encode a binary string in base16 call:
 To encode a binary string in base16 call:
 
 
-\index{base32\_encode()}
+\index{base16\_encode()}
 \begin{verbatim}
 \begin{verbatim}
 int base16_encode(const unsigned char *in,  unsigned long  inlen,
 int base16_encode(const unsigned char *in,  unsigned long  inlen,
                                  char *out, unsigned long *outlen,
                                  char *out, unsigned long *outlen,
@@ -6644,9 +6644,9 @@ and \textit{caps} is either $0$ to use lower-letter \textit{a..f} or else to use
 
 
 To decode a base16 string call:
 To decode a base16 string call:
 
 
-\index{base32\_decode()}
+\index{base16\_decode()}
 \begin{verbatim}
 \begin{verbatim}
-int base16_decode(const          char *in,
+int base16_decode(const          char *in,  unsigned long  inlen,
                         unsigned char *out, unsigned long *outlen);
                         unsigned char *out, unsigned long *outlen);
 \end{verbatim}
 \end{verbatim}
 
 

+ 1 - 1
src/headers/tomcrypt_misc.h

@@ -51,7 +51,7 @@ int base32_decode(const          char *in,  unsigned long inlen,
 int base16_encode(const unsigned char *in,  unsigned long  inlen,
 int base16_encode(const unsigned char *in,  unsigned long  inlen,
                                  char *out, unsigned long *outlen,
                                  char *out, unsigned long *outlen,
                                  int  caps);
                                  int  caps);
-int base16_decode(const          char *in,
+int base16_decode(const          char *in,  unsigned long  inlen,
                         unsigned char *out, unsigned long *outlen);
                         unsigned char *out, unsigned long *outlen);
 #endif
 #endif
 
 

+ 24 - 15
src/misc/base16/base16_decode.c

@@ -25,33 +25,42 @@
    @param outlen   [in/out] The max size and resulting size of the decoded data
    @param outlen   [in/out] The max size and resulting size of the decoded data
    @return CRYPT_OK if successful
    @return CRYPT_OK if successful
 */
 */
-int base16_decode(const          char *in,
+int base16_decode(const          char *in,  unsigned long  inlen,
                         unsigned char *out, unsigned long *outlen)
                         unsigned char *out, unsigned long *outlen)
 {
 {
-   unsigned long pos, in_len, out_len;
-   unsigned char idx0;
-   unsigned char idx1;
+   unsigned long pos, out_len;
+   unsigned char idx0, idx1;
+   char in0, in1;
 
 
    const unsigned char hashmap[] = {
    const unsigned char hashmap[] = {
          0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 01234567 */
          0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 01234567 */
-         0x08, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 89:;<=>? */
-         0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, /* @ABCDEFG */
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* HIJKLMNO */
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* PQRSTUVW */
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* XYZ[\]^_ */
-         0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, /* `abcdefg */
+         0x08, 0x09, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 89:;<=>? */
+         0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xff, /* @ABCDEFG */
+         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* HIJKLMNO */
+         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* PQRSTUVW */
+         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* XYZ[\]^_ */
+         0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xff, /* `abcdefg */
    };
    };
 
 
    LTC_ARGCHK(in     != NULL);
    LTC_ARGCHK(in     != NULL);
    LTC_ARGCHK(out    != NULL);
    LTC_ARGCHK(out    != NULL);
    LTC_ARGCHK(outlen != NULL);
    LTC_ARGCHK(outlen != NULL);
 
 
-   in_len = strlen(in);
-   if ((in_len % 2) == 1) return CRYPT_INVALID_PACKET;
+   if ((inlen % 2) == 1) return CRYPT_INVALID_PACKET;
    out_len = *outlen * 2;
    out_len = *outlen * 2;
-   for (pos = 0; ((pos + 1 < out_len) && (pos + 1 < in_len)); pos += 2) {
-      idx0 = (unsigned char) (in[pos + 0] & 0x1F) ^ 0x10;
-      idx1 = (unsigned char) (in[pos + 1] & 0x1F) ^ 0x10;
+   for (pos = 0; ((pos + 1 < out_len) && (pos + 1 < inlen)); pos += 2) {
+      in0 = in[pos + 0];
+      in1 = in[pos + 1];
+
+      if ((in0 < '0') || (in0 > 'g')) return CRYPT_INVALID_PACKET;
+      if ((in1 < '0') || (in1 > 'g')) return CRYPT_INVALID_PACKET;
+
+      idx0 = (unsigned char) (in0 & 0x1F) ^ 0x10;
+      idx1 = (unsigned char) (in1 & 0x1F) ^ 0x10;
+
+      if (hashmap[idx0] == 0xff) return CRYPT_INVALID_PACKET;
+      if (hashmap[idx1] == 0xff) return CRYPT_INVALID_PACKET;
+
       out[pos / 2] = (unsigned char) (hashmap[idx0] << 4) | hashmap[idx1];
       out[pos / 2] = (unsigned char) (hashmap[idx0] << 4) | hashmap[idx1];
    }
    }
    *outlen = pos / 2;
    *outlen = pos / 2;

+ 9 - 2
tests/base16_test.c

@@ -20,6 +20,7 @@ int base16_test(void)
       "0123456789abcdef",
       "0123456789abcdef",
       "0123456789ABCDEF",
       "0123456789ABCDEF",
    };
    };
+   const char *failing_decode = "test";
    unsigned long x, l1, l2;
    unsigned long x, l1, l2;
    int idx;
    int idx;
 
 
@@ -28,8 +29,9 @@ int base16_test(void)
          yarrow_read(in, x, &yarrow_prng);
          yarrow_read(in, x, &yarrow_prng);
          l1 = sizeof(out);
          l1 = sizeof(out);
          DO(base16_encode(in, x, out, &l1, idx));
          DO(base16_encode(in, x, out, &l1, idx));
+         l1--;
          l2 = sizeof(tmp);
          l2 = sizeof(tmp);
-         DO(base16_decode(out, tmp, &l2));
+         DO(base16_decode(out, l1, tmp, &l2));
          DO(do_compare_testvector(tmp, l2, in, x, "random base16", idx * 100 + x));
          DO(do_compare_testvector(tmp, l2, in, x, "random base16", idx * 100 + x));
       }
       }
    }
    }
@@ -38,11 +40,16 @@ int base16_test(void)
       l1 = sizeof(out);
       l1 = sizeof(out);
       DO(base16_encode(testin, sizeof(testin), out, &l1, idx));
       DO(base16_encode(testin, sizeof(testin), out, &l1, idx));
       DO(do_compare_testvector(out, strlen(out), testout[idx], strlen(testout[idx]), "testout base16", idx));
       DO(do_compare_testvector(out, strlen(out), testout[idx], strlen(testout[idx]), "testout base16", idx));
+      l1--;
       l2 = sizeof(tmp);
       l2 = sizeof(tmp);
-      DO(base16_decode(out, tmp, &l2));
+      DO(base16_decode(out, l1, tmp, &l2));
       DO(do_compare_testvector(tmp, l2, testin, sizeof(testin), "testin base16", idx));
       DO(do_compare_testvector(tmp, l2, testin, sizeof(testin), "testin base16", idx));
    }
    }
 
 
+   l1 = 4;
+   l2 = sizeof(tmp);
+   DO(base16_decode(failing_decode, l1, tmp, &l2) == CRYPT_OK ? CRYPT_FAIL_TESTVECTOR : CRYPT_OK);
+
    return CRYPT_OK;
    return CRYPT_OK;
 }
 }