diff --git a/docs/getting_started.md b/docs/getting_started.md index 3008a19ce..84ed891ac 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -510,7 +510,7 @@ Generate a piece of random 128-bit AES data: psa_set_key_policy(slot, &policy); /* Generate a key */ - psa_generate_key(slot, PSA_KEY_TYPE_AES, bits, NULL, 0); + psa_generate_key(slot, PSA_KEY_TYPE_AES, bits); psa_export_key(slot, exported, exported_size, &exported_length) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 1045cd4c7..9ec3b9074 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -339,12 +339,15 @@ static size_t psa_get_key_bits(const psa_key_attributes_t *attributes); * the key type identifier and the key size. * The format for the required domain parameters varies by the key type. * - * - For RSA keys, you can use this function to choose a non-default - * public exponent when generating a key. The public exponent is + * - For RSA keys (#PSA_KEY_TYPE_RSA_PUBLIC_KEY or #PSA_KEY_TYPE_RSA_KEYPAIR), + * the domain parameter data consists of the public exponent, * represented as a big-endian integer with no leading zeros. + * This information is used when generating an RSA key pair. * When importing a key, the public exponent is read from the imported * key data and the exponent recorded in the attribute structure is ignored. - * - For DSA public keys (#PSA_KEY_TYPE_DSA_PUBLIC_KEY), + * As an exception, the public exponent 65537 is represented by an empty + * byte string. + * - For DSA keys (#PSA_KEY_TYPE_DSA_PUBLIC_KEY or #PSA_KEY_TYPE_DSA_KEYPAIR), * the `Dss-Parms` format as defined by RFC 3279 §2.3.2. * ``` * Dss-Parms ::= SEQUENCE { @@ -353,7 +356,8 @@ static size_t psa_get_key_bits(const psa_key_attributes_t *attributes); * g INTEGER * } * ``` - * - For Diffie-Hellman key exchange keys (#PSA_KEY_TYPE_DH_PUBLIC_KEY), the + * - For Diffie-Hellman key exchange keys (#PSA_KEY_TYPE_DH_PUBLIC_KEY or + * #PSA_KEY_TYPE_DH_KEYPAIR), the * `DomainParameters` format as defined by RFC 3279 §2.3.3. * ``` * DomainParameters ::= SEQUENCE { @@ -3354,57 +3358,29 @@ psa_status_t psa_key_agreement_raw_shared_secret(psa_algorithm_t alg, psa_status_t psa_generate_random(uint8_t *output, size_t output_size); -/** Extra parameters for RSA key generation. - * - * You may pass a pointer to a structure of this type as the \c extra - * parameter to psa_generate_key(). - */ -typedef struct { - uint32_t e; /**< Public exponent value. Default: 65537. */ -} psa_generate_key_extra_rsa; - /** * \brief Generate a key or key pair. * + * The key is generated randomly. + * Its location, policy, type and size are taken from \p attributes. + * + * If the type requires additional domain parameters, these are taken + * from \p attributes as well. The following types use domain parameters: + * - When generating an RSA key (#PSA_KEY_TYPE_RSA_KEYPAIR), + * the default public exponent is 65537. This value is used if + * \p attributes was set with psa_set_key_type() or by passing an empty + * byte string as domain parameters to psa_set_key_domain_parameters(). + * If psa_set_key_domain_parameters() was used to set a non-empty + * domain parameter string in \p attributes, this string is read as + * a big-endian integer which is used as the public exponent. + * - When generating a DSA key (#PSA_KEY_TYPE_DSA_KEYPAIR) or a + * Diffie-Hellman key (#PSA_KEY_TYPE_DH_KEYPAIR), the domain parameters + * from \p attributes are interpreted as described for + * psa_set_key_domain_parameters(). + * * \param[in] attributes The attributes for the new key. * \param[out] handle On success, a handle to the newly created key. * \c 0 on failure. - * \param[in] extra Extra parameters for key generation. The - * interpretation of this parameter depends on - * the key type \c type. All types support \c NULL to - * use default parameters. Implementation that support - * the generation of vendor-specific key types - * that allow extra parameters shall document - * the format of these extra parameters and - * the default values. For standard parameters, - * the meaning of \p extra is as follows: - * - For a symmetric key type (a type such - * that #PSA_KEY_TYPE_IS_ASYMMETRIC(\c type) is - * false), \p extra must be \c NULL. - * - For an elliptic curve key type (a type - * such that #PSA_KEY_TYPE_IS_ECC(\c type) is - * false), \p extra must be \c NULL. - * - For an RSA key (\c type is - * #PSA_KEY_TYPE_RSA_KEYPAIR), \p extra is an - * optional #psa_generate_key_extra_rsa structure - * specifying the public exponent. The - * default public exponent used when \p extra - * is \c NULL is 65537. - * - For an DSA key (\c type is - * #PSA_KEY_TYPE_DSA_KEYPAIR), \p extra is an - * optional structure specifying the key domain - * parameters. The key domain parameters can also be - * provided by psa_set_key_domain_parameters(), - * which documents the format of the structure. - * - For a DH key (\c type is - * #PSA_KEY_TYPE_DH_KEYPAIR), the \p extra is an - * optional structure specifying the key domain - * parameters. The key domain parameters can also be - * provided by psa_set_key_domain_parameters(), - * which documents the format of the structure. - * \param extra_size Size of the buffer that \p extra - * points to, in bytes. Note that if \p extra is - * \c NULL then \p extra_size must be zero. * * \retval #PSA_SUCCESS * Success. @@ -3426,9 +3402,7 @@ typedef struct { * results in this error code. */ psa_status_t psa_generate_key(const psa_key_attributes_t *attributes, - psa_key_handle_t *handle, - const void *extra, - size_t extra_size); + psa_key_handle_t *handle); /**@}*/ diff --git a/library/psa_crypto.c b/library/psa_crypto.c index dba244a40..abef43a17 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -5098,14 +5098,41 @@ psa_status_t mbedtls_psa_inject_entropy( const unsigned char *seed, } #endif /* MBEDTLS_PSA_INJECT_ENTROPY */ -static psa_status_t psa_generate_key_internal( psa_key_slot_t *slot, - size_t bits, - const void *extra, - size_t extra_size ) +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_GENPRIME) +static psa_status_t psa_read_rsa_exponent( const uint8_t *domain_parameters, + size_t domain_parameters_size, + int *exponent ) +{ + size_t i; + uint32_t acc = 0; + + if( domain_parameters_size == 0 ) + { + *exponent = 65537; + return( PSA_SUCCESS ); + } + + /* Mbed TLS encodes the public exponent as an int. For simplicity, only + * support values that fit in a 32-bit integer, which is larger than + * int on just about every platform anyway. */ + if( domain_parameters_size > sizeof( acc ) ) + return( PSA_ERROR_NOT_SUPPORTED ); + for( i = 0; i < domain_parameters_size; i++ ) + acc = ( acc << 8 ) | domain_parameters[i]; + if( acc > INT_MAX ) + return( PSA_ERROR_NOT_SUPPORTED ); + *exponent = acc; + return( PSA_SUCCESS ); +} +#endif /* MBEDTLS_RSA_C && MBEDTLS_GENPRIME */ + +static psa_status_t psa_generate_key_internal( + psa_key_slot_t *slot, size_t bits, + const uint8_t *domain_parameters, size_t domain_parameters_size ) { psa_key_type_t type = slot->type; - if( extra == NULL && extra_size != 0 ) + if( domain_parameters == NULL && domain_parameters_size != 0 ) return( PSA_ERROR_INVALID_ARGUMENT ); if( key_type_is_raw_bytes( type ) ) @@ -5134,26 +5161,19 @@ static psa_status_t psa_generate_key_internal( psa_key_slot_t *slot, { mbedtls_rsa_context *rsa; int ret; - int exponent = 65537; + int exponent; + psa_status_t status; if( bits > PSA_VENDOR_RSA_MAX_KEY_BITS ) return( PSA_ERROR_NOT_SUPPORTED ); /* Accept only byte-aligned keys, for the same reasons as * in psa_import_rsa_key(). */ if( bits % 8 != 0 ) return( PSA_ERROR_NOT_SUPPORTED ); - if( extra != NULL ) - { - const psa_generate_key_extra_rsa *p = extra; - if( extra_size != sizeof( *p ) ) - return( PSA_ERROR_INVALID_ARGUMENT ); -#if INT_MAX < 0xffffffff - /* Check that the uint32_t value passed by the caller fits - * in the range supported by this implementation. */ - if( p->e > INT_MAX ) - return( PSA_ERROR_NOT_SUPPORTED ); -#endif - exponent = p->e; - } + status = psa_read_rsa_exponent( domain_parameters, + domain_parameters_size, + &exponent ); + if( status != PSA_SUCCESS ) + return( status ); rsa = mbedtls_calloc( 1, sizeof( *rsa ) ); if( rsa == NULL ) return( PSA_ERROR_INSUFFICIENT_MEMORY ); @@ -5183,7 +5203,7 @@ static psa_status_t psa_generate_key_internal( psa_key_slot_t *slot, mbedtls_ecp_curve_info_from_grp_id( grp_id ); mbedtls_ecp_keypair *ecp; int ret; - if( extra != NULL ) + if( domain_parameters_size != 0 ) return( PSA_ERROR_NOT_SUPPORTED ); if( grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL ) return( PSA_ERROR_NOT_SUPPORTED ); @@ -5221,6 +5241,12 @@ psa_status_t psa_generate_key_to_handle( psa_key_handle_t handle, psa_key_slot_t *slot; psa_status_t status; +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_GENPRIME) + /* The old public exponent encoding is no longer supported. */ + if( extra_size != 0 ) + return( PSA_ERROR_NOT_SUPPORTED ); +#endif + status = psa_get_empty_key_slot( handle, &slot ); if( status != PSA_SUCCESS ) return( status ); @@ -5241,17 +5267,16 @@ psa_status_t psa_generate_key_to_handle( psa_key_handle_t handle, } psa_status_t psa_generate_key( const psa_key_attributes_t *attributes, - psa_key_handle_t *handle, - const void *extra, - size_t extra_size ) + psa_key_handle_t *handle ) { psa_status_t status; psa_key_slot_t *slot = NULL; status = psa_start_key_creation( attributes, handle, &slot ); if( status == PSA_SUCCESS ) { - status = psa_generate_key_internal( slot, attributes->bits, - extra, extra_size ); + status = psa_generate_key_internal( + slot, attributes->bits, + attributes->domain_parameters, attributes->domain_parameters_size ); } if( status == PSA_SUCCESS ) status = psa_finish_key_creation( slot ); diff --git a/programs/psa/crypto_examples.c b/programs/psa/crypto_examples.c index 72fa12fcb..1a81f45f8 100644 --- a/programs/psa/crypto_examples.c +++ b/programs/psa/crypto_examples.c @@ -164,7 +164,7 @@ cipher_example_encrypt_decrypt_aes_cbc_nopad_1_block( void ) psa_set_key_type( &attributes, PSA_KEY_TYPE_AES ); psa_set_key_bits( &attributes, key_bits ); - status = psa_generate_key( &attributes, &key_handle, NULL, 0 ); + status = psa_generate_key( &attributes, &key_handle ); ASSERT_STATUS( status, PSA_SUCCESS ); status = cipher_encrypt( key_handle, alg, iv, sizeof( iv ), @@ -215,7 +215,7 @@ static psa_status_t cipher_example_encrypt_decrypt_aes_cbc_pkcs7_multi( void ) psa_set_key_type( &attributes, PSA_KEY_TYPE_AES ); psa_set_key_bits( &attributes, key_bits ); - status = psa_generate_key( &attributes, &key_handle, NULL, 0 ); + status = psa_generate_key( &attributes, &key_handle ); ASSERT_STATUS( status, PSA_SUCCESS ); status = cipher_encrypt( key_handle, alg, iv, sizeof( iv ), @@ -262,7 +262,7 @@ static psa_status_t cipher_example_encrypt_decrypt_aes_ctr_multi( void ) psa_set_key_type( &attributes, PSA_KEY_TYPE_AES ); psa_set_key_bits( &attributes, key_bits ); - status = psa_generate_key( &attributes, &key_handle, NULL, 0 ); + status = psa_generate_key( &attributes, &key_handle ); ASSERT_STATUS( status, PSA_SUCCESS ); status = cipher_encrypt( key_handle, alg, iv, sizeof( iv ), diff --git a/programs/psa/key_ladder_demo.c b/programs/psa/key_ladder_demo.c index c1e296fd8..6d4c707ac 100644 --- a/programs/psa/key_ladder_demo.c +++ b/programs/psa/key_ladder_demo.c @@ -208,7 +208,7 @@ static psa_status_t generate( const char *key_file_name ) psa_set_key_type( &attributes, PSA_KEY_TYPE_DERIVE ); psa_set_key_bits( &attributes, PSA_BYTES_TO_BITS( KEY_SIZE_BYTES ) ); - PSA_CHECK( psa_generate_key( &attributes, &key_handle, NULL, 0 ) ); + PSA_CHECK( psa_generate_key( &attributes, &key_handle ) ); PSA_CHECK( save_key( key_handle, key_file_name ) ); diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index c91094cff..e29cbf7e3 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -2036,6 +2036,24 @@ PSA generate key: ECC, SECP256R1, incorrect bit size depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_C 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_ANY:PSA_ERROR_INVALID_ARGUMENT +PSA generate key: RSA, default e +generate_key_rsa:512:"":PSA_SUCCESS + +PSA generate key: RSA, e=3 +generate_key_rsa:512:"03":PSA_SUCCESS + +PSA generate key: RSA, e=65537 +generate_key_rsa:512:"010001":PSA_SUCCESS + +PSA generate key: RSA, e=513 +generate_key_rsa:512:"0201":PSA_SUCCESS + +PSA generate key: RSA, e=1 +generate_key_rsa:512:"01":PSA_ERROR_INVALID_ARGUMENT + +PSA generate key: RSA, e=2 +generate_key_rsa:512:"01":PSA_ERROR_INVALID_ARGUMENT + PSA import persistent key: raw data, 0 bits depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PSA_CRYPTO_STORAGE_C persistent_key_load_key_from_storage:"":PSA_KEY_TYPE_RAW_DATA:0:PSA_KEY_USAGE_EXPORT:0:IMPORT_KEY diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index 8bf67e63e..9e9378ae8 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -4684,8 +4684,6 @@ void generate_key( int type_arg, size_t bits = bits_arg; psa_algorithm_t alg = alg_arg; psa_status_t expected_status = expected_status_arg; - psa_status_t expected_info_status = - expected_status == PSA_SUCCESS ? PSA_SUCCESS : PSA_ERROR_DOES_NOT_EXIST; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_key_attributes_t got_attributes = PSA_KEY_ATTRIBUTES_INIT; @@ -4697,9 +4695,8 @@ void generate_key( int type_arg, psa_set_key_bits( &attributes, bits ); /* Generate a key */ - TEST_EQUAL( psa_generate_key( &attributes, &handle, NULL, 0 ), - expected_status ); - if( expected_info_status != PSA_SUCCESS ) + TEST_EQUAL( psa_generate_key( &attributes, &handle ), expected_status ); + if( expected_status != PSA_SUCCESS ) goto exit; /* Test the key information */ @@ -4718,6 +4715,109 @@ exit: } /* END_CASE */ +/* BEGIN_CASE depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15 */ +void generate_key_rsa( int bits_arg, + data_t *e_arg, + int expected_status_arg ) +{ + psa_key_handle_t handle = 0; + psa_key_type_t type = PSA_KEY_TYPE_RSA_KEYPAIR; + size_t bits = bits_arg; + psa_key_usage_t usage = PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT; + psa_algorithm_t alg = PSA_ALG_RSA_PKCS1V15_SIGN_RAW; + psa_status_t expected_status = expected_status_arg; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + uint8_t *exported = NULL; + size_t exported_size = + PSA_KEY_EXPORT_MAX_SIZE( PSA_KEY_TYPE_RSA_PUBLIC_KEY, bits ); + size_t exported_length = SIZE_MAX; + uint8_t *e_read_buffer = NULL; + int is_default_public_exponent = 0; + size_t e_read_size = e_arg->len; + size_t e_read_length = SIZE_MAX; + + if( e_arg->len == 0 || + ( e_arg->len == 3 && + e_arg->x[0] == 1 && e_arg->x[1] == 0 && e_arg->x[2] == 1 ) ) + { + is_default_public_exponent = 1; + e_read_size = 0; + } + ASSERT_ALLOC( e_read_buffer, e_read_size ); + ASSERT_ALLOC( exported, exported_size ); + + PSA_ASSERT( psa_crypto_init( ) ); + + psa_set_key_usage_flags( &attributes, usage ); + psa_set_key_algorithm( &attributes, alg ); + PSA_ASSERT( psa_set_key_domain_parameters( &attributes, type, + e_arg->x, e_arg->len ) ); + psa_set_key_bits( &attributes, bits ); + + /* Generate a key */ + TEST_EQUAL( psa_generate_key( &attributes, &handle ), expected_status ); + if( expected_status != PSA_SUCCESS ) + goto exit; + + /* Test the key information */ + PSA_ASSERT( psa_get_key_attributes( handle, &attributes ) ); + TEST_EQUAL( psa_get_key_type( &attributes ), type ); + TEST_EQUAL( psa_get_key_bits( &attributes ), bits ); + PSA_ASSERT( psa_get_key_domain_parameters( &attributes, + e_read_buffer, e_read_size, + &e_read_length ) ); + if( is_default_public_exponent ) + TEST_EQUAL( e_read_length, 0 ); + else + ASSERT_COMPARE( e_read_buffer, e_read_length, e_arg->x, e_arg->len ); + + /* Do something with the key according to its type and permitted usage. */ + if( ! exercise_key( handle, usage, alg ) ) + goto exit; + + /* Export the key and check the public exponent. */ + PSA_ASSERT( psa_export_public_key( handle, + exported, exported_size, + &exported_length ) ); + { + uint8_t *p = exported; + uint8_t *end = exported + exported_length; + size_t len; + /* RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER } -- e + */ + TEST_EQUAL( 0, mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_SEQUENCE | + MBEDTLS_ASN1_CONSTRUCTED ) ); + TEST_ASSERT( asn1_skip_integer( &p, end, bits, bits, 1 ) ); + TEST_EQUAL( 0, mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_INTEGER ) ); + if( len >= 1 && p[0] == 0 ) + { + ++p; + --len; + } + if( e_arg->len == 0 ) + { + TEST_EQUAL( len, 3 ); + TEST_EQUAL( p[0], 1 ); + TEST_EQUAL( p[1], 0 ); + TEST_EQUAL( p[2], 1 ); + } + else + ASSERT_COMPARE( p, len, e_arg->x, e_arg->len ); + } + +exit: + psa_reset_key_attributes( &attributes ); + psa_destroy_key( handle ); + mbedtls_psa_crypto_free( ); + mbedtls_free( e_read_buffer ); + mbedtls_free( exported ); +} +/* END_CASE */ + /* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C */ void persistent_key_load_key_from_storage( data_t *data, int type_arg, int bits_arg, @@ -4763,7 +4863,7 @@ void persistent_key_load_key_from_storage( data_t *data, case GENERATE_KEY: /* Generate a key */ - PSA_ASSERT( psa_generate_key( &attributes, &handle, NULL, 0 ) ); + PSA_ASSERT( psa_generate_key( &attributes, &handle ) ); break; case DERIVE_KEY: