1
0
mirror of https://github.com/Mbed-TLS/mbedtls.git synced 2025-07-30 22:43:08 +03:00

Merge branch 'development' into iotssl-247

This commit is contained in:
Hanno Becker
2018-01-15 11:31:34 +00:00
163 changed files with 8013 additions and 2147 deletions

View File

@ -48,6 +48,7 @@ set(src_crypto
platform.c
ripemd160.c
rsa.c
rsa_internal.c
sha1.c
sha256.c
sha512.c

View File

@ -59,9 +59,9 @@ OBJS_CRYPTO= aes.o aesni.o arc4.o \
padlock.o pem.o pk.o \
pk_wrap.o pkcs12.o pkcs5.o \
pkparse.o pkwrite.o platform.o \
ripemd160.o rsa.o sha1.o \
sha256.o sha512.o threading.o \
timing.o version.o \
ripemd160.o rsa_internal.o rsa.o \
sha1.o sha256.o sha512.o \
threading.o timing.o version.o \
version_features.o xtea.o
OBJS_X509= certs.o pkcs11.o x509.o \

View File

@ -1235,9 +1235,11 @@ static const int aes_test_ctr_len[3] =
*/
int mbedtls_aes_self_test( int verbose )
{
int ret = 0, i, j, u, v;
int ret = 0, i, j, u, mode;
unsigned int keybits;
unsigned char key[32];
unsigned char buf[64];
const unsigned char *aes_tests;
#if defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB)
unsigned char iv[16];
#endif
@ -1263,45 +1265,52 @@ int mbedtls_aes_self_test( int verbose )
for( i = 0; i < 6; i++ )
{
u = i >> 1;
v = i & 1;
keybits = 128 + u * 64;
mode = i & 1;
if( verbose != 0 )
mbedtls_printf( " AES-ECB-%3d (%s): ", 128 + u * 64,
( v == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
mbedtls_printf( " AES-ECB-%3d (%s): ", keybits,
( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
memset( buf, 0, 16 );
if( v == MBEDTLS_AES_DECRYPT )
if( mode == MBEDTLS_AES_DECRYPT )
{
mbedtls_aes_setkey_dec( &ctx, key, 128 + u * 64 );
for( j = 0; j < 10000; j++ )
mbedtls_aes_crypt_ecb( &ctx, v, buf, buf );
if( memcmp( buf, aes_test_ecb_dec[u], 16 ) != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
ret = 1;
goto exit;
}
ret = mbedtls_aes_setkey_dec( &ctx, key, keybits );
aes_tests = aes_test_ecb_dec[u];
}
else
{
mbedtls_aes_setkey_enc( &ctx, key, 128 + u * 64 );
ret = mbedtls_aes_setkey_enc( &ctx, key, keybits );
aes_tests = aes_test_ecb_enc[u];
}
for( j = 0; j < 10000; j++ )
mbedtls_aes_crypt_ecb( &ctx, v, buf, buf );
/*
* AES-192 is an optional feature that may be unavailable when
* there is an alternative underlying implementation i.e. when
* MBEDTLS_AES_ALT is defined.
*/
if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 )
{
mbedtls_printf( "skipped\n" );
continue;
}
else if( ret != 0 )
{
goto exit;
}
if( memcmp( buf, aes_test_ecb_enc[u], 16 ) != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
ret = 1;
for( j = 0; j < 10000; j++ )
{
ret = mbedtls_aes_crypt_ecb( &ctx, mode, buf, buf );
if( ret != 0 )
goto exit;
}
}
if( memcmp( buf, aes_tests, 16 ) != 0 )
{
ret = 1;
goto exit;
}
if( verbose != 0 )
@ -1318,55 +1327,64 @@ int mbedtls_aes_self_test( int verbose )
for( i = 0; i < 6; i++ )
{
u = i >> 1;
v = i & 1;
keybits = 128 + u * 64;
mode = i & 1;
if( verbose != 0 )
mbedtls_printf( " AES-CBC-%3d (%s): ", 128 + u * 64,
( v == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
mbedtls_printf( " AES-CBC-%3d (%s): ", keybits,
( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
memset( iv , 0, 16 );
memset( prv, 0, 16 );
memset( buf, 0, 16 );
if( v == MBEDTLS_AES_DECRYPT )
if( mode == MBEDTLS_AES_DECRYPT )
{
mbedtls_aes_setkey_dec( &ctx, key, 128 + u * 64 );
for( j = 0; j < 10000; j++ )
mbedtls_aes_crypt_cbc( &ctx, v, 16, iv, buf, buf );
if( memcmp( buf, aes_test_cbc_dec[u], 16 ) != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
ret = 1;
goto exit;
}
ret = mbedtls_aes_setkey_dec( &ctx, key, keybits );
aes_tests = aes_test_cbc_dec[u];
}
else
{
mbedtls_aes_setkey_enc( &ctx, key, 128 + u * 64 );
ret = mbedtls_aes_setkey_enc( &ctx, key, keybits );
aes_tests = aes_test_cbc_enc[u];
}
for( j = 0; j < 10000; j++ )
/*
* AES-192 is an optional feature that may be unavailable when
* there is an alternative underlying implementation i.e. when
* MBEDTLS_AES_ALT is defined.
*/
if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 )
{
mbedtls_printf( "skipped\n" );
continue;
}
else if( ret != 0 )
{
goto exit;
}
for( j = 0; j < 10000; j++ )
{
if( mode == MBEDTLS_AES_ENCRYPT )
{
unsigned char tmp[16];
mbedtls_aes_crypt_cbc( &ctx, v, 16, iv, buf, buf );
memcpy( tmp, prv, 16 );
memcpy( prv, buf, 16 );
memcpy( buf, tmp, 16 );
}
if( memcmp( prv, aes_test_cbc_enc[u], 16 ) != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
ret = 1;
ret = mbedtls_aes_crypt_cbc( &ctx, mode, 16, iv, buf, buf );
if( ret != 0 )
goto exit;
}
}
if( memcmp( buf, aes_tests, 16 ) != 0 )
{
ret = 1;
goto exit;
}
if( verbose != 0 )
@ -1384,45 +1402,52 @@ int mbedtls_aes_self_test( int verbose )
for( i = 0; i < 6; i++ )
{
u = i >> 1;
v = i & 1;
keybits = 128 + u * 64;
mode = i & 1;
if( verbose != 0 )
mbedtls_printf( " AES-CFB128-%3d (%s): ", 128 + u * 64,
( v == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
mbedtls_printf( " AES-CFB128-%3d (%s): ", keybits,
( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
memcpy( iv, aes_test_cfb128_iv, 16 );
memcpy( key, aes_test_cfb128_key[u], 16 + u * 8 );
memcpy( key, aes_test_cfb128_key[u], keybits / 8 );
offset = 0;
mbedtls_aes_setkey_enc( &ctx, key, 128 + u * 64 );
ret = mbedtls_aes_setkey_enc( &ctx, key, keybits );
/*
* AES-192 is an optional feature that may be unavailable when
* there is an alternative underlying implementation i.e. when
* MBEDTLS_AES_ALT is defined.
*/
if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 )
{
mbedtls_printf( "skipped\n" );
continue;
}
else if( ret != 0 )
{
goto exit;
}
if( v == MBEDTLS_AES_DECRYPT )
if( mode == MBEDTLS_AES_DECRYPT )
{
memcpy( buf, aes_test_cfb128_ct[u], 64 );
mbedtls_aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf );
if( memcmp( buf, aes_test_cfb128_pt, 64 ) != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
ret = 1;
goto exit;
}
aes_tests = aes_test_cfb128_pt;
}
else
{
memcpy( buf, aes_test_cfb128_pt, 64 );
mbedtls_aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf );
aes_tests = aes_test_cfb128_ct[u];
}
if( memcmp( buf, aes_test_cfb128_ct[u], 64 ) != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
ret = mbedtls_aes_crypt_cfb128( &ctx, mode, 64, &offset, iv, buf, buf );
if( ret != 0 )
goto exit;
ret = 1;
goto exit;
}
if( memcmp( buf, aes_tests, 64 ) != 0 )
{
ret = 1;
goto exit;
}
if( verbose != 0 )
@ -1440,51 +1465,41 @@ int mbedtls_aes_self_test( int verbose )
for( i = 0; i < 6; i++ )
{
u = i >> 1;
v = i & 1;
mode = i & 1;
if( verbose != 0 )
mbedtls_printf( " AES-CTR-128 (%s): ",
( v == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
memcpy( nonce_counter, aes_test_ctr_nonce_counter[u], 16 );
memcpy( key, aes_test_ctr_key[u], 16 );
offset = 0;
mbedtls_aes_setkey_enc( &ctx, key, 128 );
if( ( ret = mbedtls_aes_setkey_enc( &ctx, key, 128 ) ) != 0 )
goto exit;
if( v == MBEDTLS_AES_DECRYPT )
len = aes_test_ctr_len[u];
if( mode == MBEDTLS_AES_DECRYPT )
{
len = aes_test_ctr_len[u];
memcpy( buf, aes_test_ctr_ct[u], len );
mbedtls_aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block,
buf, buf );
if( memcmp( buf, aes_test_ctr_pt[u], len ) != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
ret = 1;
goto exit;
}
aes_tests = aes_test_ctr_pt[u];
}
else
{
len = aes_test_ctr_len[u];
memcpy( buf, aes_test_ctr_pt[u], len );
aes_tests = aes_test_ctr_ct[u];
}
mbedtls_aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block,
buf, buf );
ret = mbedtls_aes_crypt_ctr( &ctx, len, &offset, nonce_counter,
stream_block, buf, buf );
if( ret != 0 )
goto exit;
if( memcmp( buf, aes_test_ctr_ct[u], len ) != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
ret = 1;
goto exit;
}
if( memcmp( buf, aes_tests, len ) != 0 )
{
ret = 1;
goto exit;
}
if( verbose != 0 )
@ -1498,6 +1513,9 @@ int mbedtls_aes_self_test( int verbose )
ret = 0;
exit:
if( ret != 0 && verbose != 0 )
mbedtls_printf( "failed\n" );
mbedtls_aes_free( &ctx );
return( ret );

View File

@ -49,6 +49,8 @@
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
#if !defined(MBEDTLS_CCM_ALT)
/* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize( void *v, size_t n ) {
volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
@ -348,6 +350,7 @@ int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
return( 0 );
}
#endif /* !MBEDTLS_CCM_ALT */
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
/*

View File

@ -65,6 +65,8 @@
#endif /* MBEDTLS_SELF_TEST */
#endif /* MBEDTLS_PLATFORM_C */
#if !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST)
/* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize( void *v, size_t n ) {
volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
@ -164,7 +166,9 @@ exit:
return( ret );
}
#endif /* !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST) */
#if !defined(MBEDTLS_CMAC_ALT)
static void cmac_xor_block( unsigned char *output, const unsigned char *input1,
const unsigned char *input2,
const size_t block_size )
@ -468,6 +472,8 @@ exit:
}
#endif /* MBEDTLS_AES_C */
#endif /* !MBEDTLS_CMAC_ALT */
#if defined(MBEDTLS_SELF_TEST)
/*
* CMAC test data for SP800-38B

View File

@ -38,6 +38,7 @@
#include <string.h>
#if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT)
/*
* Generate public key: simple wrapper around mbedtls_ecp_gen_keypair
*/
@ -47,7 +48,9 @@ int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp
{
return mbedtls_ecp_gen_keypair( grp, d, Q, f_rng, p_rng );
}
#endif /* MBEDTLS_ECDH_GEN_PUBLIC_ALT */
#if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT)
/*
* Compute shared secret (SEC1 3.3.1)
*/
@ -81,6 +84,7 @@ cleanup:
return( ret );
}
#endif /* MBEDTLS_ECDH_COMPUTE_SHARED_ALT */
/*
* Initialize context

View File

@ -65,6 +65,7 @@ cleanup:
return( ret );
}
#if !defined(MBEDTLS_ECDSA_SIGN_ALT)
/*
* Compute ECDSA signature of a hashed message (SEC1 4.1.3)
* Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message)
@ -81,6 +82,10 @@ int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
if( grp->N.p == NULL )
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
/* Make sure d is in range 1..n-1 */
if( mbedtls_mpi_cmp_int( d, 1 ) < 0 || mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 )
return( MBEDTLS_ERR_ECP_INVALID_KEY );
mbedtls_ecp_point_init( &R );
mbedtls_mpi_init( &k ); mbedtls_mpi_init( &e ); mbedtls_mpi_init( &t );
@ -153,6 +158,7 @@ cleanup:
return( ret );
}
#endif /* MBEDTLS_ECDSA_SIGN_ALT */
#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
/*
@ -192,6 +198,7 @@ cleanup:
}
#endif /* MBEDTLS_ECDSA_DETERMINISTIC */
#if !defined(MBEDTLS_ECDSA_VERIFY_ALT)
/*
* Verify ECDSA signature of hashed message (SEC1 4.1.4)
* Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message)
@ -277,6 +284,7 @@ cleanup:
return( ret );
}
#endif /* MBEDTLS_ECDSA_VERIFY_ALT */
/*
* Convert a signature (given by context) to ASN.1
@ -402,6 +410,7 @@ cleanup:
return( ret );
}
#if !defined(MBEDTLS_ECDSA_GENKEY_ALT)
/*
* Generate key pair
*/
@ -411,6 +420,7 @@ int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid,
return( mbedtls_ecp_group_load( &ctx->grp, gid ) ||
mbedtls_ecp_gen_keypair( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) );
}
#endif /* MBEDTLS_ECDSA_GENKEY_ALT */
/*
* Set context from an mbedtls_ecp_keypair

View File

@ -83,6 +83,9 @@ void mbedtls_entropy_init( mbedtls_entropy_context *ctx )
mbedtls_havege_init( &ctx->havege_data );
#endif
/* Reminder: Update ENTROPY_HAVE_STRONG in the test files
* when adding more strong entropy sources here. */
#if defined(MBEDTLS_TEST_NULL_ENTROPY)
mbedtls_entropy_add_source( ctx, mbedtls_null_entropy_poll, NULL,
1, MBEDTLS_ENTROPY_SOURCE_STRONG );

View File

@ -331,6 +331,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
mbedtls_snprintf( buf, buflen, "RSA - The output buffer for decryption is not large enough" );
if( use_ret == -(MBEDTLS_ERR_RSA_RNG_FAILED) )
mbedtls_snprintf( buf, buflen, "RSA - The random generator failed to generate non-zeros" );
if( use_ret == -(MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION) )
mbedtls_snprintf( buf, buflen, "RSA - The implementation doesn't offer the requested operation, e.g. because of security violations or lack of functionality" );
#endif /* MBEDTLS_RSA_C */
#if defined(MBEDTLS_SSL_TLS_C)
@ -518,6 +520,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
mbedtls_snprintf( buf, buflen, "AES - Invalid key length" );
if( use_ret == -(MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH) )
mbedtls_snprintf( buf, buflen, "AES - Invalid data input length" );
if( use_ret == -(MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE) )
mbedtls_snprintf( buf, buflen, "AES - Feature not available, e.g. unsupported AES key size" );
#endif /* MBEDTLS_AES_C */
#if defined(MBEDTLS_ASN1_PARSE_C)

View File

@ -46,6 +46,7 @@
#endif
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
#include "mbedtls/aes.h"
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
@ -54,6 +55,8 @@
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
#if !defined(MBEDTLS_GCM_ALT)
/*
* 32-bit integer manipulation macros (big endian)
*/
@ -508,6 +511,8 @@ void mbedtls_gcm_free( mbedtls_gcm_context *ctx )
mbedtls_zeroize( ctx, sizeof( mbedtls_gcm_context ) );
}
#endif /* !MBEDTLS_GCM_ALT */
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
/*
* AES-GCM test vectors from:
@ -744,34 +749,48 @@ int mbedtls_gcm_self_test( int verbose )
int i, j, ret;
mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
mbedtls_gcm_init( &ctx );
for( j = 0; j < 3; j++ )
{
int key_len = 128 + 64 * j;
for( i = 0; i < MAX_TESTS; i++ )
{
mbedtls_gcm_init( &ctx );
if( verbose != 0 )
mbedtls_printf( " AES-GCM-%3d #%d (%s): ",
key_len, i, "enc" );
key_len, i, "enc" );
mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len );
ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]],
key_len );
/*
* AES-192 is an optional feature that may be unavailable when
* there is an alternative underlying implementation i.e. when
* MBEDTLS_AES_ALT is defined.
*/
if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && key_len == 192 )
{
mbedtls_printf( "skipped\n" );
break;
}
else if( ret != 0 )
{
goto exit;
}
ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_ENCRYPT,
pt_len[i],
iv[iv_index[i]], iv_len[i],
additional[add_index[i]], add_len[i],
pt[pt_index[i]], buf, 16, tag_buf );
pt_len[i],
iv[iv_index[i]], iv_len[i],
additional[add_index[i]], add_len[i],
pt[pt_index[i]], buf, 16, tag_buf );
if( ret != 0 )
goto exit;
if( ret != 0 ||
memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
if ( memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
return( 1 );
ret = 1;
goto exit;
}
mbedtls_gcm_free( &ctx );
@ -779,26 +798,31 @@ int mbedtls_gcm_self_test( int verbose )
if( verbose != 0 )
mbedtls_printf( "passed\n" );
mbedtls_gcm_init( &ctx );
if( verbose != 0 )
mbedtls_printf( " AES-GCM-%3d #%d (%s): ",
key_len, i, "dec" );
key_len, i, "dec" );
mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len );
ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]],
key_len );
if( ret != 0 )
goto exit;
ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_DECRYPT,
pt_len[i],
iv[iv_index[i]], iv_len[i],
additional[add_index[i]], add_len[i],
ct[j * 6 + i], buf, 16, tag_buf );
pt_len[i],
iv[iv_index[i]], iv_len[i],
additional[add_index[i]], add_len[i],
ct[j * 6 + i], buf, 16, tag_buf );
if( ret != 0 ||
memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
if( ret != 0 )
goto exit;
if( memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
return( 1 );
ret = 1;
goto exit;
}
mbedtls_gcm_free( &ctx );
@ -806,66 +830,51 @@ int mbedtls_gcm_self_test( int verbose )
if( verbose != 0 )
mbedtls_printf( "passed\n" );
mbedtls_gcm_init( &ctx );
if( verbose != 0 )
mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
key_len, i, "enc" );
key_len, i, "enc" );
mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len );
ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]],
key_len );
if( ret != 0 )
goto exit;
ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_ENCRYPT,
iv[iv_index[i]], iv_len[i],
additional[add_index[i]], add_len[i] );
iv[iv_index[i]], iv_len[i],
additional[add_index[i]], add_len[i] );
if( ret != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
return( 1 );
}
goto exit;
if( pt_len[i] > 32 )
{
size_t rest_len = pt_len[i] - 32;
ret = mbedtls_gcm_update( &ctx, 32, pt[pt_index[i]], buf );
if( ret != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
return( 1 );
}
goto exit;
ret = mbedtls_gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32,
buf + 32 );
if( ret != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
return( 1 );
}
goto exit;
}
else
{
ret = mbedtls_gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf );
if( ret != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
return( 1 );
}
goto exit;
}
ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
if( ret != 0 ||
memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
if( ret != 0 )
goto exit;
if( memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
return( 1 );
ret = 1;
goto exit;
}
mbedtls_gcm_free( &ctx );
@ -873,80 +882,75 @@ int mbedtls_gcm_self_test( int verbose )
if( verbose != 0 )
mbedtls_printf( "passed\n" );
mbedtls_gcm_init( &ctx );
if( verbose != 0 )
mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
key_len, i, "dec" );
key_len, i, "dec" );
mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len );
ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]],
key_len );
if( ret != 0 )
goto exit;
ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_DECRYPT,
iv[iv_index[i]], iv_len[i],
additional[add_index[i]], add_len[i] );
if( ret != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
return( 1 );
}
goto exit;
if( pt_len[i] > 32 )
{
size_t rest_len = pt_len[i] - 32;
ret = mbedtls_gcm_update( &ctx, 32, ct[j * 6 + i], buf );
if( ret != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
return( 1 );
}
goto exit;
ret = mbedtls_gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32,
buf + 32 );
buf + 32 );
if( ret != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
return( 1 );
}
goto exit;
}
else
{
ret = mbedtls_gcm_update( &ctx, pt_len[i], ct[j * 6 + i], buf );
ret = mbedtls_gcm_update( &ctx, pt_len[i], ct[j * 6 + i],
buf );
if( ret != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
return( 1 );
}
goto exit;
}
ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
if( ret != 0 ||
memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
if( ret != 0 )
goto exit;
if( memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
return( 1 );
ret = 1;
goto exit;
}
mbedtls_gcm_free( &ctx );
if( verbose != 0 )
mbedtls_printf( "passed\n" );
}
}
if( verbose != 0 )
mbedtls_printf( "\n" );
return( 0 );
ret = 0;
exit:
if( ret != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
mbedtls_gcm_free( &ctx );
}
return( ret );
}
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */

