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.
This commit is contained in:
Steffen Jaeckel 2017-02-17 11:18:58 +01:00 committed by Karel Miko
parent 53359ccfc6
commit c1dd1cbe30
7 changed files with 51 additions and 35 deletions

View File

@ -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

View File

@ -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 <=== */

View File

@ -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
@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_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, 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
@return CRYPT_OK if successful
*/
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);
}
#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);
}

View File

@ -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

View File

@ -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),

View File

@ -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

View File

@ -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));