From 12313cd84c57be7ad3d150706171adadc529a3ff Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 20 Jun 2018 00:20:32 +0200 Subject: [PATCH] Implement psa_generate_key: AES, DES, RSA, ECP In the test cases, try exporting the generated key and perform sanity checks on it. --- library/psa_crypto.c | 144 +++++++++++++++++++- tests/suites/test_suite_psa_crypto.data | 51 +++++++ tests/suites/test_suite_psa_crypto.function | 130 ++++++++++++++++++ 3 files changed, 324 insertions(+), 1 deletion(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 8e7aeefa2..d75226cc6 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -346,6 +346,41 @@ static psa_ecc_curve_t mbedtls_ecc_group_to_psa( mbedtls_ecp_group_id grpid ) } } +static mbedtls_ecp_group_id mbedtls_ecc_group_of_psa( psa_ecc_curve_t curve ) +{ + switch( curve ) + { + case PSA_ECC_CURVE_SECP192R1: + return( MBEDTLS_ECP_DP_SECP192R1 ); + case PSA_ECC_CURVE_SECP224R1: + return( MBEDTLS_ECP_DP_SECP224R1 ); + case PSA_ECC_CURVE_SECP256R1: + return( MBEDTLS_ECP_DP_SECP256R1 ); + case PSA_ECC_CURVE_SECP384R1: + return( MBEDTLS_ECP_DP_SECP384R1 ); + case PSA_ECC_CURVE_SECP521R1: + return( MBEDTLS_ECP_DP_SECP521R1 ); + case PSA_ECC_CURVE_BRAINPOOL_P256R1: + return( MBEDTLS_ECP_DP_BP256R1 ); + case PSA_ECC_CURVE_BRAINPOOL_P384R1: + return( MBEDTLS_ECP_DP_BP384R1 ); + case PSA_ECC_CURVE_BRAINPOOL_P512R1: + return( MBEDTLS_ECP_DP_BP512R1 ); + case PSA_ECC_CURVE_CURVE25519: + return( MBEDTLS_ECP_DP_CURVE25519 ); + case PSA_ECC_CURVE_SECP192K1: + return( MBEDTLS_ECP_DP_SECP192K1 ); + case PSA_ECC_CURVE_SECP224K1: + return( MBEDTLS_ECP_DP_SECP224K1 ); + case PSA_ECC_CURVE_SECP256K1: + return( MBEDTLS_ECP_DP_SECP256K1 ); + case PSA_ECC_CURVE_CURVE448: + return( MBEDTLS_ECP_DP_CURVE448 ); + default: + return( MBEDTLS_ECP_DP_NONE ); + } +} + static psa_status_t prepare_raw_data_slot( psa_key_type_t type, size_t bits, struct raw_data *raw ) @@ -2495,7 +2530,114 @@ psa_status_t psa_generate_key( psa_key_slot_t key, const void *parameters, size_t parameters_size ) { - return( PSA_ERROR_NOT_SUPPORTED ); + key_slot_t *slot; + + if( key == 0 || key > PSA_KEY_SLOT_COUNT ) + return( PSA_ERROR_INVALID_ARGUMENT ); + slot = &global_data.key_slots[key]; + if( slot->type != PSA_KEY_TYPE_NONE ) + return( PSA_ERROR_OCCUPIED_SLOT ); + if( parameters == NULL && parameters_size != 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + if( PSA_KEY_TYPE_IS_RAW_BYTES( type ) ) + { + psa_status_t status = prepare_raw_data_slot( type, bits, + &slot->data.raw ); + if( status != PSA_SUCCESS ) + return( status ); + status = psa_generate_random( slot->data.raw.data, + slot->data.raw.bytes ); + if( status != PSA_SUCCESS ) + { + mbedtls_free( slot->data.raw.data ); + return( status ); + } +#if defined(MBEDTLS_DES_C) + if( type == PSA_KEY_TYPE_DES ) + { + mbedtls_des_key_set_parity( slot->data.raw.data ); + if( slot->data.raw.bytes >= 16 ) + mbedtls_des_key_set_parity( slot->data.raw.data + 8 ); + if( slot->data.raw.bytes == 24 ) + mbedtls_des_key_set_parity( slot->data.raw.data + 16 ); + } +#endif /* MBEDTLS_DES_C */ + } + else + +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_GENPRIME) + if ( type == PSA_KEY_TYPE_RSA_KEYPAIR ) + { + mbedtls_rsa_context *rsa; + int ret; + int exponent = 65537; + if( parameters != NULL ) + { + const unsigned *p = parameters; + if( parameters_size != sizeof( *p ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + if( *p > INT_MAX ) + return( PSA_ERROR_INVALID_ARGUMENT ); + exponent = *p; + } + rsa = mbedtls_calloc( 1, sizeof( *rsa ) ); + if( rsa == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + mbedtls_rsa_init( rsa, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_NONE ); + ret = mbedtls_rsa_gen_key( rsa, + mbedtls_ctr_drbg_random, + &global_data.ctr_drbg, + bits, + exponent ); + if( ret != 0 ) + { + mbedtls_rsa_free( rsa ); + mbedtls_free( rsa ); + return( mbedtls_to_psa_error( ret ) ); + } + slot->data.rsa = rsa; + } + else +#endif /* MBEDTLS_RSA_C && MBEDTLS_GENPRIME */ + +#if defined(MBEDTLS_ECP_C) + if ( PSA_KEY_TYPE_IS_ECC( type ) && PSA_KEY_TYPE_IS_KEYPAIR( type ) ) + { + psa_ecc_curve_t curve = PSA_KEY_TYPE_GET_CURVE( type ); + mbedtls_ecp_group_id grp_id = mbedtls_ecc_group_of_psa( curve ); + const mbedtls_ecp_curve_info *curve_info = + mbedtls_ecp_curve_info_from_grp_id( grp_id ); + mbedtls_ecp_keypair *ecp; + int ret; + if( parameters != NULL ) + return( PSA_ERROR_NOT_SUPPORTED ); + if( grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL ) + return( PSA_ERROR_NOT_SUPPORTED ); + if( curve_info->bit_size != bits ) + return( PSA_ERROR_INVALID_ARGUMENT ); + ecp = mbedtls_calloc( 1, sizeof( *ecp ) ); + if( ecp == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + mbedtls_ecp_keypair_init( ecp ); + ret = mbedtls_ecp_gen_key( grp_id, ecp, + mbedtls_ctr_drbg_random, + &global_data.ctr_drbg ); + if( ret != 0 ) + { + mbedtls_ecp_keypair_free( ecp ); + mbedtls_free( ecp ); + return( mbedtls_to_psa_error( ret ) ); + } + slot->data.ecp = ecp; + } + else +#endif /* MBEDTLS_ECP_C */ + + return( PSA_ERROR_NOT_SUPPORTED ); + + slot->type = type; + return( PSA_SUCCESS ); } diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index b4c0fa97a..9902a0ecb 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -479,3 +479,54 @@ generate_random:16:0 PSA generate random: 19 bytes generate_random:19:0 + +PSA generate key: bad type (0xffffffff) +generate_key:0xffffffff:128:PSA_KEY_USAGE_EXPORT:0:PSA_ERROR_NOT_SUPPORTED + +PSA generate key: bad type (RSA public key) +generate_key:PSA_KEY_TYPE_RSA_PUBLIC_KEY:512:PSA_KEY_USAGE_EXPORT:0:PSA_ERROR_NOT_SUPPORTED + +PSA generate key: raw data, 0 bits +generate_key:PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_EXPORT:0:PSA_SUCCESS + +PSA generate key: raw data, 8 bits +generate_key:PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_EXPORT:0:PSA_SUCCESS + +PSA generate key: raw data, 7 bits +generate_key:PSA_KEY_TYPE_AES:7:PSA_KEY_USAGE_EXPORT:0:PSA_ERROR_INVALID_ARGUMENT + +PSA generate key: AES, 128 bits, CTR +depends_on:MBEDTLS_AES_C +generate_key:PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_EXPORT|PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR:PSA_SUCCESS + +PSA generate key: DES, 64 bits, CTR +depends_on:MBEDTLS_DES_C +generate_key:PSA_KEY_TYPE_DES:64:PSA_KEY_USAGE_EXPORT|PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR:PSA_SUCCESS + +PSA generate key: DES, 128 bits, CTR +depends_on:MBEDTLS_DES_C +generate_key:PSA_KEY_TYPE_DES:64:PSA_KEY_USAGE_EXPORT|PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR:PSA_SUCCESS + +PSA generate key: DES, 192 bits, CTR +depends_on:MBEDTLS_DES_C +generate_key:PSA_KEY_TYPE_DES:64:PSA_KEY_USAGE_EXPORT|PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR:PSA_SUCCESS + +PSA generate key: invalid key size: AES, 64 bits +depends_on:MBEDTLS_AES_C +generate_key:PSA_KEY_TYPE_AES:64:PSA_KEY_USAGE_EXPORT|PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR:PSA_ERROR_INVALID_ARGUMENT + +PSA generate key: RSA, 512 bits, good +depends_on:MBEDTLS_RSA_C +generate_key:PSA_KEY_TYPE_RSA_KEYPAIR:512:PSA_KEY_USAGE_EXPORT|PSA_KEY_USAGE_SIGN|PSA_KEY_USAGE_VERIFY:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_SUCCESS + +PSA generate key: RSA, 1024 bits, good +depends_on:MBEDTLS_RSA_C +generate_key:PSA_KEY_TYPE_RSA_KEYPAIR:1024:PSA_KEY_USAGE_EXPORT|PSA_KEY_USAGE_SIGN|PSA_KEY_USAGE_VERIFY:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_SUCCESS + +PSA generate key: ECC, SECP256R1, good +depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED +generate_key:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):256:PSA_KEY_USAGE_EXPORT|PSA_KEY_USAGE_SIGN|PSA_KEY_USAGE_VERIFY:PSA_ALG_ECDSA_RAW:PSA_SUCCESS + +PSA generate key: ECC, SECP256R1, incorrect bit size +depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED +generate_key:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):128:PSA_KEY_USAGE_EXPORT|PSA_KEY_USAGE_SIGN|PSA_KEY_USAGE_VERIFY:PSA_ALG_ECDSA_RAW:PSA_ERROR_INVALID_ARGUMENT diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index 958637560..1cd9c22a0 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -1585,3 +1585,133 @@ exit: mbedtls_free( buffer2 ); } /* END_CASE */ + +/* BEGIN_CASE */ +void generate_key( int type_arg, + int bits_arg, + int usage_arg, + int alg_arg, + int expected_status_arg ) +{ + int slot = 1; + psa_key_type_t type = type_arg; + psa_key_usage_t usage = usage_arg; + size_t bits = bits_arg; + psa_algorithm_t alg = alg_arg; + psa_status_t expected_status = expected_status_arg; + psa_key_type_t got_type; + size_t got_bits; + unsigned char exported[616] = {0}; /* enough for a 1024-bit RSA key */ + size_t exported_length; + psa_status_t expected_export_status = + usage & PSA_KEY_USAGE_EXPORT ? PSA_SUCCESS : PSA_ERROR_NOT_PERMITTED; + psa_status_t expected_info_status = + expected_status == PSA_SUCCESS ? PSA_SUCCESS : PSA_ERROR_EMPTY_SLOT; + psa_key_policy_t policy; + + TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + + psa_key_policy_init( &policy ); + psa_key_policy_set_usage( &policy, usage, alg ); + TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS ); + + /* Generate a key */ + TEST_ASSERT( psa_generate_key( slot, type, bits, + NULL, 0 ) == expected_status ); + + /* Test the key information */ + TEST_ASSERT( psa_get_key_information( slot, + &got_type, + &got_bits ) == expected_info_status ); + if( expected_info_status != PSA_SUCCESS ) + goto exit; + TEST_ASSERT( got_type == type ); + TEST_ASSERT( got_bits == bits ); + + /* Export the key */ + TEST_ASSERT( psa_export_key( slot, + exported, sizeof( exported ), + &exported_length ) == expected_export_status ); + if( expected_export_status == PSA_SUCCESS ) + { + if( PSA_KEY_TYPE_IS_RAW_BYTES( type ) ) + TEST_ASSERT( exported_length == ( bits + 7 ) / 8 ); +#if defined(MBEDTLS_DES_C) + if( type == PSA_KEY_TYPE_DES ) + { + /* Check the parity bits. */ + unsigned i; + for( i = 0; i < bits / 8; i++ ) + { + unsigned bit_count = 0; + unsigned m; + for( m = 1; m <= 0x100; m <<= 1 ) + { + if( exported[i] & m ) + ++bit_count; + } + TEST_ASSERT( bit_count % 2 != 0 ); + } + } +#endif +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PK_PARSE_C) + if( type == PSA_KEY_TYPE_RSA_KEYPAIR ) + { + /* Sanity check: does this look like the beginning of a PKCS#8 + * RSA key pair? Assumes bits is a multiple of 8. */ + size_t n_bytes = bits / 8 + 1; + size_t n_encoded_bytes; + unsigned char *n_end; + TEST_ASSERT( exported_length >= 7 + ( n_bytes + 3 ) * 9 / 2 ); + TEST_ASSERT( exported[0] == 0x30 ); + TEST_ASSERT( exported[1] == 0x82 ); // assumes >=416-bit key + TEST_ASSERT( exported[4] == 0x02 ); + TEST_ASSERT( exported[5] == 0x01 ); + TEST_ASSERT( exported[6] == 0x00 ); + TEST_ASSERT( exported[7] == 0x02 ); + n_encoded_bytes = exported[8]; + n_end = exported + 9 + n_encoded_bytes; + if( n_encoded_bytes & 0x80 ) + { + n_encoded_bytes = ( n_encoded_bytes & 0x7f ) << 7; + n_encoded_bytes |= exported[9] & 0x7f; + n_end += 1; + } + /* The encoding of n should start with a 0 byte since it should + * have its high bit set. However Mbed TLS is not compliant and + * generates an invalid, but widely tolerated, encoding of + * positive INTEGERs with a bit size that is a multiple of 8 + * with no leading 0 byte. Accept this here. */ + TEST_ASSERT( n_bytes == n_encoded_bytes || + n_bytes == n_encoded_bytes + 1 ); + if( n_bytes == n_encoded_bytes ) + TEST_ASSERT( exported[n_encoded_bytes <= 127 ? 9 : 10] == 0x00 ); + /* Sanity check: e must be 3 */ + TEST_ASSERT( n_end[0] == 0x02 ); + TEST_ASSERT( n_end[1] == 0x03 ); + TEST_ASSERT( n_end[2] == 0x01 ); + TEST_ASSERT( n_end[3] == 0x00 ); + TEST_ASSERT( n_end[4] == 0x01 ); + TEST_ASSERT( n_end[5] == 0x02 ); + } +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECP_C) + if( PSA_KEY_TYPE_IS_ECC( type ) ) + { + /* Sanity check: does this look like the beginning of a PKCS#8 + * elliptic curve key pair? */ + TEST_ASSERT( exported_length >= bits * 3 / 8 + 10 ); + TEST_ASSERT( exported[0] == 0x30 ); + } +#endif /* MBEDTLS_ECP_C */ + } + + /* We should do something with the key according to its permitted usage. + * This would require figuring out what the key type allows or + * specifying it somehow in the test data. */ + +exit: + psa_destroy_key( slot ); + mbedtls_psa_crypto_free( ); +} +/* END_CASE */