View File

@ -63,8 +63,8 @@
#endif
#endif /* _MSC_VER */
#define read(fd,buf,len) recv(fd,(char*)buf,(int) len,0)
#define write(fd,buf,len) send(fd,(char*)buf,(int) len,0)
#define read(fd,buf,len) recv( fd, (char*)( buf ), (int)( len ), 0 )
#define write(fd,buf,len) send( fd, (char*)( buf ), (int)( len ), 0 )
#define close(fd) closesocket(fd)
static int wsa_init_done = 0;
@ -85,7 +85,7 @@ static int wsa_init_done = 0;
#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
/* Some MS functions want int and MSVC warns if we pass size_t,
* but the standard fucntions use socklen_t, so cast only for MSVC */
* but the standard functions use socklen_t, so cast only for MSVC */
#if defined(_MSC_VER)
#define MSVC_INT_CAST (int)
#else
@ -270,13 +270,18 @@ static int net_would_block( const mbedtls_net_context *ctx )
*/
static int net_would_block( const mbedtls_net_context *ctx )
{
int err = errno;
/*
* Never return 'WOULD BLOCK' on a non-blocking socket
*/
if( ( fcntl( ctx->fd, F_GETFL ) & O_NONBLOCK ) != O_NONBLOCK )
{
errno = err;
return( 0 );
}
switch( errno )
switch( errno = err )
{
#if defined EAGAIN
case EAGAIN:

View File

@ -134,45 +134,55 @@ static void pem_pbkdf1( unsigned char *key, size_t keylen,
/*
* Decrypt with DES-CBC, using PBKDF1 for key derivation
*/
static void pem_des_decrypt( unsigned char des_iv[8],
unsigned char *buf, size_t buflen,
const unsigned char *pwd, size_t pwdlen )
static int pem_des_decrypt( unsigned char des_iv[8],
unsigned char *buf, size_t buflen,
const unsigned char *pwd, size_t pwdlen )
{
mbedtls_des_context des_ctx;
unsigned char des_key[8];
int ret;
mbedtls_des_init( &des_ctx );
pem_pbkdf1( des_key, 8, des_iv, pwd, pwdlen );
mbedtls_des_setkey_dec( &des_ctx, des_key );
mbedtls_des_crypt_cbc( &des_ctx, MBEDTLS_DES_DECRYPT, buflen,
if( ( ret = mbedtls_des_setkey_dec( &des_ctx, des_key ) ) != 0 )
goto exit;
ret = mbedtls_des_crypt_cbc( &des_ctx, MBEDTLS_DES_DECRYPT, buflen,
des_iv, buf, buf );
exit:
mbedtls_des_free( &des_ctx );
mbedtls_zeroize( des_key, 8 );
return( ret );
}
/*
* Decrypt with 3DES-CBC, using PBKDF1 for key derivation
*/
static void pem_des3_decrypt( unsigned char des3_iv[8],
unsigned char *buf, size_t buflen,
const unsigned char *pwd, size_t pwdlen )
static int pem_des3_decrypt( unsigned char des3_iv[8],
unsigned char *buf, size_t buflen,
const unsigned char *pwd, size_t pwdlen )
{
mbedtls_des3_context des3_ctx;
unsigned char des3_key[24];
int ret;
mbedtls_des3_init( &des3_ctx );
pem_pbkdf1( des3_key, 24, des3_iv, pwd, pwdlen );
mbedtls_des3_set3key_dec( &des3_ctx, des3_key );
mbedtls_des3_crypt_cbc( &des3_ctx, MBEDTLS_DES_DECRYPT, buflen,
if( ( ret = mbedtls_des3_set3key_dec( &des3_ctx, des3_key ) ) != 0 )
goto exit;
ret = mbedtls_des3_crypt_cbc( &des3_ctx, MBEDTLS_DES_DECRYPT, buflen,
des3_iv, buf, buf );
exit:
mbedtls_des3_free( &des3_ctx );
mbedtls_zeroize( des3_key, 24 );
return( ret );
}
#endif /* MBEDTLS_DES_C */
@ -180,23 +190,28 @@ static void pem_des3_decrypt( unsigned char des3_iv[8],
/*
* Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation
*/
static void pem_aes_decrypt( unsigned char aes_iv[16], unsigned int keylen,
unsigned char *buf, size_t buflen,
const unsigned char *pwd, size_t pwdlen )
static int pem_aes_decrypt( unsigned char aes_iv[16], unsigned int keylen,
unsigned char *buf, size_t buflen,
const unsigned char *pwd, size_t pwdlen )
{
mbedtls_aes_context aes_ctx;
unsigned char aes_key[32];
int ret;
mbedtls_aes_init( &aes_ctx );
pem_pbkdf1( aes_key, keylen, aes_iv, pwd, pwdlen );
mbedtls_aes_setkey_dec( &aes_ctx, aes_key, keylen * 8 );
mbedtls_aes_crypt_cbc( &aes_ctx, MBEDTLS_AES_DECRYPT, buflen,
if( ( ret = mbedtls_aes_setkey_dec( &aes_ctx, aes_key, keylen * 8 ) ) != 0 )
goto exit;
ret = mbedtls_aes_crypt_cbc( &aes_ctx, MBEDTLS_AES_DECRYPT, buflen,
aes_iv, buf, buf );
exit:
mbedtls_aes_free( &aes_ctx );
mbedtls_zeroize( aes_key, keylen );
return( ret );
}
#endif /* MBEDTLS_AES_C */
@ -345,22 +360,30 @@ int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const
return( MBEDTLS_ERR_PEM_PASSWORD_REQUIRED );
}
ret = 0;
#if defined(MBEDTLS_DES_C)
if( enc_alg == MBEDTLS_CIPHER_DES_EDE3_CBC )
pem_des3_decrypt( pem_iv, buf, len, pwd, pwdlen );
ret = pem_des3_decrypt( pem_iv, buf, len, pwd, pwdlen );
else if( enc_alg == MBEDTLS_CIPHER_DES_CBC )
pem_des_decrypt( pem_iv, buf, len, pwd, pwdlen );
ret = pem_des_decrypt( pem_iv, buf, len, pwd, pwdlen );
#endif /* MBEDTLS_DES_C */
#if defined(MBEDTLS_AES_C)
if( enc_alg == MBEDTLS_CIPHER_AES_128_CBC )
pem_aes_decrypt( pem_iv, 16, buf, len, pwd, pwdlen );
ret = pem_aes_decrypt( pem_iv, 16, buf, len, pwd, pwdlen );
else if( enc_alg == MBEDTLS_CIPHER_AES_192_CBC )
pem_aes_decrypt( pem_iv, 24, buf, len, pwd, pwdlen );
ret = pem_aes_decrypt( pem_iv, 24, buf, len, pwd, pwdlen );
else if( enc_alg == MBEDTLS_CIPHER_AES_256_CBC )
pem_aes_decrypt( pem_iv, 32, buf, len, pwd, pwdlen );
ret = pem_aes_decrypt( pem_iv, 32, buf, len, pwd, pwdlen );
#endif /* MBEDTLS_AES_C */
if( ret != 0 )
{
mbedtls_free( buf );
return( ret );
}
/*
* The result will be ASN.1 starting with a SEQUENCE tag, with 1 to 3
* length bytes (allow 4 to be sure) in all known use cases.

View File

@ -29,8 +29,6 @@
#include "mbedtls/pk.h"
#include "mbedtls/pk_internal.h"
#include "mbedtls/bignum.h"
#if defined(MBEDTLS_RSA_C)
#include "mbedtls/rsa.h"
#endif
@ -42,6 +40,7 @@
#endif
#include <limits.h>
#include <stdint.h>
/* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize( void *v, size_t n ) {
@ -213,10 +212,10 @@ int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options,
int ret;
const mbedtls_pk_rsassa_pss_options *pss_opts;
#if defined(MBEDTLS_HAVE_INT64)
#if SIZE_MAX > UINT_MAX
if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
#endif /* MBEDTLS_HAVE_INT64 */
#endif /* SIZE_MAX > UINT_MAX */
if( options == NULL )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );

View File

@ -30,7 +30,6 @@
/* Even if RSA not activated, for the sake of RSA-alt */
#include "mbedtls/rsa.h"
#include "mbedtls/bignum.h"
#include <string.h>
@ -51,6 +50,7 @@
#endif
#include <limits.h>
#include <stdint.h>
#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
/* Implementation that should never be optimized out by the compiler */
@ -68,7 +68,8 @@ static int rsa_can_do( mbedtls_pk_type_t type )
static size_t rsa_get_bitlen( const void *ctx )
{
return( 8 * ((const mbedtls_rsa_context *) ctx)->len );
const mbedtls_rsa_context * rsa = (const mbedtls_rsa_context *) ctx;
return( 8 * mbedtls_rsa_get_len( rsa ) );
}
static int rsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg,
@ -76,21 +77,23 @@ static int rsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg,
const unsigned char *sig, size_t sig_len )
{
int ret;
mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx;
size_t rsa_len = mbedtls_rsa_get_len( rsa );
#if defined(MBEDTLS_HAVE_INT64)
#if SIZE_MAX > UINT_MAX
if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
#endif /* MBEDTLS_HAVE_INT64 */
#endif /* SIZE_MAX > UINT_MAX */
if( sig_len < ((mbedtls_rsa_context *) ctx)->len )
if( sig_len < rsa_len )
return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
if( ( ret = mbedtls_rsa_pkcs1_verify( (mbedtls_rsa_context *) ctx, NULL, NULL,
if( ( ret = mbedtls_rsa_pkcs1_verify( rsa, NULL, NULL,
MBEDTLS_RSA_PUBLIC, md_alg,
(unsigned int) hash_len, hash, sig ) ) != 0 )
return( ret );
if( sig_len > ((mbedtls_rsa_context *) ctx)->len )
if( sig_len > rsa_len )
return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH );
return( 0 );
@ -101,14 +104,16 @@ static int rsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg,
unsigned char *sig, size_t *sig_len,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
{
#if defined(MBEDTLS_HAVE_INT64)
mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx;
#if SIZE_MAX > UINT_MAX
if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
#endif /* MBEDTLS_HAVE_INT64 */
#endif /* SIZE_MAX > UINT_MAX */
*sig_len = ((mbedtls_rsa_context *) ctx)->len;
*sig_len = mbedtls_rsa_get_len( rsa );
return( mbedtls_rsa_pkcs1_sign( (mbedtls_rsa_context *) ctx, f_rng, p_rng, MBEDTLS_RSA_PRIVATE,
return( mbedtls_rsa_pkcs1_sign( rsa, f_rng, p_rng, MBEDTLS_RSA_PRIVATE,
md_alg, (unsigned int) hash_len, hash, sig ) );
}
@ -117,10 +122,12 @@ static int rsa_decrypt_wrap( void *ctx,
unsigned char *output, size_t *olen, size_t osize,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
{
if( ilen != ((mbedtls_rsa_context *) ctx)->len )
mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx;
if( ilen != mbedtls_rsa_get_len( rsa ) )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
return( mbedtls_rsa_pkcs1_decrypt( (mbedtls_rsa_context *) ctx, f_rng, p_rng,
return( mbedtls_rsa_pkcs1_decrypt( rsa, f_rng, p_rng,
MBEDTLS_RSA_PRIVATE, olen, input, output, osize ) );
}
@ -129,13 +136,14 @@ static int rsa_encrypt_wrap( void *ctx,
unsigned char *output, size_t *olen, size_t osize,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
{
*olen = ((mbedtls_rsa_context *) ctx)->len;
mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx;
*olen = mbedtls_rsa_get_len( rsa );
if( *olen > osize )
return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE );
return( mbedtls_rsa_pkcs1_encrypt( (mbedtls_rsa_context *) ctx,
f_rng, p_rng, MBEDTLS_RSA_PUBLIC, ilen, input, output ) );
return( mbedtls_rsa_pkcs1_encrypt( rsa, f_rng, p_rng, MBEDTLS_RSA_PUBLIC,
ilen, input, output ) );
}
static int rsa_check_pair_wrap( const void *pub, const void *prv )
@ -415,10 +423,10 @@ static int rsa_alt_sign_wrap( void *ctx, mbedtls_md_type_t md_alg,
{
mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx;
#if defined(MBEDTLS_HAVE_INT64)
#if SIZE_MAX > UINT_MAX
if( UINT_MAX < hash_len )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
#endif /* MBEDTLS_HAVE_INT64 */
#endif /* SIZE_MAX > UINT_MAX */
*sig_len = rsa_alt->key_len_func( rsa_alt->key );

View File

@ -60,12 +60,15 @@
#define mbedtls_free free
#endif
#if defined(MBEDTLS_FS_IO)
#if defined(MBEDTLS_FS_IO) || \
defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
/* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize( void *v, size_t n ) {
volatile unsigned char *p = v; while( n-- ) *p++ = 0;
}
#endif
#if defined(MBEDTLS_FS_IO)
/*
* Load all data from a file into a given buffer.
*
@ -520,19 +523,36 @@ static int pk_get_rsapubkey( unsigned char **p,
return( MBEDTLS_ERR_PK_INVALID_PUBKEY +
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
if( ( ret = mbedtls_asn1_get_mpi( p, end, &rsa->N ) ) != 0 ||
( ret = mbedtls_asn1_get_mpi( p, end, &rsa->E ) ) != 0 )
/* Import N */
if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 )
return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret );
if( ( ret = mbedtls_rsa_import_raw( rsa, *p, len, NULL, 0, NULL, 0,
NULL, 0, NULL, 0 ) ) != 0 )
return( MBEDTLS_ERR_PK_INVALID_PUBKEY );
*p += len;
/* Import E */
if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 )
return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret );
if( ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0,
NULL, 0, *p, len ) ) != 0 )
return( MBEDTLS_ERR_PK_INVALID_PUBKEY );
*p += len;
if( mbedtls_rsa_complete( rsa ) != 0 ||
mbedtls_rsa_check_pubkey( rsa ) != 0 )
{
return( MBEDTLS_ERR_PK_INVALID_PUBKEY );
}
if( *p != end )
return( MBEDTLS_ERR_PK_INVALID_PUBKEY +
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
if( ( ret = mbedtls_rsa_check_pubkey( rsa ) ) != 0 )
return( MBEDTLS_ERR_PK_INVALID_PUBKEY );
rsa->len = mbedtls_mpi_size( &rsa->N );
return( 0 );
}
#endif /* MBEDTLS_RSA_C */
@ -643,10 +663,13 @@ static int pk_parse_key_pkcs1_der( mbedtls_rsa_context *rsa,
const unsigned char *key,
size_t keylen )
{
int ret;
int ret, version;
size_t len;
unsigned char *p, *end;
mbedtls_mpi T;
mbedtls_mpi_init( &T );
p = (unsigned char *) key;
end = p + keylen;
@ -674,45 +697,88 @@ static int pk_parse_key_pkcs1_der( mbedtls_rsa_context *rsa,
end = p + len;
if( ( ret = mbedtls_asn1_get_int( &p, end, &rsa->ver ) ) != 0 )
if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 )
{
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
}
if( rsa->ver != 0 )
if( version != 0 )
{
return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION );
}
if( ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->N ) ) != 0 ||
( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->E ) ) != 0 ||
( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->D ) ) != 0 ||
( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->P ) ) != 0 ||
( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->Q ) ) != 0 ||
( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->DP ) ) != 0 ||
( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0 ||
( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->QP ) ) != 0 )
{
mbedtls_rsa_free( rsa );
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
}
/* Import N */
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
MBEDTLS_ASN1_INTEGER ) ) != 0 ||
( ret = mbedtls_rsa_import_raw( rsa, p, len, NULL, 0, NULL, 0,
NULL, 0, NULL, 0 ) ) != 0 )
goto cleanup;
p += len;
rsa->len = mbedtls_mpi_size( &rsa->N );
/* Import E */
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
MBEDTLS_ASN1_INTEGER ) ) != 0 ||
( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0,
NULL, 0, p, len ) ) != 0 )
goto cleanup;
p += len;
/* Import D */
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
MBEDTLS_ASN1_INTEGER ) ) != 0 ||
( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0,
p, len, NULL, 0 ) ) != 0 )
goto cleanup;
p += len;
/* Import P */
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
MBEDTLS_ASN1_INTEGER ) ) != 0 ||
( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, p, len, NULL, 0,
NULL, 0, NULL, 0 ) ) != 0 )
goto cleanup;
p += len;
/* Import Q */
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
MBEDTLS_ASN1_INTEGER ) ) != 0 ||
( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, p, len,
NULL, 0, NULL, 0 ) ) != 0 )
goto cleanup;
p += len;
/* Complete the RSA private key */
if( ( ret = mbedtls_rsa_complete( rsa ) ) != 0 )
goto cleanup;
/* Check optional parameters */
if( ( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 ||
( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 ||
( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 )
goto cleanup;
if( p != end )
{
mbedtls_rsa_free( rsa );
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ;
}
if( ( ret = mbedtls_rsa_check_privkey( rsa ) ) != 0 )
cleanup:
mbedtls_mpi_free( &T );
if( ret != 0 )
{
/* Wrap error code if it's coming from a lower level */
if( ( ret & 0xff80 ) == 0 )
ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret;
else
ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
mbedtls_rsa_free( rsa );
return( ret );
}
return( 0 );
return( ret );
}
#endif /* MBEDTLS_RSA_C */
@ -844,6 +910,16 @@ static int pk_parse_key_sec1_der( mbedtls_ecp_keypair *eck,
/*
* Parse an unencrypted PKCS#8 encoded private key
*
* Notes:
*
* - This function does not own the key buffer. It is the
* responsibility of the caller to take care of zeroizing
* and freeing it after use.
*
* - The function is responsible for freeing the provided
* PK context on failure.
*
*/
static int pk_parse_key_pkcs8_unencrypted_der(
mbedtls_pk_context *pk,
@ -859,7 +935,7 @@ static int pk_parse_key_pkcs8_unencrypted_der(
const mbedtls_pk_info_t *pk_info;
/*
* This function parses the PrivatKeyInfo object (PKCS#8 v1.2 = RFC 5208)
* This function parses the PrivateKeyInfo object (PKCS#8 v1.2 = RFC 5208)
*
* PrivateKeyInfo ::= SEQUENCE {
* version Version,
@ -932,16 +1008,22 @@ static int pk_parse_key_pkcs8_unencrypted_der(
/*
* Parse an encrypted PKCS#8 encoded private key
*
* To save space, the decryption happens in-place on the given key buffer.
* Also, while this function may modify the keybuffer, it doesn't own it,
* and instead it is the responsibility of the caller to zeroize and properly
* free it after use.
*
*/
#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
static int pk_parse_key_pkcs8_encrypted_der(
mbedtls_pk_context *pk,
const unsigned char *key, size_t keylen,
unsigned char *key, size_t keylen,
const unsigned char *pwd, size_t pwdlen )
{
int ret, decrypted = 0;
size_t len;
unsigned char buf[2048];
unsigned char *buf;
unsigned char *p, *end;
mbedtls_asn1_buf pbe_alg_oid, pbe_params;
#if defined(MBEDTLS_PKCS12_C)
@ -949,16 +1031,14 @@ static int pk_parse_key_pkcs8_encrypted_der(
mbedtls_md_type_t md_alg;
#endif
memset( buf, 0, sizeof( buf ) );
p = (unsigned char *) key;
p = key;
end = p + keylen;
if( pwdlen == 0 )
return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED );
/*
* This function parses the EncryptedPrivatKeyInfo object (PKCS#8)
* This function parses the EncryptedPrivateKeyInfo object (PKCS#8)
*
* EncryptedPrivateKeyInfo ::= SEQUENCE {
* encryptionAlgorithm EncryptionAlgorithmIdentifier,
@ -970,6 +1050,7 @@ static int pk_parse_key_pkcs8_encrypted_der(
* EncryptedData ::= OCTET STRING
*
* The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo
*
*/
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
@ -985,11 +1066,10 @@ static int pk_parse_key_pkcs8_encrypted_der(
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
if( len > sizeof( buf ) )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
buf = p;
/*
* Decrypt EncryptedData with appropriate PDE
* Decrypt EncryptedData with appropriate PBE
*/
#if defined(MBEDTLS_PKCS12_C)
if( mbedtls_oid_get_pkcs12_pbe_alg( &pbe_alg_oid, &md_alg, &cipher_alg ) == 0 )
@ -1081,10 +1161,8 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk,
if( ret == 0 )
{
if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL )
return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ||
pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA );
if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ||
( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ),
pem.buf, pem.buflen ) ) != 0 )
{
@ -1113,10 +1191,9 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk,
key, pwd, pwdlen, &len );
if( ret == 0 )
{
if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ) ) == NULL )
return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY );
if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ||
if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ||
( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ),
pem.buf, pem.buflen ) ) != 0 )
{
@ -1194,12 +1271,24 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk,
* error
*/
#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk, key, keylen,
pwd, pwdlen ) ) == 0 )
{
return( 0 );
unsigned char *key_copy;
if( ( key_copy = mbedtls_calloc( 1, keylen ) ) == NULL )
return( MBEDTLS_ERR_PK_ALLOC_FAILED );
memcpy( key_copy, key, keylen );
ret = pk_parse_key_pkcs8_encrypted_der( pk, key_copy, keylen,
pwd, pwdlen );
mbedtls_zeroize( key_copy, keylen );
mbedtls_free( key_copy );
}
if( ret == 0 )
return( 0 );
mbedtls_pk_free( pk );
if( ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH )
@ -1214,29 +1303,35 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk,
mbedtls_pk_free( pk );
#if defined(MBEDTLS_RSA_C)
if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL )
return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ||
( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), key, keylen ) ) == 0 )
pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA );
if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ||
( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ),
key, keylen ) ) != 0 )
{
mbedtls_pk_free( pk );
}
else
{
return( 0 );
}
mbedtls_pk_free( pk );
#endif /* MBEDTLS_RSA_C */
#if defined(MBEDTLS_ECP_C)
if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ) ) == NULL )
return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ||
( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), key, keylen ) ) == 0 )
pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY );
if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ||
( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ),
key, keylen ) ) != 0 )
{
mbedtls_pk_free( pk );
}
else
{
return( 0 );
}
mbedtls_pk_free( pk );
#endif /* MBEDTLS_ECP_C */
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );

