mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2025-07-30 22:43:08 +03:00
Merge branch 'development' into development-restricted
This commit is contained in:
@ -48,6 +48,7 @@ set(src_crypto
|
||||
platform.c
|
||||
ripemd160.c
|
||||
rsa.c
|
||||
rsa_internal.c
|
||||
sha1.c
|
||||
sha256.c
|
||||
sha512.c
|
||||
|
@ -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 \
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
@ -157,6 +158,7 @@ cleanup:
|
||||
|
||||
return( ret );
|
||||
}
|
||||
#endif /* MBEDTLS_ECDSA_SIGN_ALT */
|
||||
|
||||
#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
|
||||
/*
|
||||
@ -196,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)
|
||||
@ -281,6 +284,7 @@ cleanup:
|
||||
|
||||
return( ret );
|
||||
}
|
||||
#endif /* MBEDTLS_ECDSA_VERIFY_ALT */
|
||||
|
||||
/*
|
||||
* Convert a signature (given by context) to ASN.1
|
||||
@ -406,6 +410,7 @@ cleanup:
|
||||
return( ret );
|
||||
}
|
||||
|
||||
#if !defined(MBEDTLS_ECDSA_GENKEY_ALT)
|
||||
/*
|
||||
* Generate key pair
|
||||
*/
|
||||
@ -415,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
|
||||
|
@ -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 SIZE_MAX > UINT_MAX
|
||||
if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len )
|
||||
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
|
||||
#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 )
|
||||
{
|
||||
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 /* 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 )
|
||||
|
@ -526,19 +526,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 */
|
||||
@ -649,10 +666,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;
|
||||
|
||||
@ -680,45 +700,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 */
|
||||
|
||||
|
@ -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 */
|
||||
|
599
library/rsa.c
599
library/rsa.c
@ -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,11 +68,378 @@
|
||||
#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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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
|
||||
*/
|
||||
@ -96,6 +465,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)
|
||||
|
||||
/*
|
||||
@ -107,7 +486,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 );
|
||||
@ -115,8 +494,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:
|
||||
@ -127,10 +506,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;
|
||||
@ -140,31 +519,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 )
|
||||
{
|
||||
@ -182,82 +573,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 );
|
||||
}
|
||||
@ -265,9 +622,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 );
|
||||
@ -293,6 +651,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)
|
||||
@ -409,14 +770,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)
|
||||
@ -1633,13 +1995,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 ) );
|
||||
@ -1660,16 +2025,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"
|
||||
@ -1709,21 +2081,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"
|
||||
@ -1766,17 +2123,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: " );
|
||||
@ -1795,8 +2158,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" );
|
||||
@ -1807,9 +2171,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" );
|
||||
@ -1834,8 +2198,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" );
|
||||
@ -1846,8 +2211,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" );
|
||||
@ -1863,6 +2229,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
487
library/rsa_internal.c
Normal 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 */
|
@ -108,9 +108,6 @@ static const char *features[] = {
|
||||
#if defined(MBEDTLS_GCM_ALT)
|
||||
"MBEDTLS_GCM_ALT",
|
||||
#endif /* MBEDTLS_GCM_ALT */
|
||||
#if defined(MBEDTLS_XTEA_ALT)
|
||||
"MBEDTLS_XTEA_ALT",
|
||||
#endif /* MBEDTLS_XTEA_ALT */
|
||||
#if defined(MBEDTLS_MD2_ALT)
|
||||
"MBEDTLS_MD2_ALT",
|
||||
#endif /* MBEDTLS_MD2_ALT */
|
||||
@ -123,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 */
|
||||
@ -132,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 */
|
||||
@ -177,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 */
|
||||
|
Reference in New Issue
Block a user