From 79250c255f365e295ab475019cd6477f7833c6fc Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Tue, 9 Oct 2018 17:32:46 +0100 Subject: [PATCH 1/6] Add identifiers for TLS-1.2 PRF This commit adds KDF algorithm identifiers `PSA_ALG_TLS12_PRF(HASH)` to the PSA crypto API. They represent the key derivation functions used by TLS 1.2 for the PreMasterSecret->MasterSecret and MasterSecret->KeyBlock conversions. --- include/psa/crypto.h | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 64f343c6e..8e439bab0 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -1199,6 +1199,39 @@ 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_TLS12_PRF_BASE ((psa_algorithm_t)0x30000200) +/** Macro to build a TLS-1.2 PRF algorithm. + * + * For example, `PSA_ALG_TLS12_PRF(PSA_ALG_SHA256)` represents the + * TLS 1.2 PRF using HMAC-SHA-256. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * + * \return The corresponding TLS-1.2 PRF algorithm. + * \return Unspecified if \p alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_TLS12_PRF(hash_alg) \ + (PSA_ALG_TLS12_PRF_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) + +/** Whether the specified algorithm is a TLS-1.2 PRF algorithm. + * + * TLS 1.2 uses a custom pseudorandom function (PRF) for key schedule, + * specified in Section 5 of RFC 5246. It is based on HMAC and can be + * used with either SHA-256 or SHA-384. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a TLS-1.2 PRF algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key derivation algorithm identifier. + */ +#define PSA_ALG_IS_TLS12_PRF(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_TLS12_PRF_BASE) +#define PSA_ALG_TLS12_PRF_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. From c8a41d71cba5b03f7be075cd3b904b5075011294 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Tue, 9 Oct 2018 17:33:01 +0100 Subject: [PATCH 2/6] Add implementation of TLS-1.2 PRF --- include/psa/crypto_struct.h | 30 +++++ library/psa_crypto.c | 240 ++++++++++++++++++++++++++++++++++++ 2 files changed, 270 insertions(+) diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h index e38a9bfba..2d7bb2682 100644 --- a/include/psa/crypto_struct.h +++ b/include/psa/crypto_struct.h @@ -144,6 +144,35 @@ typedef struct uint8_t block_number; } psa_hkdf_generator_t; +typedef struct psa_tls12_prf_generator_s +{ + /* The TLS 1.2 PRF uses the key for each HMAC iteration, + * hence we must store it for the lifetime of the generator. + * This is different from HKDF, where the key is only used + * in the extraction phase, but not during expansion. */ + unsigned char *key; + size_t key_len; + + /* `A(i) + seed` in the notation of RFC 5246, Sect. 5 */ + uint8_t Ai_with_seed[PSA_HASH_MAX_SIZE + 64]; + size_t seed_length; + + /* `HMAC_hash( prk, A(i) + seed )` in the notation of RFC 5246, Sect. 5. */ + uint8_t output_block[PSA_HASH_MAX_SIZE]; + +#if PSA_HASH_MAX_SIZE > 0xff +#error "PSA_HASH_MAX_SIZE does not fit in uint8_t" +#endif + + /* Indicates how many bytes in the current HMAC block have + * already been read by the user. */ + uint8_t offset_in_block; + + /* The 1-based number of the block. */ + uint8_t block_number; + +} psa_tls12_prf_generator_t; + struct psa_crypto_generator_s { psa_algorithm_t alg; @@ -157,6 +186,7 @@ struct psa_crypto_generator_s } buffer; #if defined(MBEDTLS_MD_C) psa_hkdf_generator_t hkdf; + psa_tls12_prf_generator_t tls12_prf; #endif } ctx; }; diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 763074c9b..ef4623716 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -1506,6 +1506,12 @@ static psa_status_t psa_hmac_abort_internal( psa_hmac_internal_data *hmac ) mbedtls_zeroize( hmac->opad, sizeof( hmac->opad ) ); return( psa_hash_abort( &hmac->hash_ctx ) ); } + +static void psa_hmac_init_internal( psa_hmac_internal_data *hmac ) +{ + /* Instances of psa_hash_operation_s can be initialized by zeroization. */ + memset( hmac, 0, sizeof( *hmac ) ); +} #endif /* MBEDTLS_MD_C */ psa_status_t psa_mac_abort( psa_mac_operation_t *operation ) @@ -3258,6 +3264,15 @@ psa_status_t psa_generator_abort( psa_crypto_generator_t *generator ) mbedtls_free( generator->ctx.hkdf.info ); status = psa_hmac_abort_internal( &generator->ctx.hkdf.hmac ); } + else if( PSA_ALG_IS_TLS12_PRF( generator->alg ) ) + { + if( generator->ctx.tls12_prf.key != NULL ) + { + mbedtls_zeroize( generator->ctx.tls12_prf.key, + generator->ctx.tls12_prf.key_len ); + mbedtls_free( generator->ctx.tls12_prf.key ); + } + } else #endif /* MBEDTLS_MD_C */ { @@ -3340,6 +3355,172 @@ static psa_status_t psa_generator_hkdf_read( psa_hkdf_generator_t *hkdf, return( PSA_SUCCESS ); } + +static psa_status_t psa_generator_tls12_prf_generate_next_block( + psa_tls12_prf_generator_t *tls12_prf, + psa_algorithm_t alg ) +{ + psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH( alg ); + uint8_t hash_length = PSA_HASH_SIZE( hash_alg ); + psa_hmac_internal_data hmac; + psa_status_t status, cleanup_status; + + /* We can't be wanting more output after block 0xff, otherwise + * the capacity check in psa_generator_read() would have + * prevented this call. It could happen only if the generator + * object was corrupted or if this function is called directly + * inside the library. */ + if( tls12_prf->block_number == 0xff ) + return( PSA_ERROR_BAD_STATE ); + + /* We need a new block */ + ++tls12_prf->block_number; + tls12_prf->offset_in_block = 0; + + /* Recall the definition of the TLS-1.2-PRF from RFC 5246: + * + * PRF(secret, label, seed) = P_(secret, label + seed) + * + * P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) + + * HMAC_hash(secret, A(2) + seed) + + * HMAC_hash(secret, A(3) + seed) + ... + * + * A(0) = seed + * A(i) = HMAC_hash( secret, A(i-1) ) + * + * The `psa_tls12_prf_generator` structures saves the block + * `HMAC_hash(secret, A(i) + seed)` from which the output + * is currently extracted as `output_block`, while + * `A(i) + seed` is stored in `Ai_with_seed`. + * + * Generating a new block means recalculating `Ai_with_seed` + * from the A(i)-part of it, and afterwards recalculating + * `output_block`. + * + * A(0) is computed at setup time. + * + */ + + psa_hmac_init_internal( &hmac ); + + /* We must distinguish the calculation of A(1) from those + * of A(2) and higher, because A(0)=seed has a different + * length than the other A(i). */ + if( tls12_prf->block_number == 1 ) + { + /* Compute A(1) = HMAC_hash(secret, label + seed) */ + status = psa_hmac_setup_internal( &hmac, + tls12_prf->key, + tls12_prf->key_len, + hash_alg ); + if( status != PSA_SUCCESS ) + goto cleanup; + + status = psa_hash_update( &hmac.hash_ctx, + /* This omits the (so far undefined) + * first hash_length bytes. */ + tls12_prf->Ai_with_seed + hash_length, + tls12_prf->seed_length ); + if( status != PSA_SUCCESS ) + goto cleanup; + status = psa_hmac_finish_internal( &hmac, + tls12_prf->Ai_with_seed, + hash_length ); + if( status != PSA_SUCCESS ) + goto cleanup; + } + else + { + /* Compute A(i+1) = HMAC_hash(secret, A(i)) */ + status = psa_hmac_setup_internal( &hmac, + tls12_prf->key, + tls12_prf->key_len, + hash_alg ); + if( status != PSA_SUCCESS ) + goto cleanup; + + status = psa_hash_update( &hmac.hash_ctx, + tls12_prf->Ai_with_seed, + /* This omits the seed part of A(i) */ + hash_length ); + if( status != PSA_SUCCESS ) + goto cleanup; + + status = psa_hmac_finish_internal( &hmac, + tls12_prf->Ai_with_seed, + hash_length ); + if( status != PSA_SUCCESS ) + goto cleanup; + } + + /* Compute the next block `HMAC_hash(secret, A(i+1) + seed)`. */ + status = psa_hmac_setup_internal( &hmac, + tls12_prf->key, + tls12_prf->key_len, + hash_alg ); + if( status != PSA_SUCCESS ) + goto cleanup; + + status = psa_hash_update( &hmac.hash_ctx, + tls12_prf->Ai_with_seed, + hash_length + tls12_prf->seed_length ); + if( status != PSA_SUCCESS ) + goto cleanup; + + status = psa_hmac_finish_internal( &hmac, + tls12_prf->output_block, + hash_length ); + if( status != PSA_SUCCESS ) + goto cleanup; + +cleanup: + + cleanup_status = psa_hmac_abort_internal( &hmac ); + if( status == PSA_SUCCESS && cleanup_status != PSA_SUCCESS ) + status = cleanup_status; + + return( status ); +} + +/* Read some bytes from an TLS-1.2-PRF-based generator. + * See Section 5 of RFC 5246. */ +static psa_status_t psa_generator_tls12_prf_read( + psa_tls12_prf_generator_t *tls12_prf, + psa_algorithm_t alg, + uint8_t *output, + size_t output_length ) +{ + psa_algorithm_t hash_alg = PSA_ALG_TLS12_PRF_GET_HASH( alg ); + uint8_t hash_length = PSA_HASH_SIZE( hash_alg ); + psa_status_t status; + + while( output_length != 0 ) + { + /* Copy what remains of the current block */ + uint8_t n = hash_length - tls12_prf->offset_in_block; + + /* Check if we have fully processed the current block. */ + if( n == 0 ) + { + status = psa_generator_tls12_prf_generate_next_block( tls12_prf, + alg ); + if( status != PSA_SUCCESS ) + return( status ); + + continue; + } + + if( n > output_length ) + n = (uint8_t) output_length; + memcpy( output, tls12_prf->output_block + tls12_prf->offset_in_block, + n ); + output += n; + output_length -= n; + tls12_prf->offset_in_block += n; + } + + return( PSA_SUCCESS ); +} #endif /* MBEDTLS_MD_C */ psa_status_t psa_generator_read( psa_crypto_generator_t *generator, @@ -3393,6 +3574,12 @@ psa_status_t psa_generator_read( psa_crypto_generator_t *generator, status = psa_generator_hkdf_read( &generator->ctx.hkdf, hash_alg, output, output_length ); } + else if( PSA_ALG_IS_TLS12_PRF( generator->alg ) ) + { + status = psa_generator_tls12_prf_read( &generator->ctx.tls12_prf, + generator->alg, output, + output_length ); + } else #endif /* MBEDTLS_MD_C */ { @@ -3495,6 +3682,41 @@ static psa_status_t psa_generator_hkdf_setup( psa_hkdf_generator_t *hkdf, return( PSA_SUCCESS ); } +/* Set up a TLS-1.2-prf-based generator (see RFC 5246, Section 5). */ +static psa_status_t psa_generator_tls12_prf_setup( + psa_tls12_prf_generator_t *tls12_prf, + const unsigned char *key, + size_t key_len, + psa_algorithm_t hash_alg, + const uint8_t *salt, + size_t salt_length, + const uint8_t *label, + size_t label_length ) +{ + uint8_t hash_length = PSA_HASH_SIZE( hash_alg ); + + tls12_prf->key = mbedtls_calloc( 1, key_len ); + if( tls12_prf->key == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + tls12_prf->key_len = key_len; + memcpy( tls12_prf->key, key, key_len ); + + /* Write `label + seed' at the end of the `A(i) + seed` buffer, + * leaving the initial `hash_length` bytes unspecified for now. */ + memcpy( tls12_prf->Ai_with_seed + hash_length, label, label_length ); + memcpy( tls12_prf->Ai_with_seed + hash_length + label_length, + salt, salt_length ); + + tls12_prf->seed_length = label_length + salt_length; + + /* The first block gets generated when + * psa_generator_read() is called. */ + tls12_prf->block_number = 0; + tls12_prf->offset_in_block = hash_length; + + return( PSA_SUCCESS ); +} + static psa_status_t psa_key_derivation_internal( psa_crypto_generator_t *generator, const uint8_t *secret, size_t secret_length, @@ -3538,6 +3760,24 @@ static psa_status_t psa_key_derivation_internal( salt, salt_length, label, label_length ); } + else if( PSA_ALG_IS_TLS12_PRF( alg ) ) + { + psa_algorithm_t hash_alg = PSA_ALG_TLS12_PRF_GET_HASH( alg ); + size_t hash_size = PSA_HASH_SIZE( hash_alg ); + + /* TLS-1.2 PRF supports only SHA-256 and SHA-384. */ + if( hash_alg != PSA_ALG_SHA_256 && + hash_alg != PSA_ALG_SHA_384 ) + { + return( PSA_ERROR_NOT_SUPPORTED ); + } + + max_capacity = 255 * hash_size; + status = psa_generator_tls12_prf_setup( &generator->ctx.tls12_prf, + secret, secret_length, + hash_alg, salt, salt_length, + label, label_length ); + } else #endif { From 24658c4ba1b9aa1a81117e38f1a959327a07a51a Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Tue, 9 Oct 2018 17:33:08 +0100 Subject: [PATCH 3/6] Add test vectors for TLS 1.2 PRF Taken from https://www.ietf.org/mail-archive/web/tls/current/msg03416.html --- tests/suites/test_suite_psa_crypto.data | 69 +++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 4 deletions(-) diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index 5b8166428..7f37db197 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -434,18 +434,30 @@ PSA key policy: asymmetric signature, neither sign nor verify depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15 asymmetric_signature_key_policy:0:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEYPAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_SIGN_RAW -PSA key policy: derive, permitted +PSA key policy: derive via HKDF, permitted 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_256) -PSA key policy: derive, not permitted +PSA key policy: derive via TLS 1.2 PRF, permitted +depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C +derive_key_policy:PSA_KEY_USAGE_DERIVE:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):PSA_KEY_TYPE_DERIVE:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256) + +PSA key policy: derive via HKDF, not permitted depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C derive_key_policy:0:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_TYPE_DERIVE:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HKDF(PSA_ALG_SHA_256) -PSA key policy: derive, wrong algorithm +PSA key policy: derive via TLS 1.2 PRF, not permitted +depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C +derive_key_policy:0:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):PSA_KEY_TYPE_DERIVE:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256) + +PSA key policy: derive via HKDF, 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: derive via TLS 1.2 PRF, wrong algorithm +depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C +derive_key_policy:PSA_KEY_USAGE_DERIVE:PSA_ALG_TLS12_PRF(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):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_ALG_ECDH(PSA_ALG_SELECT_RAW) @@ -1400,10 +1412,18 @@ PSA key derivation: HKDF-SHA-512, good case depends_on:MBEDTLS_MD_C:MBEDTLS_SHA512_C derive_setup:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_HKDF(PSA_ALG_SHA_512):"":"":42:PSA_SUCCESS -PSA key derivation: bad key type +PSA key derivation: HKDF-SHA-256, 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: TLS 1.2 PRF SHA-256, good case +depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C +derive_setup:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):"":"":42:PSA_SUCCESS + +PSA key derivation: TLS 1.2 PRF SHA-256, bad key type +depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C +derive_setup:PSA_KEY_TYPE_RAW_DATA:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):"":"":42:PSA_ERROR_INVALID_ARGUMENT + 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 @@ -1476,6 +1496,47 @@ PSA key derivation: HKDF SHA-1, RFC5869 #7, output 42+0 depends_on:MBEDTLS_MD_C:MBEDTLS_SHA1_C derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_1):"0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c":"":"":42:"2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48":"" +# Test vectors taken from https://www.ietf.org/mail-archive/web/tls/current/msg03416.html +PSA key derivation: TLS 1.2 PRF SHA-256, output 100+0 +depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C +derive_output:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):"9bbe436ba940f017b17652849a71db35":"a0ba9f936cda311827a6f796ffd5198c":"74657374206c6162656c":100:"e3f229ba727be17b8d122620557cd453c2aab21d07c3d495329b52d4e61edb5a6b301791e90d35c9c9a46b4e14baf9af0fa022f7077def17abfd3797c0564bab4fbc91666e9def9b97fce34f796789baa48082d122ee42c5a72e5a5110fff70187347b66":"" + +PSA key derivation: TLS 1.2 PRF SHA-256, output 99+1 +depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C +derive_output:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):"9bbe436ba940f017b17652849a71db35":"a0ba9f936cda311827a6f796ffd5198c":"74657374206c6162656c":100:"e3f229ba727be17b8d122620557cd453c2aab21d07c3d495329b52d4e61edb5a6b301791e90d35c9c9a46b4e14baf9af0fa022f7077def17abfd3797c0564bab4fbc91666e9def9b97fce34f796789baa48082d122ee42c5a72e5a5110fff70187347b":"66" + +PSA key derivation: TLS 1.2 PRF SHA-256, output 1+99 +depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C +derive_output:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):"9bbe436ba940f017b17652849a71db35":"a0ba9f936cda311827a6f796ffd5198c":"74657374206c6162656c":100:"e3":"f229ba727be17b8d122620557cd453c2aab21d07c3d495329b52d4e61edb5a6b301791e90d35c9c9a46b4e14baf9af0fa022f7077def17abfd3797c0564bab4fbc91666e9def9b97fce34f796789baa48082d122ee42c5a72e5a5110fff70187347b66" + +PSA key derivation: TLS 1.2 PRF SHA-256, output 50+50 +depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C +derive_output:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):"9bbe436ba940f017b17652849a71db35":"a0ba9f936cda311827a6f796ffd5198c":"74657374206c6162656c":100:"e3f229ba727be17b8d122620557cd453c2aab21d07c3d495329b52d4e61edb5a6b301791e90d35c9c9a46b4e14baf9af0fa0":"22f7077def17abfd3797c0564bab4fbc91666e9def9b97fce34f796789baa48082d122ee42c5a72e5a5110fff70187347b66" + +PSA key derivation: TLS 1.2 PRF SHA-256, output 50+49 +depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C +derive_output:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):"9bbe436ba940f017b17652849a71db35":"a0ba9f936cda311827a6f796ffd5198c":"74657374206c6162656c":100:"e3f229ba727be17b8d122620557cd453c2aab21d07c3d495329b52d4e61edb5a6b301791e90d35c9c9a46b4e14baf9af0fa0":"22f7077def17abfd3797c0564bab4fbc91666e9def9b97fce34f796789baa48082d122ee42c5a72e5a5110fff70187347b" + +PSA key derivation: TLS 1.2 PRF SHA-384, output 148+0 +depends_on:MBEDTLS_MD_C:MBEDTLS_SHA512_C +derive_output:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_384):"b80b733d6ceefcdc71566ea48e5567df":"cd665cf6a8447dd6ff8b27555edb7465":"74657374206c6162656c":148:"7b0c18e9ced410ed1804f2cfa34a336a1c14dffb4900bb5fd7942107e81c83cde9ca0faa60be9fe34f82b1233c9146a0e534cb400fed2700884f9dc236f80edd8bfa961144c9e8d792eca722a7b32fc3d416d473ebc2c5fd4abfdad05d9184259b5bf8cd4d90fa0d31e2dec479e4f1a26066f2eea9a69236a3e52655c9e9aee691c8f3a26854308d5eaa3be85e0990703d73e56f":"" + +PSA key derivation: TLS 1.2 PRF SHA-384, output 147+1 +depends_on:MBEDTLS_MD_C:MBEDTLS_SHA512_C +derive_output:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_384):"b80b733d6ceefcdc71566ea48e5567df":"cd665cf6a8447dd6ff8b27555edb7465":"74657374206c6162656c":148:"7b0c18e9ced410ed1804f2cfa34a336a1c14dffb4900bb5fd7942107e81c83cde9ca0faa60be9fe34f82b1233c9146a0e534cb400fed2700884f9dc236f80edd8bfa961144c9e8d792eca722a7b32fc3d416d473ebc2c5fd4abfdad05d9184259b5bf8cd4d90fa0d31e2dec479e4f1a26066f2eea9a69236a3e52655c9e9aee691c8f3a26854308d5eaa3be85e0990703d73e5":"6f" + +PSA key derivation: TLS 1.2 PRF SHA-384, output 1+147 +depends_on:MBEDTLS_MD_C:MBEDTLS_SHA512_C +derive_output:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_384):"b80b733d6ceefcdc71566ea48e5567df":"cd665cf6a8447dd6ff8b27555edb7465":"74657374206c6162656c":148:"7b":"0c18e9ced410ed1804f2cfa34a336a1c14dffb4900bb5fd7942107e81c83cde9ca0faa60be9fe34f82b1233c9146a0e534cb400fed2700884f9dc236f80edd8bfa961144c9e8d792eca722a7b32fc3d416d473ebc2c5fd4abfdad05d9184259b5bf8cd4d90fa0d31e2dec479e4f1a26066f2eea9a69236a3e52655c9e9aee691c8f3a26854308d5eaa3be85e0990703d73e56f" + +PSA key derivation: TLS 1.2 PRF SHA-384, output 74+74 +depends_on:MBEDTLS_MD_C:MBEDTLS_SHA512_C +derive_output:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_384):"b80b733d6ceefcdc71566ea48e5567df":"cd665cf6a8447dd6ff8b27555edb7465":"74657374206c6162656c":148:"7b0c18e9ced410ed1804f2cfa34a336a1c14dffb4900bb5fd7942107e81c83cde9ca0faa60be9fe34f82b1233c9146a0e534cb400fed2700884f9dc236f80edd8bfa961144c9e8d792ec":"a722a7b32fc3d416d473ebc2c5fd4abfdad05d9184259b5bf8cd4d90fa0d31e2dec479e4f1a26066f2eea9a69236a3e52655c9e9aee691c8f3a26854308d5eaa3be85e0990703d73e56f" + +PSA key derivation: TLS 1.2 PRF SHA-384, output 74+73 +depends_on:MBEDTLS_MD_C:MBEDTLS_SHA512_C +derive_output:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_384):"b80b733d6ceefcdc71566ea48e5567df":"cd665cf6a8447dd6ff8b27555edb7465":"74657374206c6162656c":148:"7b0c18e9ced410ed1804f2cfa34a336a1c14dffb4900bb5fd7942107e81c83cde9ca0faa60be9fe34f82b1233c9146a0e534cb400fed2700884f9dc236f80edd8bfa961144c9e8d792ec":"a722a7b32fc3d416d473ebc2c5fd4abfdad05d9184259b5bf8cd4d90fa0d31e2dec479e4f1a26066f2eea9a69236a3e52655c9e9aee691c8f3a26854308d5eaa3be85e0990703d73e5" + PSA key derivation: HKDF SHA-256, request maximum capacity depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":255 * 32:"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865":"" From 580fba143101b4c1403d45dc9f8c4691aa68320f Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Tue, 13 Nov 2018 20:50:45 +0000 Subject: [PATCH 4/6] Dynamically allocate `A(i) + seed` buffer for TLS-1.2 PRF --- include/psa/crypto_struct.h | 4 ++-- library/psa_crypto.c | 25 +++++++++++++++++++++---- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h index 2d7bb2682..f11b87cca 100644 --- a/include/psa/crypto_struct.h +++ b/include/psa/crypto_struct.h @@ -154,8 +154,8 @@ typedef struct psa_tls12_prf_generator_s size_t key_len; /* `A(i) + seed` in the notation of RFC 5246, Sect. 5 */ - uint8_t Ai_with_seed[PSA_HASH_MAX_SIZE + 64]; - size_t seed_length; + uint8_t *Ai_with_seed; + size_t Ai_with_seed_len; /* `HMAC_hash( prk, A(i) + seed )` in the notation of RFC 5246, Sect. 5. */ uint8_t output_block[PSA_HASH_MAX_SIZE]; diff --git a/library/psa_crypto.c b/library/psa_crypto.c index ef4623716..2030315dd 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -3272,6 +3272,13 @@ psa_status_t psa_generator_abort( psa_crypto_generator_t *generator ) generator->ctx.tls12_prf.key_len ); mbedtls_free( generator->ctx.tls12_prf.key ); } + + if( generator->ctx.tls12_prf.Ai_with_seed != NULL ) + { + mbedtls_zeroize( generator->ctx.tls12_prf.Ai_with_seed, + generator->ctx.tls12_prf.Ai_with_seed_len ); + mbedtls_free( generator->ctx.tls12_prf.Ai_with_seed ); + } } else #endif /* MBEDTLS_MD_C */ @@ -3420,7 +3427,7 @@ static psa_status_t psa_generator_tls12_prf_generate_next_block( /* This omits the (so far undefined) * first hash_length bytes. */ tls12_prf->Ai_with_seed + hash_length, - tls12_prf->seed_length ); + tls12_prf->Ai_with_seed_len - hash_length ); if( status != PSA_SUCCESS ) goto cleanup; status = psa_hmac_finish_internal( &hmac, @@ -3463,7 +3470,7 @@ static psa_status_t psa_generator_tls12_prf_generate_next_block( status = psa_hash_update( &hmac.hash_ctx, tls12_prf->Ai_with_seed, - hash_length + tls12_prf->seed_length ); + tls12_prf->Ai_with_seed_len ); if( status != PSA_SUCCESS ) goto cleanup; @@ -3694,6 +3701,8 @@ static psa_status_t psa_generator_tls12_prf_setup( size_t label_length ) { uint8_t hash_length = PSA_HASH_SIZE( hash_alg ); + size_t Ai_with_seed_len = hash_length + salt_length + label_length; + int overflow; tls12_prf->key = mbedtls_calloc( 1, key_len ); if( tls12_prf->key == NULL ) @@ -3701,14 +3710,22 @@ static psa_status_t psa_generator_tls12_prf_setup( tls12_prf->key_len = key_len; memcpy( tls12_prf->key, key, key_len ); + overflow = ( salt_length + label_length < salt_length ) || + ( salt_length + label_length + hash_length < hash_length ); + if( overflow ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + tls12_prf->Ai_with_seed = mbedtls_calloc( 1, Ai_with_seed_len ); + if( tls12_prf->Ai_with_seed == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + tls12_prf->Ai_with_seed_len = Ai_with_seed_len; + /* Write `label + seed' at the end of the `A(i) + seed` buffer, * leaving the initial `hash_length` bytes unspecified for now. */ memcpy( tls12_prf->Ai_with_seed + hash_length, label, label_length ); memcpy( tls12_prf->Ai_with_seed + hash_length + label_length, salt, salt_length ); - tls12_prf->seed_length = label_length + salt_length; - /* The first block gets generated when * psa_generator_read() is called. */ tls12_prf->block_number = 0; From 3b339e23427a315a294397f500d0c69fb73849d1 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Tue, 13 Nov 2018 20:56:14 +0000 Subject: [PATCH 5/6] Simplify psa_generator_tls12_prf_generate_next_block() --- library/psa_crypto.c | 66 +++++++++++++++++--------------------------- 1 file changed, 26 insertions(+), 40 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 2030315dd..5ee43e4d6 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -3372,6 +3372,9 @@ static psa_status_t psa_generator_tls12_prf_generate_next_block( psa_hmac_internal_data hmac; psa_status_t status, cleanup_status; + unsigned char *Ai; + size_t Ai_len; + /* We can't be wanting more output after block 0xff, otherwise * the capacity check in psa_generator_read() would have * prevented this call. It could happen only if the generator @@ -3415,51 +3418,34 @@ static psa_status_t psa_generator_tls12_prf_generate_next_block( * length than the other A(i). */ if( tls12_prf->block_number == 1 ) { - /* Compute A(1) = HMAC_hash(secret, label + seed) */ - status = psa_hmac_setup_internal( &hmac, - tls12_prf->key, - tls12_prf->key_len, - hash_alg ); - if( status != PSA_SUCCESS ) - goto cleanup; - - status = psa_hash_update( &hmac.hash_ctx, - /* This omits the (so far undefined) - * first hash_length bytes. */ - tls12_prf->Ai_with_seed + hash_length, - tls12_prf->Ai_with_seed_len - hash_length ); - if( status != PSA_SUCCESS ) - goto cleanup; - status = psa_hmac_finish_internal( &hmac, - tls12_prf->Ai_with_seed, - hash_length ); - if( status != PSA_SUCCESS ) - goto cleanup; + Ai = tls12_prf->Ai_with_seed + hash_length; + Ai_len = tls12_prf->Ai_with_seed_len - hash_length; } else { - /* Compute A(i+1) = HMAC_hash(secret, A(i)) */ - status = psa_hmac_setup_internal( &hmac, - tls12_prf->key, - tls12_prf->key_len, - hash_alg ); - if( status != PSA_SUCCESS ) - goto cleanup; - - status = psa_hash_update( &hmac.hash_ctx, - tls12_prf->Ai_with_seed, - /* This omits the seed part of A(i) */ - hash_length ); - if( status != PSA_SUCCESS ) - goto cleanup; - - status = psa_hmac_finish_internal( &hmac, - tls12_prf->Ai_with_seed, - hash_length ); - if( status != PSA_SUCCESS ) - goto cleanup; + Ai = tls12_prf->Ai_with_seed; + Ai_len = hash_length; } + /* Compute A(i+1) = HMAC_hash(secret, A(i)) */ + status = psa_hmac_setup_internal( &hmac, + tls12_prf->key, + tls12_prf->key_len, + hash_alg ); + if( status != PSA_SUCCESS ) + goto cleanup; + + status = psa_hash_update( &hmac.hash_ctx, + Ai, Ai_len ); + if( status != PSA_SUCCESS ) + goto cleanup; + + status = psa_hmac_finish_internal( &hmac, + tls12_prf->Ai_with_seed, + hash_length ); + if( status != PSA_SUCCESS ) + goto cleanup; + /* Compute the next block `HMAC_hash(secret, A(i+1) + seed)`. */ status = psa_hmac_setup_internal( &hmac, tls12_prf->key, From 353e45361d9dc733f1ef5102eda0f0b28864848a Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Thu, 15 Nov 2018 09:53:57 +0000 Subject: [PATCH 6/6] Don't call memcpy() with 0-length arguments The standard prohibits calling memcpy() with NULL pointer arguments, even if the size argument is 0. The TLS-1.2 PRF generator setup function previously called memcpy() with the label and salt as the source, even if they were of length 0, as exercised by the derive_key_policy test case in the PSA crypto test suite. This commit adds guards around the memcpy() calls so that they are only executed of salt or label have positive length, respectively. --- library/psa_crypto.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 5ee43e4d6..f0de86124 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -3708,9 +3708,17 @@ static psa_status_t psa_generator_tls12_prf_setup( /* Write `label + seed' at the end of the `A(i) + seed` buffer, * leaving the initial `hash_length` bytes unspecified for now. */ - memcpy( tls12_prf->Ai_with_seed + hash_length, label, label_length ); - memcpy( tls12_prf->Ai_with_seed + hash_length + label_length, - salt, salt_length ); + if( label_length != 0 ) + { + memcpy( tls12_prf->Ai_with_seed + hash_length, + label, label_length ); + } + + if( salt_length != 0 ) + { + memcpy( tls12_prf->Ai_with_seed + hash_length + label_length, + salt, salt_length ); + } /* The first block gets generated when * psa_generator_read() is called. */