View File

@ -62,13 +62,31 @@
* }
*/
static int pk_write_rsa_pubkey( unsigned char **p, unsigned char *start,
mbedtls_rsa_context *rsa )
mbedtls_rsa_context *rsa )
{
int ret;
size_t len = 0;
mbedtls_mpi T;
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( p, start, &rsa->E ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( p, start, &rsa->N ) );
mbedtls_mpi_init( &T );
/* Export E */
if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, NULL, NULL, &T ) ) != 0 ||
( ret = mbedtls_asn1_write_mpi( p, start, &T ) ) < 0 )
goto end_of_export;
len += ret;
/* Export N */
if ( ( ret = mbedtls_rsa_export( rsa, &T, NULL, NULL, NULL, NULL ) ) != 0 ||
( ret = mbedtls_asn1_write_mpi( p, start, &T ) ) < 0 )
goto end_of_export;
len += ret;
end_of_export:
mbedtls_mpi_free( &T );
if( ret < 0 )
return( ret );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED |
@ -83,7 +101,7 @@ static int pk_write_rsa_pubkey( unsigned char **p, unsigned char *start,
* EC public key is an EC point
*/
static int pk_write_ec_pubkey( unsigned char **p, unsigned char *start,
mbedtls_ecp_keypair *ec )
mbedtls_ecp_keypair *ec )
{
int ret;
size_t len = 0;
@ -111,7 +129,7 @@ static int pk_write_ec_pubkey( unsigned char **p, unsigned char *start,
* }
*/
static int pk_write_ec_param( unsigned char **p, unsigned char *start,
mbedtls_ecp_keypair *ec )
mbedtls_ecp_keypair *ec )
{
int ret;
size_t len = 0;
@ -128,7 +146,7 @@ static int pk_write_ec_param( unsigned char **p, unsigned char *start,
#endif /* MBEDTLS_ECP_C */
int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start,
const mbedtls_pk_context *key )
const mbedtls_pk_context *key )
{
int ret;
size_t len = 0;
@ -205,21 +223,79 @@ int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_
#if defined(MBEDTLS_RSA_C)
if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA )
{
mbedtls_mpi T; /* Temporary holding the exported parameters */
mbedtls_rsa_context *rsa = mbedtls_pk_rsa( *key );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->QP ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->DQ ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->DP ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->Q ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->P ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->D ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->E ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->N ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 0 ) );
/*
* Export the parameters one after another to avoid simultaneous copies.
*/
mbedtls_mpi_init( &T );
/* Export QP */
if( ( ret = mbedtls_rsa_export_crt( rsa, NULL, NULL, &T ) ) != 0 ||
( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
goto end_of_export;
len += ret;
/* Export DQ */
if( ( ret = mbedtls_rsa_export_crt( rsa, NULL, &T, NULL ) ) != 0 ||
( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
goto end_of_export;
len += ret;
/* Export DP */
if( ( ret = mbedtls_rsa_export_crt( rsa, &T, NULL, NULL ) ) != 0 ||
( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
goto end_of_export;
len += ret;
/* Export Q */
if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL,
&T, NULL, NULL ) ) != 0 ||
( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
goto end_of_export;
len += ret;
/* Export P */
if ( ( ret = mbedtls_rsa_export( rsa, NULL, &T,
NULL, NULL, NULL ) ) != 0 ||
( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
goto end_of_export;
len += ret;
/* Export D */
if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL,
NULL, &T, NULL ) ) != 0 ||
( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
goto end_of_export;
len += ret;
/* Export E */
if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL,
NULL, NULL, &T ) ) != 0 ||
( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
goto end_of_export;
len += ret;
/* Export N */
if ( ( ret = mbedtls_rsa_export( rsa, &T, NULL,
NULL, NULL, NULL ) ) != 0 ||
( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
goto end_of_export;
len += ret;
end_of_export:
mbedtls_mpi_free( &T );
if( ret < 0 )
return( ret );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 0 ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED |
MBEDTLS_ASN1_SEQUENCE ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c,
buf, MBEDTLS_ASN1_CONSTRUCTED |
MBEDTLS_ASN1_SEQUENCE ) );
}
else
#endif /* MBEDTLS_RSA_C */

View File

@ -18,6 +18,7 @@
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
/*
* The following sources were referenced in the design of this implementation
* of the RSA algorithm:
@ -45,6 +46,7 @@
#if defined(MBEDTLS_RSA_C)
#include "mbedtls/rsa.h"
#include "mbedtls/rsa_internal.h"
#include "mbedtls/oid.h"
#include <string.h>
@ -66,6 +68,8 @@
#define mbedtls_free free
#endif
#if !defined(MBEDTLS_RSA_ALT)
/* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize( void *v, size_t n ) {
volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
@ -85,6 +89,371 @@ static inline int mbedtls_safer_memcmp( const void *a, const void *b, size_t n )
return( diff );
}
int mbedtls_rsa_import( mbedtls_rsa_context *ctx,
const mbedtls_mpi *N,
const mbedtls_mpi *P, const mbedtls_mpi *Q,
const mbedtls_mpi *D, const mbedtls_mpi *E )
{
int ret;
if( ( N != NULL && ( ret = mbedtls_mpi_copy( &ctx->N, N ) ) != 0 ) ||
( P != NULL && ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ) ||
( Q != NULL && ( ret = mbedtls_mpi_copy( &ctx->Q, Q ) ) != 0 ) ||
( D != NULL && ( ret = mbedtls_mpi_copy( &ctx->D, D ) ) != 0 ) ||
( E != NULL && ( ret = mbedtls_mpi_copy( &ctx->E, E ) ) != 0 ) )
{
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret );
}
if( N != NULL )
ctx->len = mbedtls_mpi_size( &ctx->N );
return( 0 );
}
int mbedtls_rsa_import_raw( mbedtls_rsa_context *ctx,
unsigned char const *N, size_t N_len,
unsigned char const *P, size_t P_len,
unsigned char const *Q, size_t Q_len,
unsigned char const *D, size_t D_len,
unsigned char const *E, size_t E_len )
{
int ret = 0;
if( N != NULL )
{
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->N, N, N_len ) );
ctx->len = mbedtls_mpi_size( &ctx->N );
}
if( P != NULL )
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->P, P, P_len ) );
if( Q != NULL )
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->Q, Q, Q_len ) );
if( D != NULL )
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->D, D, D_len ) );
if( E != NULL )
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->E, E, E_len ) );
cleanup:
if( ret != 0 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret );
return( 0 );
}
/*
* Checks whether the context fields are set in such a way
* that the RSA primitives will be able to execute without error.
* It does *not* make guarantees for consistency of the parameters.
*/
static int rsa_check_context( mbedtls_rsa_context const *ctx, int is_priv,
int blinding_needed )
{
#if !defined(MBEDTLS_RSA_NO_CRT)
/* blinding_needed is only used for NO_CRT to decide whether
* P,Q need to be present or not. */
((void) blinding_needed);
#endif
if( ctx->len != mbedtls_mpi_size( &ctx->N ) ||
ctx->len > MBEDTLS_MPI_MAX_SIZE )
{
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
}
/*
* 1. Modular exponentiation needs positive, odd moduli.
*/
/* Modular exponentiation wrt. N is always used for
* RSA public key operations. */
if( mbedtls_mpi_cmp_int( &ctx->N, 0 ) <= 0 ||
mbedtls_mpi_get_bit( &ctx->N, 0 ) == 0 )
{
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
}
#if !defined(MBEDTLS_RSA_NO_CRT)
/* Modular exponentiation for P and Q is only
* used for private key operations and if CRT
* is used. */
if( is_priv &&
( mbedtls_mpi_cmp_int( &ctx->P, 0 ) <= 0 ||
mbedtls_mpi_get_bit( &ctx->P, 0 ) == 0 ||
mbedtls_mpi_cmp_int( &ctx->Q, 0 ) <= 0 ||
mbedtls_mpi_get_bit( &ctx->Q, 0 ) == 0 ) )
{
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
}
#endif /* !MBEDTLS_RSA_NO_CRT */
/*
* 2. Exponents must be positive
*/
/* Always need E for public key operations */
if( mbedtls_mpi_cmp_int( &ctx->E, 0 ) <= 0 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
#if defined(MBEDTLS_RSA_NO_CRT)
/* For private key operations, use D or DP & DQ
* as (unblinded) exponents. */
if( is_priv && mbedtls_mpi_cmp_int( &ctx->D, 0 ) <= 0 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
#else
if( is_priv &&
( mbedtls_mpi_cmp_int( &ctx->DP, 0 ) <= 0 ||
mbedtls_mpi_cmp_int( &ctx->DQ, 0 ) <= 0 ) )
{
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
}
#endif /* MBEDTLS_RSA_NO_CRT */
/* Blinding shouldn't make exponents negative either,
* so check that P, Q >= 1 if that hasn't yet been
* done as part of 1. */
#if defined(MBEDTLS_RSA_NO_CRT)
if( is_priv && blinding_needed &&
( mbedtls_mpi_cmp_int( &ctx->P, 0 ) <= 0 ||
mbedtls_mpi_cmp_int( &ctx->Q, 0 ) <= 0 ) )
{
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
}
#endif
/* It wouldn't lead to an error if it wasn't satisfied,
* but check for QP >= 1 nonetheless. */
#if !defined(MBEDTLS_RSA_NO_CRT)
if( is_priv &&
mbedtls_mpi_cmp_int( &ctx->QP, 0 ) <= 0 )
{
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
}
#endif
return( 0 );
}
int mbedtls_rsa_complete( mbedtls_rsa_context *ctx )
{
int ret = 0;
const int have_N = ( mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 );
const int have_P = ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 );
const int have_Q = ( mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 );
const int have_D = ( mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 );
const int have_E = ( mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0 );
/*
* Check whether provided parameters are enough
* to deduce all others. The following incomplete
* parameter sets for private keys are supported:
*
* (1) P, Q missing.
* (2) D and potentially N missing.
*
*/
const int n_missing = have_P && have_Q && have_D && have_E;
const int pq_missing = have_N && !have_P && !have_Q && have_D && have_E;
const int d_missing = have_P && have_Q && !have_D && have_E;
const int is_pub = have_N && !have_P && !have_Q && !have_D && have_E;
/* These three alternatives are mutually exclusive */
const int is_priv = n_missing || pq_missing || d_missing;
if( !is_priv && !is_pub )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
/*
* Step 1: Deduce N if P, Q are provided.
*/
if( !have_N && have_P && have_Q )
{
if( ( ret = mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P,
&ctx->Q ) ) != 0 )
{
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret );
}
ctx->len = mbedtls_mpi_size( &ctx->N );
}
/*
* Step 2: Deduce and verify all remaining core parameters.
*/
if( pq_missing )
{
ret = mbedtls_rsa_deduce_primes( &ctx->N, &ctx->E, &ctx->D,
&ctx->P, &ctx->Q );
if( ret != 0 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret );
}
else if( d_missing )
{
if( ( ret = mbedtls_rsa_deduce_private_exponent( &ctx->P,
&ctx->Q,
&ctx->E,
&ctx->D ) ) != 0 )
{
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret );
}
}
/*
* Step 3: Deduce all additional parameters specific
* to our current RSA implementation.
*/
#if !defined(MBEDTLS_RSA_NO_CRT)
if( is_priv )
{
ret = mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D,
&ctx->DP, &ctx->DQ, &ctx->QP );
if( ret != 0 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret );
}
#endif /* MBEDTLS_RSA_NO_CRT */
/*
* Step 3: Basic sanity checks
*/
return( rsa_check_context( ctx, is_priv, 1 ) );
}
int mbedtls_rsa_export_raw( const mbedtls_rsa_context *ctx,
unsigned char *N, size_t N_len,
unsigned char *P, size_t P_len,
unsigned char *Q, size_t Q_len,
unsigned char *D, size_t D_len,
unsigned char *E, size_t E_len )
{
int ret = 0;
/* Check if key is private or public */
const int is_priv =
mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 &&
mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 &&
mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 &&
mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 &&
mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0;
if( !is_priv )
{
/* If we're trying to export private parameters for a public key,
* something must be wrong. */
if( P != NULL || Q != NULL || D != NULL )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
}
if( N != NULL )
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->N, N, N_len ) );
if( P != NULL )
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->P, P, P_len ) );
if( Q != NULL )
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->Q, Q, Q_len ) );
if( D != NULL )
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->D, D, D_len ) );
if( E != NULL )
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->E, E, E_len ) );
cleanup:
return( ret );
}
int mbedtls_rsa_export( const mbedtls_rsa_context *ctx,
mbedtls_mpi *N, mbedtls_mpi *P, mbedtls_mpi *Q,
mbedtls_mpi *D, mbedtls_mpi *E )
{
int ret;
/* Check if key is private or public */
int is_priv =
mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 &&
mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 &&
mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 &&
mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 &&
mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0;
if( !is_priv )
{
/* If we're trying to export private parameters for a public key,
* something must be wrong. */
if( P != NULL || Q != NULL || D != NULL )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
}
/* Export all requested core parameters. */
if( ( N != NULL && ( ret = mbedtls_mpi_copy( N, &ctx->N ) ) != 0 ) ||
( P != NULL && ( ret = mbedtls_mpi_copy( P, &ctx->P ) ) != 0 ) ||
( Q != NULL && ( ret = mbedtls_mpi_copy( Q, &ctx->Q ) ) != 0 ) ||
( D != NULL && ( ret = mbedtls_mpi_copy( D, &ctx->D ) ) != 0 ) ||
( E != NULL && ( ret = mbedtls_mpi_copy( E, &ctx->E ) ) != 0 ) )
{
return( ret );
}
return( 0 );
}
/*
* Export CRT parameters
* This must also be implemented if CRT is not used, for being able to
* write DER encoded RSA keys. The helper function mbedtls_rsa_deduce_crt
* can be used in this case.
*/
int mbedtls_rsa_export_crt( const mbedtls_rsa_context *ctx,
mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP )
{
int ret;
/* Check if key is private or public */
int is_priv =
mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 &&
mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 &&
mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 &&
mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 &&
mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0;
if( !is_priv )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
#if !defined(MBEDTLS_RSA_NO_CRT)
/* Export all requested blinding parameters. */
if( ( DP != NULL && ( ret = mbedtls_mpi_copy( DP, &ctx->DP ) ) != 0 ) ||
( DQ != NULL && ( ret = mbedtls_mpi_copy( DQ, &ctx->DQ ) ) != 0 ) ||
( QP != NULL && ( ret = mbedtls_mpi_copy( QP, &ctx->QP ) ) != 0 ) )
{
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret );
}
#else
if( ( ret = mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D,
DP, DQ, QP ) ) != 0 )
{
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret );
}
#endif
return( 0 );
}
/*
* Initialize an RSA context
*/
@ -110,6 +479,16 @@ void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, int hash_id
ctx->hash_id = hash_id;
}
/*
* Get length in bytes of RSA modulus
*/
size_t mbedtls_rsa_get_len( const mbedtls_rsa_context *ctx )
{
return( ctx->len );
}
#if defined(MBEDTLS_GENPRIME)
/*
@ -121,7 +500,7 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx,
unsigned int nbits, int exponent )
{
int ret;
mbedtls_mpi P1, Q1, H, G;
mbedtls_mpi H, G;
if( f_rng == NULL || nbits < 128 || exponent < 3 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
@ -129,8 +508,8 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx,
if( nbits % 2 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 );
mbedtls_mpi_init( &H ); mbedtls_mpi_init( &G );
mbedtls_mpi_init( &H );
mbedtls_mpi_init( &G );
/*
* find primes P and Q with Q < P so that:
@ -141,10 +520,10 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx,
do
{
MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->P, nbits >> 1, 0,
f_rng, p_rng ) );
f_rng, p_rng ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->Q, nbits >> 1, 0,
f_rng, p_rng ) );
f_rng, p_rng ) );
if( mbedtls_mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 )
continue;
@ -154,31 +533,43 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx,
continue;
if( mbedtls_mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 )
mbedtls_mpi_swap( &ctx->P, &ctx->Q );
mbedtls_mpi_swap( &ctx->P, &ctx->Q );
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &P1, &Q1 ) );
/* Temporarily replace P,Q by P-1, Q-1 */
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &ctx->P, &ctx->P, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &ctx->Q, &ctx->Q, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &ctx->P, &ctx->Q ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->E, &H ) );
}
while( mbedtls_mpi_cmp_int( &G, 1 ) != 0 );
/* Restore P,Q */
MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &ctx->P, &ctx->P, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &ctx->Q, &ctx->Q, 1 ) );
ctx->len = mbedtls_mpi_size( &ctx->N );
/*
* D = E^-1 mod ((P-1)*(Q-1))
* DP = D mod (P - 1)
* DQ = D mod (Q - 1)
* QP = Q^-1 mod P
*/
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->D , &ctx->E, &H ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) );
ctx->len = ( mbedtls_mpi_bitlen( &ctx->N ) + 7 ) >> 3;
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->D, &ctx->E, &H ) );
#if !defined(MBEDTLS_RSA_NO_CRT)
MBEDTLS_MPI_CHK( mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D,
&ctx->DP, &ctx->DQ, &ctx->QP ) );
#endif /* MBEDTLS_RSA_NO_CRT */
/* Double-check */
MBEDTLS_MPI_CHK( mbedtls_rsa_check_privkey( ctx ) );
cleanup:
mbedtls_mpi_free( &P1 ); mbedtls_mpi_free( &Q1 ); mbedtls_mpi_free( &H ); mbedtls_mpi_free( &G );
mbedtls_mpi_free( &H );
mbedtls_mpi_free( &G );
if( ret != 0 )
{
@ -196,82 +587,48 @@ cleanup:
*/
int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx )
{
if( !ctx->N.p || !ctx->E.p )
if( rsa_check_context( ctx, 0 /* public */, 0 /* no blinding */ ) != 0 )
return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
if( ( ctx->N.p[0] & 1 ) == 0 ||
( ctx->E.p[0] & 1 ) == 0 )
if( mbedtls_mpi_bitlen( &ctx->N ) < 128 )
{
return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
}
if( mbedtls_mpi_bitlen( &ctx->N ) < 128 ||
mbedtls_mpi_bitlen( &ctx->N ) > MBEDTLS_MPI_MAX_BITS )
return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
if( mbedtls_mpi_bitlen( &ctx->E ) < 2 ||
if( mbedtls_mpi_get_bit( &ctx->E, 0 ) == 0 ||
mbedtls_mpi_bitlen( &ctx->E ) < 2 ||
mbedtls_mpi_cmp_mpi( &ctx->E, &ctx->N ) >= 0 )
{
return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
}
return( 0 );
}
/*
* Check a private RSA key
* Check for the consistency of all fields in an RSA private key context
*/
int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx )
{
int ret;
mbedtls_mpi PQ, DE, P1, Q1, H, I, G, G2, L1, L2, DP, DQ, QP;
if( ( ret = mbedtls_rsa_check_pubkey( ctx ) ) != 0 )
return( ret );
if( !ctx->P.p || !ctx->Q.p || !ctx->D.p )
return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
mbedtls_mpi_init( &PQ ); mbedtls_mpi_init( &DE ); mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 );
mbedtls_mpi_init( &H ); mbedtls_mpi_init( &I ); mbedtls_mpi_init( &G ); mbedtls_mpi_init( &G2 );
mbedtls_mpi_init( &L1 ); mbedtls_mpi_init( &L2 ); mbedtls_mpi_init( &DP ); mbedtls_mpi_init( &DQ );
mbedtls_mpi_init( &QP );
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &PQ, &ctx->P, &ctx->Q ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DE, &ctx->D, &ctx->E ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &P1, &Q1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->E, &H ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G2, &P1, &Q1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &L1, &L2, &H, &G2 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &I, &DE, &L1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &DP, &ctx->D, &P1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &DQ, &ctx->D, &Q1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &QP, &ctx->Q, &ctx->P ) );
/*
* Check for a valid PKCS1v2 private key
*/
if( mbedtls_mpi_cmp_mpi( &PQ, &ctx->N ) != 0 ||
mbedtls_mpi_cmp_mpi( &DP, &ctx->DP ) != 0 ||
mbedtls_mpi_cmp_mpi( &DQ, &ctx->DQ ) != 0 ||
mbedtls_mpi_cmp_mpi( &QP, &ctx->QP ) != 0 ||
mbedtls_mpi_cmp_int( &L2, 0 ) != 0 ||
mbedtls_mpi_cmp_int( &I, 1 ) != 0 ||
mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
if( mbedtls_rsa_check_pubkey( ctx ) != 0 ||
rsa_check_context( ctx, 1 /* private */, 1 /* blinding */ ) != 0 )
{
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
}
cleanup:
mbedtls_mpi_free( &PQ ); mbedtls_mpi_free( &DE ); mbedtls_mpi_free( &P1 ); mbedtls_mpi_free( &Q1 );
mbedtls_mpi_free( &H ); mbedtls_mpi_free( &I ); mbedtls_mpi_free( &G ); mbedtls_mpi_free( &G2 );
mbedtls_mpi_free( &L1 ); mbedtls_mpi_free( &L2 ); mbedtls_mpi_free( &DP ); mbedtls_mpi_free( &DQ );
mbedtls_mpi_free( &QP );
if( mbedtls_rsa_validate_params( &ctx->N, &ctx->P, &ctx->Q,
&ctx->D, &ctx->E, NULL, NULL ) != 0 )
{
return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
}
if( ret == MBEDTLS_ERR_RSA_KEY_CHECK_FAILED )
return( ret );
if( ret != 0 )
return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED + ret );
#if !defined(MBEDTLS_RSA_NO_CRT)
else if( mbedtls_rsa_validate_crt( &ctx->P, &ctx->Q, &ctx->D,
&ctx->DP, &ctx->DQ, &ctx->QP ) != 0 )
{
return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
}
#endif
return( 0 );
}
@ -279,9 +636,10 @@ cleanup:
/*
* Check if contexts holding a public and private key match
*/
int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, const mbedtls_rsa_context *prv )
int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub,
const mbedtls_rsa_context *prv )
{
if( mbedtls_rsa_check_pubkey( pub ) != 0 ||
if( mbedtls_rsa_check_pubkey( pub ) != 0 ||
mbedtls_rsa_check_privkey( prv ) != 0 )
{
return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
@ -307,6 +665,9 @@ int mbedtls_rsa_public( mbedtls_rsa_context *ctx,
size_t olen;
mbedtls_mpi T;
if( rsa_check_context( ctx, 0 /* public */, 0 /* no blinding */ ) )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
mbedtls_mpi_init( &T );
#if defined(MBEDTLS_THREADING_C)
@ -423,14 +784,15 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx,
mbedtls_mpi *DQ = &ctx->DQ;
#endif
/* Make sure we have private key info, prevent possible misuse */
if( ctx->P.p == NULL || ctx->Q.p == NULL || ctx->D.p == NULL )
if( rsa_check_context( ctx, 1 /* private key checks */,
f_rng != NULL /* blinding y/n */ ) != 0 )
{
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
}
mbedtls_mpi_init( &T ); mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 ); mbedtls_mpi_init( &R );
if( f_rng != NULL )
{
#if defined(MBEDTLS_RSA_NO_CRT)
@ -1666,13 +2028,16 @@ int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src )
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->D, &src->D ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->P, &src->P ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Q, &src->Q ) );
#if !defined(MBEDTLS_RSA_NO_CRT)
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DP, &src->DP ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DQ, &src->DQ ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->QP, &src->QP ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RN, &src->RN ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RP, &src->RP ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RQ, &src->RQ ) );
#endif
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RN, &src->RN ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vi, &src->Vi ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vf, &src->Vf ) );
@ -1693,16 +2058,23 @@ cleanup:
void mbedtls_rsa_free( mbedtls_rsa_context *ctx )
{
mbedtls_mpi_free( &ctx->Vi ); mbedtls_mpi_free( &ctx->Vf );
mbedtls_mpi_free( &ctx->RQ ); mbedtls_mpi_free( &ctx->RP ); mbedtls_mpi_free( &ctx->RN );
mbedtls_mpi_free( &ctx->QP ); mbedtls_mpi_free( &ctx->DQ ); mbedtls_mpi_free( &ctx->DP );
mbedtls_mpi_free( &ctx->Q ); mbedtls_mpi_free( &ctx->P ); mbedtls_mpi_free( &ctx->D );
mbedtls_mpi_free( &ctx->RN ); mbedtls_mpi_free( &ctx->D );
mbedtls_mpi_free( &ctx->Q ); mbedtls_mpi_free( &ctx->P );
mbedtls_mpi_free( &ctx->E ); mbedtls_mpi_free( &ctx->N );
#if !defined(MBEDTLS_RSA_NO_CRT)
mbedtls_mpi_free( &ctx->RQ ); mbedtls_mpi_free( &ctx->RP );
mbedtls_mpi_free( &ctx->QP ); mbedtls_mpi_free( &ctx->DQ );
mbedtls_mpi_free( &ctx->DP );
#endif /* MBEDTLS_RSA_NO_CRT */
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_free( &ctx->mutex );
#endif
}
#endif /* !MBEDTLS_RSA_ALT */
#if defined(MBEDTLS_SELF_TEST)
#include "mbedtls/sha1.h"
@ -1742,21 +2114,6 @@ void mbedtls_rsa_free( mbedtls_rsa_context *ctx )
"910E4168387E3C30AA1E00C339A79508" \
"8452DD96A9A5EA5D9DCA68DA636032AF"
#define RSA_DP "C1ACF567564274FB07A0BBAD5D26E298" \
"3C94D22288ACD763FD8E5600ED4A702D" \
"F84198A5F06C2E72236AE490C93F07F8" \
"3CC559CD27BC2D1CA488811730BB5725"
#define RSA_DQ "4959CBF6F8FEF750AEE6977C155579C7" \
"D8AAEA56749EA28623272E4F7D0592AF" \
"7C1F1313CAC9471B5C523BFE592F517B" \
"407A1BD76C164B93DA2D32A383E58357"
#define RSA_QP "9AE7FBC99546432DF71896FC239EADAE" \
"F38D18D2B2F0E2DD275AA977E2BF4411" \
"F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \
"A74206CEC169D74BF5A8C50D6F48EA08"
#define PT_LEN 24
#define RSA_PT "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \
"\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD"
@ -1799,17 +2156,23 @@ int mbedtls_rsa_self_test( int verbose )
unsigned char sha1sum[20];
#endif
mbedtls_mpi K;
mbedtls_mpi_init( &K );
mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 );
rsa.len = KEY_LEN;
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.N , 16, RSA_N ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.E , 16, RSA_E ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.D , 16, RSA_D ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.P , 16, RSA_P ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.Q , 16, RSA_Q ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.DP, 16, RSA_DP ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.DQ, 16, RSA_DQ ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.QP, 16, RSA_QP ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_N ) );
MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, &K, NULL, NULL, NULL, NULL ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_P ) );
MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, &K, NULL, NULL, NULL ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_Q ) );
MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, &K, NULL, NULL ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_D ) );
MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, NULL, &K, NULL ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_E ) );
MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, NULL, NULL, &K ) );
MBEDTLS_MPI_CHK( mbedtls_rsa_complete( &rsa ) );
if( verbose != 0 )
mbedtls_printf( " RSA key validation: " );
@ -1828,8 +2191,9 @@ int mbedtls_rsa_self_test( int verbose )
memcpy( rsa_plaintext, RSA_PT, PT_LEN );
if( mbedtls_rsa_pkcs1_encrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PUBLIC, PT_LEN,
rsa_plaintext, rsa_ciphertext ) != 0 )
if( mbedtls_rsa_pkcs1_encrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PUBLIC,
PT_LEN, rsa_plaintext,
rsa_ciphertext ) != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
@ -1840,9 +2204,9 @@ int mbedtls_rsa_self_test( int verbose )
if( verbose != 0 )
mbedtls_printf( "passed\n PKCS#1 decryption : " );
if( mbedtls_rsa_pkcs1_decrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PRIVATE, &len,
rsa_ciphertext, rsa_decrypted,
sizeof(rsa_decrypted) ) != 0 )
if( mbedtls_rsa_pkcs1_decrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PRIVATE,
&len, rsa_ciphertext, rsa_decrypted,
sizeof(rsa_decrypted) ) != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
@ -1867,8 +2231,9 @@ int mbedtls_rsa_self_test( int verbose )
mbedtls_sha1( rsa_plaintext, PT_LEN, sha1sum );
if( mbedtls_rsa_pkcs1_sign( &rsa, myrand, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 0,
sha1sum, rsa_ciphertext ) != 0 )
if( mbedtls_rsa_pkcs1_sign( &rsa, myrand, NULL,
MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 0,
sha1sum, rsa_ciphertext ) != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
@ -1879,8 +2244,9 @@ int mbedtls_rsa_self_test( int verbose )
if( verbose != 0 )
mbedtls_printf( "passed\n PKCS#1 sig. verify: " );
if( mbedtls_rsa_pkcs1_verify( &rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 0,
sha1sum, rsa_ciphertext ) != 0 )
if( mbedtls_rsa_pkcs1_verify( &rsa, NULL, NULL,
MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 0,
sha1sum, rsa_ciphertext ) != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
@ -1896,6 +2262,7 @@ int mbedtls_rsa_self_test( int verbose )
mbedtls_printf( "\n" );
cleanup:
mbedtls_mpi_free( &K );
mbedtls_rsa_free( &rsa );
#else /* MBEDTLS_PKCS1_V15 */
((void) verbose);

487
library/rsa_internal.c Normal file
View File

@ -0,0 +1,487 @@
/*
* Helper functions for the RSA module
*
* Copyright (C) 2006-2017, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*
*/
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_RSA_C)
#include "mbedtls/rsa.h"
#include "mbedtls/bignum.h"
#include "mbedtls/rsa_internal.h"
/*
* Compute RSA prime factors from public and private exponents
*
* Summary of algorithm:
* Setting F := lcm(P-1,Q-1), the idea is as follows:
*
* (a) For any 1 <= X < N with gcd(X,N)=1, we have X^F = 1 modulo N, so X^(F/2)
* is a square root of 1 in Z/NZ. Since Z/NZ ~= Z/PZ x Z/QZ by CRT and the
* square roots of 1 in Z/PZ and Z/QZ are +1 and -1, this leaves the four
* possibilities X^(F/2) = (+-1, +-1). If it happens that X^(F/2) = (-1,+1)
* or (+1,-1), then gcd(X^(F/2) + 1, N) will be equal to one of the prime
* factors of N.
*
* (b) If we don't know F/2 but (F/2) * K for some odd (!) K, then the same
* construction still applies since (-)^K is the identity on the set of
* roots of 1 in Z/NZ.
*
* The public and private key primitives (-)^E and (-)^D are mutually inverse
* bijections on Z/NZ if and only if (-)^(DE) is the identity on Z/NZ, i.e.
* if and only if DE - 1 is a multiple of F, say DE - 1 = F * L.
* Splitting L = 2^t * K with K odd, we have
*
* DE - 1 = FL = (F/2) * (2^(t+1)) * K,
*
* so (F / 2) * K is among the numbers
*
* (DE - 1) >> 1, (DE - 1) >> 2, ..., (DE - 1) >> ord
*
* where ord is the order of 2 in (DE - 1).
* We can therefore iterate through these numbers apply the construction
* of (a) and (b) above to attempt to factor N.
*
*/
int mbedtls_rsa_deduce_primes( mbedtls_mpi const *N,
mbedtls_mpi const *E, mbedtls_mpi const *D,
mbedtls_mpi *P, mbedtls_mpi *Q )
{
int ret = 0;
uint16_t attempt; /* Number of current attempt */
uint16_t iter; /* Number of squares computed in the current attempt */
uint16_t order; /* Order of 2 in DE - 1 */
mbedtls_mpi T; /* Holds largest odd divisor of DE - 1 */
mbedtls_mpi K; /* Temporary holding the current candidate */
const unsigned char primes[] = { 2,
3, 5, 7, 11, 13, 17, 19, 23,
29, 31, 37, 41, 43, 47, 53, 59,
61, 67, 71, 73, 79, 83, 89, 97,
101, 103, 107, 109, 113, 127, 131, 137,
139, 149, 151, 157, 163, 167, 173, 179,
181, 191, 193, 197, 199, 211, 223, 227,
229, 233, 239, 241, 251
};
const size_t num_primes = sizeof( primes ) / sizeof( *primes );
if( P == NULL || Q == NULL || P->p != NULL || Q->p != NULL )
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 ||
mbedtls_mpi_cmp_int( D, 1 ) <= 0 ||
mbedtls_mpi_cmp_mpi( D, N ) >= 0 ||
mbedtls_mpi_cmp_int( E, 1 ) <= 0 ||
mbedtls_mpi_cmp_mpi( E, N ) >= 0 )
{
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
}
/*
* Initializations and temporary changes
*/
mbedtls_mpi_init( &K );
mbedtls_mpi_init( &T );
/* T := DE - 1 */
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, D, E ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &T, &T, 1 ) );
if( ( order = (uint16_t) mbedtls_mpi_lsb( &T ) ) == 0 )
{
ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
goto cleanup;
}
/* After this operation, T holds the largest odd divisor of DE - 1. */
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &T, order ) );
/*
* Actual work
*/
/* Skip trying 2 if N == 1 mod 8 */
attempt = 0;
if( N->p[0] % 8 == 1 )
attempt = 1;
for( ; attempt < num_primes; ++attempt )
{
mbedtls_mpi_lset( &K, primes[attempt] );
/* Check if gcd(K,N) = 1 */
MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( P, &K, N ) );
if( mbedtls_mpi_cmp_int( P, 1 ) != 0 )
continue;
/* Go through K^T + 1, K^(2T) + 1, K^(4T) + 1, ...
* and check whether they have nontrivial GCD with N. */
MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &K, &K, &T, N,
Q /* temporarily use Q for storing Montgomery
* multiplication helper values */ ) );
for( iter = 1; iter <= order; ++iter )
{
/* If we reach 1 prematurely, there's no point
* in continuing to square K */
if( mbedtls_mpi_cmp_int( &K, 1 ) == 0 )
break;
MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &K, &K, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( P, &K, N ) );
if( mbedtls_mpi_cmp_int( P, 1 ) == 1 &&
mbedtls_mpi_cmp_mpi( P, N ) == -1 )
{
/*
* Have found a nontrivial divisor P of N.
* Set Q := N / P.
*/
MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( Q, NULL, N, P ) );
goto cleanup;
}
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, &K, &K ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, N ) );
}
/*
* If we get here, then either we prematurely aborted the loop because
* we reached 1, or K holds primes[attempt]^(DE - 1) mod N, which must
* be 1 if D,E,N were consistent.
* Check if that's the case and abort if not, to avoid very long,
* yet eventually failing, computations if N,D,E were not sane.
*/
if( mbedtls_mpi_cmp_int( &K, 1 ) != 0 )
{
break;
}
}
ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
cleanup:
mbedtls_mpi_free( &K );
mbedtls_mpi_free( &T );
return( ret );
}
/*
* Given P, Q and the public exponent E, deduce D.
* This is essentially a modular inversion.
*/
int mbedtls_rsa_deduce_private_exponent( mbedtls_mpi const *P,
mbedtls_mpi const *Q,
mbedtls_mpi const *E,
mbedtls_mpi *D )
{
int ret = 0;
mbedtls_mpi K, L;
if( D == NULL || mbedtls_mpi_cmp_int( D, 0 ) != 0 )
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
if( mbedtls_mpi_cmp_int( P, 1 ) <= 0 ||
mbedtls_mpi_cmp_int( Q, 1 ) <= 0 ||
mbedtls_mpi_cmp_int( E, 0 ) == 0 )
{
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
}
mbedtls_mpi_init( &K );
mbedtls_mpi_init( &L );
/* Temporarily put K := P-1 and L := Q-1 */
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, Q, 1 ) );
/* Temporarily put D := gcd(P-1, Q-1) */
MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( D, &K, &L ) );
/* K := LCM(P-1, Q-1) */
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, &K, &L ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &K, NULL, &K, D ) );
/* Compute modular inverse of E in LCM(P-1, Q-1) */
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( D, E, &K ) );
cleanup:
mbedtls_mpi_free( &K );
mbedtls_mpi_free( &L );
return( ret );
}
/*
* Check that RSA CRT parameters are in accordance with core parameters.
*/
int mbedtls_rsa_validate_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q,
const mbedtls_mpi *D, const mbedtls_mpi *DP,
const mbedtls_mpi *DQ, const mbedtls_mpi *QP )
{
int ret = 0;
mbedtls_mpi K, L;
mbedtls_mpi_init( &K );
mbedtls_mpi_init( &L );
/* Check that DP - D == 0 mod P - 1 */
if( DP != NULL )
{
if( P == NULL )
{
ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
goto cleanup;
}
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &L, DP, D ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &L, &L, &K ) );
if( mbedtls_mpi_cmp_int( &L, 0 ) != 0 )
{
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup;
}
}
/* Check that DQ - D == 0 mod Q - 1 */
if( DQ != NULL )
{
if( Q == NULL )
{
ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
goto cleanup;
}
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, Q, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &L, DQ, D ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &L, &L, &K ) );
if( mbedtls_mpi_cmp_int( &L, 0 ) != 0 )
{
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup;
}
}
/* Check that QP * Q - 1 == 0 mod P */
if( QP != NULL )
{
if( P == NULL || Q == NULL )
{
ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
goto cleanup;
}
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, QP, Q ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, P ) );
if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 )
{
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup;
}
}
cleanup:
/* Wrap MPI error codes by RSA check failure error code */
if( ret != 0 &&
ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED &&
ret != MBEDTLS_ERR_RSA_BAD_INPUT_DATA )
{
ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
}
mbedtls_mpi_free( &K );
mbedtls_mpi_free( &L );
return( ret );
}
/*
* Check that core RSA parameters are sane.
*/
int mbedtls_rsa_validate_params( const mbedtls_mpi *N, const mbedtls_mpi *P,
const mbedtls_mpi *Q, const mbedtls_mpi *D,
const mbedtls_mpi *E,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
int ret = 0;
mbedtls_mpi K, L;
mbedtls_mpi_init( &K );
mbedtls_mpi_init( &L );
/*
* Step 1: If PRNG provided, check that P and Q are prime
*/
#if defined(MBEDTLS_GENPRIME)
if( f_rng != NULL && P != NULL &&
( ret = mbedtls_mpi_is_prime( P, f_rng, p_rng ) ) != 0 )
{
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup;
}
if( f_rng != NULL && Q != NULL &&
( ret = mbedtls_mpi_is_prime( Q, f_rng, p_rng ) ) != 0 )
{
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup;
}
#else
((void) f_rng);
((void) p_rng);
#endif /* MBEDTLS_GENPRIME */
/*
* Step 2: Check that 1 < N = P * Q
*/
if( P != NULL && Q != NULL && N != NULL )
{
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, P, Q ) );
if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 ||
mbedtls_mpi_cmp_mpi( &K, N ) != 0 )
{
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup;
}
}
/*
* Step 3: Check and 1 < D, E < N if present.
*/
if( N != NULL && D != NULL && E != NULL )
{
if ( mbedtls_mpi_cmp_int( D, 1 ) <= 0 ||
mbedtls_mpi_cmp_int( E, 1 ) <= 0 ||
mbedtls_mpi_cmp_mpi( D, N ) >= 0 ||
mbedtls_mpi_cmp_mpi( E, N ) >= 0 )
{
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup;
}
}
/*
* Step 4: Check that D, E are inverse modulo P-1 and Q-1
*/
if( P != NULL && Q != NULL && D != NULL && E != NULL )
{
if( mbedtls_mpi_cmp_int( P, 1 ) <= 0 ||
mbedtls_mpi_cmp_int( Q, 1 ) <= 0 )
{
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup;
}
/* Compute DE-1 mod P-1 */
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, D, E ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, P, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, &L ) );
if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 )
{
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup;
}
/* Compute DE-1 mod Q-1 */
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, D, E ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, Q, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, &L ) );
if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 )
{
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup;
}
}
cleanup:
mbedtls_mpi_free( &K );
mbedtls_mpi_free( &L );
/* Wrap MPI error codes by RSA check failure error code */
if( ret != 0 && ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED )
{
ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
}
return( ret );
}
int mbedtls_rsa_deduce_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q,
const mbedtls_mpi *D, mbedtls_mpi *DP,
mbedtls_mpi *DQ, mbedtls_mpi *QP )
{
int ret = 0;
mbedtls_mpi K;
mbedtls_mpi_init( &K );
/* DP = D mod P-1 */
if( DP != NULL )
{
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( DP, D, &K ) );
}
/* DQ = D mod Q-1 */
if( DQ != NULL )
{
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, Q, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( DQ, D, &K ) );
}
/* QP = Q^{-1} mod P */
if( QP != NULL )
{
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( QP, Q, P ) );
}
cleanup:
mbedtls_mpi_free( &K );
return( ret );
}
#endif /* MBEDTLS_RSA_C */

View File

@ -321,6 +321,7 @@ void mbedtls_ssl_cache_free( mbedtls_ssl_cache_context *cache )
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_free( &cache->mutex );
#endif
cache->chain = NULL;
}
#endif /* MBEDTLS_SSL_CACHE_C */

View File

@ -80,6 +80,13 @@ static void ssl_write_hostname_ext( mbedtls_ssl_context *ssl,
}
/*
* Sect. 3, RFC 6066 (TLS Extensions Definitions)
*
* In order to provide any of the server names, clients MAY include an
* extension of type "server_name" in the (extended) client hello. The
* "extension_data" field of this extension SHALL contain
* "ServerNameList" where:
*
* struct {
* NameType name_type;
* select (name_type) {
@ -96,6 +103,7 @@ static void ssl_write_hostname_ext( mbedtls_ssl_context *ssl,
* struct {
* ServerName server_name_list<1..2^16-1>
* } ServerNameList;
*
*/
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SERVERNAME >> 8 ) & 0xFF );
*p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SERVERNAME ) & 0xFF );
@ -126,6 +134,9 @@ static void ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl,
*olen = 0;
/* We're always including an TLS_EMPTY_RENEGOTIATION_INFO_SCSV in the
* initial ClientHello, in which case also adding the renegotiation
* info extension is NOT RECOMMENDED as per RFC 5746 Section 3.4. */
if( ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS )
return;
@ -963,6 +974,8 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
ext_len += olen;
#endif
/* Note that TLS_EMPTY_RENEGOTIATION_INFO_SCSV is always added
* even if MBEDTLS_SSL_RENEGOTIATION is not defined. */
#if defined(MBEDTLS_SSL_RENEGOTIATION)
ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, &olen );
ext_len += olen;
@ -1440,9 +1453,6 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
#endif
int handshake_failure = 0;
const mbedtls_ssl_ciphersuite_t *suite_info;
#if defined(MBEDTLS_DEBUG_C)
uint32_t t;
#endif
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello" ) );
@ -1545,13 +1555,11 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION );
}
#if defined(MBEDTLS_DEBUG_C)
t = ( (uint32_t) buf[2] << 24 )
| ( (uint32_t) buf[3] << 16 )
| ( (uint32_t) buf[4] << 8 )
| ( (uint32_t) buf[5] );
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", t ) );
#endif
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu",
( (uint32_t) buf[2] << 24 ) |
( (uint32_t) buf[3] << 16 ) |
( (uint32_t) buf[4] << 8 ) |
( (uint32_t) buf[5] ) ) );
memcpy( ssl->handshake->randbytes + 32, buf + 2, 32 );
@ -2258,7 +2266,7 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
int ret;
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
ssl->transform_negotiate->ciphersuite_info;
unsigned char *p, *end;
unsigned char *p = NULL, *end = NULL;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server key exchange" ) );

