From a0c0655c912500e96a5d78f93e76d90261b16825 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 21 May 2019 15:54:54 +0200 Subject: [PATCH 1/8] Add missing declarations to the API document PSA_KEY_ATTRIBUTES_INIT and psa_key_attributes_init weren't declared in the API document, only defined in our implementation, but they are referenced in the API document. --- include/psa/crypto.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index f4198c8d0..f1a290d7b 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -204,6 +204,22 @@ psa_status_t psa_crypto_init(void); */ typedef struct psa_key_attributes_s psa_key_attributes_t; +/** \def PSA_KEY_ATTRIBUTES_INIT + * + * This macro returns a suitable initializer for a key attribute structure + * of type #psa_key_attributes_t. + */ +#ifdef __DOXYGEN_ONLY__ +/* This is an example definition for documentation purposes. + * Implementations should define a suitable value in `crypto_struct.h`. + */ +#define PSA_KEY_ATTRIBUTES_INIT {0} +#endif + +/** Return an initial value for a key attributes structure. + */ +static psa_key_attributes_t psa_key_attributes_init(void); + /** Declare a key as persistent and set its key identifier. * * If the attribute structure currently declares the key as volatile (which From d7d43b9791c1fe84c8c96a4a54d837e3999eca42 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 21 May 2019 15:56:03 +0200 Subject: [PATCH 2/8] Convert code samples to the new attribute-based key creation API --- include/psa/crypto_sizes.h | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/include/psa/crypto_sizes.h b/include/psa/crypto_sizes.h index e7b0bb444..02c1892e8 100644 --- a/include/psa/crypto_sizes.h +++ b/include/psa/crypto_sizes.h @@ -641,14 +641,16 @@ * The following code illustrates how to allocate enough memory to export * a key by querying the key type and size at runtime. * \code{c} - * psa_key_type_t key_type; - * size_t key_bits; + * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; * psa_status_t status; - * status = psa_get_key_information(key, &key_type, &key_bits); + * status = psa_get_key_attributes(key, &attributes); * if (status != PSA_SUCCESS) handle_error(...); + * psa_key_type_t key_type = psa_get_key_type(&attributes); + * size_t key_bits = psa_get_key_bits(&attributes); * size_t buffer_size = PSA_KEY_EXPORT_MAX_SIZE(key_type, key_bits); + * psa_reset_key_attributes(&attributes); * unsigned char *buffer = malloc(buffer_size); - * if (buffer != NULL) handle_error(...); + * if (buffer == NULL) handle_error(...); * size_t buffer_length; * status = psa_export_key(key, buffer, buffer_size, &buffer_length); * if (status != PSA_SUCCESS) handle_error(...); @@ -658,15 +660,17 @@ * public key type. You can use the macro #PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR * to convert a key pair type to the corresponding public key type. * \code{c} - * psa_key_type_t key_type; - * size_t key_bits; + * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; * psa_status_t status; - * status = psa_get_key_information(key, &key_type, &key_bits); + * status = psa_get_key_attributes(key, &attributes); * if (status != PSA_SUCCESS) handle_error(...); + * psa_key_type_t key_type = psa_get_key_type(&attributes); * psa_key_type_t public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(key_type); + * size_t key_bits = psa_get_key_bits(&attributes); * size_t buffer_size = PSA_KEY_EXPORT_MAX_SIZE(public_key_type, key_bits); + * psa_reset_key_attributes(&attributes); * unsigned char *buffer = malloc(buffer_size); - * if (buffer != NULL) handle_error(...); + * if (buffer == NULL) handle_error(...); * size_t buffer_length; * status = psa_export_public_key(key, buffer, buffer_size, &buffer_length); * if (status != PSA_SUCCESS) handle_error(...); From 4754cdeef806f5167edc0d140b7fce52581c9aa5 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 21 May 2019 15:56:29 +0200 Subject: [PATCH 3/8] Improve description of psa_open_key() Remove obsolete reference to psa_make_key_persistent(). --- include/psa/crypto.h | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index f1a290d7b..f099967a0 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -461,10 +461,17 @@ void psa_reset_key_attributes(psa_key_attributes_t *attributes); /** Open a handle to an existing persistent key. * - * Open a handle to a key which was previously created with - * psa_make_key_persistent() when setting its attributes. - * The handle should eventually be closed with psa_close_key() - * to release associated resources. + * Open a handle to a persistent key. A key is persistent if it was created + * with a lifetime other than #PSA_KEY_LIFETIME_VOLATILE. A persistent key + * always has a nonzero key identifier, set with psa_set_key_id() when + * creating the key. Implementations may provide additional pre-provisioned + * keys with identifiers in the range + * #PSA_KEY_ID_VENDOR_MIN–#PSA_KEY_ID_VENDOR_MAX. + * + * The application must eventually close the handle with psa_close_key() + * to release associated resources. If the application dies without calling + * psa_close_key(), the implementation should perform the equivalent of a + * call to psa_close_key(). * * Implementations may provide additional keys that can be opened with * psa_open_key(). Such keys have a key identifier in the vendor range, From 6c6195d7bab6edc0664fa552695efb4752887460 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 21 May 2019 15:57:11 +0200 Subject: [PATCH 4/8] Remove implementation comment from API specification --- include/psa/crypto_types.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/psa/crypto_types.h b/include/psa/crypto_types.h index 02c26788f..156838daf 100644 --- a/include/psa/crypto_types.h +++ b/include/psa/crypto_types.h @@ -46,8 +46,8 @@ * * This is either #PSA_SUCCESS (which is zero), indicating success, * or a nonzero value indicating that an error occurred. Errors are - * encoded as one of the \c PSA_ERROR_xxx values defined here. - * If #PSA_SUCCESS is already defined, it means that #psa_status_t + * encoded as one of the \c PSA_ERROR_xxx values defined here. */ +/* If #PSA_SUCCESS is already defined, it means that #psa_status_t * is also defined in an external header, so prevent its multiple * definition. */ From 2cb9e39b505eeaf6b9e2859027f64adc1d2f8646 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 21 May 2019 15:58:13 +0200 Subject: [PATCH 5/8] Convert TLS1.2 KDF descriptions to multistep key derivation Convert the description of PSA_ALG_TLS12_PRF and PSA_ALG_TLS12_PSK_TO_MS to the key derivation API that takes one input at a time rather than the old {secret,salt,label} interface. Define a new input category "seed". --- include/psa/crypto_values.h | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index c50b63742..b78d11a3b 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -1232,11 +1232,14 @@ * specified in Section 5 of RFC 5246. It is based on HMAC and can be * used with either SHA-256 or SHA-384. * - * For the application to TLS-1.2, the salt and label arguments passed - * to psa_key_derivation() are what's called 'seed' and 'label' in RFC 5246, - * respectively. For example, for TLS key expansion, the salt is the + * This key derivation algorithm uses the following inputs: + * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key. + * - #PSA_KEY_DERIVATION_INPUT_LABEL is the label. + * - #PSA_KEY_DERIVATION_INPUT_SEED is the seed. + * + * For the application to TLS-1.2 key expansion, the seed is the * concatenation of ServerHello.Random + ClientHello.Random, - * while the label is "key expansion". + * and the label is "key expansion". * * For example, `PSA_ALG_TLS12_PRF(PSA_ALG_SHA256)` represents the * TLS 1.2 PRF using HMAC-SHA-256. @@ -1273,10 +1276,15 @@ * The latter is based on HMAC and can be used with either SHA-256 * or SHA-384. * - * For the application to TLS-1.2, the salt passed to psa_key_derivation() - * (and forwarded to the TLS-1.2 PRF) is the concatenation of the - * ClientHello.Random + ServerHello.Random, while the label is "master secret" - * or "extended master secret". + * This key derivation algorithm uses the following inputs: + * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key. + * - #PSA_KEY_DERIVATION_INPUT_LABEL is the label. + * - #PSA_KEY_DERIVATION_INPUT_SEED is the seed. + * + * For the application to TLS-1.2, the seed (which is + * forwarded to the TLS-1.2 PRF) is the concatenation of the + * ClientHello.Random + ServerHello.Random, + * and the label is "master secret" or "extended master secret". * * For example, `PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA256)` represents the * TLS-1.2 PSK to MasterSecret derivation PRF using HMAC-SHA-256. @@ -1586,6 +1594,12 @@ */ #define PSA_KEY_DERIVATION_INPUT_INFO ((psa_key_derivation_step_t)0x0203) +/** A seed for key derivation. + * + * This must be a direct input. + */ +#define PSA_KEY_DERIVATION_INPUT_SEED ((psa_key_derivation_step_t)0x0204) + /**@}*/ #endif /* PSA_CRYPTO_VALUES_H */ From 56e2dc8010902bdfb6ba87658b510e943b06dbcc Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 21 May 2019 15:59:56 +0200 Subject: [PATCH 6/8] Use "sufficient buffer size" in buffer size macros Don't use "safe buffer size", because this it's somewhat misleading to make it about safety: a buffer size that's too small will lead to a runtime error, not to undefined behavior. --- include/psa/crypto_sizes.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/include/psa/crypto_sizes.h b/include/psa/crypto_sizes.h index 02c1892e8..f0f31e6dc 100644 --- a/include/psa/crypto_sizes.h +++ b/include/psa/crypto_sizes.h @@ -426,9 +426,9 @@ #define PSA_ECDSA_SIGNATURE_SIZE(curve_bits) \ (PSA_BITS_TO_BYTES(curve_bits) * 2) -/** Safe signature buffer size for psa_asymmetric_sign(). +/** Sufficient signature buffer size for psa_asymmetric_sign(). * - * This macro returns a safe buffer size for a signature using a key + * This macro returns a sufficient buffer size for a signature using a key * of the specified type and size, with the specified algorithm. * Note that the actual size of the signature may be smaller * (some algorithms produce a variable-size signature). @@ -457,9 +457,9 @@ PSA_KEY_TYPE_IS_ECC(key_type) ? PSA_ECDSA_SIGNATURE_SIZE(key_bits) : \ ((void)alg, 0)) -/** Safe output buffer size for psa_asymmetric_encrypt(). +/** Sufficient output buffer size for psa_asymmetric_encrypt(). * - * This macro returns a safe buffer size for a ciphertext produced using + * This macro returns a sufficient buffer size for a ciphertext produced using * a key of the specified type and size, with the specified algorithm. * Note that the actual size of the ciphertext may be smaller, depending * on the algorithm. @@ -488,9 +488,9 @@ ((void)alg, PSA_BITS_TO_BYTES(key_bits)) : \ 0) -/** Safe output buffer size for psa_asymmetric_decrypt(). +/** Sufficient output buffer size for psa_asymmetric_decrypt(). * - * This macro returns a safe buffer size for a ciphertext produced using + * This macro returns a sufficient buffer size for a ciphertext produced using * a key of the specified type and size, with the specified algorithm. * Note that the actual size of the ciphertext may be smaller, depending * on the algorithm. @@ -629,7 +629,7 @@ #define PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(key_bits) \ (PSA_BITS_TO_BYTES(key_bits)) -/** Safe output buffer size for psa_export_key() or psa_export_public_key(). +/** Sufficient output buffer size for psa_export_key() or psa_export_public_key(). * * This macro returns a compile-time constant if its arguments are * compile-time constants. From 737c6bef6a4509586023ce627c6eb0e540661ed9 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 21 May 2019 16:01:06 +0200 Subject: [PATCH 7/8] Fix grammar --- include/psa/crypto_values.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index b78d11a3b..d766b9d24 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -373,7 +373,7 @@ */ #define PSA_KEY_TYPE_DERIVE ((psa_key_type_t)0x52000000) -/** Key for an cipher, AEAD or MAC algorithm based on the AES block cipher. +/** Key for a cipher, AEAD or MAC algorithm based on the AES block cipher. * * The size of the key can be 16 bytes (AES-128), 24 bytes (AES-192) or * 32 bytes (AES-256). @@ -391,7 +391,7 @@ */ #define PSA_KEY_TYPE_DES ((psa_key_type_t)0x40000002) -/** Key for an cipher, AEAD or MAC algorithm based on the +/** Key for a cipher, AEAD or MAC algorithm based on the * Camellia block cipher. */ #define PSA_KEY_TYPE_CAMELLIA ((psa_key_type_t)0x40000003) From a741d39893e017941136dd994c2ff61f0329106e Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 21 May 2019 16:01:09 +0200 Subject: [PATCH 8/8] State that all error codes are negative --- include/psa/crypto_types.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/psa/crypto_types.h b/include/psa/crypto_types.h index 156838daf..7f0f38cdd 100644 --- a/include/psa/crypto_types.h +++ b/include/psa/crypto_types.h @@ -45,7 +45,7 @@ * \brief Function return status. * * This is either #PSA_SUCCESS (which is zero), indicating success, - * or a nonzero value indicating that an error occurred. Errors are + * or a small negative value indicating that an error occurred. Errors are * encoded as one of the \c PSA_ERROR_xxx values defined here. */ /* If #PSA_SUCCESS is already defined, it means that #psa_status_t * is also defined in an external header, so prevent its multiple