Browse Source

re-work strict/relaxed base64 decoding implementation

Instead of one API function with an option parameter, provide two API
functions.
Instead of defaulting to strict decoding, default to relaxed decoding.
Steffen Jaeckel 8 years ago
parent
commit
c1dd1cbe30

+ 0 - 5
src/headers/tomcrypt_custom.h

@@ -476,11 +476,6 @@
    #define LTC_PKCS_1
 #endif
 
-#if (defined(LTC_BASE64) || defined(LTC_BASE64_URL)) && !defined(LTC_BASE64_STRICT)
-   /* By default we're doing strict decoding now */
-   #define LTC_BASE64_STRICT 1
-#endif
-
 #if defined(TFM_DESC) && defined(LTC_RSA_BLINDING)
     #warning RSA blinding currently not supported in combination with TFM
     #undef LTC_RSA_BLINDING

+ 8 - 6
src/headers/tomcrypt_misc.h

@@ -3,18 +3,20 @@
 int base64_encode(const unsigned char *in,  unsigned long len,
                         unsigned char *out, unsigned long *outlen);
 
-#define base64_decode(i, il, o, ol) base64_decode_ex(i, il, o, ol, LTC_BASE64_STRICT)
-int base64_decode_ex(const unsigned char *in,  unsigned long len,
-                        unsigned char *out, unsigned long *outlen, int strict);
+int base64_decode(const unsigned char *in,  unsigned long len,
+                        unsigned char *out, unsigned long *outlen);
+int base64_strict_decode(const unsigned char *in,  unsigned long len,
+                        unsigned char *out, unsigned long *outlen);
 #endif
 
 #ifdef LTC_BASE64_URL
 int base64url_encode(const unsigned char *in,  unsigned long len,
                         unsigned char *out, unsigned long *outlen);
 
-#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);
+int base64url_decode(const unsigned char *in,  unsigned long len,
+                        unsigned char *out, unsigned long *outlen);
+int base64url_strict_decode(const unsigned char *in,  unsigned long len,
+                        unsigned char *out, unsigned long *outlen);
 #endif
 
 /* ===> LTC_HKDF -- RFC5869 HMAC-based Key Derivation Function <=== */

+ 34 - 11
src/misc/base64/base64_decode.c

@@ -71,9 +71,14 @@ static const unsigned char map_base64url[256] = {
 255, 255, 255, 255 };
 #endif /* LTC_BASE64_URL */
 
