From 92587dbf2b9c03f7fac62e6b1631e3c24d85ae0c Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 18 Sep 2018 12:12:42 +0200 Subject: [PATCH 01/26] Write missing bit of the documentation of psa_key_derivation --- include/psa/crypto.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 732bc2fad..6efaa0242 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -3040,7 +3040,10 @@ psa_status_t psa_generator_abort(psa_crypto_generator_t *generator); * and \p label is the info string used in the "expand" step. * * \param[in,out] generator The generator object to set up. It must - * have been initialized to . + * have been initialized to all-bits-zero, + * a logical zero (`{0}`), + * \c PSA_CRYPTO_GENERATOR_INIT or + * psa_crypto_generator_init(). * \param key Slot containing the secret key to use. * \param alg The key derivation algorithm to compute * (\c PSA_ALG_XXX value such that From e8f0e3dc3c1c97cdb0d850118aa9a29a2dad9747 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 18 Sep 2018 11:52:10 +0200 Subject: [PATCH 02/26] New algorithm category: key selection A key selection algorithm is similar to a key derivation algorithm in that it takes a secret input and produces a secret output stream. However, unlike key derivation algorithms, there is no expectation that the input cannot be reconstructed from the output. Key selection algorithms are exclusively meant to be used on the output of a key agreement algorithm to select chunks of the shared secret. --- include/psa/crypto.h | 35 ++++++++- tests/suites/test_suite_psa_crypto.data | 6 +- .../test_suite_psa_crypto_metadata.data | 2 + .../test_suite_psa_crypto_metadata.function | 71 ++++++++++++++----- 4 files changed, 94 insertions(+), 20 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 6efaa0242..f344e1467 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -603,6 +603,7 @@ typedef uint32_t psa_algorithm_t; #define PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION ((psa_algorithm_t)0x12000000) #define PSA_ALG_CATEGORY_KEY_AGREEMENT ((psa_algorithm_t)0x22000000) #define PSA_ALG_CATEGORY_KEY_DERIVATION ((psa_algorithm_t)0x30000000) +#define PSA_ALG_CATEGORY_KEY_SELECTION ((psa_algorithm_t)0x31000000) #define PSA_ALG_IS_VENDOR_DEFINED(alg) \ (((alg) & PSA_ALG_VENDOR_FLAG) != 0) @@ -674,6 +675,7 @@ typedef uint32_t psa_algorithm_t; #define PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(alg) \ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION) +#define PSA_ALG_KEY_SELECTION_FLAG ((psa_algorithm_t)0x01000000) /** Whether the specified algorithm is a key agreement algorithm. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). @@ -683,7 +685,8 @@ typedef uint32_t psa_algorithm_t; * algorithm identifier. */ #define PSA_ALG_IS_KEY_AGREEMENT(alg) \ - (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_AGREEMENT) + (((alg) & PSA_ALG_CATEGORY_MASK & ~PSA_ALG_KEY_SELECTION_FLAG) == \ + PSA_ALG_CATEGORY_KEY_AGREEMENT) /** Whether the specified algorithm is a key derivation algorithm. * @@ -696,6 +699,17 @@ typedef uint32_t psa_algorithm_t; #define PSA_ALG_IS_KEY_DERIVATION(alg) \ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_DERIVATION) +/** Whether the specified algorithm is a key selection algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a key selection algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_KEY_SELECTION(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_SELECTION) + #define PSA_ALG_HASH_MASK ((psa_algorithm_t)0x000000ff) #define PSA_ALG_MD2 ((psa_algorithm_t)0x01000001) #define PSA_ALG_MD4 ((psa_algorithm_t)0x01000002) @@ -1185,6 +1199,25 @@ typedef uint32_t psa_algorithm_t; #define PSA_ALG_HKDF_GET_HASH(hkdf_alg) \ (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) +#define PSA_ALG_KEY_DERIVATION_MASK ((psa_algorithm_t)0x010fffff) + +/** Use a shared secret as is. + * + * Specify this algorithm as the selection component of a key agreement + * to use the raw result of the key agreement as key material. + * + * \warning The raw result of a key agreement algorithm such as finite-field + * Diffie-Hellman or elliptic curve Diffie-Hellman has biases and should + * not be used directly as key material. It can however be used as the secret + * input in a key derivation algorithm. + */ +#define PSA_ALG_SELECT_RAW ((psa_algorithm_t)0x31000001) + +#define PSA_ALG_KEY_AGREEMENT_GET_KDF(alg) \ + (((alg) & PSA_ALG_KEY_DERIVATION_MASK) | PSA_ALG_CATEGORY_KEY_DERIVATION) + +#define PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) \ + ((alg) & ~PSA_ALG_KEY_DERIVATION_MASK) /**@}*/ /** \defgroup key_management Key management diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index 229fa81c5..5759a15df 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -1377,7 +1377,11 @@ PSA key derivation: bad key type depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C derive_setup:PSA_KEY_TYPE_RAW_DATA:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_HKDF(PSA_ALG_SHA_256):"":"":42:PSA_ERROR_INVALID_ARGUMENT -PSA key derivation: not a key derivation algorithm +PSA key derivation: not a key derivation algorithm (selection) +depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C +derive_setup:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_SELECT_RAW:"":"":42:PSA_ERROR_INVALID_ARGUMENT + +PSA key derivation: not a key derivation algorithm (HMAC) depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C derive_setup:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_HMAC(PSA_ALG_SHA_256):"":"":42:PSA_ERROR_INVALID_ARGUMENT diff --git a/tests/suites/test_suite_psa_crypto_metadata.data b/tests/suites/test_suite_psa_crypto_metadata.data index c9df6c74e..09544f4fb 100644 --- a/tests/suites/test_suite_psa_crypto_metadata.data +++ b/tests/suites/test_suite_psa_crypto_metadata.data @@ -242,6 +242,8 @@ Key derivation: HKDF using SHA-256 depends_on:MBEDTLS_SHA256_C key_derivation_algorithm:PSA_ALG_HKDF( PSA_ALG_SHA_256 ):ALG_IS_HKDF +Key selection: raw +key_selection_algorithm:PSA_ALG_SELECT_RAW:0 Key type: raw data key_type:PSA_KEY_TYPE_RAW_DATA:KEY_TYPE_IS_UNSTRUCTURED diff --git a/tests/suites/test_suite_psa_crypto_metadata.function b/tests/suites/test_suite_psa_crypto_metadata.function index 215110a32..4faa4341e 100644 --- a/tests/suites/test_suite_psa_crypto_metadata.function +++ b/tests/suites/test_suite_psa_crypto_metadata.function @@ -107,6 +107,7 @@ void mac_algorithm_core( psa_algorithm_t alg, int classification_flags, TEST_ASSERT( ! PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) ); TEST_ASSERT( ! PSA_ALG_IS_KEY_AGREEMENT( alg ) ); TEST_ASSERT( ! PSA_ALG_IS_KEY_DERIVATION( alg ) ); + TEST_ASSERT( ! PSA_ALG_IS_KEY_SELECTION( alg ) ); algorithm_classification( alg, classification_flags ); /* Length */ @@ -127,6 +128,7 @@ void aead_algorithm_core( psa_algorithm_t alg, int classification_flags, TEST_ASSERT( ! PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) ); TEST_ASSERT( ! PSA_ALG_IS_KEY_AGREEMENT( alg ) ); TEST_ASSERT( ! PSA_ALG_IS_KEY_DERIVATION( alg ) ); + TEST_ASSERT( ! PSA_ALG_IS_KEY_SELECTION( alg ) ); algorithm_classification( alg, classification_flags ); /* Tag length */ @@ -166,6 +168,7 @@ void hash_algorithm( int alg_arg, int length_arg ) TEST_ASSERT( ! PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) ); TEST_ASSERT( ! PSA_ALG_IS_KEY_AGREEMENT( alg ) ); TEST_ASSERT( ! PSA_ALG_IS_KEY_DERIVATION( alg ) ); + TEST_ASSERT( ! PSA_ALG_IS_KEY_SELECTION( alg ) ); algorithm_classification( alg, 0 ); /* Dependent algorithms */ @@ -262,6 +265,7 @@ void cipher_algorithm( int alg_arg, int classification_flags ) TEST_ASSERT( ! PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) ); TEST_ASSERT( ! PSA_ALG_IS_KEY_AGREEMENT( alg ) ); TEST_ASSERT( ! PSA_ALG_IS_KEY_DERIVATION( alg ) ); + TEST_ASSERT( ! PSA_ALG_IS_KEY_SELECTION( alg ) ); algorithm_classification( alg, classification_flags ); } /* END_CASE */ @@ -313,6 +317,7 @@ void asymmetric_signature_algorithm( int alg_arg, int classification_flags ) TEST_ASSERT( ! PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) ); TEST_ASSERT( ! PSA_ALG_IS_KEY_AGREEMENT( alg ) ); TEST_ASSERT( ! PSA_ALG_IS_KEY_DERIVATION( alg ) ); + TEST_ASSERT( ! PSA_ALG_IS_KEY_SELECTION( alg ) ); algorithm_classification( alg, classification_flags ); } /* END_CASE */ @@ -331,24 +336,7 @@ void asymmetric_encryption_algorithm( int alg_arg, int classification_flags ) TEST_ASSERT( PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) ); TEST_ASSERT( ! PSA_ALG_IS_KEY_AGREEMENT( alg ) ); TEST_ASSERT( ! PSA_ALG_IS_KEY_DERIVATION( alg ) ); - algorithm_classification( alg, classification_flags ); -} -/* END_CASE */ - -/* BEGIN_CASE */ -void key_agreement_algorithm( int alg_arg, int classification_flags ) -{ - psa_algorithm_t alg = alg_arg; - - /* Algorithm classification */ - TEST_ASSERT( ! PSA_ALG_IS_HASH( alg ) ); - TEST_ASSERT( ! PSA_ALG_IS_MAC( alg ) ); - TEST_ASSERT( ! PSA_ALG_IS_CIPHER( alg ) ); - TEST_ASSERT( ! PSA_ALG_IS_AEAD( alg ) ); - TEST_ASSERT( ! PSA_ALG_IS_SIGN( alg ) ); - TEST_ASSERT( ! PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) ); - TEST_ASSERT( PSA_ALG_IS_KEY_AGREEMENT( alg ) ); - TEST_ASSERT( ! PSA_ALG_IS_KEY_DERIVATION( alg ) ); + TEST_ASSERT( ! PSA_ALG_IS_KEY_SELECTION( alg ) ); algorithm_classification( alg, classification_flags ); } /* END_CASE */ @@ -367,10 +355,57 @@ void key_derivation_algorithm( int alg_arg, int classification_flags ) TEST_ASSERT( ! PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) ); TEST_ASSERT( ! PSA_ALG_IS_KEY_AGREEMENT( alg ) ); TEST_ASSERT( PSA_ALG_IS_KEY_DERIVATION( alg ) ); + TEST_ASSERT( ! PSA_ALG_IS_KEY_SELECTION( alg ) ); algorithm_classification( alg, classification_flags ); } /* END_CASE */ +/* BEGIN_CASE */ +void key_selection_algorithm( int alg_arg, int classification_flags ) +{ + psa_algorithm_t alg = alg_arg; + + /* Algorithm classification */ + TEST_ASSERT( ! PSA_ALG_IS_HASH( alg ) ); + TEST_ASSERT( ! PSA_ALG_IS_MAC( alg ) ); + TEST_ASSERT( ! PSA_ALG_IS_CIPHER( alg ) ); + TEST_ASSERT( ! PSA_ALG_IS_AEAD( alg ) ); + TEST_ASSERT( ! PSA_ALG_IS_SIGN( alg ) ); + TEST_ASSERT( ! PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) ); + TEST_ASSERT( ! PSA_ALG_IS_KEY_AGREEMENT( alg ) ); + TEST_ASSERT( ! PSA_ALG_IS_KEY_DERIVATION( alg ) ); + TEST_ASSERT( PSA_ALG_IS_KEY_SELECTION( alg ) ); + algorithm_classification( alg, classification_flags ); +} +/* END_CASE */ + +/* BEGIN_CASE */ +void key_agreement_algorithm( int alg_arg, int classification_flags, + int post_alg_arg ) +{ + psa_algorithm_t alg = alg_arg; + psa_algorithm_t actual_post_alg = PSA_ALG_KEY_AGREEMENT_GET_KDF( alg ); + psa_algorithm_t expected_post_alg = post_alg_arg; + + /* Algorithm classification */ + TEST_ASSERT( ! PSA_ALG_IS_HASH( alg ) ); + TEST_ASSERT( ! PSA_ALG_IS_MAC( alg ) ); + TEST_ASSERT( ! PSA_ALG_IS_CIPHER( alg ) ); + TEST_ASSERT( ! PSA_ALG_IS_AEAD( alg ) ); + TEST_ASSERT( ! PSA_ALG_IS_SIGN( alg ) ); + TEST_ASSERT( ! PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) ); + TEST_ASSERT( PSA_ALG_IS_KEY_AGREEMENT( alg ) ); + TEST_ASSERT( ! PSA_ALG_IS_KEY_DERIVATION( alg ) ); + TEST_ASSERT( ! PSA_ALG_IS_KEY_SELECTION( alg ) ); + algorithm_classification( alg, classification_flags ); + + /* Shared secret derivation properties */ + TEST_ASSERT( PSA_ALG_IS_KEY_DERIVATION( actual_post_alg ) || + PSA_ALG_IS_KEY_SELECTION( actual_post_alg ) ); + TEST_ASSERT( actual_post_alg == expected_post_alg ); +} +/* END_CASE */ + /* BEGIN_CASE */ void key_type( int type_arg, int classification_flags ) { From 93098fd996c466bc863bbb3109a6a5b6bf828cc1 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 18 Sep 2018 11:54:43 +0200 Subject: [PATCH 03/26] Key agreement: macros for finite-field Diffie-Hellman, ECDH Declare macros to represent key agreement algorithms. --- include/psa/crypto.h | 67 +++++++++++++++++++ .../test_suite_psa_crypto_metadata.data | 17 +++++ .../test_suite_psa_crypto_metadata.function | 14 ++++ 3 files changed, 98 insertions(+) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index f344e1467..515e65f3d 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -1218,6 +1218,73 @@ typedef uint32_t psa_algorithm_t; #define PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) \ ((alg) & ~PSA_ALG_KEY_DERIVATION_MASK) + +#define PSA_ALG_FFDH_BASE ((psa_algorithm_t)0x22100000) +/** The Diffie-Hellman key agreement algorithm. + * + * This algorithm combines the finite-field Diffie-Hellman-Merkle key + * agreement to produce a shared secret from a private key and the peer's + * public key, with a key selection or key derivation algorithm to produce + * one or more shared keys and other shared cryptographic material. + * + * \param kdf_alg A key derivation algorithm (\c PSA_ALG_XXX value such + * that #PSA_ALG_IS_KEY_DERIVATION(\p hash_alg) is true) + * or a key selection algorithm (\c PSA_ALG_XXX value such + * that #PSA_ALG_IS_SELECTION(\p hash_alg) is true). + * + * \return The Diffie-Hellman algorithm with the specified + * selection or derivation algorithm. + */ +#define PSA_ALG_FFDH(kdf_alg) \ + (PSA_ALG_FFDH_BASE | ((kdf_alg) & PSA_ALG_KEY_DERIVATION_MASK)) +/** Whether the specified algorithm is a finite field Diffie-Hellman algorithm. + * + * This includes every supported key selection or key agreement algorithm + * for the output of the Diffie-Hellman calculation. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a finite field Diffie-Hellman algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key agreement algorithm identifier. + */ +#define PSA_ALG_IS_FFDH(alg) \ + (PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) == PSA_ALG_FFDH_BASE) + +#define PSA_ALG_ECDH_BASE ((psa_algorithm_t)0x22200000) +/** The elliptic curve Diffie-Hellman key agreement algorithm. + * + * This algorithm combines the elliptic curve Diffie-Hellman key + * agreement to produce a shared secret from a private key and the peer's + * public key, with a key selection or key derivation algorithm to produce + * one or more shared keys and other shared cryptographic material. + * + * \param kdf_alg A key derivation algorithm (\c PSA_ALG_XXX value such + * that #PSA_ALG_IS_KEY_DERIVATION(\p hash_alg) is true) + * or a selection algorithm (\c PSA_ALG_XXX value such + * that #PSA_ALG_IS_KEY_SELECTION(\p hash_alg) is true). + * + * \return The Diffie-Hellman algorithm with the specified + * selection or derivation algorithm. + */ +#define PSA_ALG_ECDH(kdf_alg) \ + (PSA_ALG_ECDH_BASE | ((kdf_alg) & PSA_ALG_KEY_DERIVATION_MASK)) +/** Whether the specified algorithm is an elliptic curve Diffie-Hellman + * algorithm. + * + * This includes every supported key selection or key agreement algorithm + * for the output of the Diffie-Hellman calculation. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is an elliptic curve Diffie-Hellman algorithm, + * 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key agreement algorithm identifier. + */ +#define PSA_ALG_IS_ECDH(alg) \ + (PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) == PSA_ALG_ECDH_BASE) + /**@}*/ /** \defgroup key_management Key management diff --git a/tests/suites/test_suite_psa_crypto_metadata.data b/tests/suites/test_suite_psa_crypto_metadata.data index 09544f4fb..b61d8e1aa 100644 --- a/tests/suites/test_suite_psa_crypto_metadata.data +++ b/tests/suites/test_suite_psa_crypto_metadata.data @@ -244,6 +244,23 @@ key_derivation_algorithm:PSA_ALG_HKDF( PSA_ALG_SHA_256 ):ALG_IS_HKDF Key selection: raw key_selection_algorithm:PSA_ALG_SELECT_RAW:0 + +Key agreement: FFDH, raw output +depends_on:MBEDTLS_DHM_C +key_agreement_algorithm:PSA_ALG_FFDH( PSA_ALG_SELECT_RAW ):ALG_IS_FFDH:PSA_ALG_SELECT_RAW + +Key agreement: FFDH, HKDF using SHA-256 +depends_on:MBEDTLS_DHM_C +key_agreement_algorithm:PSA_ALG_FFDH( PSA_ALG_HKDF( PSA_ALG_SHA_256 ) ):ALG_IS_FFDH:PSA_ALG_HKDF( PSA_ALG_SHA_256 ) + +Key agreement: ECDH, raw output +depends_on:MBEDTLS_ECDH_C +key_agreement_algorithm:PSA_ALG_ECDH( PSA_ALG_SELECT_RAW ):ALG_IS_ECDH:PSA_ALG_SELECT_RAW + +Key agreement: ECDH, HKDF using SHA-256 +depends_on:MBEDTLS_ECDH_C +key_agreement_algorithm:PSA_ALG_ECDH( PSA_ALG_HKDF( PSA_ALG_SHA_256 ) ):ALG_IS_ECDH:PSA_ALG_HKDF( PSA_ALG_SHA_256 ) + Key type: raw data key_type:PSA_KEY_TYPE_RAW_DATA:KEY_TYPE_IS_UNSTRUCTURED diff --git a/tests/suites/test_suite_psa_crypto_metadata.function b/tests/suites/test_suite_psa_crypto_metadata.function index 4faa4341e..a8316c40d 100644 --- a/tests/suites/test_suite_psa_crypto_metadata.function +++ b/tests/suites/test_suite_psa_crypto_metadata.function @@ -31,6 +31,8 @@ #define ALG_IS_RANDOMIZED_ECDSA ( 1u << 13 ) #define ALG_IS_RSA_OAEP ( 1u << 14 ) #define ALG_IS_HKDF ( 1u << 15 ) +#define ALG_IS_FFDH ( 1u << 16 ) +#define ALG_IS_ECDH ( 1u << 17 ) /* Flags for key type classification macros. There is a flag for every * key type classification macro PSA_KEY_TYPE_IS_xxx except for some that @@ -357,6 +359,12 @@ void key_derivation_algorithm( int alg_arg, int classification_flags ) TEST_ASSERT( PSA_ALG_IS_KEY_DERIVATION( alg ) ); TEST_ASSERT( ! PSA_ALG_IS_KEY_SELECTION( alg ) ); algorithm_classification( alg, classification_flags ); + + /* Check combinations with key agreements */ + TEST_ASSERT( PSA_ALG_IS_KEY_AGREEMENT( PSA_ALG_FFDH( alg ) ) ); + TEST_ASSERT( PSA_ALG_IS_KEY_AGREEMENT( PSA_ALG_ECDH( alg ) ) ); + TEST_ASSERT( PSA_ALG_KEY_AGREEMENT_GET_KDF( PSA_ALG_ECDH( alg ) ) == alg ); + TEST_ASSERT( PSA_ALG_KEY_AGREEMENT_GET_KDF( PSA_ALG_FFDH( alg ) ) == alg ); } /* END_CASE */ @@ -376,6 +384,12 @@ void key_selection_algorithm( int alg_arg, int classification_flags ) TEST_ASSERT( ! PSA_ALG_IS_KEY_DERIVATION( alg ) ); TEST_ASSERT( PSA_ALG_IS_KEY_SELECTION( alg ) ); algorithm_classification( alg, classification_flags ); + + /* Check combinations with key agreements */ + TEST_ASSERT( PSA_ALG_IS_KEY_AGREEMENT( PSA_ALG_FFDH( alg ) ) ); + TEST_ASSERT( PSA_ALG_IS_KEY_AGREEMENT( PSA_ALG_ECDH( alg ) ) ); + TEST_ASSERT( PSA_ALG_KEY_AGREEMENT_GET_KDF( PSA_ALG_ECDH( alg ) ) == alg ); + TEST_ASSERT( PSA_ALG_KEY_AGREEMENT_GET_KDF( PSA_ALG_FFDH( alg ) ) == alg ); } /* END_CASE */ From cce18aec4ca3d68c53232c58a0b6d8a05ad956c4 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 18 Sep 2018 12:03:52 +0200 Subject: [PATCH 04/26] Split off psa_key_derivation_internal Refactor psa_key_derivation to prepare for key agreement algorithms which need to plug into key derivation after argument validation. --- library/psa_crypto.c | 100 ++++++++++++++++++++++++++++--------------- 1 file changed, 65 insertions(+), 35 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 4584f6bde..b99c808ca 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -3432,7 +3432,8 @@ exit: /* Set up an HKDF-based generator. This is exactly the extract phase * of the HKDF algorithm. */ static psa_status_t psa_generator_hkdf_setup( psa_hkdf_generator_t *hkdf, - key_slot_t *slot, + const uint8_t *secret, + size_t secret_length, psa_algorithm_t hash_alg, const uint8_t *salt, size_t salt_length, @@ -3445,9 +3446,7 @@ static psa_status_t psa_generator_hkdf_setup( psa_hkdf_generator_t *hkdf, PSA_ALG_HMAC_GET_HASH( hash_alg ) ); if( status != PSA_SUCCESS ) return( status ); - status = psa_hash_update( &hkdf->hmac.hash_ctx, - slot->data.raw.data, - slot->data.raw.bytes ); + status = psa_hash_update( &hkdf->hmac.hash_ctx, secret, secret_length ); if( status != PSA_SUCCESS ) return( status ); status = psa_hmac_finish_internal( &hkdf->hmac, @@ -3468,6 +3467,51 @@ static psa_status_t psa_generator_hkdf_setup( psa_hkdf_generator_t *hkdf, return( PSA_SUCCESS ); } +static psa_status_t psa_key_derivation_internal( + psa_crypto_generator_t *generator, + const uint8_t *secret, size_t secret_length, + psa_algorithm_t alg, + const uint8_t *salt, size_t salt_length, + const uint8_t *label, size_t label_length, + size_t capacity ) +{ + psa_status_t status; + size_t max_capacity; + + /* Set generator->alg even on failure so that abort knows what to do. */ + generator->alg = alg; + +#if defined(MBEDTLS_MD_C) + if( PSA_ALG_IS_HKDF( alg ) ) + { + psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH( alg ); + size_t hash_size = PSA_HASH_SIZE( hash_alg ); + if( hash_size == 0 ) + return( PSA_ERROR_NOT_SUPPORTED ); + max_capacity = 255 * hash_size; + status = psa_generator_hkdf_setup( &generator->ctx.hkdf, + secret, secret_length, + hash_alg, + salt, salt_length, + label, label_length ); + } + else +#endif + { + return( PSA_ERROR_NOT_SUPPORTED ); + } + + if( status != PSA_SUCCESS ) + return( status ); + + if( capacity <= max_capacity ) + generator->capacity = capacity; + else + return( PSA_ERROR_INVALID_ARGUMENT ); + + return( PSA_SUCCESS ); +} + psa_status_t psa_key_derivation( psa_crypto_generator_t *generator, psa_key_slot_t key, psa_algorithm_t alg, @@ -3483,41 +3527,27 @@ psa_status_t psa_key_derivation( psa_crypto_generator_t *generator, if( generator->alg != 0 ) return( PSA_ERROR_BAD_STATE ); - status = psa_get_key_from_slot( key, &slot, PSA_KEY_USAGE_DERIVE, alg ); - if( status != PSA_SUCCESS ) - return( status ); - if( slot->type != PSA_KEY_TYPE_DERIVE ) - return( PSA_ERROR_INVALID_ARGUMENT ); - + /* Make sure that alg is a key derivation algorithm. This prevents + * key selection algorithms, which psa_key_derivation_internal + * accepts for the sake of key agreement. */ if( ! PSA_ALG_IS_KEY_DERIVATION( alg ) ) return( PSA_ERROR_INVALID_ARGUMENT ); -#if defined(MBEDTLS_MD_C) - if( PSA_ALG_IS_HKDF( alg ) ) - { - psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH( alg ); - size_t hash_size = PSA_HASH_SIZE( hash_alg ); - if( hash_size == 0 ) - return( PSA_ERROR_NOT_SUPPORTED ); - if( capacity > 255 * hash_size ) - return( PSA_ERROR_INVALID_ARGUMENT ); - status = psa_generator_hkdf_setup( &generator->ctx.hkdf, - slot, - hash_alg, - salt, salt_length, - label, label_length ); - } - else -#endif - { - return( PSA_ERROR_NOT_SUPPORTED ); - } + status = psa_get_key_from_slot( key, &slot, PSA_KEY_USAGE_DERIVE, alg ); + if( status != PSA_SUCCESS ) + return( status ); - /* Set generator->alg even on failure so that abort knows what to do. */ - generator->alg = alg; - if( status == PSA_SUCCESS ) - generator->capacity = capacity; - else + if( slot->type != PSA_KEY_TYPE_DERIVE ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + status = psa_key_derivation_internal( generator, + slot->data.raw.data, + slot->data.raw.bytes, + alg, + salt, salt_length, + label, label_length, + capacity ); + if( status != PSA_SUCCESS ) psa_generator_abort( generator ); return( status ); } From 751d965dfcd518d90e74ccaa22f6480f73bca990 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 18 Sep 2018 12:05:44 +0200 Subject: [PATCH 05/26] Implement PSA_ALG_SELECT_RAW --- library/psa_crypto.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index b99c808ca..202552391 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -3241,6 +3241,16 @@ psa_status_t psa_generator_abort( psa_crypto_generator_t *generator ) * nothing to do. */ } else + if( generator->alg == PSA_ALG_SELECT_RAW ) + { + if( generator->ctx.buffer.data != NULL ) + { + mbedtls_zeroize( generator->ctx.buffer.data, + generator->ctx.buffer.size ); + mbedtls_free( generator->ctx.buffer.data ); + } + } + else #if defined(MBEDTLS_MD_C) if( PSA_ALG_IS_HKDF( generator->alg ) ) { @@ -3358,6 +3368,14 @@ psa_status_t psa_generator_read( psa_crypto_generator_t *generator, } generator->capacity -= output_length; + if( generator->alg == PSA_ALG_SELECT_RAW ) + { + size_t offset = + generator->ctx.buffer.size - generator->capacity - output_length; + memcpy( output, generator->ctx.buffer.data + offset, output_length ); + status = PSA_SUCCESS; + } + else #if defined(MBEDTLS_MD_C) if( PSA_ALG_IS_HKDF( generator->alg ) ) { @@ -3481,6 +3499,21 @@ static psa_status_t psa_key_derivation_internal( /* Set generator->alg even on failure so that abort knows what to do. */ generator->alg = alg; + if( alg == PSA_ALG_SELECT_RAW ) + { + if( salt_length != 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + if( label_length != 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + generator->ctx.buffer.data = mbedtls_calloc( 1, secret_length ); + if( generator->ctx.buffer.data == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + memcpy( generator->ctx.buffer.data, secret, secret_length ); + generator->ctx.buffer.size = secret_length; + max_capacity = secret_length; + status = PSA_SUCCESS; + } + else #if defined(MBEDTLS_MD_C) if( PSA_ALG_IS_HKDF( alg ) ) { From 8feb3a886d8427aa6f541b1f389360a9f972f095 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 18 Sep 2018 12:06:11 +0200 Subject: [PATCH 06/26] Support key derivation with non-predefined capacity psa_key_derivation requires the caller to specify a maximum capacity. This commit adds a special value that indicates that the maximum capacity should be the maximum supported by the algorithm. This is currently meant only for selection algorithms used on the shared secret produced by a key agreement. --- include/psa/crypto.h | 9 +++++++++ library/psa_crypto.c | 2 ++ 2 files changed, 11 insertions(+) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 515e65f3d..8059ab9e2 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -3122,6 +3122,15 @@ psa_status_t psa_generator_import_key(psa_key_slot_t key, */ psa_status_t psa_generator_abort(psa_crypto_generator_t *generator); +/** Use the maximum possible capacity for a generator. + * + * Use this value as the capacity argument when setting up a generator + * to indicate that the generator should have the maximum possible capacity. + * The value of the maximum possible capacity depends on the generator + * algorithm. + */ +#define PSA_GENERATOR_UNBRIDLED_CAPACITY ((size_t)(-1)) + /**@}*/ /** \defgroup derivation Key derivation diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 202552391..3c1cec930 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -3539,6 +3539,8 @@ static psa_status_t psa_key_derivation_internal( if( capacity <= max_capacity ) generator->capacity = capacity; + else if( capacity == PSA_GENERATOR_UNBRIDLED_CAPACITY ) + generator->capacity = max_capacity; else return( PSA_ERROR_INVALID_ARGUMENT ); From 01d718cee89bfd057af43d4ff95e80e3acf9b372 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 18 Sep 2018 12:01:02 +0200 Subject: [PATCH 07/26] New API function: psa_key_agreement Set up a generator from a key agreement. --- include/psa/crypto.h | 40 ++++++ library/psa_crypto.c | 60 +++++++++ tests/suites/test_suite_psa_crypto.data | 20 +++ tests/suites/test_suite_psa_crypto.function | 136 ++++++++++++++++++++ 4 files changed, 256 insertions(+) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 8059ab9e2..8fb641fdc 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -3191,6 +3191,46 @@ psa_status_t psa_key_derivation(psa_crypto_generator_t *generator, size_t label_length, size_t capacity); +/** Set up a key agreement operation. + * + * A key agreement algorithm takes two inputs: a private key \p private_key + * a public key \p peer_key. + * The result of this function is a byte generator which can + * be used to produce keys and other cryptographic material. + * + * \param[in,out] generator The generator object to set up. It must + * have been initialized to all-bits-zero, + * a logical zero (`{0}`), + * \c PSA_CRYPTO_GENERATOR_INIT or + * psa_crypto_generator_init(). + * \param private_key Slot containing the private key to use. + * \param[in] peer_key Public key of the peer. + * \param peer_key_length Size of \p peer_key in bytes. + * \param alg The key agreement algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_KEY_AGREEMENT(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_EMPTY_SLOT + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c private_key is not compatible with \c alg, + * or \p peer_key is not valid for \c alg or not compatible with + * \c private_key. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \c alg is not supported or is not a key derivation algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_TAMPERING_DETECTED + */ +psa_status_t psa_key_agreement(psa_crypto_generator_t *generator, + psa_key_slot_t private_key, + const uint8_t *peer_key, + size_t peer_key_length, + psa_algorithm_t alg); + /**@}*/ /** \defgroup random Random generation diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 3c1cec930..6f25d8b29 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -3589,6 +3589,66 @@ psa_status_t psa_key_derivation( psa_crypto_generator_t *generator, +/****************************************************************/ +/* Key agreement */ +/****************************************************************/ + +#define PSA_KEY_AGREEMENT_MAX_SHARED_SECRET_SIZE MBEDTLS_ECP_MAX_BYTES + +static psa_status_t psa_key_agreement_internal( psa_crypto_generator_t *generator, + key_slot_t *private_key, + const uint8_t *peer_key, + size_t peer_key_length, + psa_algorithm_t alg ) +{ + psa_status_t status; + uint8_t shared_secret[PSA_KEY_AGREEMENT_MAX_SHARED_SECRET_SIZE]; + size_t shared_secret_length = 0; + + /* Step 1: run the secret agreement algorithm to generate the shared + * secret. */ + switch( PSA_ALG_KEY_AGREEMENT_GET_BASE( alg ) ) + { + default: + return( PSA_ERROR_NOT_SUPPORTED ); + } + if( status != PSA_SUCCESS ) + goto exit; + + /* Step 2: set up the key derivation to generate key material from + * the shared secret. */ + status = psa_key_derivation_internal( generator, + shared_secret, shared_secret_length, + PSA_ALG_KEY_AGREEMENT_GET_KDF( alg ), + NULL, 0, NULL, 0, + PSA_GENERATOR_UNBRIDLED_CAPACITY ); +exit: + mbedtls_zeroize( shared_secret, shared_secret_length ); + return( status ); +} + +psa_status_t psa_key_agreement( psa_crypto_generator_t *generator, + psa_key_slot_t private_key, + const uint8_t *peer_key, + size_t peer_key_length, + psa_algorithm_t alg ) +{ + key_slot_t *slot; + psa_status_t status; + if( ! PSA_ALG_IS_KEY_AGREEMENT( alg ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + status = psa_get_key_from_slot( private_key, &slot, + PSA_KEY_USAGE_DERIVE, alg ); + if( status != PSA_SUCCESS ) + return( status ); + return( psa_key_agreement_internal( generator, + slot, + peer_key, peer_key_length, + alg ) ); +} + + + /****************************************************************/ /* Random generation */ /****************************************************************/ diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index 5759a15df..d321e68ff 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -435,6 +435,18 @@ PSA key policy: derive, wrong algorithm depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C derive_key_policy:PSA_KEY_USAGE_DERIVE:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_TYPE_DERIVE:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HKDF(PSA_ALG_SHA_224) +PSA key policy: agreement, permitted +depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C +agreement_key_policy:PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3077020101042049c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eeea00a06082a8648ce3d030107a144034200047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45":PSA_ALG_ECDH(PSA_ALG_SELECT_RAW) + +PSA key policy: agreement, not permitted +depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C +agreement_key_policy:0:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3077020101042049c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eeea00a06082a8648ce3d030107a144034200047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45":PSA_ALG_ECDH(PSA_ALG_SELECT_RAW) + +PSA key policy: agreement, wrong algorithm +depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C +agreement_key_policy:PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3077020101042049c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eeea00a06082a8648ce3d030107a144034200047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45":PSA_ALG_FFDH(PSA_ALG_SELECT_RAW) + PSA key lifetime: set and get volatile key_lifetime:PSA_KEY_LIFETIME_VOLATILE @@ -1525,6 +1537,14 @@ PSA key derivation: HKDF SHA-256, derive key, 1+41 depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C derive_key_export:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":1:41 +PSA key agreement setup: ECDH, unknown KDF +depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C +key_agreement_setup:PSA_ALG_ECDH(0):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3078020101042100c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433a00a06082a8648ce3d030107a14403420004dad0b65394221cf9b051e1feca5787d098dfe637fc90b9ef945d0c37725811805271a0461cdb8252d61f1c456fa3e59ab1f45b33accf5f58389e0577b8990bb3":"3059301306072a8648ce3d020106082a8648ce3d03010703420004d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":PSA_ERROR_NOT_SUPPORTED + +PSA key agreement setup: not a key agreement algorithm +depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C +key_agreement_setup:PSA_ALG_HKDF( PSA_ALG_SHA_256 ):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3078020101042100c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433a00a06082a8648ce3d030107a14403420004dad0b65394221cf9b051e1feca5787d098dfe637fc90b9ef945d0c37725811805271a0461cdb8252d61f1c456fa3e59ab1f45b33accf5f58389e0577b8990bb3":"3059301306072a8648ce3d020106082a8648ce3d03010703420004d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":PSA_ERROR_INVALID_ARGUMENT + PSA generate random: 0 bytes generate_random:0 diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index d2875ae34..b7b7c4c5d 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -392,6 +392,51 @@ exit: return( 0 ); } +static int exercise_key_agreement_key( psa_key_slot_t key, + psa_key_usage_t usage, + psa_algorithm_t alg ) +{ + psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT; + psa_key_type_t key_type; + psa_key_type_t public_key_type; + size_t key_bits; + uint8_t *public_key = NULL; + size_t public_key_length; + unsigned char output[1]; + int ok = 0; + + if( usage & PSA_KEY_USAGE_DERIVE ) + { + /* We need two keys to exercise key agreement. Exercise the + * private key against its own public key. */ + TEST_ASSERT( psa_get_key_information( key, + &key_type, + &key_bits ) == PSA_SUCCESS ); + public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR( key_type ); + public_key_length = PSA_KEY_EXPORT_MAX_SIZE( public_key_type, + key_bits ); + public_key = mbedtls_calloc( 1, public_key_length ); + TEST_ASSERT( public_key != NULL ); + TEST_ASSERT( + psa_export_public_key( key, + public_key, public_key_length, + &public_key_length ) == PSA_SUCCESS ); + TEST_ASSERT( psa_key_agreement( &generator, + key, + public_key, public_key_length, + alg ) == PSA_SUCCESS ); + TEST_ASSERT( psa_generator_read( &generator, + output, + sizeof( output ) ) == PSA_SUCCESS ); + TEST_ASSERT( psa_generator_abort( &generator ) == PSA_SUCCESS ); + } + ok = 1; + +exit: + mbedtls_free( public_key ); + return( ok ); +} + static int is_oid_of_key_type( psa_key_type_t type, const uint8_t *oid, size_t oid_length ) { @@ -737,6 +782,8 @@ static int exercise_key( psa_key_slot_t slot, ok = exercise_asymmetric_encryption_key( slot, usage, alg ); else if( PSA_ALG_IS_KEY_DERIVATION( alg ) ) ok = exercise_key_derivation_key( slot, usage, alg ); + else if( PSA_ALG_IS_KEY_AGREEMENT( alg ) ) + ok = exercise_key_agreement_key( slot, usage, alg ); else { char message[40]; @@ -1271,6 +1318,7 @@ void import_and_exercise_key( data_t *data, PSA_KEY_USAGE_ENCRYPT : PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT ) : PSA_ALG_IS_KEY_DERIVATION( alg ) ? PSA_KEY_USAGE_DERIVE : + PSA_ALG_IS_KEY_AGREEMENT( alg ) ? PSA_KEY_USAGE_DERIVE : 0 ); psa_key_policy_t policy; psa_key_type_t got_type; @@ -1642,6 +1690,61 @@ exit: } /* END_CASE */ +/* BEGIN_CASE */ +void agreement_key_policy( int policy_usage, + int policy_alg, + int key_type_arg, + data_t *key_data, + int exercise_alg ) +{ + int key_slot = 1; + psa_key_policy_t policy; + psa_key_type_t key_type = key_type_arg; + psa_key_type_t public_key_type; + size_t key_bits; + uint8_t *public_key = NULL; + size_t public_key_length; + psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT; + psa_status_t status; + + TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + + psa_key_policy_init( &policy ); + psa_key_policy_set_usage( &policy, policy_usage, policy_alg ); + TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS ); + + TEST_ASSERT( psa_import_key( key_slot, key_type, + key_data->x, key_data->len ) == PSA_SUCCESS ); + + /* We need two keys to exercise key agreement. Exercise the + * private key against its own public key. */ + TEST_ASSERT( psa_get_key_information( key_slot, + &key_type, + &key_bits ) == PSA_SUCCESS ); + public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR( key_type ); + public_key_length = PSA_KEY_EXPORT_MAX_SIZE( public_key_type, key_bits ); + public_key = mbedtls_calloc( 1, public_key_length ); + TEST_ASSERT( public_key != NULL ); + TEST_ASSERT( psa_export_public_key( key_slot, + public_key, public_key_length, + &public_key_length ) == PSA_SUCCESS ); + + status = psa_key_agreement( &generator, key_slot, + public_key, public_key_length, + exercise_alg ); + if( policy_alg == exercise_alg && + ( policy_usage & PSA_KEY_USAGE_DERIVE ) != 0 ) + TEST_ASSERT( status == PSA_SUCCESS ); + else + TEST_ASSERT( status == PSA_ERROR_NOT_PERMITTED ); + +exit: + psa_generator_abort( &generator ); + psa_destroy_key( key_slot ); + mbedtls_psa_crypto_free( ); +} +/* END_CASE */ + /* BEGIN_CASE */ void key_lifetime( int lifetime_arg ) { @@ -3655,6 +3758,39 @@ exit: } /* END_CASE */ +/* BEGIN_CASE */ +void key_agreement_setup( int alg_arg, + int our_key_type_arg, data_t *our_key_data, + data_t *peer_key_data, + int expected_status_arg ) +{ + psa_key_slot_t our_key = 1; + psa_algorithm_t alg = alg_arg; + psa_key_type_t our_key_type = our_key_type_arg; + psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT; + psa_key_policy_t policy; + + TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + + psa_key_policy_init( &policy ); + psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg ); + TEST_ASSERT( psa_set_key_policy( our_key, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_import_key( our_key, our_key_type, + our_key_data->x, + our_key_data->len ) == PSA_SUCCESS ); + + TEST_ASSERT( psa_key_agreement( &generator, + our_key, + peer_key_data->x, peer_key_data->len, + alg ) == expected_status_arg ); + +exit: + psa_generator_abort( &generator ); + psa_destroy_key( our_key ); + mbedtls_psa_crypto_free( ); +} +/* END_CASE */ + /* BEGIN_CASE */ void generate_random( int bytes_arg ) { From 5968559a9cf5e7c03691de741e0b9e604617c1b8 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 18 Sep 2018 12:11:34 +0200 Subject: [PATCH 08/26] Key agreement test functions --- tests/suites/test_suite_psa_crypto.function | 81 +++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index b7b7c4c5d..fc02453e3 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -3791,6 +3791,87 @@ exit: } /* END_CASE */ +/* BEGIN_CASE */ +void key_agreement_capacity( int alg_arg, + int our_key_type_arg, data_t *our_key_data, + data_t *peer_key_data, + int expected_capacity_arg ) +{ + psa_key_slot_t our_key = 1; + psa_algorithm_t alg = alg_arg; + psa_key_type_t our_key_type = our_key_type_arg; + psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT; + psa_key_policy_t policy; + size_t actual_capacity; + + TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + + psa_key_policy_init( &policy ); + psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg ); + TEST_ASSERT( psa_set_key_policy( our_key, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_import_key( our_key, our_key_type, + our_key_data->x, + our_key_data->len ) == PSA_SUCCESS ); + + TEST_ASSERT( psa_key_agreement( &generator, + our_key, + peer_key_data->x, peer_key_data->len, + alg ) == PSA_SUCCESS ); + + TEST_ASSERT( psa_get_generator_capacity( + &generator, &actual_capacity ) == PSA_SUCCESS ); + TEST_ASSERT( actual_capacity == (size_t) expected_capacity_arg ); + +exit: + psa_generator_abort( &generator ); + psa_destroy_key( our_key ); + mbedtls_psa_crypto_free( ); +} +/* END_CASE */ + +/* BEGIN_CASE */ +void key_agreement_output( int alg_arg, + int our_key_type_arg, data_t *our_key_data, + data_t *peer_key_data, + data_t *expected_output ) +{ + psa_key_slot_t our_key = 1; + psa_algorithm_t alg = alg_arg; + psa_key_type_t our_key_type = our_key_type_arg; + psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT; + psa_key_policy_t policy; + uint8_t *actual_output = mbedtls_calloc( 1, expected_output->len ); + + TEST_ASSERT( actual_output != NULL ); + + TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + + psa_key_policy_init( &policy ); + psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg ); + TEST_ASSERT( psa_set_key_policy( our_key, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_import_key( our_key, our_key_type, + our_key_data->x, + our_key_data->len ) == PSA_SUCCESS ); + + TEST_ASSERT( psa_key_agreement( &generator, + our_key, + peer_key_data->x, peer_key_data->len, + alg ) == PSA_SUCCESS ); + + TEST_ASSERT( psa_generator_read( &generator, + actual_output, + expected_output->len ) == PSA_SUCCESS ); + TEST_ASSERT( memcmp( actual_output, expected_output->x, + expected_output->len ) == 0 ); + +exit: + psa_generator_abort( &generator ); + psa_destroy_key( our_key ); + mbedtls_psa_crypto_free( ); + mbedtls_free( actual_output ); +} +/* END_CASE */ + /* BEGIN_CASE */ void generate_random( int bytes_arg ) { From b7ecdf0509742d1f0a03286ecbf38a69a8329d1d Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 18 Sep 2018 12:11:27 +0200 Subject: [PATCH 09/26] Implement ECDH --- library/psa_crypto.c | 54 ++++++++++++++++++ tests/suites/test_suite_psa_crypto.data | 74 +++++++++++++++++++++++-- 2 files changed, 123 insertions(+), 5 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 6f25d8b29..c18c8f022 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -62,6 +62,7 @@ #include "mbedtls/cmac.h" #include "mbedtls/ctr_drbg.h" #include "mbedtls/des.h" +#include "mbedtls/ecdh.h" #include "mbedtls/ecp.h" #include "mbedtls/entropy.h" #include "mbedtls/error.h" @@ -3593,6 +3594,48 @@ psa_status_t psa_key_derivation( psa_crypto_generator_t *generator, /* Key agreement */ /****************************************************************/ +static psa_status_t psa_key_agreement_ecdh( const uint8_t *peer_key, + size_t peer_key_length, + const mbedtls_ecp_keypair *our_key, + uint8_t *shared_secret, + size_t shared_secret_size, + size_t *shared_secret_length ) +{ + mbedtls_pk_context pk; + mbedtls_ecp_keypair *their_key = NULL; + mbedtls_ecdh_context ecdh; + int ret; + mbedtls_ecdh_init( &ecdh ); + mbedtls_pk_init( &pk ); + + ret = mbedtls_pk_parse_public_key( &pk, peer_key, peer_key_length ); + if( ret != 0 ) + goto exit; + if( mbedtls_pk_get_type( &pk ) != MBEDTLS_PK_ECKEY ) + { + ret = MBEDTLS_ERR_ECP_INVALID_KEY; + goto exit; + } + their_key = mbedtls_pk_ec( pk ); + ret = mbedtls_ecdh_get_params( &ecdh, their_key, MBEDTLS_ECDH_THEIRS ); + if( ret != 0 ) + goto exit; + ret = mbedtls_ecdh_get_params( &ecdh, our_key, MBEDTLS_ECDH_OURS ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_ecdh_calc_secret( &ecdh, + shared_secret_length, + shared_secret, shared_secret_size, + mbedtls_ctr_drbg_random, + &global_data.ctr_drbg ); + +exit: + mbedtls_pk_free( &pk ); + mbedtls_ecdh_free( &ecdh ); + return( mbedtls_to_psa_error( ret ) ); +} + #define PSA_KEY_AGREEMENT_MAX_SHARED_SECRET_SIZE MBEDTLS_ECP_MAX_BYTES static psa_status_t psa_key_agreement_internal( psa_crypto_generator_t *generator, @@ -3609,6 +3652,17 @@ static psa_status_t psa_key_agreement_internal( psa_crypto_generator_t *generato * secret. */ switch( PSA_ALG_KEY_AGREEMENT_GET_BASE( alg ) ) { +#if defined(MBEDTLS_ECDH_C) + case PSA_ALG_ECDH_BASE: + if( ! PSA_KEY_TYPE_IS_ECC_KEYPAIR( private_key->type ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + status = psa_key_agreement_ecdh( peer_key, peer_key_length, + private_key->data.ecp, + shared_secret, + sizeof( shared_secret ), + &shared_secret_length ); + break; +#endif /* MBEDTLS_ECDH_C */ default: return( PSA_ERROR_NOT_SUPPORTED ); } diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index d321e68ff..374d3035a 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -437,15 +437,15 @@ derive_key_policy:PSA_KEY_USAGE_DERIVE:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_TYP PSA key policy: agreement, permitted depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C -agreement_key_policy:PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3077020101042049c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eeea00a06082a8648ce3d030107a144034200047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45":PSA_ALG_ECDH(PSA_ALG_SELECT_RAW) +agreement_key_policy:PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_ALG_ECDH(PSA_ALG_SELECT_RAW) PSA key policy: agreement, not permitted depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C -agreement_key_policy:0:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3077020101042049c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eeea00a06082a8648ce3d030107a144034200047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45":PSA_ALG_ECDH(PSA_ALG_SELECT_RAW) +agreement_key_policy:0:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_ALG_ECDH(PSA_ALG_SELECT_RAW) PSA key policy: agreement, wrong algorithm depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C -agreement_key_policy:PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3077020101042049c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eeea00a06082a8648ce3d030107a144034200047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45":PSA_ALG_FFDH(PSA_ALG_SELECT_RAW) +agreement_key_policy:PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_ALG_FFDH(PSA_ALG_SELECT_RAW) PSA key lifetime: set and get volatile key_lifetime:PSA_KEY_LIFETIME_VOLATILE @@ -1109,6 +1109,10 @@ PSA import/exercise: ECP SECP256R1 keypair, deterministic ECDSA depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_C:MBEDTLS_ECDSA_DETERMINISTIC:MBEDTLS_SHA256_C import_and_exercise_key:"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):256:PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ) +PSA import/exercise: ECP SECP256R1 keypair, ECDH +depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C +import_and_exercise_key:"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):256:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW) + PSA sign: RSA PKCS#1 v1.5, raw depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15 sign_deterministic:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN_RAW:"616263":"2c7744983f023ac7bb1c55529d83ed11a76a7898a1bb5ce191375a4aa7495a633d27879ff58eba5a57371c34feb1180e8b850d552476ebb5634df620261992f12ebee9097041dbbea85a42d45b344be5073ceb772ffc604954b9158ba81ec3dc4d9d65e3ab7aa318165f38c36f841f1c69cb1cfa494aa5cbb4d6c0efbafb043a" @@ -1537,13 +1541,73 @@ PSA key derivation: HKDF SHA-256, derive key, 1+41 depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C derive_key_export:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":1:41 +PSA key agreement setup: ECDH, raw: good +depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C +key_agreement_setup:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"3059301306072a8648ce3d020106082a8648ce3d03010703420004d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":PSA_SUCCESS + +PSA key agreement setup: ECDH, raw: public key on different curve +depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C +key_agreement_setup:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"3076301006072a8648ce3d020106052b8104002203620004e558dbef53eecde3d3fccfc1aea08a89a987475d12fd950d83cfa41732bc509d0d1ac43a0336def96fda41d0774a3571dcfbec7aacf3196472169e838430367f66eebe3c6e70c416dd5f0c68759dd1fff83fa40142209dff5eaad96db9e6386c":PSA_ERROR_INVALID_ARGUMENT + +PSA key agreement setup: ECDH, raw: public key instead of private key +depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C +key_agreement_setup:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_CURVE_SECP256R1):"3059301306072a8648ce3d020106082a8648ce3d03010703420004d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":"3059301306072a8648ce3d020106082a8648ce3d03010703420004d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":PSA_ERROR_INVALID_ARGUMENT + PSA key agreement setup: ECDH, unknown KDF depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C -key_agreement_setup:PSA_ALG_ECDH(0):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3078020101042100c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433a00a06082a8648ce3d030107a14403420004dad0b65394221cf9b051e1feca5787d098dfe637fc90b9ef945d0c37725811805271a0461cdb8252d61f1c456fa3e59ab1f45b33accf5f58389e0577b8990bb3":"3059301306072a8648ce3d020106082a8648ce3d03010703420004d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":PSA_ERROR_NOT_SUPPORTED +key_agreement_setup:PSA_ALG_ECDH(0):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"3059301306072a8648ce3d020106082a8648ce3d03010703420004d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":PSA_ERROR_NOT_SUPPORTED PSA key agreement setup: not a key agreement algorithm depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C -key_agreement_setup:PSA_ALG_HKDF( PSA_ALG_SHA_256 ):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3078020101042100c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433a00a06082a8648ce3d030107a14403420004dad0b65394221cf9b051e1feca5787d098dfe637fc90b9ef945d0c37725811805271a0461cdb8252d61f1c456fa3e59ab1f45b33accf5f58389e0577b8990bb3":"3059301306072a8648ce3d020106082a8648ce3d03010703420004d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":PSA_ERROR_INVALID_ARGUMENT +key_agreement_setup:PSA_ALG_HKDF( PSA_ALG_SHA_256 ):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"3059301306072a8648ce3d020106082a8648ce3d03010703420004d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":PSA_ERROR_INVALID_ARGUMENT + +PSA key agreement: ECDH SECP256R1 (RFC 5903), raw: capacity=32 +depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C +key_agreement_capacity:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"3059301306072a8648ce3d020106082a8648ce3d03010703420004d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":32 + +PSA key agreement: ECDH SECP256R1 (RFC 5903), raw: read +depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C +key_agreement_output:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"3059301306072a8648ce3d020106082a8648ce3d03010703420004d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":"d6840f6b42f6edafd13116e0e12565202fef8e9ece7dce03812464d04b9442de" + +PSA key agreement: ECDH SECP384R1 (RFC 5903), raw: capacity=48 +depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_ECDH_C +key_agreement_capacity:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP384R1):"099f3c7034d4a2c699884d73a375a67f7624ef7c6b3c0f160647b67414dce655e35b538041e649ee3faef896783ab194":"3076301006072a8648ce3d020106052b8104002203620004e558dbef53eecde3d3fccfc1aea08a89a987475d12fd950d83cfa41732bc509d0d1ac43a0336def96fda41d0774a3571dcfbec7aacf3196472169e838430367f66eebe3c6e70c416dd5f0c68759dd1fff83fa40142209dff5eaad96db9e6386c":48 + +PSA key agreement: ECDH SECP384R1 (RFC 5903), raw: read +depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_ECDH_C +key_agreement_output:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP384R1):"099f3c7034d4a2c699884d73a375a67f7624ef7c6b3c0f160647b67414dce655e35b538041e649ee3faef896783ab194":"3076301006072a8648ce3d020106052b8104002203620004e558dbef53eecde3d3fccfc1aea08a89a987475d12fd950d83cfa41732bc509d0d1ac43a0336def96fda41d0774a3571dcfbec7aacf3196472169e838430367f66eebe3c6e70c416dd5f0c68759dd1fff83fa40142209dff5eaad96db9e6386c":"11187331c279962d93d604243fd592cb9d0a926f422e47187521287e7156c5c4d603135569b9e9d09cf5d4a270f59746" + +PSA key agreement: ECDH SECP521R1 (RFC 5903), raw: capacity=66 +depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP521R1_ENABLED:MBEDTLS_ECDH_C +key_agreement_capacity:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP521R1):"0037ade9319a89f4dabdb3ef411aaccca5123c61acab57b5393dce47608172a095aa85a30fe1c2952c6771d937ba9777f5957b2639bab072462f68c27a57382d4a52":"30819b301006072a8648ce3d020106052b81040023038186000400d0b3975ac4b799f5bea16d5e13e9af971d5e9b984c9f39728b5e5739735a219b97c356436adc6e95bb0352f6be64a6c2912d4ef2d0433ced2b6171640012d9460f015c68226383956e3bd066e797b623c27ce0eac2f551a10c2c724d9852077b87220b6536c5c408a1d2aebb8e86d678ae49cb57091f4732296579ab44fcd17f0fc56a":66 + +PSA key agreement: ECDH SECP521R1 (RFC 5903), raw: read +depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP521R1_ENABLED:MBEDTLS_ECDH_C +key_agreement_output:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP521R1):"0037ade9319a89f4dabdb3ef411aaccca5123c61acab57b5393dce47608172a095aa85a30fe1c2952c6771d937ba9777f5957b2639bab072462f68c27a57382d4a52":"30819b301006072a8648ce3d020106052b81040023038186000400d0b3975ac4b799f5bea16d5e13e9af971d5e9b984c9f39728b5e5739735a219b97c356436adc6e95bb0352f6be64a6c2912d4ef2d0433ced2b6171640012d9460f015c68226383956e3bd066e797b623c27ce0eac2f551a10c2c724d9852077b87220b6536c5c408a1d2aebb8e86d678ae49cb57091f4732296579ab44fcd17f0fc56a":"01144c7d79ae6956bc8edb8e7c787c4521cb086fa64407f97894e5e6b2d79b04d1427e73ca4baa240a34786859810c06b3c715a3a8cc3151f2bee417996d19f3ddea" + +PSA key agreement: ECDH brainpoolP256r1 (RFC 7027), raw: capacity=32 +depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_BP256R1_ENABLED:MBEDTLS_ECDH_C +key_agreement_capacity:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_BRAINPOOL_P256R1):"81db1ee100150ff2ea338d708271be38300cb54241d79950f77b063039804f1d":"305a301406072a8648ce3d020106092b2403030208010107034200048d2d688c6cf93e1160ad04cc4429117dc2c41825e1e9fca0addd34e6f1b39f7b990c57520812be512641e47034832106bc7d3e8dd0e4c7f1136d7006547cec6a":32 + +PSA key agreement: ECDH brainpoolP256r1 (RFC 7027), raw: read +depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_BP256R1_ENABLED:MBEDTLS_ECDH_C +key_agreement_output:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_BRAINPOOL_P256R1):"81db1ee100150ff2ea338d708271be38300cb54241d79950f77b063039804f1d":"305a301406072a8648ce3d020106092b2403030208010107034200048d2d688c6cf93e1160ad04cc4429117dc2c41825e1e9fca0addd34e6f1b39f7b990c57520812be512641e47034832106bc7d3e8dd0e4c7f1136d7006547cec6a":"89afc39d41d3b327814b80940b042590f96556ec91e6ae7939bce31f3a18bf2b" + +PSA key agreement: ECDH brainpoolP384r1 (RFC 7027), raw: capacity=48 +depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_BP384R1_ENABLED:MBEDTLS_ECDH_C +key_agreement_capacity:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_BRAINPOOL_P384R1):"1e20f5e048a5886f1f157c74e91bde2b98c8b52d58e5003d57053fc4b0bd65d6f15eb5d1ee1610df870795143627d042":"307a301406072a8648ce3d020106092b240303020801010b036200044d44326f269a597a5b58bba565da5556ed7fd9a8a9eb76c25f46db69d19dc8ce6ad18e404b15738b2086df37e71d1eb462d692136de56cbe93bf5fa3188ef58bc8a3a0ec6c1e151a21038a42e9185329b5b275903d192f8d4e1f32fe9cc78c48":48 + +PSA key agreement: ECDH brainpoolP384r1 (RFC 7027), raw: read +depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_BP384R1_ENABLED:MBEDTLS_ECDH_C +key_agreement_output:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_BRAINPOOL_P384R1):"1e20f5e048a5886f1f157c74e91bde2b98c8b52d58e5003d57053fc4b0bd65d6f15eb5d1ee1610df870795143627d042":"307a301406072a8648ce3d020106092b240303020801010b036200044d44326f269a597a5b58bba565da5556ed7fd9a8a9eb76c25f46db69d19dc8ce6ad18e404b15738b2086df37e71d1eb462d692136de56cbe93bf5fa3188ef58bc8a3a0ec6c1e151a21038a42e9185329b5b275903d192f8d4e1f32fe9cc78c48":"0bd9d3a7ea0b3d519d09d8e48d0785fb744a6b355e6304bc51c229fbbce239bbadf6403715c35d4fb2a5444f575d4f42" + +PSA key agreement: ECDH brainpoolP512r1 (RFC 7027), raw: capacity=64 +depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_BP512R1_ENABLED:MBEDTLS_ECDH_C +key_agreement_capacity:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_BRAINPOOL_P512R1):"16302ff0dbbb5a8d733dab7141c1b45acbc8715939677f6a56850a38bd87bd59b09e80279609ff333eb9d4c061231fb26f92eeb04982a5f1d1764cad57665422":"30819b301406072a8648ce3d020106092b240303020801010d03818200049d45f66de5d67e2e6db6e93a59ce0bb48106097ff78a081de781cdb31fce8ccbaaea8dd4320c4119f1e9cd437a2eab3731fa9668ab268d871deda55a5473199f2fdc313095bcdd5fb3a91636f07a959c8e86b5636a1e930e8396049cb481961d365cc11453a06c719835475b12cb52fc3c383bce35e27ef194512b71876285fa":64 + +PSA key agreement: ECDH brainpoolP512r1 (RFC 7027), raw: read +depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_BP512R1_ENABLED:MBEDTLS_ECDH_C +key_agreement_output:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_BRAINPOOL_P512R1):"16302ff0dbbb5a8d733dab7141c1b45acbc8715939677f6a56850a38bd87bd59b09e80279609ff333eb9d4c061231fb26f92eeb04982a5f1d1764cad57665422":"30819b301406072a8648ce3d020106092b240303020801010d03818200049d45f66de5d67e2e6db6e93a59ce0bb48106097ff78a081de781cdb31fce8ccbaaea8dd4320c4119f1e9cd437a2eab3731fa9668ab268d871deda55a5473199f2fdc313095bcdd5fb3a91636f07a959c8e86b5636a1e930e8396049cb481961d365cc11453a06c719835475b12cb52fc3c383bce35e27ef194512b71876285fa":"a7927098655f1f9976fa50a9d566865dc530331846381c87256baf3226244b76d36403c024d7bbf0aa0803eaff405d3d24f11a9b5c0bef679fe1454b21c4cd1f" PSA generate random: 0 bytes generate_random:0 From 1d7c082124547fcd2b2dc1203671bf99162bd69d Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 8 Oct 2018 19:05:22 +0200 Subject: [PATCH 10/26] Fix a memory leak in a test --- tests/suites/test_suite_psa_crypto.function | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index fc02453e3..5685a61cf 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -1684,6 +1684,7 @@ void derive_key_policy( int policy_usage, TEST_ASSERT( status == PSA_ERROR_NOT_PERMITTED ); exit: + mbedtls_free( public_key ); psa_generator_abort( &generator ); psa_destroy_key( key_slot ); mbedtls_psa_crypto_free( ); From 2607bca6664e38f130ea239a289deb1e75a7db38 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 25 Oct 2018 22:21:03 +0200 Subject: [PATCH 11/26] Give "DH" and "DHM" as alternative names Be consistent about calling it just "Diffie-Hellman", except once where I state that "Diffie-Hellman-Merkle" is an alternative name. --- include/psa/crypto.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 8fb641fdc..1ec9627eb 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -1222,8 +1222,9 @@ typedef uint32_t psa_algorithm_t; #define PSA_ALG_FFDH_BASE ((psa_algorithm_t)0x22100000) /** The Diffie-Hellman key agreement algorithm. * - * This algorithm combines the finite-field Diffie-Hellman-Merkle key - * agreement to produce a shared secret from a private key and the peer's + * This algorithm combines the finite-field Diffie-Hellman (DH) key + * agreement, also known as Diffie-Hellman-Merkle (DHM) key agreement, + * to produce a shared secret from a private key and the peer's * public key, with a key selection or key derivation algorithm to produce * one or more shared keys and other shared cryptographic material. * @@ -1252,7 +1253,7 @@ typedef uint32_t psa_algorithm_t; (PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) == PSA_ALG_FFDH_BASE) #define PSA_ALG_ECDH_BASE ((psa_algorithm_t)0x22200000) -/** The elliptic curve Diffie-Hellman key agreement algorithm. +/** The elliptic curve Diffie-Hellman (ECDH) key agreement algorithm. * * This algorithm combines the elliptic curve Diffie-Hellman key * agreement to produce a shared secret from a private key and the peer's From 79dd6229e4f767cf5a152fc4bea4514c8ec350dd Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 25 Oct 2018 22:22:11 +0200 Subject: [PATCH 12/26] Clarify the format of the (EC)DH shared secret --- include/psa/crypto.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 1ec9627eb..51d3716cd 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -1228,6 +1228,9 @@ typedef uint32_t psa_algorithm_t; * public key, with a key selection or key derivation algorithm to produce * one or more shared keys and other shared cryptographic material. * + * The input to \p kdf_alg is the shared secret `g^{ab}` in big-endian format. + * It is `ceiling(n / 8)` bytes long where `n` is the size of the prime `p`. + * * \param kdf_alg A key derivation algorithm (\c PSA_ALG_XXX value such * that #PSA_ALG_IS_KEY_DERIVATION(\p hash_alg) is true) * or a key selection algorithm (\c PSA_ALG_XXX value such @@ -1260,6 +1263,10 @@ typedef uint32_t psa_algorithm_t; * public key, with a key selection or key derivation algorithm to produce * one or more shared keys and other shared cryptographic material. * + * The input to \p kdf_alg is the shared secret `d_A Q_B = d_B Q_A` in + * big-endian format. It is `ceiling(n / 8)` bytes long where `n` is the + * curve size in bits. + * * \param kdf_alg A key derivation algorithm (\c PSA_ALG_XXX value such * that #PSA_ALG_IS_KEY_DERIVATION(\p hash_alg) is true) * or a selection algorithm (\c PSA_ALG_XXX value such From 211a436f2e78e9f94086e76809a7a987da5ca759 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 25 Oct 2018 22:22:31 +0200 Subject: [PATCH 13/26] Document that key agreement produces a maximum-capacity generator --- include/psa/crypto.h | 3 +++ library/psa_crypto.c | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 51d3716cd..cc233f26e 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -3206,6 +3206,9 @@ psa_status_t psa_key_derivation(psa_crypto_generator_t *generator, * The result of this function is a byte generator which can * be used to produce keys and other cryptographic material. * + * The resulting generator always has the maximum capacity permitted by + * the algorithm. + * * \param[in,out] generator The generator object to set up. It must * have been initialized to all-bits-zero, * a logical zero (`{0}`), diff --git a/library/psa_crypto.c b/library/psa_crypto.c index c18c8f022..bc306cbd1 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -3371,6 +3371,15 @@ psa_status_t psa_generator_read( psa_crypto_generator_t *generator, if( generator->alg == PSA_ALG_SELECT_RAW ) { + /* Initially, the capacity of a selection generator is always + * the size of the buffer, i.e. `generator->ctx.buffer.size`, + * abbreviated in this comment as `size`. When the remaining + * capacity is `c`, the next bytes to serve start `c` bytes + * from the end of the buffer, i.e. `size - c` from the + * beginning of the buffer. Since `generator->capacity` was just + * decremented above, we need to serve the bytes from + * `size - generator->capacity - output_length` to + * `size - generator->capacity`. */ size_t offset = generator->ctx.buffer.size - generator->capacity - output_length; memcpy( output, generator->ctx.buffer.data + offset, output_length ); From fc411f1ac13b949c8c7459e0a1fdf69f9add9f4e Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 25 Oct 2018 22:34:48 +0200 Subject: [PATCH 14/26] Use ASSERT_ALLOC in key agreement tests --- tests/suites/test_suite_psa_crypto.function | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index 5685a61cf..2245cfd34 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -11,6 +11,8 @@ #include "psa/crypto.h" +#define MAX( x, y ) ( ( x ) > ( y ) ? ( x ) : ( y ) ) + #define ARRAY_LENGTH( array ) ( sizeof( array ) / sizeof( *( array ) ) ) #if(UINT32_MAX > SIZE_MAX) @@ -415,7 +417,7 @@ static int exercise_key_agreement_key( psa_key_slot_t key, public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR( key_type ); public_key_length = PSA_KEY_EXPORT_MAX_SIZE( public_key_type, key_bits ); - public_key = mbedtls_calloc( 1, public_key_length ); + ASSERT_ALLOC( public_key, public_key_length ); TEST_ASSERT( public_key != NULL ); TEST_ASSERT( psa_export_public_key( key, @@ -1724,7 +1726,7 @@ void agreement_key_policy( int policy_usage, &key_bits ) == PSA_SUCCESS ); public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR( key_type ); public_key_length = PSA_KEY_EXPORT_MAX_SIZE( public_key_type, key_bits ); - public_key = mbedtls_calloc( 1, public_key_length ); + ASSERT_ALLOC( public_key, public_key_length ); TEST_ASSERT( public_key != NULL ); TEST_ASSERT( psa_export_public_key( key_slot, public_key, public_key_length, From 10df341436a04690baa6bfff9f7ca897e411be65 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 25 Oct 2018 22:35:43 +0200 Subject: [PATCH 15/26] Factor usage_to_exercise into its own function --- tests/suites/test_suite_psa_crypto.function | 41 ++++++++++++++------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index 2245cfd34..59020f763 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -802,6 +802,33 @@ static int exercise_key( psa_key_slot_t slot, return( ok ); } +static psa_key_usage_t usage_to_exercise( psa_key_type_t type, + psa_algorithm_t alg ) +{ + if( PSA_ALG_IS_MAC( alg ) || PSA_ALG_IS_SIGN( alg ) ) + { + return( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ? + PSA_KEY_USAGE_VERIFY : + PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY ); + } + else if( PSA_ALG_IS_CIPHER( alg ) || PSA_ALG_IS_AEAD( alg ) || + PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) ) + { + return( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ? + PSA_KEY_USAGE_ENCRYPT : + PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT ); + } + else if( PSA_ALG_IS_KEY_DERIVATION( alg ) || + PSA_ALG_IS_KEY_AGREEMENT( alg ) ) + { + return( PSA_KEY_USAGE_DERIVE ); + } + else + { + return( 0 ); + } + +} /* END_HEADER */ /* BEGIN_DEPENDENCIES @@ -1309,19 +1336,7 @@ void import_and_exercise_key( data_t *data, psa_key_type_t type = type_arg; size_t bits = bits_arg; psa_algorithm_t alg = alg_arg; - psa_key_usage_t usage = - ( PSA_ALG_IS_MAC( alg ) || PSA_ALG_IS_SIGN( alg ) ? - ( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ? - PSA_KEY_USAGE_VERIFY : - PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY ) : - PSA_ALG_IS_CIPHER( alg ) || PSA_ALG_IS_AEAD( alg ) || - PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) ? - ( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ? - PSA_KEY_USAGE_ENCRYPT : - PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT ) : - PSA_ALG_IS_KEY_DERIVATION( alg ) ? PSA_KEY_USAGE_DERIVE : - PSA_ALG_IS_KEY_AGREEMENT( alg ) ? PSA_KEY_USAGE_DERIVE : - 0 ); + psa_key_usage_t usage = usage_to_exercise( type, alg ); psa_key_policy_t policy; psa_key_type_t got_type; size_t got_bits; From bf49197c9bb1b8d5086d7ee9f39ccdd1ad74da18 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 25 Oct 2018 22:36:12 +0200 Subject: [PATCH 16/26] key_agreement_capacity: test the actual capacity as well After testing that the advertized capacity is what the test data says, read that many bytes to test that this is also actual capacity. --- tests/suites/test_suite_psa_crypto.function | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index 59020f763..a0f038107 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -3821,6 +3821,7 @@ void key_agreement_capacity( int alg_arg, psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT; psa_key_policy_t policy; size_t actual_capacity; + unsigned char output[16]; TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); @@ -3836,10 +3837,25 @@ void key_agreement_capacity( int alg_arg, peer_key_data->x, peer_key_data->len, alg ) == PSA_SUCCESS ); + /* Test the advertized capacity. */ TEST_ASSERT( psa_get_generator_capacity( &generator, &actual_capacity ) == PSA_SUCCESS ); TEST_ASSERT( actual_capacity == (size_t) expected_capacity_arg ); + /* Test the actual capacity by reading the output. */ + while( actual_capacity > sizeof( output ) ) + { + TEST_ASSERT( psa_generator_read( &generator, + output, sizeof( output ) ) == + PSA_SUCCESS ); + actual_capacity -= sizeof( output ); + } + TEST_ASSERT( psa_generator_read( &generator, + output, actual_capacity ) == + PSA_SUCCESS ); + TEST_ASSERT( psa_generator_read( &generator, output, 1 ) == + PSA_ERROR_INSUFFICIENT_CAPACITY ); + exit: psa_generator_abort( &generator ); psa_destroy_key( our_key ); From 3ec8ed8b512fcd573100859cbe519ec411cbb7d5 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 25 Oct 2018 22:37:15 +0200 Subject: [PATCH 17/26] Add multipart key agreement tests Add test cases that do key agreement with raw selection in pieces, to validate that selection works even when the application doesn't read everything in one chunk. --- tests/suites/test_suite_psa_crypto.data | 26 ++++++++++++++------ tests/suites/test_suite_psa_crypto.function | 27 +++++++++++++++------ 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index 374d3035a..6b1c38eee 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -1565,9 +1565,21 @@ PSA key agreement: ECDH SECP256R1 (RFC 5903), raw: capacity=32 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C key_agreement_capacity:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"3059301306072a8648ce3d020106082a8648ce3d03010703420004d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":32 -PSA key agreement: ECDH SECP256R1 (RFC 5903), raw: read +PSA key agreement: ECDH SECP256R1 (RFC 5903), raw: read 32 (full) depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C -key_agreement_output:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"3059301306072a8648ce3d020106082a8648ce3d03010703420004d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":"d6840f6b42f6edafd13116e0e12565202fef8e9ece7dce03812464d04b9442de" +key_agreement_output:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"3059301306072a8648ce3d020106082a8648ce3d03010703420004d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":"d6840f6b42f6edafd13116e0e12565202fef8e9ece7dce03812464d04b9442de":"" + +PSA key agreement: ECDH SECP256R1 (RFC 5903), raw: read 0+32 +depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C +key_agreement_output:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"3059301306072a8648ce3d020106082a8648ce3d03010703420004d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":"":"d6840f6b42f6edafd13116e0e12565202fef8e9ece7dce03812464d04b9442de" + +PSA key agreement: ECDH SECP256R1 (RFC 5903), raw: read 20+12 +depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C +key_agreement_output:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"3059301306072a8648ce3d020106082a8648ce3d03010703420004d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":"d6840f6b42f6edafd13116e0e12565202fef8e9e":"ce7dce03812464d04b9442de" + +PSA key agreement: ECDH SECP256R1 (RFC 5903), raw: read 7+15 +depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C +key_agreement_output:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"3059301306072a8648ce3d020106082a8648ce3d03010703420004d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":"d6840f6b42f6ed":"afd13116e0e12565202fef8e9ece7d" PSA key agreement: ECDH SECP384R1 (RFC 5903), raw: capacity=48 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_ECDH_C @@ -1575,7 +1587,7 @@ key_agreement_capacity:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR PSA key agreement: ECDH SECP384R1 (RFC 5903), raw: read depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_ECDH_C -key_agreement_output:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP384R1):"099f3c7034d4a2c699884d73a375a67f7624ef7c6b3c0f160647b67414dce655e35b538041e649ee3faef896783ab194":"3076301006072a8648ce3d020106052b8104002203620004e558dbef53eecde3d3fccfc1aea08a89a987475d12fd950d83cfa41732bc509d0d1ac43a0336def96fda41d0774a3571dcfbec7aacf3196472169e838430367f66eebe3c6e70c416dd5f0c68759dd1fff83fa40142209dff5eaad96db9e6386c":"11187331c279962d93d604243fd592cb9d0a926f422e47187521287e7156c5c4d603135569b9e9d09cf5d4a270f59746" +key_agreement_output:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP384R1):"099f3c7034d4a2c699884d73a375a67f7624ef7c6b3c0f160647b67414dce655e35b538041e649ee3faef896783ab194":"3076301006072a8648ce3d020106052b8104002203620004e558dbef53eecde3d3fccfc1aea08a89a987475d12fd950d83cfa41732bc509d0d1ac43a0336def96fda41d0774a3571dcfbec7aacf3196472169e838430367f66eebe3c6e70c416dd5f0c68759dd1fff83fa40142209dff5eaad96db9e6386c":"11187331c279962d93d604243fd592cb9d0a926f422e47187521287e7156c5c4d603135569b9e9d09cf5d4a270f59746":"" PSA key agreement: ECDH SECP521R1 (RFC 5903), raw: capacity=66 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP521R1_ENABLED:MBEDTLS_ECDH_C @@ -1583,7 +1595,7 @@ key_agreement_capacity:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR PSA key agreement: ECDH SECP521R1 (RFC 5903), raw: read depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP521R1_ENABLED:MBEDTLS_ECDH_C -key_agreement_output:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP521R1):"0037ade9319a89f4dabdb3ef411aaccca5123c61acab57b5393dce47608172a095aa85a30fe1c2952c6771d937ba9777f5957b2639bab072462f68c27a57382d4a52":"30819b301006072a8648ce3d020106052b81040023038186000400d0b3975ac4b799f5bea16d5e13e9af971d5e9b984c9f39728b5e5739735a219b97c356436adc6e95bb0352f6be64a6c2912d4ef2d0433ced2b6171640012d9460f015c68226383956e3bd066e797b623c27ce0eac2f551a10c2c724d9852077b87220b6536c5c408a1d2aebb8e86d678ae49cb57091f4732296579ab44fcd17f0fc56a":"01144c7d79ae6956bc8edb8e7c787c4521cb086fa64407f97894e5e6b2d79b04d1427e73ca4baa240a34786859810c06b3c715a3a8cc3151f2bee417996d19f3ddea" +key_agreement_output:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP521R1):"0037ade9319a89f4dabdb3ef411aaccca5123c61acab57b5393dce47608172a095aa85a30fe1c2952c6771d937ba9777f5957b2639bab072462f68c27a57382d4a52":"30819b301006072a8648ce3d020106052b81040023038186000400d0b3975ac4b799f5bea16d5e13e9af971d5e9b984c9f39728b5e5739735a219b97c356436adc6e95bb0352f6be64a6c2912d4ef2d0433ced2b6171640012d9460f015c68226383956e3bd066e797b623c27ce0eac2f551a10c2c724d9852077b87220b6536c5c408a1d2aebb8e86d678ae49cb57091f4732296579ab44fcd17f0fc56a":"01144c7d79ae6956bc8edb8e7c787c4521cb086fa64407f97894e5e6b2d79b04d1427e73ca4baa240a34786859810c06b3c715a3a8cc3151f2bee417996d19f3ddea":"" PSA key agreement: ECDH brainpoolP256r1 (RFC 7027), raw: capacity=32 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_BP256R1_ENABLED:MBEDTLS_ECDH_C @@ -1591,7 +1603,7 @@ key_agreement_capacity:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR PSA key agreement: ECDH brainpoolP256r1 (RFC 7027), raw: read depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_BP256R1_ENABLED:MBEDTLS_ECDH_C -key_agreement_output:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_BRAINPOOL_P256R1):"81db1ee100150ff2ea338d708271be38300cb54241d79950f77b063039804f1d":"305a301406072a8648ce3d020106092b2403030208010107034200048d2d688c6cf93e1160ad04cc4429117dc2c41825e1e9fca0addd34e6f1b39f7b990c57520812be512641e47034832106bc7d3e8dd0e4c7f1136d7006547cec6a":"89afc39d41d3b327814b80940b042590f96556ec91e6ae7939bce31f3a18bf2b" +key_agreement_output:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_BRAINPOOL_P256R1):"81db1ee100150ff2ea338d708271be38300cb54241d79950f77b063039804f1d":"305a301406072a8648ce3d020106092b2403030208010107034200048d2d688c6cf93e1160ad04cc4429117dc2c41825e1e9fca0addd34e6f1b39f7b990c57520812be512641e47034832106bc7d3e8dd0e4c7f1136d7006547cec6a":"89afc39d41d3b327814b80940b042590f96556ec91e6ae7939bce31f3a18bf2b":"" PSA key agreement: ECDH brainpoolP384r1 (RFC 7027), raw: capacity=48 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_BP384R1_ENABLED:MBEDTLS_ECDH_C @@ -1599,7 +1611,7 @@ key_agreement_capacity:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR PSA key agreement: ECDH brainpoolP384r1 (RFC 7027), raw: read depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_BP384R1_ENABLED:MBEDTLS_ECDH_C -key_agreement_output:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_BRAINPOOL_P384R1):"1e20f5e048a5886f1f157c74e91bde2b98c8b52d58e5003d57053fc4b0bd65d6f15eb5d1ee1610df870795143627d042":"307a301406072a8648ce3d020106092b240303020801010b036200044d44326f269a597a5b58bba565da5556ed7fd9a8a9eb76c25f46db69d19dc8ce6ad18e404b15738b2086df37e71d1eb462d692136de56cbe93bf5fa3188ef58bc8a3a0ec6c1e151a21038a42e9185329b5b275903d192f8d4e1f32fe9cc78c48":"0bd9d3a7ea0b3d519d09d8e48d0785fb744a6b355e6304bc51c229fbbce239bbadf6403715c35d4fb2a5444f575d4f42" +key_agreement_output:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_BRAINPOOL_P384R1):"1e20f5e048a5886f1f157c74e91bde2b98c8b52d58e5003d57053fc4b0bd65d6f15eb5d1ee1610df870795143627d042":"307a301406072a8648ce3d020106092b240303020801010b036200044d44326f269a597a5b58bba565da5556ed7fd9a8a9eb76c25f46db69d19dc8ce6ad18e404b15738b2086df37e71d1eb462d692136de56cbe93bf5fa3188ef58bc8a3a0ec6c1e151a21038a42e9185329b5b275903d192f8d4e1f32fe9cc78c48":"0bd9d3a7ea0b3d519d09d8e48d0785fb744a6b355e6304bc51c229fbbce239bbadf6403715c35d4fb2a5444f575d4f42":"" PSA key agreement: ECDH brainpoolP512r1 (RFC 7027), raw: capacity=64 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_BP512R1_ENABLED:MBEDTLS_ECDH_C @@ -1607,7 +1619,7 @@ key_agreement_capacity:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR PSA key agreement: ECDH brainpoolP512r1 (RFC 7027), raw: read depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_BP512R1_ENABLED:MBEDTLS_ECDH_C -key_agreement_output:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_BRAINPOOL_P512R1):"16302ff0dbbb5a8d733dab7141c1b45acbc8715939677f6a56850a38bd87bd59b09e80279609ff333eb9d4c061231fb26f92eeb04982a5f1d1764cad57665422":"30819b301406072a8648ce3d020106092b240303020801010d03818200049d45f66de5d67e2e6db6e93a59ce0bb48106097ff78a081de781cdb31fce8ccbaaea8dd4320c4119f1e9cd437a2eab3731fa9668ab268d871deda55a5473199f2fdc313095bcdd5fb3a91636f07a959c8e86b5636a1e930e8396049cb481961d365cc11453a06c719835475b12cb52fc3c383bce35e27ef194512b71876285fa":"a7927098655f1f9976fa50a9d566865dc530331846381c87256baf3226244b76d36403c024d7bbf0aa0803eaff405d3d24f11a9b5c0bef679fe1454b21c4cd1f" +key_agreement_output:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_BRAINPOOL_P512R1):"16302ff0dbbb5a8d733dab7141c1b45acbc8715939677f6a56850a38bd87bd59b09e80279609ff333eb9d4c061231fb26f92eeb04982a5f1d1764cad57665422":"30819b301406072a8648ce3d020106092b240303020801010d03818200049d45f66de5d67e2e6db6e93a59ce0bb48106097ff78a081de781cdb31fce8ccbaaea8dd4320c4119f1e9cd437a2eab3731fa9668ab268d871deda55a5473199f2fdc313095bcdd5fb3a91636f07a959c8e86b5636a1e930e8396049cb481961d365cc11453a06c719835475b12cb52fc3c383bce35e27ef194512b71876285fa":"a7927098655f1f9976fa50a9d566865dc530331846381c87256baf3226244b76d36403c024d7bbf0aa0803eaff405d3d24f11a9b5c0bef679fe1454b21c4cd1f":"" PSA generate random: 0 bytes generate_random:0 diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index a0f038107..bcd07c15f 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -3867,16 +3867,17 @@ exit: void key_agreement_output( int alg_arg, int our_key_type_arg, data_t *our_key_data, data_t *peer_key_data, - data_t *expected_output ) + data_t *expected_output1, data_t *expected_output2 ) { psa_key_slot_t our_key = 1; psa_algorithm_t alg = alg_arg; psa_key_type_t our_key_type = our_key_type_arg; psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT; psa_key_policy_t policy; - uint8_t *actual_output = mbedtls_calloc( 1, expected_output->len ); + uint8_t *actual_output = NULL; - TEST_ASSERT( actual_output != NULL ); + ASSERT_ALLOC( actual_output, MAX( expected_output1->len, + expected_output2->len ) ); TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); @@ -3892,11 +3893,21 @@ void key_agreement_output( int alg_arg, peer_key_data->x, peer_key_data->len, alg ) == PSA_SUCCESS ); - TEST_ASSERT( psa_generator_read( &generator, - actual_output, - expected_output->len ) == PSA_SUCCESS ); - TEST_ASSERT( memcmp( actual_output, expected_output->x, - expected_output->len ) == 0 ); + TEST_ASSERT( + psa_generator_read( &generator, + actual_output, + expected_output1->len ) == PSA_SUCCESS ); + TEST_ASSERT( memcmp( actual_output, expected_output1->x, + expected_output1->len ) == 0 ); + if( expected_output2->len != 0 ) + { + TEST_ASSERT( + psa_generator_read( &generator, + actual_output, + expected_output2->len ) == PSA_SUCCESS ); + TEST_ASSERT( memcmp( actual_output, expected_output2->x, + expected_output2->len ) == 0 ); + } exit: psa_generator_abort( &generator ); From 714e16b37a576f57771ea48c6b00e24f45347c85 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 25 Oct 2018 22:49:49 +0200 Subject: [PATCH 18/26] Add import/export test of EC public key --- tests/suites/test_suite_psa_crypto.data | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index 6b1c38eee..e8d836168 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -190,7 +190,7 @@ PSA import RSA keypair: 1023-bit (not supported) depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C import:"3082025a0201000281806c49704e91f3df44fc99e9b3c0fee5025cc04d09529a1dd05754f2da2751d7a9aa5a79f7070132f2c47b31963e37cd74675f9c93ee7c85a143fefe303e94d1ee0e4d30898d17ab3a229e8457ef21fd179039f748305babe7f134f6d58ce5d721a1a5da98f63503d2466c6a515e53494a41180a91e535bd5b55d4dce2c17419870203010001028180491b277413fb35efe82dace68b544a9dd6aa8917d329731955ec66ec3b0178fcf5a29196e1a6c093bf6c8064b36a8f0d9840a78003d11392754a70a77788975515a1442a6c806cafa2f07fe99cac78a86fa868888d654cec4baf205352cf8255acaa47e2455f23b58c0e5ae43fa297bbffe5b970caa80f71e82084fd35425479024100ef27f3fb2df90ac4910ed95fdde4877d09b0dc4e95079f12a7e2041300a8884a39372a1c79691338cd5c3965bcf3a24f2ce9e10de19d4cb87c7546d60ca0aa0d024073e9e1283475e9ab3075da0b005ca7c7b05e76325f8deb648238831c8353041d594307f784cd527cfee9187b997713d71c0ff98f01beac4d1a85583be52e90e302402f0c801e311c2677274671933f96fee4a56c6adaf6ccaa09c4875d5fd3a8542fadf3e14ffabea62e6d90302688b6b17ebc0a42e1353a79e66d6db102d9371e5d02406731ef3c8607fbf266806590a9cfd3a79a435ee355e2d9906fc6b4236c5f3a288ed178844a7d295512f49ed15b3d82325e4f729478af3262aa9bd083f273d49502410090a32c0e8ca3bcd4c66f092cdc369cd1abb4a05b9a6f0e65e5a51da1d96d5aca8c1525b3f11322c0588062fc8592ebf25b7950f918d39018e82b8acccc8f7e7a":PSA_KEY_TYPE_RSA_KEYPAIR:PSA_ERROR_NOT_SUPPORTED -PSA import/export EC secp224r1: good +PSA import/export EC secp224r1 key pair: good depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP224R1_ENABLED import_export:"6849f97d1066f6997759637c7e3899464cee3ec7ac970653a0be0742":PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP224R1):PSA_ALG_ECDSA_ANY:PSA_KEY_USAGE_EXPORT:224:0:PSA_SUCCESS:1 @@ -198,7 +198,7 @@ PSA import/export-public EC secp224r1: good depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP224R1_ENABLED import_export_public_key:"6849f97d1066f6997759637c7e3899464cee3ec7ac970653a0be0742":PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP224R1):PSA_ALG_ECDSA_ANY:0:PSA_SUCCESS:"304e301006072a8648ce3d020106052b81040021033a00041693a290f7f0b571fe2b41d5d84b01327631f4a860f995fa332c097f54192bb10f00113f2affb13c1a24ce44914571a95440ae014a00cbf7" -PSA import/export EC secp256r1: good +PSA import/export EC secp256r1 key pair: good depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED import_export:"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):PSA_ALG_ECDSA_ANY:PSA_KEY_USAGE_EXPORT:256:0:PSA_SUCCESS:1 @@ -206,7 +206,7 @@ PSA import/export-public EC secp256r1: good depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED import_export_public_key:"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):PSA_ALG_ECDSA_ANY:0:PSA_SUCCESS:"3059301306072a8648ce3d020106082a8648ce3d030107034200047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45" -PSA import/export EC secp384r1: good +PSA import/export EC secp384r1 key pair: good depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED import_export:"3f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76a":PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP384R1):PSA_ALG_ECDSA_ANY:PSA_KEY_USAGE_EXPORT:384:0:PSA_SUCCESS:1 @@ -214,7 +214,7 @@ PSA import/export-public EC secp384r1: good depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED import_export_public_key:"3f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76a":PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP384R1):PSA_ALG_ECDSA_ANY:0:PSA_SUCCESS:"3076301006072a8648ce3d020106052b8104002203620004d9c662b50ba29ca47990450e043aeaf4f0c69b15676d112f622a71c93059af999691c5680d2b44d111579db12f4a413a2ed5c45fcfb67b5b63e00b91ebe59d09a6b1ac2c0c4282aa12317ed5914f999bc488bb132e8342cc36f2ca5e3379c747" -PSA import/export EC secp521r1: good +PSA import/export EC secp521r1 key pair: good depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP521R1_ENABLED import_export:"01b1b6ad07bb79e7320da59860ea28e055284f6058f279de666e06d435d2af7bda28d99fa47b7dd0963e16b0073078ee8b8a38d966a582f46d19ff95df3ad9685aae":PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP521R1):PSA_ALG_ECDSA_ANY:PSA_KEY_USAGE_EXPORT:521:0:PSA_SUCCESS:1 @@ -222,7 +222,7 @@ PSA import/export-public EC secp521r1: good depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP521R1_ENABLED import_export_public_key:"01b1b6ad07bb79e7320da59860ea28e055284f6058f279de666e06d435d2af7bda28d99fa47b7dd0963e16b0073078ee8b8a38d966a582f46d19ff95df3ad9685aae":PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP521R1):PSA_ALG_ECDSA_ANY:0:PSA_SUCCESS:"30819b301006072a8648ce3d020106052b810400230381860004001de142d54f69eb038ee4b7af9d3ca07736fd9cf719eb354d69879ee7f3c136fb0fbf9f08f86be5fa128ec1a051d3e6c643e85ada8ffacf3663c260bd2c844b6f5600cee8e48a9e65d09cadd89f235dee05f3b8a646be715f1f67d5b434e0ff23a1fc07ef7740193e40eeff6f3bcdfd765aa9155033524fe4f205f5444e292c4c2f6ac1" -PSA import/export EC brainpool256r1: good +PSA import/export EC brainpool256r1 key pair: good depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_BP256R1_ENABLED import_export:"2161d6f2db76526fa62c16f356a80f01f32f776784b36aa99799a8b7662080ff":PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_BRAINPOOL_P256R1):PSA_ALG_ECDSA_ANY:PSA_KEY_USAGE_EXPORT:256:0:PSA_SUCCESS:1 @@ -230,7 +230,7 @@ PSA import/export-public EC brainpool256r1: good depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_BP256R1_ENABLED import_export_public_key:"2161d6f2db76526fa62c16f356a80f01f32f776784b36aa99799a8b7662080ff":PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_BRAINPOOL_P256R1):PSA_ALG_ECDSA_ANY:0:PSA_SUCCESS:"305a301406072a8648ce3d020106092b240303020801010703420004768c8cae4abca6306db0ed81b0c4a6215c378066ec6d616c146e13f1c7df809b96ab6911c27d8a02339f0926840e55236d3d1efbe2669d090e4c4c660fada91d" -PSA import/export EC brainpool384r1: good +PSA import/export EC brainpool384r1 key pair: good depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_BP384R1_ENABLED import_export:"3dd92e750d90d7d39fc1885cd8ad12ea9441f22b9334b4d965202adb1448ce24c5808a85dd9afc229af0a3124f755bcb":PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_BRAINPOOL_P384R1):PSA_ALG_ECDSA_ANY:PSA_KEY_USAGE_EXPORT:384:0:PSA_SUCCESS:1 @@ -238,7 +238,7 @@ PSA import/export-public EC brainpool384r1: good depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_BP384R1_ENABLED import_export_public_key:"3dd92e750d90d7d39fc1885cd8ad12ea9441f22b9334b4d965202adb1448ce24c5808a85dd9afc229af0a3124f755bcb":PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_BRAINPOOL_P384R1):PSA_ALG_ECDSA_ANY:0:PSA_SUCCESS:"307a301406072a8648ce3d020106092b240303020801010b03620004719f9d093a627e0d350385c661cebf00c61923566fe9006a3107af1d871bc6bb68985fd722ea32be316f8e783b7cd1957785f66cfc0cb195dd5c99a8e7abaa848553a584dfd2b48e76d445fe00dd8be59096d877d4696d23b4bc8db14724e66a" -PSA import/export EC brainpool512r1: good +PSA import/export EC brainpool512r1 key pair: good depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_BP512R1_ENABLED import_export:"372c9778f69f726cbca3f4a268f16b4d617d10280d79a6a029cd51879fe1012934dfe5395455337df6906dc7d6d2eea4dbb2065c0228f73b3ed716480e7d71d2":PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_BRAINPOOL_P512R1):PSA_ALG_ECDSA_ANY:PSA_KEY_USAGE_EXPORT:512:0:PSA_SUCCESS:1 @@ -250,6 +250,10 @@ PSA import/export-public: cannot export-public a symmetric key depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C import_export_public_key:"2b7e151628aed2a6abf7158809cf4f3c":PSA_KEY_TYPE_AES:PSA_ALG_CBC_NO_PADDING:0:PSA_ERROR_INVALID_ARGUMENT:"" +PSA import/export EC secp256r1 public key: good +depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED +import_export:"3059301306072a8648ce3d020106082a8648ce3d03010703420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_CURVE_SECP256R1):PSA_ALG_ECDSA_ANY:PSA_KEY_USAGE_EXPORT:256:0:PSA_SUCCESS:1 + PSA import/export AES key: policy forbids export depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR import_export:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_TYPE_AES:PSA_ALG_CTR:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:128:0:PSA_ERROR_NOT_PERMITTED:1 From 88714d78b8bd107c7d3787895e4a012605cc134d Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 25 Oct 2018 23:07:25 +0200 Subject: [PATCH 19/26] Allow ECDH-only public key in ECDH In ECDH key agreement, allow a public key with the OID id-ECDH, not just a public key with the OID id-ecPublicKey. Public keys with the OID id-ECDH are not permitted by psa_import_key, at least for now. There would be no way to use the key for a key agreement operation anyway in the current API. --- library/psa_crypto.c | 10 +++++++--- tests/suites/test_suite_psa_crypto.data | 11 +++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index bc306cbd1..5fe969c3c 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -3620,10 +3620,14 @@ static psa_status_t psa_key_agreement_ecdh( const uint8_t *peer_key, ret = mbedtls_pk_parse_public_key( &pk, peer_key, peer_key_length ); if( ret != 0 ) goto exit; - if( mbedtls_pk_get_type( &pk ) != MBEDTLS_PK_ECKEY ) + switch( mbedtls_pk_get_type( &pk ) ) { - ret = MBEDTLS_ERR_ECP_INVALID_KEY; - goto exit; + case MBEDTLS_PK_ECKEY: + case MBEDTLS_PK_ECKEY_DH: + break; + default: + ret = MBEDTLS_ERR_ECP_INVALID_KEY; + goto exit; } their_key = mbedtls_pk_ec( pk ); ret = mbedtls_ecdh_get_params( &ecdh, their_key, MBEDTLS_ECDH_THEIRS ); diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index e8d836168..5b8166428 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -312,6 +312,13 @@ depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED # it's looking for an OID where there is no OID. import:"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_CURVE_SECP256R1):PSA_ERROR_NOT_SUPPORTED +# A key with the OID id-ECDH is only valid for ECDH, not for ECDSA. +# Such keys are currently not allowed by psa_import_key, only by +# psa_key_agreement. +PSA import EC public key: ECDH-only +depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED +import:"3057301106052b8104010c06082a8648ce3d03010703420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_CURVE_SECP256R1):PSA_ERROR_INVALID_ARGUMENT + PSA import EC keypair: valid key but RSA depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_BP512R1_ENABLED:MBEDTLS_RSA_C import:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_BRAINPOOL_P512R1):PSA_ERROR_INVALID_ARGUMENT @@ -1573,6 +1580,10 @@ PSA key agreement: ECDH SECP256R1 (RFC 5903), raw: read 32 (full) depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C key_agreement_output:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"3059301306072a8648ce3d020106082a8648ce3d03010703420004d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":"d6840f6b42f6edafd13116e0e12565202fef8e9ece7dce03812464d04b9442de":"" +PSA key agreement: ECDH SECP256R1 with ECDH-only public key +depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C +key_agreement_output:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"3057301106052b8104010c06082a8648ce3d03010703420004d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":"d6840f6b42f6edafd13116e0e12565202fef8e9ece7dce03812464d04b9442de":"" + PSA key agreement: ECDH SECP256R1 (RFC 5903), raw: read 0+32 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C key_agreement_output:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"3059301306072a8648ce3d020106082a8648ce3d03010703420004d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":"":"d6840f6b42f6edafd13116e0e12565202fef8e9ece7dce03812464d04b9442de" From f5f442a50c3e19f738618d20a5288e1838760458 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 7 Nov 2018 18:20:48 +0100 Subject: [PATCH 20/26] More accurate description of the shared secret for ECDH Don't refer to the "curve size", call it the "size of the order of the curve". --- include/psa/crypto.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index cc233f26e..412fe5a75 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -1263,9 +1263,10 @@ typedef uint32_t psa_algorithm_t; * public key, with a key selection or key derivation algorithm to produce * one or more shared keys and other shared cryptographic material. * - * The input to \p kdf_alg is the shared secret `d_A Q_B = d_B Q_A` in - * big-endian format. It is `ceiling(n / 8)` bytes long where `n` is the - * curve size in bits. + * The input to \p kdf_alg is the x-coordinate of the shared secret + * `d_A Q_B = d_B Q_A` in big-endian format. It has the same size of + * the order of the curve, i.e. `ceiling(n / 8)` bytes where `n` is + * the size of the order of the curve. * * \param kdf_alg A key derivation algorithm (\c PSA_ALG_XXX value such * that #PSA_ALG_IS_KEY_DERIVATION(\p hash_alg) is true) From c7998b78b8f4c6f58ad5a0216d321063d59f17a9 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 7 Nov 2018 18:45:02 +0100 Subject: [PATCH 21/26] Factor common code into key_agreement_with_self --- tests/suites/test_suite_psa_crypto.function | 80 ++++++++++----------- 1 file changed, 38 insertions(+), 42 deletions(-) diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index bcd07c15f..674a6e9fe 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -394,16 +394,46 @@ exit: return( 0 ); } +/* We need two keys to exercise key agreement. Exercise the + * private key against its own public key. */ +static psa_status_t key_agreement_with_self( psa_crypto_generator_t *generator, + psa_key_type_t key_slot, + psa_algorithm_t alg ) +{ + psa_key_type_t private_key_type; + psa_key_type_t public_key_type; + size_t key_bits; + uint8_t *public_key = NULL; + size_t public_key_length; + /* Return UNKNOWN_ERROR if something other than the final call to + * psa_key_agreement fails. This isn't fully satisfactory, but it's + * good enough: callers will report it as a failed test anyway. */ + psa_status_t status = PSA_ERROR_UNKNOWN_ERROR; + + TEST_ASSERT( psa_get_key_information( key_slot, + &private_key_type, + &key_bits ) == PSA_SUCCESS ); + public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR( private_key_type ); + public_key_length = PSA_KEY_EXPORT_MAX_SIZE( public_key_type, key_bits ); + ASSERT_ALLOC( public_key, public_key_length ); + TEST_ASSERT( public_key != NULL ); + TEST_ASSERT( psa_export_public_key( key_slot, + public_key, public_key_length, + &public_key_length ) == PSA_SUCCESS ); + + status = psa_key_agreement( generator, key_slot, + public_key, public_key_length, + alg ); +exit: + mbedtls_free( public_key ); + return( status ); +} + static int exercise_key_agreement_key( psa_key_slot_t key, psa_key_usage_t usage, psa_algorithm_t alg ) { psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT; - psa_key_type_t key_type; - psa_key_type_t public_key_type; - size_t key_bits; - uint8_t *public_key = NULL; - size_t public_key_length; unsigned char output[1]; int ok = 0; @@ -411,22 +441,8 @@ static int exercise_key_agreement_key( psa_key_slot_t key, { /* We need two keys to exercise key agreement. Exercise the * private key against its own public key. */ - TEST_ASSERT( psa_get_key_information( key, - &key_type, - &key_bits ) == PSA_SUCCESS ); - public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR( key_type ); - public_key_length = PSA_KEY_EXPORT_MAX_SIZE( public_key_type, - key_bits ); - ASSERT_ALLOC( public_key, public_key_length ); - TEST_ASSERT( public_key != NULL ); - TEST_ASSERT( - psa_export_public_key( key, - public_key, public_key_length, - &public_key_length ) == PSA_SUCCESS ); - TEST_ASSERT( psa_key_agreement( &generator, - key, - public_key, public_key_length, - alg ) == PSA_SUCCESS ); + TEST_ASSERT( key_agreement_with_self( &generator, key, alg ) == + PSA_SUCCESS ); TEST_ASSERT( psa_generator_read( &generator, output, sizeof( output ) ) == PSA_SUCCESS ); @@ -435,7 +451,6 @@ static int exercise_key_agreement_key( psa_key_slot_t key, ok = 1; exit: - mbedtls_free( public_key ); return( ok ); } @@ -1701,7 +1716,6 @@ void derive_key_policy( int policy_usage, TEST_ASSERT( status == PSA_ERROR_NOT_PERMITTED ); exit: - mbedtls_free( public_key ); psa_generator_abort( &generator ); psa_destroy_key( key_slot ); mbedtls_psa_crypto_free( ); @@ -1718,10 +1732,6 @@ void agreement_key_policy( int policy_usage, int key_slot = 1; psa_key_policy_t policy; psa_key_type_t key_type = key_type_arg; - psa_key_type_t public_key_type; - size_t key_bits; - uint8_t *public_key = NULL; - size_t public_key_length; psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT; psa_status_t status; @@ -1734,22 +1744,8 @@ void agreement_key_policy( int policy_usage, TEST_ASSERT( psa_import_key( key_slot, key_type, key_data->x, key_data->len ) == PSA_SUCCESS ); - /* We need two keys to exercise key agreement. Exercise the - * private key against its own public key. */ - TEST_ASSERT( psa_get_key_information( key_slot, - &key_type, - &key_bits ) == PSA_SUCCESS ); - public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR( key_type ); - public_key_length = PSA_KEY_EXPORT_MAX_SIZE( public_key_type, key_bits ); - ASSERT_ALLOC( public_key, public_key_length ); - TEST_ASSERT( public_key != NULL ); - TEST_ASSERT( psa_export_public_key( key_slot, - public_key, public_key_length, - &public_key_length ) == PSA_SUCCESS ); + status = key_agreement_with_self( &generator, key_slot, exercise_alg ); - status = psa_key_agreement( &generator, key_slot, - public_key, public_key_length, - exercise_alg ); if( policy_alg == exercise_alg && ( policy_usage & PSA_KEY_USAGE_DERIVE ) != 0 ) TEST_ASSERT( status == PSA_SUCCESS ); From b408661be987451e71fc94be5d6e23a111dfd002 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 14 Nov 2018 20:51:23 +0100 Subject: [PATCH 22/26] ECDH: check that the keys are on the same curve In psa_key_agreement_ecdh, check that the public key is on the same curve as the private key. The underlying mbedtls API doesn't check. If the curves don't match, psa_key_agreement_ecdh is practically guaranteed to return INVALID_ARGUMENT anyway, because way the code is written, the public point is interpreted on the curve of the private point, and it is rejected because the point is not on the curve. This is why the test case "PSA key agreement setup: ECDH, raw: public key on different curve" passed even before adding this check. --- library/psa_crypto.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 5fe969c3c..763074c9b 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -3630,6 +3630,12 @@ static psa_status_t psa_key_agreement_ecdh( const uint8_t *peer_key, goto exit; } their_key = mbedtls_pk_ec( pk ); + if( their_key->grp.id != our_key->grp.id ) + { + ret = MBEDTLS_ERR_ECP_INVALID_KEY; + goto exit; + } + ret = mbedtls_ecdh_get_params( &ecdh, their_key, MBEDTLS_ECDH_THEIRS ); if( ret != 0 ) goto exit; From 7b5b4a01a4b3cdb269a5b0535313203b2458b85f Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 14 Nov 2018 21:05:10 +0100 Subject: [PATCH 23/26] Correct description of the ECDH shared secret The endianness actually depends on the curve type. Correct the terminology around "curve size" and "order of the curve". I tried to find a formulation that is comprehensible to programmers who do not know the underlying mathematics, but nonetheless correct and precise. Use similar terminology in other places that were using "order of the curve" to describe the bit size associated with the curve. --- include/psa/crypto.h | 34 +++++++++++++++++++++++++++------- include/psa/crypto_sizes.h | 7 ++++--- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 412fe5a75..df760ddd5 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -1263,10 +1263,29 @@ typedef uint32_t psa_algorithm_t; * public key, with a key selection or key derivation algorithm to produce * one or more shared keys and other shared cryptographic material. * - * The input to \p kdf_alg is the x-coordinate of the shared secret - * `d_A Q_B = d_B Q_A` in big-endian format. It has the same size of - * the order of the curve, i.e. `ceiling(n / 8)` bytes where `n` is - * the size of the order of the curve. + * The shared secret produced by key agreement and passed as input to the + * derivation or selection algorithm \p kdf_alg is the x-coordinate of + * the shared secret point. It is always `ceiling(q / 8)` bytes long where + * `q` is the bit size associated with the curve, i.e. the bit size of the + * order of the curve's coordinate field. When `q` is not a multiple of 8, + * the byte containing the most significant bit of the shared secret + * is padded with zero bits. The byte order is either little-endian + * or big-endian depending on the curve type. + * + * - For Montgomery curves (curve types `PSA_ECC_CURVE_CURVEXXX`), + * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` + * in little-endian byte order. + * The bit size is 448 for Curve448 and 255 for Curve25519. + * - For Weierstrass curves over prime fields (curve types + * `PSA_ECC_CURVE_SECPXXX` and `PSA_ECC_CURVE_BRAINPOOL_PXXX`), + * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` + * in big-endian byte order. + * The bit size is `q = ceiling(log_2(p))` for the field `F_p`. + * - For Weierstrass curves over binary fields (curve types + * `PSA_ECC_CURVE_SECTXXX`), + * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` + * in big-endian byte order. + * The bit size is `q = m` for the field `F_{2^m}`. * * \param kdf_alg A key derivation algorithm (\c PSA_ALG_XXX value such * that #PSA_ALG_IS_KEY_DERIVATION(\p hash_alg) is true) @@ -1567,9 +1586,10 @@ psa_status_t psa_export_key(psa_key_slot_t key, * * ECPoint ::= ... * -- first 8 bits: 0x04; - * -- then x_P as an n-bit string, big endian; - * -- then y_P as a n-bit string, big endian, - * -- where n is the order of the curve. + * -- then x_P as a `ceiling(n/8)`-byte string, big endian; + * -- then y_P as a `ceiling(n/8)`-byte string, big endian; + * -- where `n` is the bit size associated with the curve, + * -- i.e. the bit size of `q` for a curve over `F_q`. * * EcpkParameters ::= CHOICE { -- other choices are not allowed * namedCurve OBJECT IDENTIFIER } diff --git a/include/psa/crypto_sizes.h b/include/psa/crypto_sizes.h index edddca47a..f4feb4d20 100644 --- a/include/psa/crypto_sizes.h +++ b/include/psa/crypto_sizes.h @@ -422,9 +422,10 @@ * parameters OBJECT IDENTIFIER } -- namedCurve * ECPoint ::= ... * -- first 8 bits: 0x04; - * -- then x_P as an n-bit string, big endian; - * -- then y_P as a n-bit string, big endian, - * -- where n is the order of the curve. + * -- then x_P as a `ceiling(n/8)`-byte string, big endian; + * -- then y_P as a `ceiling(n/8)`-byte string, big endian; + * -- where `n` is the bit size associated with the curve, + * -- i.e. the bit size of `q` for a curve over `F_q`. * * - 2 * 4 bytes of SEQUENCE overhead; * - 1 + 1 + 7 bytes of algorithm (id-ecPublicKey OID); From 6c6a023f9994ca1854cada3d51be237e57680712 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 15 Nov 2018 17:44:43 +0100 Subject: [PATCH 24/26] More tweaks on EC-related wording Use m for the bit size of the field order, not q which is traditionally the field order. Correct and clarify the private key representation format as has been done for the private key and ECDH shared secret formats. --- include/psa/crypto.h | 25 +++++++++++++++---------- include/psa/crypto_sizes.h | 7 +++---- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index df760ddd5..6e5bbe010 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -1265,9 +1265,9 @@ typedef uint32_t psa_algorithm_t; * * The shared secret produced by key agreement and passed as input to the * derivation or selection algorithm \p kdf_alg is the x-coordinate of - * the shared secret point. It is always `ceiling(q / 8)` bytes long where - * `q` is the bit size associated with the curve, i.e. the bit size of the - * order of the curve's coordinate field. When `q` is not a multiple of 8, + * the shared secret point. It is always `ceiling(m / 8)` bytes long where + * `m` is the bit size associated with the curve, i.e. the bit size of the + * order of the curve's coordinate field. When `m` is not a multiple of 8, * the byte containing the most significant bit of the shared secret * is padded with zero bits. The byte order is either little-endian * or big-endian depending on the curve type. @@ -1280,12 +1280,12 @@ typedef uint32_t psa_algorithm_t; * `PSA_ECC_CURVE_SECPXXX` and `PSA_ECC_CURVE_BRAINPOOL_PXXX`), * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` * in big-endian byte order. - * The bit size is `q = ceiling(log_2(p))` for the field `F_p`. + * The bit size is `m = ceiling(log_2(p))` for the field `F_p`. * - For Weierstrass curves over binary fields (curve types * `PSA_ECC_CURVE_SECTXXX`), * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` * in big-endian byte order. - * The bit size is `q = m` for the field `F_{2^m}`. + * The bit size is `m` for the field `F_{2^m}`. * * \param kdf_alg A key derivation algorithm (\c PSA_ALG_XXX value such * that #PSA_ALG_IS_KEY_DERIVATION(\p hash_alg) is true) @@ -1486,8 +1486,13 @@ psa_status_t psa_get_key_information(psa_key_slot_t key, * ``` * - For elliptic curve key pairs (key types for which * #PSA_KEY_TYPE_IS_ECC_KEYPAIR is true), the format is - * a big-endian representation of the private point as a - * `ceiling(log2(n)/8)`-byte string where `n` is the order of the curve. + * a representation of the private value as a `ceiling(m/8)`-byte string + * where `m` is the bit size associated with the curve, i.e. the bit size + * of the order of the curve's coordinate field. This byte string is + * in little-endian order for Montgomery curves (curve types + * `PSA_ECC_CURVE_CURVEXXX`), and in big-endian order for Weierstrass + * curves (curve types `PSA_ECC_CURVE_SECTXXX`, `PSA_ECC_CURVE_SECPXXX` + * and `PSA_ECC_CURVE_BRAINPOOL_PXXX`). * This is the content of the `privateKey` field of the `ECPrivateKey` * format defined by RFC 5915. * - For public keys (key types for which #PSA_KEY_TYPE_IS_PUBLIC_KEY is @@ -1586,9 +1591,9 @@ psa_status_t psa_export_key(psa_key_slot_t key, * * ECPoint ::= ... * -- first 8 bits: 0x04; - * -- then x_P as a `ceiling(n/8)`-byte string, big endian; - * -- then y_P as a `ceiling(n/8)`-byte string, big endian; - * -- where `n` is the bit size associated with the curve, + * -- then x_P as a `ceiling(m/8)`-byte string, big endian; + * -- then y_P as a `ceiling(m/8)`-byte string, big endian; + * -- where `m` is the bit size associated with the curve, * -- i.e. the bit size of `q` for a curve over `F_q`. * * EcpkParameters ::= CHOICE { -- other choices are not allowed diff --git a/include/psa/crypto_sizes.h b/include/psa/crypto_sizes.h index f4feb4d20..f0a1ba7dd 100644 --- a/include/psa/crypto_sizes.h +++ b/include/psa/crypto_sizes.h @@ -422,10 +422,9 @@ * parameters OBJECT IDENTIFIER } -- namedCurve * ECPoint ::= ... * -- first 8 bits: 0x04; - * -- then x_P as a `ceiling(n/8)`-byte string, big endian; - * -- then y_P as a `ceiling(n/8)`-byte string, big endian; - * -- where `n` is the bit size associated with the curve, - * -- i.e. the bit size of `q` for a curve over `F_q`. + * -- then x_P as a `ceiling(m/8)`-byte string, big endian; + * -- then y_P as a `ceiling(m/8)`-byte string, big endian; + * -- where `m` is the bit size associated with the curve. * * - 2 * 4 bytes of SEQUENCE overhead; * - 1 + 1 + 7 bytes of algorithm (id-ecPublicKey OID); From d171e78b4691dba2d976021faffebabc3dcefec8 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 15 Nov 2018 17:46:21 +0100 Subject: [PATCH 25/26] Document the peer_key format for psa_key_agreement --- include/psa/crypto.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 6e5bbe010..a2191c664 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -3241,7 +3241,11 @@ psa_status_t psa_key_derivation(psa_crypto_generator_t *generator, * \c PSA_CRYPTO_GENERATOR_INIT or * psa_crypto_generator_init(). * \param private_key Slot containing the private key to use. - * \param[in] peer_key Public key of the peer. + * \param[in] peer_key Public key of the peer. It must be + * in the same format that psa_import_key() + * accepts. The standard formats for public + * keys are documented in the documentation + * of psa_export_public_key(). * \param peer_key_length Size of \p peer_key in bytes. * \param alg The key agreement algorithm to compute * (\c PSA_ALG_XXX value such that From 99d0259987fadf213323fe6621759c01d7ecca34 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 15 Nov 2018 17:47:25 +0100 Subject: [PATCH 26/26] Improve documentation the shared secret format for FFDH --- include/psa/crypto.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index a2191c664..64f343c6e 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -1228,8 +1228,11 @@ typedef uint32_t psa_algorithm_t; * public key, with a key selection or key derivation algorithm to produce * one or more shared keys and other shared cryptographic material. * - * The input to \p kdf_alg is the shared secret `g^{ab}` in big-endian format. - * It is `ceiling(n / 8)` bytes long where `n` is the size of the prime `p`. + * The shared secret produced by key agreement and passed as input to the + * derivation or selection algorithm \p kdf_alg is the shared secret + * `g^{ab}` in big-endian format. + * It is `ceiling(m / 8)` bytes long where `m` is the size of the prime `p` + * in bits. * * \param kdf_alg A key derivation algorithm (\c PSA_ALG_XXX value such * that #PSA_ALG_IS_KEY_DERIVATION(\p hash_alg) is true)