diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 84026c91c8..c6a13acb8d 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -105,8 +105,7 @@ psa_status_t psa_crypto_init(void); * and its lifetime. * - The key's policy, comprising usage flags and a specification of * the permitted algorithm(s). - * - Information about the key itself: the key type, the key size, and - * for some key type additional domain parameters. + * - Information about the key itself: the key type and its size. * - Implementations may define additional attributes. * * The actual key material is not considered an attribute of a key. @@ -167,7 +166,7 @@ psa_status_t psa_crypto_init(void); * * - lifetime: #PSA_KEY_LIFETIME_VOLATILE. * - key identifier: unspecified. - * - type: \c 0, with no domain parameters. + * - type: \c 0. * - key size: \c 0. * - usage flags: \c 0. * - algorithm: \c 0. @@ -179,8 +178,7 @@ psa_status_t psa_crypto_init(void); * location. * -# Set the key policy with psa_set_key_usage_flags() and * psa_set_key_algorithm(). - * -# Set the key type with psa_set_key_type(). If the key type requires - * domain parameters, call psa_set_key_domain_parameters() instead. + * -# Set the key type with psa_set_key_type(). * Skip this step if copying an existing key with psa_copy_key(). * -# When generating a random key with psa_generate_random_key() or deriving a key * with psa_key_derivation_output_key(), set the desired key size with @@ -189,11 +187,11 @@ psa_status_t psa_crypto_init(void); * psa_key_derivation_output_key() or psa_copy_key(). This function reads * the attribute structure, creates a key with these attributes, and * outputs a handle to the newly created key. - * -# The attribute structure is now no longer necessary. If you called - * psa_set_key_domain_parameters() earlier, you must call - * psa_reset_key_attributes() to free any resources used by the - * domain parameters. Otherwise calling psa_reset_key_attributes() - * is optional. + * -# The attribute structure is now no longer necessary. + * You may call psa_reset_key_attributes(), although this is optional + * with the workflow presented here because the attributes currently + * defined in this specification do not require any additional resources + * beyond the structure itself. * * A typical sequence to query a key's attributes is as follows: * -# Call psa_get_key_attributes(). @@ -349,10 +347,7 @@ static psa_algorithm_t psa_get_key_algorithm( /** Declare the type of a key. * - * If a type requires domain parameters, you must call - * psa_set_key_domain_parameters() instead of this function. - * - * This function overwrites any key type and domain parameters + * This function overwrites any key type * previously set in \p attributes. * * This function may be declared as `static` (i.e. without external @@ -403,97 +398,6 @@ static psa_key_type_t psa_get_key_type(const psa_key_attributes_t *attributes); */ static size_t psa_get_key_bits(const psa_key_attributes_t *attributes); -/** - * \brief Set domain parameters for a key. - * - * Some key types require additional domain parameters in addition to - * the key type identifier and the key size. - * The format for the required domain parameters varies by the key type. - * - * - For RSA keys (#PSA_KEY_TYPE_RSA_PUBLIC_KEY or #PSA_KEY_TYPE_RSA_KEYPAIR), - * the domain parameter data consists of the public exponent, - * represented as a big-endian integer with no leading zeros. - * This information is used when generating an RSA key pair. - * When importing a key, the public exponent is read from the imported - * key data and the exponent recorded in the attribute structure is ignored. - * As an exception, the public exponent 65537 is represented by an empty - * byte string. - * - For DSA keys (#PSA_KEY_TYPE_DSA_PUBLIC_KEY or #PSA_KEY_TYPE_DSA_KEYPAIR), - * the `Dss-Parms` format as defined by RFC 3279 §2.3.2. - * ``` - * Dss-Parms ::= SEQUENCE { - * p INTEGER, - * q INTEGER, - * g INTEGER - * } - * ``` - * - For Diffie-Hellman key exchange keys (#PSA_KEY_TYPE_DH_PUBLIC_KEY or - * #PSA_KEY_TYPE_DH_KEYPAIR), the - * `DomainParameters` format as defined by RFC 3279 §2.3.3. - * ``` - * DomainParameters ::= SEQUENCE { - * p INTEGER, -- odd prime, p=jq +1 - * g INTEGER, -- generator, g - * q INTEGER, -- factor of p-1 - * j INTEGER OPTIONAL, -- subgroup factor - * validationParms ValidationParms OPTIONAL - * } - * ValidationParms ::= SEQUENCE { - * seed BIT STRING, - * pgenCounter INTEGER - * } - * ``` - * - * \note This function may allocate memory or other resources. - * Once you have called this function on an attribute structure, - * you must call psa_reset_key_attributes() to free these resources. - * - * \param[in,out] attributes Attribute structure where the specified domain - * parameters will be stored. - * If this function fails, the content of - * \p attributes is not modified. - * \param type Key type (a \c PSA_KEY_TYPE_XXX value). - * \param[in] data Buffer containing the key domain parameters. - * The content of this buffer is interpreted - * according to \p type as described above. - * \param data_length Size of the \p data buffer in bytes. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \retval #PSA_ERROR_NOT_SUPPORTED - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - */ -psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes, - psa_key_type_t type, - const uint8_t *data, - size_t data_length); - -/** - * \brief Get domain parameters for a key. - * - * Get the domain parameters for a key with this function, if any. The format - * of the domain parameters written to \p data is specified in the - * documentation for psa_set_key_domain_parameters(). - * - * \param[in] attributes The key attribute structure to query. - * \param[out] data On success, the key domain parameters. - * \param data_size Size of the \p data buffer in bytes. - * The buffer is guaranteed to be large - * enough if its size in bytes is at least - * the value given by - * PSA_KEY_DOMAIN_PARAMETERS_SIZE(). - * \param[out] data_length On success, the number of bytes - * that make up the key domain parameters data. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - */ -psa_status_t psa_get_key_domain_parameters( - const psa_key_attributes_t *attributes, - uint8_t *data, - size_t data_size, - size_t *data_length); - /** Retrieve the attributes of a key. * * This function first resets the attribute structure as with @@ -617,9 +521,8 @@ psa_status_t psa_close_key(psa_key_handle_t handle); * \param[out] handle On success, a handle to the newly created key. * \c 0 on failure. * \param[in] data Buffer containing the key data. The content of this - * buffer is interpreted according to the type and, - * if applicable, domain parameters declared in - * \p attributes. + * buffer is interpreted according to the type declared + * in \p attributes. * All implementations must support at least the format * described in the documentation * of psa_export_key() or psa_export_public_key() for @@ -738,10 +641,6 @@ psa_status_t psa_destroy_key(psa_key_handle_t handle); * coefficient INTEGER, -- (inverse of q) mod p * } * ``` - * - For DSA private keys (#PSA_KEY_TYPE_DSA_KEYPAIR), the format is the - * representation of the private key `x` as a big-endian byte string. The - * length of the byte string is the private key size in bytes (leading zeroes - * are not stripped). * - For elliptic curve key pairs (key types for which * #PSA_KEY_TYPE_IS_ECC_KEYPAIR is true), the format is * a representation of the private value as a `ceiling(m/8)`-byte string @@ -753,7 +652,8 @@ psa_status_t psa_destroy_key(psa_key_handle_t handle); * and `PSA_ECC_CURVE_BRAINPOOL_PXXX`). * This is the content of the `privateKey` field of the `ECPrivateKey` * format defined by RFC 5915. - * - For Diffie-Hellman key exchange key pairs (#PSA_KEY_TYPE_DH_KEYPAIR), the + * - For Diffie-Hellman key exchange key pairs (key types for which + * #PSA_KEY_TYPE_IS_DH_KEYPAIR is true), the * format is the representation of the private key `x` as a big-endian byte * string. The length of the byte string is the private key size in bytes * (leading zeroes are not stripped). @@ -822,11 +722,8 @@ psa_status_t psa_export_key(psa_key_handle_t handle, * - The byte 0x04; * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; * - `y_P` as a `ceiling(m/8)`-byte string, big-endian. - * - For DSA public keys (#PSA_KEY_TYPE_DSA_PUBLIC_KEY), the format is the - * representation of the public key `y = g^x mod p` as a big-endian byte - * string. The length of the byte string is the length of the base prime `p` - * in bytes. - * - For Diffie-Hellman key exchange public keys (#PSA_KEY_TYPE_DH_PUBLIC_KEY), + * - For Diffie-Hellman key exchange public keys (key types for which + * #PSA_KEY_TYPE_IS_DH_PUBLIC_KEY is true), * the format is the representation of the public key `y = g^x mod p` as a * big-endian byte string. The length of the byte string is the length of the * base prime `p` in bytes. @@ -910,9 +807,6 @@ psa_status_t psa_export_public_key(psa_key_handle_t handle, * - The key type and size may be 0. If either is * nonzero, it must match the corresponding * attribute of the source key. - * - If \p attributes contains domain parameters, - * they must match the domain parameters of - * the source key. * - The key location (the lifetime and, for * persistent keys, the key identifier) is * used directly. @@ -936,7 +830,7 @@ psa_status_t psa_export_public_key(psa_key_handle_t handle, * The policy constraints on the source and specified in * \p attributes are incompatible. * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p attributes specifies a key type, domain parameters or key size + * \p attributes specifies a key type or key size * which does not match the attributes of the source key. * \retval #PSA_ERROR_NOT_PERMITTED * The source key does not have the #PSA_KEY_USAGE_COPY usage flag. @@ -3353,8 +3247,8 @@ psa_status_t psa_key_derivation_output_bytes( * discard the first 8 bytes, use the next 8 bytes as the first key, * and continue reading output from the operation to derive the other * two keys). - * - Finite-field Diffie-Hellman keys (#PSA_KEY_TYPE_DH_KEYPAIR), - * DSA keys (#PSA_KEY_TYPE_DSA_KEYPAIR), and + * - Finite-field Diffie-Hellman keys (#PSA_KEY_TYPE_DH_KEYPAIR(\c group) + * where \c group designates any Diffie-Hellman group) and * ECC keys on a Weierstrass elliptic curve * (#PSA_KEY_TYPE_ECC_KEYPAIR(\c curve) where \c curve designates a * Weierstrass curve). @@ -3529,19 +3423,12 @@ psa_status_t psa_generate_random(uint8_t *output, * The key is generated randomly. * Its location, policy, type and size are taken from \p attributes. * - * If the type requires additional domain parameters, these are taken - * from \p attributes as well. The following types use domain parameters: - * - When generating an RSA key (#PSA_KEY_TYPE_RSA_KEYPAIR), - * the default public exponent is 65537. This value is used if - * \p attributes was set with psa_set_key_type() or by passing an empty - * byte string as domain parameters to psa_set_key_domain_parameters(). - * If psa_set_key_domain_parameters() was used to set a non-empty - * domain parameter string in \p attributes, this string is read as - * a big-endian integer which is used as the public exponent. - * - When generating a DSA key (#PSA_KEY_TYPE_DSA_KEYPAIR) or a - * Diffie-Hellman key (#PSA_KEY_TYPE_DH_KEYPAIR), the domain parameters - * from \p attributes are interpreted as described for - * psa_set_key_domain_parameters(). + * The following type-specific considerations apply: + * - For RSA keys (#PSA_KEY_TYPE_RSA_KEYPAIR), + * the public exponent is 65537. + * The modulus is a product of two probabilistic primes + * between 2^{n-1} and 2^n where n is the bit size specified in the + * attributes. * * \param[in] attributes The attributes for the new key. * \param[out] handle On success, a handle to the newly created key. diff --git a/include/psa/crypto_extra.h b/include/psa/crypto_extra.h index 45655ddfc4..4ffd858e4a 100644 --- a/include/psa/crypto_extra.h +++ b/include/psa/crypto_extra.h @@ -444,6 +444,248 @@ psa_status_t psa_generate_random_key_to_handle(psa_key_handle_t handle, /**@}*/ + +/** \addtogroup crypto_types + * @{ + */ + +/** DSA public key. + * + * The import and export format is the + * representation of the public key `y = g^x mod p` as a big-endian byte + * string. The length of the byte string is the length of the base prime `p` + * in bytes. + */ +#define PSA_KEY_TYPE_DSA_PUBLIC_KEY ((psa_key_type_t)0x60020000) + +/** DSA key pair (private and public key). + * + * The import and export format is the + * representation of the private key `x` as a big-endian byte string. The + * length of the byte string is the private key size in bytes (leading zeroes + * are not stripped). + * + * Determinstic DSA key derivation with psa_generate_derived_key follows + * FIPS 186-4 §B.1.2: interpret the byte string as integer + * in big-endian order. Discard it if it is not in the range + * [0, *N* - 2] where *N* is the boundary of the private key domain + * (the prime *p* for Diffie-Hellman, the subprime *q* for DSA, + * or the order of the curve's base point for ECC). + * Add 1 to the resulting integer and use this as the private key *x*. + * + */ +#define PSA_KEY_TYPE_DSA_KEYPAIR ((psa_key_type_t)0x70020000) + +/** Whether a key type is an DSA key (pair or public-only). */ +#define PSA_KEY_TYPE_IS_DSA(type) \ + (PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR(type) == PSA_KEY_TYPE_DSA_PUBLIC_KEY) + +#define PSA_ALG_DSA_BASE ((psa_algorithm_t)0x10040000) +/** DSA signature with hashing. + * + * This is the signature scheme defined by FIPS 186-4, + * with a random per-message secret number (*k*). + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding DSA signature algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_DSA(hash_alg) \ + (PSA_ALG_DSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +#define PSA_ALG_DETERMINISTIC_DSA_BASE ((psa_algorithm_t)0x10050000) +#define PSA_ALG_DSA_DETERMINISTIC_FLAG ((psa_algorithm_t)0x00010000) +/** Deterministic DSA signature with hashing. + * + * This is the deterministic variant defined by RFC 6979 of + * the signature scheme defined by FIPS 186-4. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding DSA signature algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_DETERMINISTIC_DSA(hash_alg) \ + (PSA_ALG_DETERMINISTIC_DSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +#define PSA_ALG_IS_DSA(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_DSA_DETERMINISTIC_FLAG) == \ + PSA_ALG_DSA_BASE) +#define PSA_ALG_DSA_IS_DETERMINISTIC(alg) \ + (((alg) & PSA_ALG_DSA_DETERMINISTIC_FLAG) != 0) +#define PSA_ALG_IS_DETERMINISTIC_DSA(alg) \ + (PSA_ALG_IS_DSA(alg) && PSA_ALG_DSA_IS_DETERMINISTIC(alg)) +#define PSA_ALG_IS_RANDOMIZED_DSA(alg) \ + (PSA_ALG_IS_DSA(alg) && !PSA_ALG_DSA_IS_DETERMINISTIC(alg)) + + +/* We need to expand the sample definition of this macro from + * the API definition. */ +#undef PSA_ALG_IS_HASH_AND_SIGN +#define PSA_ALG_IS_HASH_AND_SIGN(alg) \ + (PSA_ALG_IS_RSA_PSS(alg) || PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || \ + PSA_ALG_IS_DSA(alg) || PSA_ALG_IS_ECDSA(alg)) + +/**@}*/ + +/** \addtogroup attributes + * @{ + */ + +/** Custom Diffie-Hellman group. + * + * For keys of type #PSA_KEY_TYPE_DH_PUBLIC_KEY(#PSA_DH_GROUP_CUSTOM) or + * #PSA_KEY_TYPE_DH_KEYPAIR(#PSA_DH_GROUP_CUSTOM), the group data comes + * from domain parameters set by psa_set_key_domain_parameters(). + */ +/* This value is reserved for private use in the TLS named group registry. */ +#define PSA_DH_GROUP_CUSTOM ((psa_dh_group_t) 0x01fc) + + +/** + * \brief Set domain parameters for a key. + * + * Some key types require additional domain parameters in addition to + * the key type identifier and the key size. Use this function instead + * of psa_set_key_type() when you need to specify domain parameters. + * + * The format for the required domain parameters varies based on the key type. + * + * - For RSA keys (#PSA_KEY_TYPE_RSA_PUBLIC_KEY or #PSA_KEY_TYPE_RSA_KEYPAIR), + * the domain parameter data consists of the public exponent, + * represented as a big-endian integer with no leading zeros. + * This information is used when generating an RSA key pair. + * When importing a key, the public exponent is read from the imported + * key data and the exponent recorded in the attribute structure is ignored. + * As an exception, the public exponent 65537 is represented by an empty + * byte string. + * - For DSA keys (#PSA_KEY_TYPE_DSA_PUBLIC_KEY or #PSA_KEY_TYPE_DSA_KEYPAIR), + * the `Dss-Parms` format as defined by RFC 3279 §2.3.2. + * ``` + * Dss-Parms ::= SEQUENCE { + * p INTEGER, + * q INTEGER, + * g INTEGER + * } + * ``` + * - For Diffie-Hellman key exchange keys + * (#PSA_KEY_TYPE_DH_PUBLIC_KEY(#PSA_DH_GROUP_CUSTOM) or + * #PSA_KEY_TYPE_DH_KEYPAIR(#PSA_DH_GROUP_CUSTOM)), the + * `DomainParameters` format as defined by RFC 3279 §2.3.3. + * ``` + * DomainParameters ::= SEQUENCE { + * p INTEGER, -- odd prime, p=jq +1 + * g INTEGER, -- generator, g + * q INTEGER, -- factor of p-1 + * j INTEGER OPTIONAL, -- subgroup factor + * validationParms ValidationParms OPTIONAL + * } + * ValidationParms ::= SEQUENCE { + * seed BIT STRING, + * pgenCounter INTEGER + * } + * ``` + * + * \note This function may allocate memory or other resources. + * Once you have called this function on an attribute structure, + * you must call psa_reset_key_attributes() to free these resources. + * + * \note This is an experimental extension to the interface. It may change + * in future versions of the library. + * + * \param[in,out] attributes Attribute structure where the specified domain + * parameters will be stored. + * If this function fails, the content of + * \p attributes is not modified. + * \param type Key type (a \c PSA_KEY_TYPE_XXX value). + * \param[in] data Buffer containing the key domain parameters. + * The content of this buffer is interpreted + * according to \p type as described above. + * \param data_length Size of the \p data buffer in bytes. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + */ +psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes, + psa_key_type_t type, + const uint8_t *data, + size_t data_length); + +/** + * \brief Get domain parameters for a key. + * + * Get the domain parameters for a key with this function, if any. The format + * of the domain parameters written to \p data is specified in the + * documentation for psa_set_key_domain_parameters(). + * + * \note This is an experimental extension to the interface. It may change + * in future versions of the library. + * + * \param[in] attributes The key attribute structure to query. + * \param[out] data On success, the key domain parameters. + * \param data_size Size of the \p data buffer in bytes. + * The buffer is guaranteed to be large + * enough if its size in bytes is at least + * the value given by + * PSA_KEY_DOMAIN_PARAMETERS_SIZE(). + * \param[out] data_length On success, the number of bytes + * that make up the key domain parameters data. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + */ +psa_status_t psa_get_key_domain_parameters( + const psa_key_attributes_t *attributes, + uint8_t *data, + size_t data_size, + size_t *data_length); + +/** Safe output buffer size for psa_get_key_domain_parameters(). + * + * This macro returns a compile-time constant if its arguments are + * compile-time constants. + * + * \warning This function may call its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \note This is an experimental extension to the interface. It may change + * in future versions of the library. + * + * \param key_type A supported key type. + * \param key_bits The size of the key in bits. + * + * \return If the parameters are valid and supported, return + * a buffer size in bytes that guarantees that + * psa_get_key_domain_parameters() will not fail with + * #PSA_ERROR_BUFFER_TOO_SMALL. + * If the parameters are a valid combination that is not supported + * by the implementation, this macro shall return either a + * sensible size or 0. + * If the parameters are not valid, the + * return value is unspecified. + */ +#define PSA_KEY_DOMAIN_PARAMETERS_SIZE(key_type, key_bits) \ + (PSA_KEY_TYPE_IS_RSA(key_type) ? sizeof(int) : \ + PSA_KEY_TYPE_IS_DH(key_type) ? PSA_DH_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) : \ + PSA_KEY_TYPE_IS_DSA(key_type) ? PSA_DSA_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) : \ + 0) +#define PSA_DH_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) \ + (4 + (PSA_BITS_TO_BYTES(key_bits) + 5) * 3 /*without optional parts*/) +#define PSA_DSA_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) \ + (4 + (PSA_BITS_TO_BYTES(key_bits) + 5) * 2 /*p, g*/ + 34 /*q*/) + +/**@}*/ + #ifdef __cplusplus } #endif diff --git a/include/psa/crypto_sizes.h b/include/psa/crypto_sizes.h index cab896e8a4..d7eb482724 100644 --- a/include/psa/crypto_sizes.h +++ b/include/psa/crypto_sizes.h @@ -447,7 +447,7 @@ * psa_asymmetric_sign() will not fail with * #PSA_ERROR_BUFFER_TOO_SMALL. * If the parameters are a valid combination that is not supported - * by the implementation, this macro either shall return either a + * by the implementation, this macro shall return either a * sensible size or 0. * If the parameters are not valid, the * return value is unspecified. @@ -478,7 +478,7 @@ * psa_asymmetric_encrypt() will not fail with * #PSA_ERROR_BUFFER_TOO_SMALL. * If the parameters are a valid combination that is not supported - * by the implementation, this macro either shall return either a + * by the implementation, this macro shall return either a * sensible size or 0. * If the parameters are not valid, the * return value is unspecified. @@ -509,7 +509,7 @@ * psa_asymmetric_decrypt() will not fail with * #PSA_ERROR_BUFFER_TOO_SMALL. * If the parameters are a valid combination that is not supported - * by the implementation, this macro either shall return either a + * by the implementation, this macro shall return either a * sensible size or 0. * If the parameters are not valid, the * return value is unspecified. @@ -680,7 +680,7 @@ * psa_asymmetric_sign() will not fail with * #PSA_ERROR_BUFFER_TOO_SMALL. * If the parameters are a valid combination that is not supported - * by the implementation, this macro either shall return either a + * by the implementation, this macro shall return either a * sensible size or 0. * If the parameters are not valid, the * return value is unspecified. @@ -695,36 +695,4 @@ PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(key_type) ? PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) : \ 0) -/** Safe output buffer size for psa_get_key_domain_parameters(). - * - * This macro returns a compile-time constant if its arguments are - * compile-time constants. - * - * \warning This function may call its arguments multiple times or - * zero times, so you should not pass arguments that contain - * side effects. - * - * \param key_type A supported key type. - * \param key_bits The size of the key in bits. - * - * \return If the parameters are valid and supported, return - * a buffer size in bytes that guarantees that - * psa_get_key_domain_parameters() will not fail with - * #PSA_ERROR_BUFFER_TOO_SMALL. - * If the parameters are a valid combination that is not supported - * by the implementation, this macro either shall return either a - * sensible size or 0. - * If the parameters are not valid, the - * return value is unspecified. - */ -#define PSA_KEY_DOMAIN_PARAMETERS_SIZE(key_type, key_bits) \ - (PSA_KEY_TYPE_IS_RSA(key_type) ? sizeof(int) : \ - PSA_KEY_TYPE_IS_DH(key_type) ? PSA_DH_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) : \ - PSA_KEY_TYPE_IS_DSA(key_type) ? PSA_DSA_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) : \ - 0) -#define PSA_DH_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) \ - (4 + (PSA_BITS_TO_BYTES(key_bits) + 5) * 3 /*without optional parts*/) -#define PSA_DSA_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) \ - (4 + (PSA_BITS_TO_BYTES(key_bits) + 5) * 2 /*p, g*/ + 34 /*q*/) - #endif /* PSA_CRYPTO_SIZES_H */ diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h index 01d3069bf8..885d90888d 100644 --- a/include/psa/crypto_struct.h +++ b/include/psa/crypto_struct.h @@ -331,6 +331,13 @@ static inline psa_algorithm_t psa_get_key_algorithm( return( attributes->policy.alg ); } +/* This function is declared in crypto_extra.h, which comes after this + * header file, but we need the function here, so repeat the declaration. */ +psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes, + psa_key_type_t type, + const uint8_t *data, + size_t data_length); + static inline void psa_set_key_type(psa_key_attributes_t *attributes, psa_key_type_t type) { diff --git a/include/psa/crypto_types.h b/include/psa/crypto_types.h index ced42de1a6..02c26788f2 100644 --- a/include/psa/crypto_types.h +++ b/include/psa/crypto_types.h @@ -68,6 +68,9 @@ typedef uint32_t psa_key_type_t; /** The type of PSA elliptic curve identifiers. */ typedef uint16_t psa_ecc_curve_t; +/** The type of PSA Diffie-Hellman group identifiers. */ +typedef uint16_t psa_dh_group_t; + /** \brief Encoding of a cryptographic algorithm. * * For algorithms that can be applied to multiple key types, this type diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index c54fc9a60f..bab7063392 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -419,14 +419,6 @@ #define PSA_KEY_TYPE_IS_RSA(type) \ (PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR(type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY) -/** DSA public key. */ -#define PSA_KEY_TYPE_DSA_PUBLIC_KEY ((psa_key_type_t)0x60020000) -/** DSA key pair (private and public key). */ -#define PSA_KEY_TYPE_DSA_KEYPAIR ((psa_key_type_t)0x70020000) -/** Whether a key type is an DSA key (pair or public-only). */ -#define PSA_KEY_TYPE_IS_DSA(type) \ - (PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR(type) == PSA_KEY_TYPE_DSA_PUBLIC_KEY) - #define PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE ((psa_key_type_t)0x60030000) #define PSA_KEY_TYPE_ECC_KEYPAIR_BASE ((psa_key_type_t)0x70030000) #define PSA_KEY_TYPE_ECC_CURVE_MASK ((psa_key_type_t)0x0000ffff) @@ -492,14 +484,45 @@ #define PSA_ECC_CURVE_CURVE25519 ((psa_ecc_curve_t) 0x001d) #define PSA_ECC_CURVE_CURVE448 ((psa_ecc_curve_t) 0x001e) -/** Diffie-Hellman key exchange public key. */ -#define PSA_KEY_TYPE_DH_PUBLIC_KEY ((psa_key_type_t)0x60040000) -/** Diffie-Hellman key exchange key pair (private and public key). */ -#define PSA_KEY_TYPE_DH_KEYPAIR ((psa_key_type_t)0x70040000) -/** Whether a key type is a Diffie-Hellman key exchange key (pair or - * public-only). */ -#define PSA_KEY_TYPE_IS_DH(type) \ - (PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR(type) == PSA_KEY_TYPE_DH_PUBLIC_KEY) +#define PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE ((psa_key_type_t)0x60040000) +#define PSA_KEY_TYPE_DH_KEYPAIR_BASE ((psa_key_type_t)0x70040000) +#define PSA_KEY_TYPE_DH_GROUP_MASK ((psa_key_type_t)0x0000ffff) +/** Diffie-Hellman key pair. */ +#define PSA_KEY_TYPE_DH_KEYPAIR(group) \ + (PSA_KEY_TYPE_DH_KEYPAIR_BASE | (group)) +/** Diffie-Hellman public key. */ +#define PSA_KEY_TYPE_DH_PUBLIC_KEY(group) \ + (PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE | (group)) + +/** Whether a key type is a Diffie-Hellman key (pair or public-only). */ +#define PSA_KEY_TYPE_IS_DH(type) \ + ((PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR(type) & \ + ~PSA_KEY_TYPE_DH_GROUP_MASK) == PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE) +/** Whether a key type is a Diffie-Hellman key pair. */ +#define PSA_KEY_TYPE_IS_DH_KEYPAIR(type) \ + (((type) & ~PSA_KEY_TYPE_DH_GROUP_MASK) == \ + PSA_KEY_TYPE_DH_KEYPAIR_BASE) +/** Whether a key type is a Diffie-Hellman public key. */ +#define PSA_KEY_TYPE_IS_DH_PUBLIC_KEY(type) \ + (((type) & ~PSA_KEY_TYPE_DH_GROUP_MASK) == \ + PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE) + +/** Extract the group from a Diffie-Hellman key type. */ +#define PSA_KEY_TYPE_GET_GROUP(type) \ + ((psa_dh_group_t) (PSA_KEY_TYPE_IS_DH(type) ? \ + ((type) & PSA_KEY_TYPE_DH_GROUP_MASK) : \ + 0)) + +/* The encoding of group identifiers is currently aligned with the + * TLS Supported Groups Registry (formerly known as the + * TLS EC Named Curve Registry) + * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 + * The values are defined by RFC 7919. */ +#define PSA_DH_GROUP_FFDHE2048 ((psa_dh_group_t) 0x0100) +#define PSA_DH_GROUP_FFDHE3072 ((psa_dh_group_t) 0x0101) +#define PSA_DH_GROUP_FFDHE4096 ((psa_dh_group_t) 0x0102) +#define PSA_DH_GROUP_FFDHE6144 ((psa_dh_group_t) 0x0103) +#define PSA_DH_GROUP_FFDHE8192 ((psa_dh_group_t) 0x0104) /** The block size of a block cipher. * @@ -667,7 +690,6 @@ * * That is, suppose that `PSA_xxx_SIGNATURE` is one of the following macros: * - #PSA_ALG_RSA_PKCS1V15_SIGN, #PSA_ALG_RSA_PSS, - * - #PSA_ALG_DSA, #PSA_ALG_DETERMINISTIC_DSA, * - #PSA_ALG_ECDSA, #PSA_ALG_DETERMINISTIC_ECDSA. * Then you may create and use a key as follows: * - Set the key usage field using #PSA_ALG_ANY_HASH, for example: @@ -1028,51 +1050,6 @@ #define PSA_ALG_IS_RSA_PSS(alg) \ (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PSS_BASE) -#define PSA_ALG_DSA_BASE ((psa_algorithm_t)0x10040000) -/** DSA signature with hashing. - * - * This is the signature scheme defined by FIPS 186-4, - * with a random per-message secret number (*k*). - * - * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_HASH(\p hash_alg) is true). - * This includes #PSA_ALG_ANY_HASH - * when specifying the algorithm in a usage policy. - * - * \return The corresponding DSA signature algorithm. - * \return Unspecified if \p hash_alg is not a supported - * hash algorithm. - */ -#define PSA_ALG_DSA(hash_alg) \ - (PSA_ALG_DSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) -#define PSA_ALG_DETERMINISTIC_DSA_BASE ((psa_algorithm_t)0x10050000) -#define PSA_ALG_DSA_DETERMINISTIC_FLAG ((psa_algorithm_t)0x00010000) -/** Deterministic DSA signature with hashing. - * - * This is the deterministic variant defined by RFC 6979 of - * the signature scheme defined by FIPS 186-4. - * - * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_HASH(\p hash_alg) is true). - * This includes #PSA_ALG_ANY_HASH - * when specifying the algorithm in a usage policy. - * - * \return The corresponding DSA signature algorithm. - * \return Unspecified if \p hash_alg is not a supported - * hash algorithm. - */ -#define PSA_ALG_DETERMINISTIC_DSA(hash_alg) \ - (PSA_ALG_DETERMINISTIC_DSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) -#define PSA_ALG_IS_DSA(alg) \ - (((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_DSA_DETERMINISTIC_FLAG) == \ - PSA_ALG_DSA_BASE) -#define PSA_ALG_DSA_IS_DETERMINISTIC(alg) \ - (((alg) & PSA_ALG_DSA_DETERMINISTIC_FLAG) != 0) -#define PSA_ALG_IS_DETERMINISTIC_DSA(alg) \ - (PSA_ALG_IS_DSA(alg) && PSA_ALG_DSA_IS_DETERMINISTIC(alg)) -#define PSA_ALG_IS_RANDOMIZED_DSA(alg) \ - (PSA_ALG_IS_DSA(alg) && !PSA_ALG_DSA_IS_DETERMINISTIC(alg)) - #define PSA_ALG_ECDSA_BASE ((psa_algorithm_t)0x10060000) /** ECDSA signature with hashing. * @@ -1156,7 +1133,7 @@ */ #define PSA_ALG_IS_HASH_AND_SIGN(alg) \ (PSA_ALG_IS_RSA_PSS(alg) || PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || \ - PSA_ALG_IS_DSA(alg) || PSA_ALG_IS_ECDSA(alg)) + PSA_ALG_IS_ECDSA(alg)) /** Get the hash used by a hash-and-sign signature algorithm. * diff --git a/programs/psa/psa_constant_names.c b/programs/psa/psa_constant_names.c index 5240b084a4..73692d0228 100644 --- a/programs/psa/psa_constant_names.c +++ b/programs/psa/psa_constant_names.c @@ -64,6 +64,7 @@ static void append_integer(char **buffer, size_t buffer_size, /* The code of these function is automatically generated and included below. */ static const char *psa_ecc_curve_name(psa_ecc_curve_t curve); +static const char *psa_dh_group_name(psa_dh_group_t group); static const char *psa_hash_algorithm_name(psa_algorithm_t hash_alg); static void append_with_curve(char **buffer, size_t buffer_size, @@ -84,6 +85,24 @@ static void append_with_curve(char **buffer, size_t buffer_size, append(buffer, buffer_size, required_size, ")", 1); } +static void append_with_group(char **buffer, size_t buffer_size, + size_t *required_size, + const char *string, size_t length, + psa_dh_group_t group) +{ + const char *group_name = psa_dh_group_name(group); + append(buffer, buffer_size, required_size, string, length); + append(buffer, buffer_size, required_size, "(", 1); + if (group_name != NULL) { + append(buffer, buffer_size, required_size, + group_name, strlen(group_name)); + } else { + append_integer(buffer, buffer_size, required_size, + "0x%04x", group); + } + append(buffer, buffer_size, required_size, ")", 1); +} + typedef const char *(*psa_get_algorithm_name_func_ptr)(psa_algorithm_t alg); static void append_with_alg(char **buffer, size_t buffer_size, @@ -137,6 +156,23 @@ static int psa_snprint_ecc_curve(char *buffer, size_t buffer_size, } } +static int psa_snprint_dh_group(char *buffer, size_t buffer_size, + psa_dh_group_t group) +{ + const char *name = psa_dh_group_name(group); + if (name == NULL) { + return snprintf(buffer, buffer_size, "0x%04x", (unsigned) group); + } else { + size_t length = strlen(name); + if (length < buffer_size) { + memcpy(buffer, name, length + 1); + return (int) length; + } else { + return (int) buffer_size; + } + } +} + static void usage(const char *program_name) { printf("Usage: %s TYPE VALUE [VALUE...]\n", @@ -145,6 +181,7 @@ static void usage(const char *program_name) printf("Supported types (with = between aliases):\n"); printf(" alg=algorithm Algorithm (psa_algorithm_t)\n"); printf(" curve=ecc_curve Elliptic curve identifier (psa_ecc_curve_t)\n"); + printf(" group=dh_group Diffie-Hellman group identifier (psa_dh_group_t)\n"); printf(" type=key_type Key type (psa_key_type_t)\n"); printf(" usage=key_usage Key usage (psa_key_usage_t)\n"); printf(" error=status Status code (psa_status_t)\n"); @@ -188,6 +225,7 @@ int process_signed(signed_value_type type, long min, long max, char **argp) typedef enum { TYPE_ALGORITHM, TYPE_ECC_CURVE, + TYPE_DH_GROUP, TYPE_KEY_TYPE, TYPE_KEY_USAGE, } unsigned_value_type; @@ -216,6 +254,10 @@ int process_unsigned(unsigned_value_type type, unsigned long max, char **argp) psa_snprint_ecc_curve(buffer, sizeof(buffer), (psa_ecc_curve_t) value); break; + case TYPE_DH_GROUP: + psa_snprint_dh_group(buffer, sizeof(buffer), + (psa_dh_group_t) value); + break; case TYPE_KEY_TYPE: psa_snprint_key_type(buffer, sizeof(buffer), (psa_key_type_t) value); @@ -252,6 +294,9 @@ int main(int argc, char *argv[]) } else if (!strcmp(argv[1], "curve") || !strcmp(argv[1], "ecc_curve")) { return process_unsigned(TYPE_ECC_CURVE, (psa_ecc_curve_t) (-1), argv + 2); + } else if (!strcmp(argv[1], "group") || !strcmp(argv[1], "dh_group")) { + return process_unsigned(TYPE_DH_GROUP, (psa_dh_group_t) (-1), + argv + 2); } else if (!strcmp(argv[1], "type") || !strcmp(argv[1], "key_type")) { return process_unsigned(TYPE_KEY_TYPE, (psa_key_type_t) (-1), argv + 2); diff --git a/scripts/generate_psa_constants.py b/scripts/generate_psa_constants.py index dac60034d4..ab7f1341f0 100755 --- a/scripts/generate_psa_constants.py +++ b/scripts/generate_psa_constants.py @@ -22,6 +22,14 @@ static const char *psa_ecc_curve_name(psa_ecc_curve_t curve) } } +static const char *psa_dh_group_name(psa_dh_group_t group) +{ + switch (group) { + %(dh_group_cases)s + default: return NULL; + } +} + static const char *psa_hash_algorithm_name(psa_algorithm_t hash_alg) { switch (hash_alg) { @@ -145,6 +153,12 @@ key_type_from_curve_template = '''if (%(tester)s(type)) { PSA_KEY_TYPE_GET_CURVE(type)); } else ''' +key_type_from_group_template = '''if (%(tester)s(type)) { + append_with_group(&buffer, buffer_size, &required_size, + "%(builder)s", %(builder_length)s, + PSA_KEY_TYPE_GET_GROUP(type)); + } else ''' + algorithm_from_hash_template = '''if (%(tester)s(core_alg)) { append(&buffer, buffer_size, &required_size, "%(builder)s(", %(builder_length)s + 1); @@ -169,7 +183,9 @@ class MacroCollector: self.statuses = set() self.key_types = set() self.key_types_from_curve = {} + self.key_types_from_group = {} self.ecc_curves = set() + self.dh_groups = set() self.algorithms = set() self.hash_algorithms = set() self.ka_algorithms = set() @@ -206,8 +222,12 @@ class MacroCollector: self.key_types.add(name) elif name.startswith('PSA_KEY_TYPE_') and parameter == 'curve': self.key_types_from_curve[name] = name[:13] + 'IS_' + name[13:] + elif name.startswith('PSA_KEY_TYPE_') and parameter == 'group': + self.key_types_from_group[name] = name[:13] + 'IS_' + name[13:] elif name.startswith('PSA_ECC_CURVE_') and not parameter: self.ecc_curves.add(name) + elif name.startswith('PSA_DH_GROUP_') and not parameter: + self.dh_groups.add(name) elif name.startswith('PSA_ALG_') and not parameter: if name in ['PSA_ALG_ECDSA_BASE', 'PSA_ALG_RSA_PKCS1V15_SIGN_BASE']: @@ -265,6 +285,10 @@ class MacroCollector: return '\n '.join(map(self.make_return_case, sorted(self.ecc_curves))) + def make_dh_group_cases(self): + return '\n '.join(map(self.make_return_case, + sorted(self.dh_groups))) + def make_key_type_cases(self): return '\n '.join(map(self.make_append_case, sorted(self.key_types))) @@ -274,11 +298,21 @@ class MacroCollector: 'builder_length': len(builder), 'tester': tester} - def make_key_type_code(self): + def make_key_type_from_group_code(self, builder, tester): + return key_type_from_group_template % {'builder': builder, + 'builder_length': len(builder), + 'tester': tester} + + def make_ecc_key_type_code(self): d = self.key_types_from_curve make = self.make_key_type_from_curve_code return ''.join([make(k, d[k]) for k in sorted(d.keys())]) + def make_dh_key_type_code(self): + d = self.key_types_from_group + make = self.make_key_type_from_group_code + return ''.join([make(k, d[k]) for k in sorted(d.keys())]) + def make_hash_algorithm_cases(self): return '\n '.join(map(self.make_return_case, sorted(self.hash_algorithms))) @@ -309,8 +343,10 @@ class MacroCollector: data = {} data['status_cases'] = self.make_status_cases() data['ecc_curve_cases'] = self.make_ecc_curve_cases() + data['dh_group_cases'] = self.make_dh_group_cases() data['key_type_cases'] = self.make_key_type_cases() - data['key_type_code'] = self.make_key_type_code() + data['key_type_code'] = (self.make_ecc_key_type_code() + + self.make_dh_key_type_code()) data['hash_algorithm_cases'] = self.make_hash_algorithm_cases() data['ka_algorithm_cases'] = self.make_ka_algorithm_cases() data['algorithm_cases'] = self.make_algorithm_cases() diff --git a/tests/scripts/test_psa_constant_names.py b/tests/scripts/test_psa_constant_names.py index 421cf4e48a..cbe68b10d2 100755 --- a/tests/scripts/test_psa_constant_names.py +++ b/tests/scripts/test_psa_constant_names.py @@ -58,6 +58,7 @@ when applicable.''' self.statuses = set(['PSA_SUCCESS']) self.algorithms = set(['0xffffffff']) self.ecc_curves = set(['0xffff']) + self.dh_groups = set(['0xffff']) self.key_types = set(['0xffffffff']) self.key_usage_flags = set(['0x80000000']) # Hard-coded value for unknown algorithms @@ -74,6 +75,7 @@ when applicable.''' 'ERROR': self.statuses, 'ALG': self.algorithms, 'CURVE': self.ecc_curves, + 'GROUP': self.dh_groups, 'KEY_TYPE': self.key_types, 'KEY_USAGE': self.key_usage_flags, } @@ -94,6 +96,7 @@ Call this after parsing all the inputs.''' self.arguments_for['kdf_alg'] = sorted(self.kdf_algorithms) self.arguments_for['aead_alg'] = sorted(self.aead_algorithms) self.arguments_for['curve'] = sorted(self.ecc_curves) + self.arguments_for['group'] = sorted(self.dh_groups) def format_arguments(self, name, arguments): '''Format a macro call with arguments..''' @@ -184,6 +187,8 @@ where each argument takes each possible value at least once.''' self.key_types.add(argument) elif function == 'ecc_key_types': self.ecc_curves.add(argument) + elif function == 'dh_key_types': + self.dh_groups.add(argument) # Regex matching a *.data line containing a test function call and # its arguments. The actual definition is partly positional, but this @@ -299,6 +304,7 @@ not as expected.''' for type, names in [('status', inputs.statuses), ('algorithm', inputs.algorithms), ('ecc_curve', inputs.ecc_curves), + ('dh_group', inputs.dh_groups), ('key_type', inputs.key_types), ('key_usage', inputs.key_usage_flags)]: c, e = do_test(options, inputs, type, names) diff --git a/tests/suites/test_suite_psa_crypto_metadata.data b/tests/suites/test_suite_psa_crypto_metadata.data index 94b80acdda..165b866543 100644 --- a/tests/suites/test_suite_psa_crypto_metadata.data +++ b/tests/suites/test_suite_psa_crypto_metadata.data @@ -454,3 +454,19 @@ ecc_key_types:PSA_ECC_CURVE_CURVE25519:255 ECC key types: Curve448 depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED ecc_key_types:PSA_ECC_CURVE_CURVE448:448 + +DH group types: FFDHE2048 +dh_key_types:PSA_DH_GROUP_FFDHE2048:2048 + +DH group types: FFDHE3072 +dh_key_types:PSA_DH_GROUP_FFDHE3072:2048 + +DH group types: FFDHE4096 +dh_key_types:PSA_DH_GROUP_FFDHE4096:2048 + +DH group types: FFDHE6144 +dh_key_types:PSA_DH_GROUP_FFDHE6144:2048 + +DH group types: FFDHE8192 +dh_key_types:PSA_DH_GROUP_FFDHE8192:2048 + diff --git a/tests/suites/test_suite_psa_crypto_metadata.function b/tests/suites/test_suite_psa_crypto_metadata.function index e1eb1c526d..81b2937fae 100644 --- a/tests/suites/test_suite_psa_crypto_metadata.function +++ b/tests/suites/test_suite_psa_crypto_metadata.function @@ -49,6 +49,7 @@ #define KEY_TYPE_IS_RSA ( 1u << 4 ) #define KEY_TYPE_IS_DSA ( 1u << 5 ) #define KEY_TYPE_IS_ECC ( 1u << 6 ) +#define KEY_TYPE_IS_DH ( 1u << 7 ) #define TEST_CLASSIFICATION_MACRO( flag, alg, flags ) \ TEST_ASSERT( PSA_##flag( alg ) == !! ( ( flags ) & flag ) ) @@ -91,6 +92,7 @@ void key_type_classification( psa_key_type_t type, unsigned flags ) TEST_CLASSIFICATION_MACRO( KEY_TYPE_IS_KEYPAIR, type, flags ); TEST_CLASSIFICATION_MACRO( KEY_TYPE_IS_RSA, type, flags ); TEST_CLASSIFICATION_MACRO( KEY_TYPE_IS_ECC, type, flags ); + TEST_CLASSIFICATION_MACRO( KEY_TYPE_IS_DH, type, flags ); /* Macros with derived semantics */ TEST_EQUAL( PSA_KEY_TYPE_IS_ASYMMETRIC( type ), @@ -102,6 +104,12 @@ void key_type_classification( psa_key_type_t type, unsigned flags ) TEST_EQUAL( PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY( type ), ( PSA_KEY_TYPE_IS_ECC( type ) && PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ) ); + TEST_EQUAL( PSA_KEY_TYPE_IS_DH_KEYPAIR( type ), + ( PSA_KEY_TYPE_IS_DH( type ) && + PSA_KEY_TYPE_IS_KEYPAIR( type ) ) ); + TEST_EQUAL( PSA_KEY_TYPE_IS_DH_PUBLIC_KEY( type ), + ( PSA_KEY_TYPE_IS_DH( type ) && + PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ) ); exit: ; } @@ -457,3 +465,22 @@ void ecc_key_types( int curve_arg, int curve_bits_arg ) TEST_ASSERT( curve_bits <= PSA_VENDOR_ECC_MAX_CURVE_BITS ); } /* END_CASE */ + +/* BEGIN_CASE depends_on:MBEDTLS_DHM_C */ +void dh_key_types( int group_arg, int group_bits_arg ) +{ + psa_dh_group_t group = group_arg; + size_t group_bits = group_bits_arg; + psa_key_type_t public_type = PSA_KEY_TYPE_DH_PUBLIC_KEY( group ); + psa_key_type_t pair_type = PSA_KEY_TYPE_DH_KEYPAIR( group ); + + test_key_type( public_type, KEY_TYPE_IS_DH | KEY_TYPE_IS_PUBLIC_KEY ); + test_key_type( pair_type, KEY_TYPE_IS_DH | KEY_TYPE_IS_KEYPAIR ); + + TEST_EQUAL( PSA_KEY_TYPE_GET_GROUP( public_type ), group ); + TEST_EQUAL( PSA_KEY_TYPE_GET_GROUP( pair_type ), group ); + + /* We have nothing to validate about the group size yet. */ + (void) group_bits; +} +/* END_CASE */