+enum {
+   relaxed = 0,
+   strict = 1
+};
+
 static int _base64_decode_internal(const unsigned char *in,  unsigned long inlen,
                                  unsigned char *out, unsigned long *outlen,
-                           const unsigned char *map, int strict)
+                           const unsigned char *map, int is_strict)
 {
    unsigned long t, x, y, z;
    unsigned char c;
@@ -87,7 +92,7 @@ static int _base64_decode_internal(const unsigned char *in,  unsigned long inlen
    for (x = y = z = t = 0; x < inlen; x++) {
        c = map[in[x]&0xFF];
        if (c == 255) {
-          if (strict)
+          if (is_strict)
              return CRYPT_INVALID_PACKET;
           else
              continue;
@@ -117,7 +122,7 @@ static int _base64_decode_internal(const unsigned char *in,  unsigned long inlen
        }
    }
    if (y != 0) {
-      if (y == 1 || map != map_base64url || strict == 1) return CRYPT_INVALID_PACKET;
+      if (y == 1 || map != map_base64url || is_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);
@@ -129,18 +134,31 @@ static int _base64_decode_internal(const unsigned char *in,  unsigned long inlen
 
 #if defined(LTC_BASE64)
 /**
-   base64 decode a block of memory
+   Relaxed base64 decode a block of memory
+   @param in       The base64 data to decode
+   @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
+   @return CRYPT_OK if successful
+*/
+int base64_decode(const unsigned char *in,  unsigned long inlen,
+                        unsigned char *out, unsigned long *outlen)
+{
+    return _base64_decode_internal(in, inlen, out, outlen, map_base64, relaxed);
+}
+
+/**
+   Strict base64 decode a block of memory
    @param in       The base64 data to decode
    @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,
-                        unsigned char *out, unsigned long *outlen, int strict)
+int base64_strict_decode(const unsigned char *in,  unsigned long inlen,
+                        unsigned char *out, unsigned long *outlen)
 {
-    return _base64_decode_internal(in, inlen, out, outlen, map_base64, strict);
+   return _base64_decode_internal(in, inlen, out, outlen, map_base64, strict);
 }
 #endif /* LTC_BASE64 */
 
@@ -151,11 +169,16 @@ 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,
-                           unsigned char *out, unsigned long *outlen, int strict)
+int base64url_decode(const unsigned char *in,  unsigned long inlen,
+                           unsigned char *out, unsigned long *outlen)
+{
+    return _base64_decode_internal(in, inlen, out, outlen, map_base64url, relaxed);
+}
+
+int base64url_strict_decode(const unsigned char *in,  unsigned long inlen,
+                           unsigned char *out, unsigned long *outlen)
 {
     return _base64_decode_internal(in, inlen, out, outlen, map_base64url, strict);
 }

+ 0 - 3
src/misc/crypt/crypt.c

@@ -337,9 +337,6 @@ const char *crypt_build_settings =
 #if defined(LTC_BASE64_URL)
     " BASE64-URL-SAFE "
 #endif
-#if defined(LTC_BASE64) || defined(LTC_BASE64_URL)
-    " "NAME_VALUE(LTC_BASE64_STRICT)" "
-#endif
 #if defined(LTC_CRC32)
     " CRC32 "
 #endif

+ 0 - 4
src/misc/crypt/crypt_constants.c

@@ -89,10 +89,6 @@ static const crypt_constant _crypt_constants[] = {
     {"LTC_CTR_MODE", 0},
 #endif
 
-#if defined(LTC_BASE64) || defined(LTC_BASE64_URL)
-    _C_STRINGIFY(LTC_BASE64_STRICT),
-#endif
-
     _C_STRINGIFY(MAXBLOCKSIZE),
     _C_STRINGIFY(TAB_SIZE),
     _C_STRINGIFY(ARGTYPE),

+ 8 - 5
testprof/base64_test.c

@@ -34,7 +34,7 @@ int base64_test(void)
 
    const struct {
       const char* s;
-      int mode;
+      int is_strict;
    } url_cases[] = {
          {"vuiSPKIl8PiR5O-rC4z9_xTQKZ0", 0},
          {"vuiSPKIl8PiR5O-rC4z9_xTQKZ0=", 1},
@@ -63,7 +63,10 @@ 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(url_cases[x].is_strict)
+          DO(base64url_strict_decode((unsigned char*)url_cases[x].s, slen1, out, &l1));
+       else
+          DO(base64url_decode((unsigned char*)url_cases[x].s, slen1, out, &l1));
        if (l1 != strlen(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, strlen(special_case));
@@ -91,16 +94,16 @@ int base64_test(void)
    out[10] = '\0';
    l1++;
    l2 = sizeof(tmp);
-   DO(base64_decode_ex(out, l1, tmp, &l2, 0));
+   DO(base64_decode(out, l1, tmp, &l2));
    if (l2 != x || memcmp(tmp, in, x)) {
-       fprintf(stderr, "loose base64 decoding failed %lu %lu %lu", x, l1, l2);
+       fprintf(stderr, "relaxed base64 decoding failed %lu %lu %lu", x, l1, l2);
        print_hex("is    ", tmp, l2);
        print_hex("should", in, x);
        print_hex("input ", out, l1);
        return 1;
    }
    l2 = sizeof(tmp);
-   DO(base64_decode_ex(out, l1, tmp, &l2, 1) == CRYPT_INVALID_PACKET ? CRYPT_OK : CRYPT_INVALID_PACKET);
+   DO(base64_strict_decode(out, l1, tmp, &l2) == CRYPT_INVALID_PACKET ? CRYPT_OK : CRYPT_INVALID_PACKET);
    return 0;
 }
 #endif

+ 1 - 1
testprof/der_tests.c

@@ -392,7 +392,7 @@ static void der_cacert_test(void)
 
   ltc_asn1_list *decoded_list, *l, *l1, *l2;
 
-  DO(base64_decode_ex(_der_tests_cacert_root_cert, sizeof(_der_tests_cacert_root_cert), buf, &len1, 0));
+  DO(base64_decode(_der_tests_cacert_root_cert, sizeof(_der_tests_cacert_root_cert), buf, &len1));
   len2 = len1;
   DO(der_decode_sequence_flexi(buf, &len2, &decoded_list));