View File

@ -1694,11 +1694,8 @@ read_record_header:
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED)
case MBEDTLS_TLS_EXT_SIG_ALG:
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found signature_algorithms extension" ) );
#if defined(MBEDTLS_SSL_RENEGOTIATION)
if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS )
break;
#endif
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found signature_algorithms extension" ) );
ret = ssl_parse_signature_algorithms_ext( ssl, ext + 4, ext_size );
if( ret != 0 )
return( ret );

View File

@ -3493,8 +3493,15 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl )
ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
#if defined(MBEDTLS_SSL_PROTO_DTLS)
/* Silently ignore invalid DTLS records as recommended by RFC 6347
* Section 4.1.2.7 */
if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM )
#endif /* MBEDTLS_SSL_PROTO_DTLS */
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
}
@ -6159,7 +6166,7 @@ void mbedtls_ssl_conf_sig_hashes( mbedtls_ssl_config *conf,
{
conf->sig_hashes = hashes;
}
#endif
#endif /* MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */
#if defined(MBEDTLS_ECP_C)
/*
@ -6170,36 +6177,53 @@ void mbedtls_ssl_conf_curves( mbedtls_ssl_config *conf,
{
conf->curve_list = curve_list;
}
#endif
#endif /* MBEDTLS_ECP_C */
#if defined(MBEDTLS_X509_CRT_PARSE_C)
int mbedtls_ssl_set_hostname( mbedtls_ssl_context *ssl, const char *hostname )
{
size_t hostname_len;
/* Initialize to suppress unnecessary compiler warning */
size_t hostname_len = 0;
/* Check if new hostname is valid before
* making any change to current one */
if( hostname != NULL )
{
hostname_len = strlen( hostname );
if( hostname_len > MBEDTLS_SSL_MAX_HOST_NAME_LEN )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
}
/* Now it's clear that we will overwrite the old hostname,
* so we can free it safely */
if( ssl->hostname != NULL )
{
mbedtls_zeroize( ssl->hostname, strlen( ssl->hostname ) );
mbedtls_free( ssl->hostname );
}
/* Passing NULL as hostname shall clear the old one */
if( hostname == NULL )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
{
ssl->hostname = NULL;
}
else
{
ssl->hostname = mbedtls_calloc( 1, hostname_len + 1 );
if( ssl->hostname == NULL )
return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
hostname_len = strlen( hostname );
memcpy( ssl->hostname, hostname, hostname_len );
if( hostname_len + 1 == 0 )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
if( hostname_len > MBEDTLS_SSL_MAX_HOST_NAME_LEN )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
ssl->hostname = mbedtls_calloc( 1, hostname_len + 1 );
if( ssl->hostname == NULL )
return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
memcpy( ssl->hostname, hostname, hostname_len );
ssl->hostname[hostname_len] = '\0';
ssl->hostname[hostname_len] = '\0';
}
return( 0 );
}
#endif
#endif /* MBEDTLS_X509_CRT_PARSE_C */
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
void mbedtls_ssl_conf_sni( mbedtls_ssl_config *conf,
@ -6859,7 +6883,6 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
}
}
#if defined(MBEDTLS_SSL_RENEGOTIATION)
if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "received handshake message" ) );
@ -6901,12 +6924,35 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
}
#endif /* MBEDTLS_SSL_SRV_C */
#if defined(MBEDTLS_SSL_RENEGOTIATION)
/* Determine whether renegotiation attempt should be accepted */
if( ! ( ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED ||
( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
ssl->conf->allow_legacy_renegotiation ==
MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) ) )
{
/*
* Accept renegotiation request
*/
if( ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED ||
( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
ssl->conf->allow_legacy_renegotiation ==
MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) )
/* DTLS clients need to know renego is server-initiated */
#if defined(MBEDTLS_SSL_PROTO_DTLS)
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT )
{
ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING;
}
#endif
ret = ssl_start_renegotiation( ssl );
if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO &&
ret != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "ssl_start_renegotiation", ret );
return( ret );
}
}
else
#endif /* MBEDTLS_SSL_RENEGOTIATION */
{
/*
* Refuse renegotiation
@ -6944,31 +6990,10 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
}
else
{
/*
* Accept renegotiation request
*/
/* DTLS clients need to know renego is server-initiated */
#if defined(MBEDTLS_SSL_PROTO_DTLS)
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT )
{
ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING;
}
#endif
ret = ssl_start_renegotiation( ssl );
if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO &&
ret != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "ssl_start_renegotiation", ret );
return( ret );
}
}
return( MBEDTLS_ERR_SSL_WANT_READ );
}
#if defined(MBEDTLS_SSL_RENEGOTIATION)
else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING )
{
if( ssl->conf->renego_max_records >= 0 )
@ -7054,7 +7079,9 @@ static int ssl_write_real( mbedtls_ssl_context *ssl,
int ret;
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
size_t max_len = mbedtls_ssl_get_max_frag_len( ssl );
#else
size_t max_len = MBEDTLS_SSL_MAX_CONTENT_LEN;
#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
if( len > max_len )
{
#if defined(MBEDTLS_SSL_PROTO_DTLS)
@ -7069,7 +7096,6 @@ static int ssl_write_real( mbedtls_ssl_context *ssl,
#endif
len = max_len;
}
#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
if( ssl->out_left != 0 )
{
@ -7100,7 +7126,7 @@ static int ssl_write_real( mbedtls_ssl_context *ssl,
*
* With non-blocking I/O, ssl_write_real() may return WANT_WRITE,
* then the caller will call us again with the same arguments, so
* remember wether we already did the split or not.
* remember whether we already did the split or not.
*/
#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING)
static int ssl_write_split( mbedtls_ssl_context *ssl,

View File

@ -244,21 +244,23 @@ volatile int mbedtls_timing_alarmed = 0;
unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset )
{
unsigned long delta;
LARGE_INTEGER offset, hfreq;
struct _hr_time *t = (struct _hr_time *) val;
QueryPerformanceCounter( &offset );
QueryPerformanceFrequency( &hfreq );
delta = (unsigned long)( ( 1000 *
( offset.QuadPart - t->start.QuadPart ) ) /
hfreq.QuadPart );
if( reset )
{
QueryPerformanceCounter( &t->start );
return( delta );
return( 0 );
}
else
{
unsigned long delta;
LARGE_INTEGER now, hfreq;
QueryPerformanceCounter( &now );
QueryPerformanceFrequency( &hfreq );
delta = (unsigned long)( ( now.QuadPart - t->start.QuadPart ) * 1000ul
/ hfreq.QuadPart );
return( delta );
}
}
/* It's OK to use a global because alarm() is supposed to be global anyway */
@ -285,23 +287,22 @@ void mbedtls_set_alarm( int seconds )
unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset )
{
unsigned long delta;
struct timeval offset;
struct _hr_time *t = (struct _hr_time *) val;
gettimeofday( &offset, NULL );
if( reset )
{
t->start.tv_sec = offset.tv_sec;
t->start.tv_usec = offset.tv_usec;
gettimeofday( &t->start, NULL );
return( 0 );
}
delta = ( offset.tv_sec - t->start.tv_sec ) * 1000
+ ( offset.tv_usec - t->start.tv_usec ) / 1000;
return( delta );
else
{
unsigned long delta;
struct timeval now;
gettimeofday( &now, NULL );
delta = ( now.tv_sec - t->start.tv_sec ) * 1000ul
+ ( now.tv_usec - t->start.tv_usec ) / 1000;
return( delta );
}
}
static void sighandler( int signum )
@ -315,6 +316,12 @@ void mbedtls_set_alarm( int seconds )
mbedtls_timing_alarmed = 0;
signal( SIGALRM, sighandler );
alarm( seconds );
if( seconds == 0 )
{
/* alarm(0) cancelled any previous pending alarm, but the
handler won't fire, so raise the flag straight away. */
mbedtls_timing_alarmed = 1;
}
}
#endif /* _WIN32 && !EFIX64 && !EFI32 */
@ -378,13 +385,21 @@ static void busy_msleep( unsigned long msec )
(void) j;
}
#define FAIL do \
{ \
if( verbose != 0 ) \
mbedtls_printf( "failed\n" ); \
\
return( 1 ); \
} while( 0 )
#define FAIL do \
{ \
if( verbose != 0 ) \
{ \
mbedtls_printf( "failed at line %d\n", __LINE__ ); \
mbedtls_printf( " cycles=%lu ratio=%lu millisecs=%lu secs=%lu hardfail=%d a=%lu b=%lu\n", \
cycles, ratio, millisecs, secs, hardfail, \
(unsigned long) a, (unsigned long) b ); \
mbedtls_printf( " elapsed(hires)=%lu elapsed(ctx)=%lu status(ctx)=%d\n", \
mbedtls_timing_get_timer( &hires, 0 ), \
mbedtls_timing_get_timer( &ctx.timer, 0 ), \
mbedtls_timing_get_delay( &ctx ) ); \
} \
return( 1 ); \
} while( 0 )
/*
* Checkup routine
@ -394,22 +409,22 @@ static void busy_msleep( unsigned long msec )
*/
int mbedtls_timing_self_test( int verbose )
{
unsigned long cycles, ratio;
unsigned long millisecs, secs;
int hardfail;
unsigned long cycles = 0, ratio = 0;
unsigned long millisecs = 0, secs = 0;
int hardfail = 0;
struct mbedtls_timing_hr_time hires;
uint32_t a, b;
uint32_t a = 0, b = 0;
mbedtls_timing_delay_context ctx;
if( verbose != 0 )
mbedtls_printf( " TIMING tests note: will take some time!\n" );
if( verbose != 0 )
mbedtls_printf( " TIMING test #1 (set_alarm / get_timer): " );
for( secs = 1; secs <= 3; secs++ )
{
secs = 1;
(void) mbedtls_timing_get_timer( &hires, 1 );
mbedtls_set_alarm( (int) secs );
@ -421,12 +436,7 @@ int mbedtls_timing_self_test( int verbose )
/* For some reason on Windows it looks like alarm has an extra delay
* (maybe related to creating a new thread). Allow some room here. */
if( millisecs < 800 * secs || millisecs > 1200 * secs + 300 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
return( 1 );
}
FAIL;
}
if( verbose != 0 )
@ -435,28 +445,22 @@ int mbedtls_timing_self_test( int verbose )
if( verbose != 0 )
mbedtls_printf( " TIMING test #2 (set/get_delay ): " );
for( a = 200; a <= 400; a += 200 )
{
for( b = 200; b <= 400; b += 200 )
{
mbedtls_timing_set_delay( &ctx, a, a + b );
a = 800;
b = 400;
mbedtls_timing_set_delay( &ctx, a, a + b ); /* T = 0 */
busy_msleep( a - a / 8 );
if( mbedtls_timing_get_delay( &ctx ) != 0 )
FAIL;
busy_msleep( a - a / 4 ); /* T = a - a/4 */
if( mbedtls_timing_get_delay( &ctx ) != 0 )
FAIL;
busy_msleep( a / 4 );
if( mbedtls_timing_get_delay( &ctx ) != 1 )
FAIL;
busy_msleep( a / 4 + b / 4 ); /* T = a + b/4 */
if( mbedtls_timing_get_delay( &ctx ) != 1 )
FAIL;
busy_msleep( b - a / 8 - b / 8 );
if( mbedtls_timing_get_delay( &ctx ) != 1 )
FAIL;
busy_msleep( b / 4 );
if( mbedtls_timing_get_delay( &ctx ) != 2 )
FAIL;
}
busy_msleep( b ); /* T = a + b + b/4 */
if( mbedtls_timing_get_delay( &ctx ) != 2 )
FAIL;
}
mbedtls_timing_set_delay( &ctx, 0, 0 );
@ -475,7 +479,6 @@ int mbedtls_timing_self_test( int verbose )
* On a 4Ghz 32-bit machine the cycle counter wraps about once per second;
* since the whole test is about 10ms, it shouldn't happen twice in a row.
*/
hardfail = 0;
hard_test:
if( hardfail > 1 )

View File

@ -96,12 +96,18 @@ static const char *features[] = {
#if defined(MBEDTLS_CAMELLIA_ALT)
"MBEDTLS_CAMELLIA_ALT",
#endif /* MBEDTLS_CAMELLIA_ALT */
#if defined(MBEDTLS_CCM_ALT)
"MBEDTLS_CCM_ALT",
#endif /* MBEDTLS_CCM_ALT */
#if defined(MBEDTLS_CMAC_ALT)
"MBEDTLS_CMAC_ALT",
#endif /* MBEDTLS_CMAC_ALT */
#if defined(MBEDTLS_DES_ALT)
"MBEDTLS_DES_ALT",
#endif /* MBEDTLS_DES_ALT */
#if defined(MBEDTLS_XTEA_ALT)
"MBEDTLS_XTEA_ALT",
#endif /* MBEDTLS_XTEA_ALT */
#if defined(MBEDTLS_GCM_ALT)
"MBEDTLS_GCM_ALT",
#endif /* MBEDTLS_GCM_ALT */
#if defined(MBEDTLS_MD2_ALT)
"MBEDTLS_MD2_ALT",
#endif /* MBEDTLS_MD2_ALT */
@ -114,6 +120,9 @@ static const char *features[] = {
#if defined(MBEDTLS_RIPEMD160_ALT)
"MBEDTLS_RIPEMD160_ALT",
#endif /* MBEDTLS_RIPEMD160_ALT */
#if defined(MBEDTLS_RSA_ALT)
"MBEDTLS_RSA_ALT",
#endif /* MBEDTLS_RSA_ALT */
#if defined(MBEDTLS_SHA1_ALT)
"MBEDTLS_SHA1_ALT",
#endif /* MBEDTLS_SHA1_ALT */
@ -123,6 +132,9 @@ static const char *features[] = {
#if defined(MBEDTLS_SHA512_ALT)
"MBEDTLS_SHA512_ALT",
#endif /* MBEDTLS_SHA512_ALT */
#if defined(MBEDTLS_XTEA_ALT)
"MBEDTLS_XTEA_ALT",
#endif /* MBEDTLS_XTEA_ALT */
#if defined(MBEDTLS_ECP_ALT)
"MBEDTLS_ECP_ALT",
#endif /* MBEDTLS_ECP_ALT */
@ -168,6 +180,21 @@ static const char *features[] = {
#if defined(MBEDTLS_AES_DECRYPT_ALT)
"MBEDTLS_AES_DECRYPT_ALT",
#endif /* MBEDTLS_AES_DECRYPT_ALT */
#if defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT)
"MBEDTLS_ECDH_GEN_PUBLIC_ALT",
#endif /* MBEDTLS_ECDH_GEN_PUBLIC_ALT */
#if defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT)
"MBEDTLS_ECDH_COMPUTE_SHARED_ALT",
#endif /* MBEDTLS_ECDH_COMPUTE_SHARED_ALT */
#if defined(MBEDTLS_ECDSA_VERIFY_ALT)
"MBEDTLS_ECDSA_VERIFY_ALT",
#endif /* MBEDTLS_ECDSA_VERIFY_ALT */
#if defined(MBEDTLS_ECDSA_SIGN_ALT)
"MBEDTLS_ECDSA_SIGN_ALT",
#endif /* MBEDTLS_ECDSA_SIGN_ALT */
#if defined(MBEDTLS_ECDSA_GENKEY_ALT)
"MBEDTLS_ECDSA_GENKEY_ALT",
#endif /* MBEDTLS_ECDSA_GENKEY_ALT */
#if defined(MBEDTLS_ECP_INTERNAL_ALT)
"MBEDTLS_ECP_INTERNAL_ALT",
#endif /* MBEDTLS_ECP_INTERNAL_ALT */

View File

@ -496,9 +496,10 @@ static int x509_parse_int( unsigned char **p, size_t n, int *res )
return( 0 );
}
static int x509_date_is_valid(const mbedtls_x509_time *t)
static int x509_date_is_valid(const mbedtls_x509_time *t )
{
int ret = MBEDTLS_ERR_X509_INVALID_DATE;
int month_len;
CHECK_RANGE( 0, 9999, t->year );
CHECK_RANGE( 0, 23, t->hour );
@ -508,17 +509,22 @@ static int x509_date_is_valid(const mbedtls_x509_time *t)
switch( t->mon )
{
case 1: case 3: case 5: case 7: case 8: case 10: case 12:
CHECK_RANGE( 1, 31, t->day );
month_len = 31;
break;
case 4: case 6: case 9: case 11:
CHECK_RANGE( 1, 30, t->day );
month_len = 30;
break;
case 2:
CHECK_RANGE( 1, 28 + (t->year % 4 == 0), t->day );
if( ( !( t->year % 4 ) && t->year % 100 ) ||
!( t->year % 400 ) )
month_len = 29;
else
month_len = 28;
break;
default:
return( ret );
}
CHECK_RANGE( 1, month_len, t->day );
return( 0 );
}

View File

@ -51,7 +51,7 @@ static void mbedtls_zeroize( void *v, size_t n ) {
void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx )
{
memset( ctx, 0, sizeof(mbedtls_x509write_cert) );
memset( ctx, 0, sizeof( mbedtls_x509write_cert ) );
mbedtls_mpi_init( &ctx->serial );
ctx->version = MBEDTLS_X509_CRT_VERSION_3;
@ -65,7 +65,7 @@ void mbedtls_x509write_crt_free( mbedtls_x509write_cert *ctx )
mbedtls_asn1_free_named_data_list( &ctx->issuer );
mbedtls_asn1_free_named_data_list( &ctx->extensions );
mbedtls_zeroize( ctx, sizeof(mbedtls_x509write_cert) );
mbedtls_zeroize( ctx, sizeof( mbedtls_x509write_cert ) );
}
void mbedtls_x509write_crt_set_version( mbedtls_x509write_cert *ctx, int version )
@ -193,14 +193,14 @@ int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *
{
int ret;
unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
unsigned char *c = buf + sizeof(buf);
unsigned char *c = buf + sizeof( buf );
size_t len = 0;
memset( buf, 0, sizeof(buf) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, ctx->issuer_key ) );
mbedtls_sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 );
c = buf + sizeof(buf) - 20;
mbedtls_sha1( buf + sizeof( buf ) - len, len, buf + sizeof( buf ) - 20 );
c = buf + sizeof( buf ) - 20;
len = 20;
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
@ -212,7 +212,7 @@ int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *
return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER,
MBEDTLS_OID_SIZE( MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER ),
0, buf + sizeof(buf) - len, len );
0, buf + sizeof( buf ) - len, len );
}
#endif /* MBEDTLS_SHA1_C */
@ -313,12 +313,18 @@ int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf,
c = tmp_buf + sizeof( tmp_buf );
/* Signature algorithm needed in TBS, and later for actual signature */
pk_alg = mbedtls_pk_get_type( ctx->issuer_key );
if( pk_alg == MBEDTLS_PK_ECKEY )
/* There's no direct way of extracting a signature algorithm
* (represented as an element of mbedtls_pk_type_t) from a PK instance. */
if( mbedtls_pk_can_do( ctx->issuer_key, MBEDTLS_PK_RSA ) )
pk_alg = MBEDTLS_PK_RSA;
else if( mbedtls_pk_can_do( ctx->issuer_key, MBEDTLS_PK_ECDSA ) )
pk_alg = MBEDTLS_PK_ECDSA;
else
return( MBEDTLS_ERR_X509_INVALID_ALG );
if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg,
&sig_oid, &sig_oid_len ) ) != 0 )
&sig_oid, &sig_oid_len ) ) != 0 )
{
return( ret );
}
@ -326,13 +332,18 @@ int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf,
/*
* Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
*/
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |
MBEDTLS_ASN1_SEQUENCE ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC |
MBEDTLS_ASN1_CONSTRUCTED | 3 ) );
/* Only for v3 */
if( ctx->version == MBEDTLS_X509_CRT_VERSION_3 )
{
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |
MBEDTLS_ASN1_SEQUENCE ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC |
MBEDTLS_ASN1_CONSTRUCTED | 3 ) );
}
/*
* SubjectPublicKeyInfo
@ -384,16 +395,21 @@ int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf,
/*
* Version ::= INTEGER { v1(0), v2(1), v3(2) }
*/
sub_len = 0;
MBEDTLS_ASN1_CHK_ADD( sub_len, mbedtls_asn1_write_int( &c, tmp_buf, ctx->version ) );
len += sub_len;
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, sub_len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC |
MBEDTLS_ASN1_CONSTRUCTED | 0 ) );
/* Can be omitted for v1 */
if( ctx->version != MBEDTLS_X509_CRT_VERSION_1 )
{
sub_len = 0;
MBEDTLS_ASN1_CHK_ADD( sub_len, mbedtls_asn1_write_int( &c, tmp_buf, ctx->version ) );
len += sub_len;
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, sub_len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC |
MBEDTLS_ASN1_CONSTRUCTED | 0 ) );
}
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |
MBEDTLS_ASN1_SEQUENCE ) );
MBEDTLS_ASN1_SEQUENCE ) );
/*
* Make signature

View File

@ -50,7 +50,7 @@ static void mbedtls_zeroize( void *v, size_t n ) {
void mbedtls_x509write_csr_init( mbedtls_x509write_csr *ctx )
{
memset( ctx, 0, sizeof(mbedtls_x509write_csr) );
memset( ctx, 0, sizeof( mbedtls_x509write_csr ) );
}
void mbedtls_x509write_csr_free( mbedtls_x509write_csr *ctx )
@ -58,7 +58,7 @@ void mbedtls_x509write_csr_free( mbedtls_x509write_csr *ctx )
mbedtls_asn1_free_named_data_list( &ctx->subject );
mbedtls_asn1_free_named_data_list( &ctx->extensions );
mbedtls_zeroize( ctx, sizeof(mbedtls_x509write_csr) );
mbedtls_zeroize( ctx, sizeof( mbedtls_x509write_csr ) );
}
void mbedtls_x509write_csr_set_md_alg( mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg )
@ -194,14 +194,21 @@ int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, s
*/
mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash );
pk_alg = mbedtls_pk_get_type( ctx->key );
if( pk_alg == MBEDTLS_PK_ECKEY )
pk_alg = MBEDTLS_PK_ECDSA;
if( ( ret = mbedtls_pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len,
f_rng, p_rng ) ) != 0 ||
( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg,
&sig_oid, &sig_oid_len ) ) != 0 )
f_rng, p_rng ) ) != 0 )
{
return( ret );
}
if( mbedtls_pk_can_do( ctx->key, MBEDTLS_PK_RSA ) )
pk_alg = MBEDTLS_PK_RSA;
else if( mbedtls_pk_can_do( ctx->key, MBEDTLS_PK_ECDSA ) )
pk_alg = MBEDTLS_PK_ECDSA;
else
return( MBEDTLS_ERR_X509_INVALID_ALG );
if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg,
&sig_oid, &sig_oid_len ) ) != 0 )
{
return( ret );
}