Expose internal base64 functions for testing
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
diff --git a/include/mbedtls/base64.h b/include/mbedtls/base64.h
index cf4149e..e86a027 100644
--- a/include/mbedtls/base64.h
+++ b/include/mbedtls/base64.h
@@ -91,6 +91,16 @@
#endif /* MBEDTLS_SELF_TEST */
+#if defined(MBEDTLS_TEST_HOOKS)
+/* These functions are only exposed in testing configurations for testing
+ * purposes and may change or disappear at any time. */
+unsigned char mbedtls_base64_mask_of_range( unsigned char low,
+ unsigned char high,
+ unsigned char c );
+unsigned char mbedtls_base64_enc_char( unsigned char val );
+signed char mbedtls_base64_dec_value( unsigned char c );
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/library/base64.c b/library/base64.c
index 6ddd501..96c94d1 100644
--- a/library/base64.c
+++ b/library/base64.c
@@ -41,8 +41,10 @@
*
* Constant flow with respect to c.
*/
-static unsigned char mask_of_range( unsigned char low, unsigned char high,
- unsigned char c )
+MBEDTLS_STATIC_TESTABLE
+unsigned char mbedtls_base64_mask_of_range( unsigned char low,
+ unsigned char high,
+ unsigned char c )
{
/* low_mask is: 0 if low <= c, 0x...ff if low > c */
unsigned low_mask = ( (unsigned) c - low ) >> 8;
@@ -55,17 +57,18 @@
* The implementation assumes that letters are consecutive (e.g. ASCII
* but not EBCDIC).
*/
-static unsigned char enc_char( unsigned char val )
+MBEDTLS_STATIC_TESTABLE
+unsigned char mbedtls_base64_enc_char( unsigned char val )
{
unsigned char digit = 0;
/* For each range of values, if val is in that range, mask digit with
* the corresponding value. Since val can only be in a single range,
* only at most one masking will change digit. */
- digit |= mask_of_range( 0, 25, val ) & ( 'A' + val );
- digit |= mask_of_range( 26, 51, val ) & ( 'a' + val - 26 );
- digit |= mask_of_range( 52, 61, val ) & ( '0' + val - 52 );
- digit |= mask_of_range( 62, 62, val ) & '+';
- digit |= mask_of_range( 63, 63, val ) & '/';
+ digit |= mbedtls_base64_mask_of_range( 0, 25, val ) & ( 'A' + val );
+ digit |= mbedtls_base64_mask_of_range( 26, 51, val ) & ( 'a' + val - 26 );
+ digit |= mbedtls_base64_mask_of_range( 52, 61, val ) & ( '0' + val - 52 );
+ digit |= mbedtls_base64_mask_of_range( 62, 62, val ) & '+';
+ digit |= mbedtls_base64_mask_of_range( 63, 63, val ) & '/';
return( digit );
}
@@ -109,10 +112,12 @@
C2 = *src++;
C3 = *src++;
- *p++ = enc_char( ( C1 >> 2 ) & 0x3F );
- *p++ = enc_char( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) ) & 0x3F );
- *p++ = enc_char( ( ( ( C2 & 15 ) << 2 ) + ( C3 >> 6 ) ) & 0x3F );
- *p++ = enc_char( C3 & 0x3F );
+ *p++ = mbedtls_base64_enc_char( ( C1 >> 2 ) & 0x3F );
+ *p++ = mbedtls_base64_enc_char( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) )
+ & 0x3F );
+ *p++ = mbedtls_base64_enc_char( ( ( ( C2 & 15 ) << 2 ) + ( C3 >> 6 ) )
+ & 0x3F );
+ *p++ = mbedtls_base64_enc_char( C3 & 0x3F );
}
if( i < slen )
@@ -120,11 +125,12 @@
C1 = *src++;
C2 = ( ( i + 1 ) < slen ) ? *src++ : 0;
- *p++ = enc_char( ( C1 >> 2 ) & 0x3F );
- *p++ = enc_char( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) ) & 0x3F );
+ *p++ = mbedtls_base64_enc_char( ( C1 >> 2 ) & 0x3F );
+ *p++ = mbedtls_base64_enc_char( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) )
+ & 0x3F );
if( ( i + 1 ) < slen )
- *p++ = enc_char( ( ( C2 & 15 ) << 2 ) & 0x3F );
+ *p++ = mbedtls_base64_enc_char( ( ( C2 & 15 ) << 2 ) & 0x3F );
else *p++ = '=';
*p++ = '=';
@@ -147,18 +153,19 @@
* on the value of c) unless the compiler inlines and optimizes a specific
* access.
*/
-static signed char dec_value( unsigned char c )
+MBEDTLS_STATIC_TESTABLE
+signed char mbedtls_base64_dec_value( unsigned char c )
{
unsigned char val = 0;
/* For each range of digits, if c is in that range, mask val with
* the corresponding value. Since c can only be in a single range,
* only at most one masking will change val. Set val to one plus
* the desired value so that it stays 0 if c is in none of the ranges. */
- val |= mask_of_range( 'A', 'Z', c ) & ( c - 'A' + 0 + 1 );
- val |= mask_of_range( 'a', 'z', c ) & ( c - 'a' + 26 + 1 );
- val |= mask_of_range( '0', '9', c ) & ( c - '0' + 52 + 1 );
- val |= mask_of_range( '+', '+', c ) & ( c - '+' + 62 + 1 );
- val |= mask_of_range( '/', '/', c ) & ( c - '/' + 63 + 1 );
+ val |= mbedtls_base64_mask_of_range( 'A', 'Z', c ) & ( c - 'A' + 0 + 1 );
+ val |= mbedtls_base64_mask_of_range( 'a', 'z', c ) & ( c - 'a' + 26 + 1 );
+ val |= mbedtls_base64_mask_of_range( '0', '9', c ) & ( c - '0' + 52 + 1 );
+ val |= mbedtls_base64_mask_of_range( '+', '+', c ) & ( c - '+' + 62 + 1 );
+ val |= mbedtls_base64_mask_of_range( '/', '/', c ) & ( c - '/' + 63 + 1 );
/* At this point, val is 0 if c is an invalid digit and v+1 if c is
* a digit with the value v. */
return( val - 1 );
@@ -216,7 +223,7 @@
{
if( equals != 0 )
return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
- if( dec_value( src[i] ) < 0 )
+ if( mbedtls_base64_dec_value( src[i] ) < 0 )
return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
}
n++;
@@ -251,7 +258,7 @@
if( *src == '=' )
++equals;
else
- x |= dec_value( *src );
+ x |= mbedtls_base64_dec_value( *src );
if( ++accumulated_digits == 4 )
{