Merge pull request #6010 from mprse/ffdh_import_export

FFDH 1, 2A, 2B: FFDH add support for import/export key, key agreement, key generation + tests
This commit is contained in:
Manuel Pégourié-Gonnard
2023-05-10 11:40:54 +02:00
committed by GitHub
13 changed files with 882 additions and 54 deletions

View File

@@ -69,6 +69,7 @@ set(src_crypto
psa_crypto_client.c
psa_crypto_driver_wrappers.c
psa_crypto_ecp.c
psa_crypto_ffdh.c
psa_crypto_hash.c
psa_crypto_mac.c
psa_crypto_pake.c

View File

@@ -134,6 +134,7 @@ OBJS_CRYPTO= \
psa_crypto_client.o \
psa_crypto_driver_wrappers.o \
psa_crypto_ecp.o \
psa_crypto_ffdh.o \
psa_crypto_hash.o \
psa_crypto_mac.o \
psa_crypto_pake.o \

View File

@@ -35,6 +35,7 @@
#include "psa_crypto_invasive.h"
#include "psa_crypto_driver_wrappers.h"
#include "psa_crypto_ecp.h"
#include "psa_crypto_ffdh.h"
#include "psa_crypto_hash.h"
#include "psa_crypto_mac.h"
#include "psa_crypto_rsa.h"
@@ -128,6 +129,21 @@ int psa_can_do_hash(psa_algorithm_t hash_alg)
(void) hash_alg;
return global_data.drivers_initialized;
}
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) || \
defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR)
static int psa_is_dh_key_size_valid(size_t bits)
{
if (bits != 2048 && bits != 3072 && bits != 4096 &&
bits != 6144 && bits != 8192) {
return 0;
}
return 1;
}
#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR ||
MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY ||
PSA_WANT_KEY_TYPE_DH_KEY_PAIR */
psa_status_t mbedtls_to_psa_error(int ret)
{
@@ -624,6 +640,23 @@ psa_status_t psa_import_key_into_slot(
return PSA_SUCCESS;
} else if (PSA_KEY_TYPE_IS_ASYMMETRIC(type)) {
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY)
if (PSA_KEY_TYPE_IS_DH(type)) {
if (psa_is_dh_key_size_valid(PSA_BYTES_TO_BITS(data_length)) == 0) {
return PSA_ERROR_INVALID_ARGUMENT;
}
/* Copy the key material. */
memcpy(key_buffer, data, data_length);
*key_buffer_length = data_length;
*bits = PSA_BYTES_TO_BITS(data_length);
(void) key_buffer_size;
return PSA_SUCCESS;
}
#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR) ||
* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) */
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY)
if (PSA_KEY_TYPE_IS_ECC(type)) {
@@ -1326,7 +1359,8 @@ psa_status_t psa_export_key_internal(
if (key_type_is_raw_bytes(type) ||
PSA_KEY_TYPE_IS_RSA(type) ||
PSA_KEY_TYPE_IS_ECC(type)) {
PSA_KEY_TYPE_IS_ECC(type) ||
PSA_KEY_TYPE_IS_DH(type)) {
return psa_export_key_buffer_internal(
key_buffer, key_buffer_size,
data, data_size, data_length);
@@ -1392,47 +1426,54 @@ psa_status_t psa_export_public_key_internal(
{
psa_key_type_t type = attributes->core.type;
if (PSA_KEY_TYPE_IS_RSA(type) || PSA_KEY_TYPE_IS_ECC(type)) {
if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) {
/* Exporting public -> public */
return psa_export_key_buffer_internal(
key_buffer, key_buffer_size,
data, data_size, data_length);
}
if (PSA_KEY_TYPE_IS_RSA(type)) {
if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type) &&
(PSA_KEY_TYPE_IS_RSA(type) || PSA_KEY_TYPE_IS_ECC(type) ||
PSA_KEY_TYPE_IS_DH(type))) {
/* Exporting public -> public */
return psa_export_key_buffer_internal(
key_buffer, key_buffer_size,
data, data_size, data_length);
} else if (PSA_KEY_TYPE_IS_RSA(type)) {
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
return mbedtls_psa_rsa_export_public_key(attributes,
key_buffer,
key_buffer_size,
data,
data_size,
data_length);
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
return mbedtls_psa_rsa_export_public_key(attributes,
key_buffer,
key_buffer_size,
data,
data_size,
data_length);
#else
/* We don't know how to convert a private RSA key to public. */
return PSA_ERROR_NOT_SUPPORTED;
/* We don't know how to convert a private RSA key to public. */
return PSA_ERROR_NOT_SUPPORTED;
#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) ||
* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
} else {
} else if (PSA_KEY_TYPE_IS_ECC(type)) {
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY)
return mbedtls_psa_ecp_export_public_key(attributes,
key_buffer,
key_buffer_size,
data,
data_size,
data_length);
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY)
return mbedtls_psa_ecp_export_public_key(attributes,
key_buffer,
key_buffer_size,
data,
data_size,
data_length);
#else
/* We don't know how to convert a private ECC key to public */
return PSA_ERROR_NOT_SUPPORTED;
/* We don't know how to convert a private ECC key to public */
return PSA_ERROR_NOT_SUPPORTED;
#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) ||
* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */
}
} else if (PSA_KEY_TYPE_IS_DH(type)) {
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY)
return mbedtls_psa_export_ffdh_public_key(attributes,
key_buffer,
key_buffer_size,
data, data_size,
data_length);
#else
return PSA_ERROR_NOT_SUPPORTED;
#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR) ||
* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) */
} else {
/* This shouldn't happen in the reference implementation, but
it is valid for a special-purpose implementation to omit
support for exporting certain key types. */
return PSA_ERROR_NOT_SUPPORTED;
}
}
@@ -5957,6 +5998,11 @@ static psa_status_t psa_key_agreement_try_support(psa_algorithm_t alg)
if (alg == PSA_ALG_ECDH) {
return PSA_SUCCESS;
}
#endif
#if defined(PSA_WANT_ALG_FFDH)
if (alg == PSA_ALG_FFDH) {
return PSA_SUCCESS;
}
#endif
(void) alg;
return PSA_ERROR_NOT_SUPPORTED;
@@ -6575,6 +6621,19 @@ psa_status_t psa_key_agreement_raw_builtin(const psa_key_attributes_t *attribute
shared_secret_size,
shared_secret_length);
#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECDH */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_FFDH)
case PSA_ALG_FFDH:
return mbedtls_psa_key_agreement_ffdh(attributes,
peer_key,
peer_key_length,
key_buffer,
key_buffer_size,
shared_secret,
shared_secret_size,
shared_secret_length);
#endif /* MBEDTLS_PSA_BUILTIN_ALG_FFDH */
default:
(void) attributes;
(void) key_buffer;
@@ -6956,6 +7015,14 @@ static psa_status_t psa_validate_key_type_and_size_for_key_generation(
return PSA_SUCCESS;
} else
#endif /* defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) */
#if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR)
if (PSA_KEY_TYPE_IS_DH(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) {
if (psa_is_dh_key_size_valid(bits) == 0) {
return PSA_ERROR_NOT_SUPPORTED;
}
} else
#endif /* defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR) */
{
return PSA_ERROR_NOT_SUPPORTED;
}
@@ -7007,6 +7074,15 @@ psa_status_t psa_generate_key_internal(
key_buffer_length);
} else
#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) */
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR)
if (PSA_KEY_TYPE_IS_DH(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) {
return mbedtls_psa_ffdh_generate_key(attributes,
key_buffer,
key_buffer_size,
key_buffer_length);
} else
#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR) */
{
(void) key_buffer_length;
return PSA_ERROR_NOT_SUPPORTED;

262
library/psa_crypto_ffdh.c Normal file
View File

@@ -0,0 +1,262 @@
/*
* PSA FFDH layer on top of Mbed TLS crypto
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "common.h"
#if defined(MBEDTLS_PSA_CRYPTO_C)
#include <psa/crypto.h>
#include "psa_crypto_core.h"
#include "psa_crypto_ffdh.h"
#include "psa_crypto_random_impl.h"
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY)
static psa_status_t mbedtls_psa_ffdh_set_prime_generator(size_t key_size,
mbedtls_mpi *P,
mbedtls_mpi *G)
{
const unsigned char *dhm_P = NULL;
const unsigned char *dhm_G = NULL;
size_t dhm_size_P = 0;
size_t dhm_size_G = 0;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if (P == NULL && G == NULL) {
return PSA_ERROR_INVALID_ARGUMENT;
}
static const unsigned char dhm_P_2048[] =
MBEDTLS_DHM_RFC7919_FFDHE2048_P_BIN;
static const unsigned char dhm_P_3072[] =
MBEDTLS_DHM_RFC7919_FFDHE3072_P_BIN;
static const unsigned char dhm_P_4096[] =
MBEDTLS_DHM_RFC7919_FFDHE4096_P_BIN;
static const unsigned char dhm_P_6144[] =
MBEDTLS_DHM_RFC7919_FFDHE6144_P_BIN;
static const unsigned char dhm_P_8192[] =
MBEDTLS_DHM_RFC7919_FFDHE8192_P_BIN;
static const unsigned char dhm_G_2048[] =
MBEDTLS_DHM_RFC7919_FFDHE2048_G_BIN;
static const unsigned char dhm_G_3072[] =
MBEDTLS_DHM_RFC7919_FFDHE3072_G_BIN;
static const unsigned char dhm_G_4096[] =
MBEDTLS_DHM_RFC7919_FFDHE4096_G_BIN;
static const unsigned char dhm_G_6144[] =
MBEDTLS_DHM_RFC7919_FFDHE6144_G_BIN;
static const unsigned char dhm_G_8192[] =
MBEDTLS_DHM_RFC7919_FFDHE8192_G_BIN;
switch (key_size) {
case sizeof(dhm_P_2048):
dhm_P = dhm_P_2048;
dhm_G = dhm_G_2048;
dhm_size_P = sizeof(dhm_P_2048);
dhm_size_G = sizeof(dhm_G_2048);
break;
case sizeof(dhm_P_3072):
dhm_P = dhm_P_3072;
dhm_G = dhm_G_3072;
dhm_size_P = sizeof(dhm_P_3072);
dhm_size_G = sizeof(dhm_G_3072);
break;
case sizeof(dhm_P_4096):
dhm_P = dhm_P_4096;
dhm_G = dhm_G_4096;
dhm_size_P = sizeof(dhm_P_4096);
dhm_size_G = sizeof(dhm_G_4096);
break;
case sizeof(dhm_P_6144):
dhm_P = dhm_P_6144;
dhm_G = dhm_G_6144;
dhm_size_P = sizeof(dhm_P_6144);
dhm_size_G = sizeof(dhm_G_6144);
break;
case sizeof(dhm_P_8192):
dhm_P = dhm_P_8192;
dhm_G = dhm_G_8192;
dhm_size_P = sizeof(dhm_P_8192);
dhm_size_G = sizeof(dhm_G_8192);
break;
default:
return PSA_ERROR_INVALID_ARGUMENT;
}
if (P != NULL) {
MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(P, dhm_P,
dhm_size_P));
}
if (G != NULL) {
MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(G, dhm_G,
dhm_size_G));
}
cleanup:
if (ret != 0) {
return mbedtls_to_psa_error(ret);
}
return PSA_SUCCESS;
}
#if defined(MBEDTLS_PSA_BUILTIN_ALG_FFDH)
psa_status_t mbedtls_psa_key_agreement_ffdh(
const psa_key_attributes_t *attributes,
const uint8_t *peer_key,
size_t peer_key_length,
const uint8_t *key_buffer,
size_t key_buffer_size,
uint8_t *shared_secret,
size_t shared_secret_size,
size_t *shared_secret_length)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi P, G, X, GY, K;
const size_t calculated_shared_secret_size = peer_key_length;
if (peer_key_length != key_buffer_size ||
calculated_shared_secret_size > shared_secret_size) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if (!PSA_KEY_TYPE_IS_DH_KEY_PAIR(psa_get_key_type(attributes))) {
return PSA_ERROR_INVALID_ARGUMENT;
}
mbedtls_mpi_init(&P); mbedtls_mpi_init(&G);
mbedtls_mpi_init(&X); mbedtls_mpi_init(&GY);
mbedtls_mpi_init(&K);
status = mbedtls_psa_ffdh_set_prime_generator(
PSA_BITS_TO_BYTES(attributes->core.bits), &P, &G);
if (status != PSA_SUCCESS) {
goto cleanup;
}
MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&X, key_buffer,
key_buffer_size));
MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&GY, peer_key,
peer_key_length));
/* Calculate shared secret public key: K = G^(XY) mod P = GY^X mod P */
MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&K, &GY, &X, &P, NULL));
MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&K, shared_secret,
calculated_shared_secret_size));
*shared_secret_length = calculated_shared_secret_size;
ret = 0;
cleanup:
mbedtls_mpi_free(&P); mbedtls_mpi_free(&G);
mbedtls_mpi_free(&X); mbedtls_mpi_free(&GY);
mbedtls_mpi_free(&K);
if (status == PSA_SUCCESS && ret != 0) {
status = mbedtls_to_psa_error(ret);
}
return status;
}
#endif /* MBEDTLS_PSA_BUILTIN_ALG_FFDH */
psa_status_t mbedtls_psa_export_ffdh_public_key(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
uint8_t *data,
size_t data_size,
size_t *data_length)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi GX, G, X, P;
(void) attributes;
mbedtls_mpi_init(&GX); mbedtls_mpi_init(&G);
mbedtls_mpi_init(&X); mbedtls_mpi_init(&P);
status = mbedtls_psa_ffdh_set_prime_generator(data_size, &P, &G);
if (status != PSA_SUCCESS) {
goto cleanup;
}
MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&X, key_buffer,
key_buffer_size));
MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&GX, &G, &X, &P, NULL));
MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&GX, data, data_size));
*data_length = data_size;
ret = 0;
cleanup:
mbedtls_mpi_free(&P); mbedtls_mpi_free(&G);
mbedtls_mpi_free(&X); mbedtls_mpi_free(&GX);
if (status == PSA_SUCCESS && ret != 0) {
status = mbedtls_to_psa_error(ret);
}
return status;
}
psa_status_t mbedtls_psa_ffdh_generate_key(
const psa_key_attributes_t *attributes,
uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length)
{
mbedtls_mpi X, P;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi_init(&P); mbedtls_mpi_init(&X);
(void) attributes;
status = mbedtls_psa_ffdh_set_prime_generator(key_buffer_size, &P, NULL);
if (status != PSA_SUCCESS) {
goto cleanup;
}
/* RFC7919: Traditional finite field Diffie-Hellman has each peer choose their
secret exponent from the range [2, P-2].
Select random value in range [3, P-1] and decrease it by 1. */
MBEDTLS_MPI_CHK(mbedtls_mpi_random(&X, 3, &P, mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE));
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&X, &X, 1));
MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&X, key_buffer, key_buffer_size));
*key_buffer_length = key_buffer_size;
cleanup:
mbedtls_mpi_free(&P); mbedtls_mpi_free(&X);
if (status == PSA_SUCCESS && ret != 0) {
return mbedtls_to_psa_error(ret);
}
return status;
}
#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR ||
MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY */
#endif /* MBEDTLS_PSA_CRYPTO_C */

