Browse Source

fix base64[url] strict/relaxed decode

Steffen Jaeckel 9 years ago
parent
commit
bc16c149fc
3 changed files with 37 additions and 3 deletions
  1. 1 1
      src/headers/tomcrypt_misc.h
  2. 7 1
      src/misc/base64/base64_decode.c
  3. 29 1
      testprof/base64_test.c

+ 1 - 1
src/headers/tomcrypt_misc.h

@@ -12,7 +12,7 @@ int base64_decode_ex(const unsigned char *in,  unsigned long len,
 int base64url_encode(const unsigned char *in,  unsigned long len,
                         unsigned char *out, unsigned long *outlen);
 
-#define base64url_decode(i, il, o, ol) base64_decode_ex(i, il, o, ol, LTC_BASE64_STRICT)
+#define base64url_decode(i, il, o, ol) base64url_decode_ex(i, il, o, ol, LTC_BASE64_STRICT)
 int base64url_decode_ex(const unsigned char *in,  unsigned long len,
                         unsigned char *out, unsigned long *outlen, int strict);
 #endif

+ 7 - 1
src/misc/base64/base64_decode.c

@@ -117,7 +117,11 @@ static int _base64_decode_internal(const unsigned char *in,  unsigned long inlen
        }
    }
    if (y != 0) {
-       return CRYPT_INVALID_PACKET;
+      if (y == 1 || map != map_base64url || strict == 1) return CRYPT_INVALID_PACKET;
+      t = t << (6 * (4 - y));
+      if (z + y - 1 > *outlen) return CRYPT_BUFFER_OVERFLOW;
+      if (y >= 2) out[z++] = (unsigned char) ((t >> 16) & 255);
+      if (y == 3) out[z++] = (unsigned char) ((t >> 8) & 255);
    }
    *outlen = z;
    return CRYPT_OK;
@@ -130,6 +134,7 @@ static int _base64_decode_internal(const unsigned char *in,  unsigned long inlen
    @param inlen    The length of the base64 data
    @param out      [out] The destination of the binary decoded data
    @param outlen   [in/out] The max size and resulting size of the decoded data
+   @param strict   Strict[1] or relaxed[0] decoding of the input
    @return CRYPT_OK if successful
 */
 int base64_decode_ex(const unsigned char *in,  unsigned long inlen,
@@ -146,6 +151,7 @@ int base64_decode_ex(const unsigned char *in,  unsigned long inlen,
    @param inlen    The length of the base64 data
    @param out      [out] The destination of the binary decoded data
    @param outlen   [in/out] The max size and resulting size of the decoded data
+   @param strict   Strict[1] or relaxed[0] decoding of the input
    @return CRYPT_OK if successful
 */
 int base64url_decode_ex(const unsigned char *in,  unsigned long inlen,

+ 29 - 1
testprof/base64_test.c

@@ -5,6 +5,9 @@ int base64_test(void)
 {
    unsigned char in[64], out[256], tmp[64];
    unsigned long x, l1, l2, slen1;
+   const char special_case[] =
+      { 0xbe, 0xe8, 0x92, 0x3c, 0xa2, 0x25, 0xf0, 0xf8, 0x91, 0xe4, 0xef, 0xab,
+            0x0b, 0x8c, 0xfd, 0xff, 0x14, 0xd0, 0x29, 0x9d };
 
    /*
     TEST CASES SOURCE:
@@ -24,7 +27,18 @@ int base64_test(void)
        {"foo", "Zm9v"       },
        {"foob", "Zm9vYg=="  },
        {"fooba", "Zm9vYmE=" },
-       {"foobar", "Zm9vYmFy"}
+       {"foobar", "Zm9vYmFy"},
+       {special_case,"vuiSPKIl8PiR5O+rC4z9/xTQKZ0="}
+   };
+
+   const struct {
+      const char* s;
+      int mode;
+   } url_cases[] = {
+         {"vuiSPKIl8PiR5O-rC4z9_xTQKZ0", 0},
+         {"vuiSPKIl8PiR5O-rC4z9_xTQKZ0=", 1},
+         {"vuiS*PKIl8P*iR5O-rC4*z9_xTQKZ0", 0},
+         {"vuiS*PKIl8P*iR5O-rC4*z9_xTQKZ0=", 0},
    };
 
    for (x = 0; x < sizeof(cases)/sizeof(cases[0]); ++x) {
@@ -45,6 +59,20 @@ int base64_test(void)
        }
    }
 
+   for (x = 0; x < sizeof(url_cases)/sizeof(url_cases[0]); ++x) {
+       slen1 = strlen(url_cases[x].s);
+       l1 = sizeof(out);
+       DO(base64url_decode_ex((unsigned char*)url_cases[x].s, slen1, out, &l1, url_cases[x].mode));
+       if (l1 != sizeof(special_case) ||  memcmp(out, special_case, l1)) {
+           fprintf(stderr, "\nbase64url failed case %lu: %s", x, url_cases[x].s);
+           print_hex("\nbase64url should", special_case, sizeof(special_case));
+           out[sizeof(out)-1] = '\0';
+           print_hex("\nbase64url is", out, l1);
+           return 1;
+       }
+   }
+
+
    for  (x = 0; x < 64; x++) {
        yarrow_read(in, x, &yarrow_prng);
        l1 = sizeof(out);