115
library/psa_crypto_ffdh.h Normal file
View File

@@ -0,0 +1,115 @@
/*
* PSA FFDH layer on top of Mbed TLS crypto
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef PSA_CRYPTO_FFDH_H
#define PSA_CRYPTO_FFDH_H
#include <psa/crypto.h>
#include <mbedtls/dhm.h>
/** Perform a key agreement and return the FFDH shared secret.
*
* \param[in] attributes The attributes of the key to use for the
* operation.
* \param[in] peer_key The buffer containing the key context
* of the peer's public key.
* \param[in] peer_key_length Size of the \p peer_key buffer in
* bytes.
* \param[in] key_buffer The buffer containing the private key
* context.
* \param[in] key_buffer_size Size of the \p key_buffer buffer in
* bytes.
* \param[out] shared_secret The buffer to which the shared secret
* is to be written.
* \param[in] shared_secret_size Size of the \p shared_secret buffer in
* bytes.
* \param[out] shared_secret_length On success, the number of bytes that make
* up the returned shared secret.
* \retval #PSA_SUCCESS
* Success. Shared secret successfully calculated.
* \retval #PSA_ERROR_INVALID_ARGUMENT
* \p key_buffer_size, \p peer_key_length, \p shared_secret_size
* do not match
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
* \retval #PSA_ERROR_CORRUPTION_DETECTED
*/
psa_status_t mbedtls_psa_key_agreement_ffdh(
const psa_key_attributes_t *attributes,
const uint8_t *peer_key,
size_t peer_key_length,
const uint8_t *key_buffer,
size_t key_buffer_size,
uint8_t *shared_secret,
size_t shared_secret_size,
size_t *shared_secret_length);
/** Export a public key or the public part of a DH key pair in binary format.
*
* \param[in] attributes The attributes for the key to export.
* \param[in] key_buffer Material or context of the key to export.
* \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes.
* \param[out] data Buffer where the key data is to be written.
* \param[in] data_size Size of the \p data buffer in bytes.
* \param[out] data_length On success, the number of bytes written in
* \p data
*
* \retval #PSA_SUCCESS The public key was exported successfully.
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* The size of \p key_buffer is too small.
* \retval #PSA_ERROR_NOT_PERMITTED
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
* \retval #PSA_ERROR_CORRUPTION_DETECTED
*/
psa_status_t mbedtls_psa_export_ffdh_public_key(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
uint8_t *data,
size_t data_size,
size_t *data_length);
/**
* \brief Generate DH key.
*
* \note The signature of the function is that of a PSA driver generate_key
* entry point.
*
* \param[in] attributes The attributes for the key to generate.
* \param[out] key_buffer Buffer where the key data is to be written.
* \param[in] key_buffer_size Size of \p key_buffer in bytes.
* \param[out] key_buffer_length On success, the number of bytes written in
* \p key_buffer.
*
* \retval #PSA_SUCCESS
* The key was generated successfully.
* \retval #PSA_ERROR_NOT_SUPPORTED
* Key size in bits is invalid.
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* The size of \p key_buffer is too small.
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
* \retval #PSA_ERROR_CORRUPTION_DETECTED
*/
psa_status_t mbedtls_psa_ffdh_generate_key(
const psa_key_attributes_t *attributes,
uint8_t *key_buffer,
size_t key_buffer_size,
size_t *key_buffer_length);
#endif /* PSA_CRYPTO_FFDH_H */