10.9. Key agreement¶
Two functions are provided for a Diffie-Hellman-style key agreement where each party combines its own private key with the peer’s public key.
The recommended approach is to use a key derivation operation with the
psa_key_derivation_key_agreement()input function, which calculates a shared secret for the key derivation function.Where an application needs direct access to the shared secret, it can call
psa_raw_key_agreement()instead. Note that in general the shared secret is not directly suitable for use as a key because it is biased.
10.9.1. Key agreement algorithms¶
PSA_ALG_FFDH (macro)¶
The finite-field Diffie-Hellman (DH) key agreement algorithm.
#define PSA_ALG_FFDH ((psa_algorithm_t)0x09010000)
This algorithm can be used directly in a call to psa_raw_key_agreement(), or combined with a key derivation operation using PSA_ALG_KEY_AGREEMENT() for use with psa_key_derivation_key_agreement().
When used as a key’s permitted-algorithm policy, the following uses are permitted:
In a call to
psa_raw_key_agreement(), with algorithmPSA_ALG_FFDH.In a call to
psa_key_derivation_key_agreement(), with any combined key agreement and key derivation algorithm constructed withPSA_ALG_FFDH.
When used as part of a multi-part key derivation operation, this implements a Diffie-Hellman key agreement scheme using a single Diffie-Hellman key-pair for each participant. This includes the dhEphem, dhOneFlow, and dhStatic schemes. The input step PSA_KEY_DERIVATION_INPUT_SECRET is used when providing the secret and peer keys to the operation.
The shared secret produced by this key agreement algorithm is g^{ab} in big-endian format. It is ceiling(m / 8) bytes long where m is the size of the prime p in bits.
This key agreement scheme is defined by NIST Special Publication 800-56A: Recommendation for Pair-Wise Key-Establishment Schemes Using Discrete Logarithm Cryptography [SP800-56A] §5.7.1.1 under the name FFC DH.
Compatible key types
PSA_ALG_ECDH (macro)¶
The elliptic curve Diffie-Hellman (ECDH) key agreement algorithm.
#define PSA_ALG_ECDH ((psa_algorithm_t)0x09020000)
This algorithm can be used directly in a call to psa_raw_key_agreement(), or combined with a key derivation operation using PSA_ALG_KEY_AGREEMENT() for use with psa_key_derivation_key_agreement().
When used as a key’s permitted-algorithm policy, the following uses are permitted:
In a call to
psa_raw_key_agreement(), with algorithmPSA_ALG_ECDH.In a call to
psa_key_derivation_key_agreement(), with any combined key agreement and key derivation algorithm constructed withPSA_ALG_ECDH.
When used as part of a multi-part key derivation operation, this implements a Diffie-Hellman key agreement scheme using a single elliptic curve key-pair for each participant. This includes the Ephemeral unified model, the Static unified model, and the One-pass Diffie-Hellman schemes. The input step PSA_KEY_DERIVATION_INPUT_SECRET is used when providing the secret and peer keys to the operation.
The shared secret produced by key agreement is the x-coordinate of the shared secret point. It is always ceiling(m / 8) bytes long where m is the bit size associated with the curve, i.e. the bit size of the order of the curve’s coordinate field. When m is not a multiple of 8, the byte containing the most significant bit of the shared secret is padded with zero bits. The byte order is either little-endian or big-endian depending on the curve type.
For Montgomery curves (curve family
PSA_ECC_FAMILY_MONTGOMERY), the shared secret is the x-coordinate ofZ = d_A Q_B = d_B Q_Ain little-endian byte order.For Curve25519, this is the X25519 function defined in Curve25519: new Diffie-Hellman speed records [Curve25519]. The bit size
mis 255.For Curve448, this is the X448 function defined in Ed448-Goldilocks, a new elliptic curve [Curve448]. The bit size
mis 448.
For Weierstrass curves (curve families
PSA_ECC_FAMILY_SECP_XX,PSA_ECC_FAMILY_SECT_XX,PSA_ECC_FAMILY_BRAINPOOL_P_R1andPSA_ECC_FAMILY_FRP) the shared secret is the x-coordinate ofZ = h d_A Q_B = h d_B Q_Ain big-endian byte order. This is the Elliptic Curve Cryptography Cofactor Diffie-Hellman primitive defined by SEC 1: Elliptic Curve Cryptography [SEC1] §3.3.2 as, and also as ECC CDH by NIST Special Publication 800-56A: Recommendation for Pair-Wise Key-Establishment Schemes Using Discrete Logarithm Cryptography [SP800-56A] §5.7.1.2.Over prime fields (curve families
PSA_ECC_FAMILY_SECP_XX,PSA_ECC_FAMILY_BRAINPOOL_P_R1andPSA_ECC_FAMILY_FRP), the bit size ism = ceiling(log_2(p))for the fieldF_p.Over binary fields (curve families
PSA_ECC_FAMILY_SECT_XX), the bit size ismfor the fieldF_{2^m}.
Note
The cofactor Diffie-Hellman primitive is equivalent to the standard elliptic curve Diffie-Hellman calculation
Z = d_A Q_B = d_B Q_A([SEC1] §3.3.1) for curves where the cofactorhis1. This is true for all curves in thePSA_ECC_FAMILY_SECP_XX,PSA_ECC_FAMILY_BRAINPOOL_P_R1, andPSA_ECC_FAMILY_FRPfamilies.
Compatible key types
where family is a Weierstrass or Montgomery Elliptic curve family. That is, one of the following values:
PSA_ECC_FAMILY_SECT_XXPSA_ECC_FAMILY_SECP_XX
PSA_ALG_KEY_AGREEMENT (macro)¶
Macro to build a combined algorithm that chains a key agreement with a key derivation.
#define PSA_ALG_KEY_AGREEMENT(ka_alg, kdf_alg) \ /* specification-defined value */
Parameters
ka_algA key agreement algorithm: a value of type
psa_algorithm_tsuch thatPSA_ALG_IS_KEY_AGREEMENT(ka_alg)is true.kdf_algA key derivation algorithm: a value of type
psa_algorithm_tsuch thatPSA_ALG_IS_KEY_DERIVATION(kdf_alg)is true.
Returns
The corresponding key agreement and derivation algorithm.
Unspecified if ka_alg is not a supported key agreement algorithm or kdf_alg is not a supported key derivation algorithm.
Description
A combined key agreement algorithm is used with a multi-part key derivation operation, using a call to psa_key_derivation_key_agreement().
The component parts of a key agreement algorithm can be extracted using PSA_ALG_KEY_AGREEMENT_GET_BASE() and PSA_ALG_KEY_AGREEMENT_GET_KDF().
Compatible key types
The resulting combined key agreement algorithm is compatible with the same key types as the raw key agreement algorithm used to construct it.
10.9.2. Standalone key agreement¶
psa_raw_key_agreement (function)¶
Perform a key agreement and return the raw shared secret.
psa_status_t psa_raw_key_agreement(psa_algorithm_t alg, psa_key_id_t private_key, const uint8_t * peer_key, size_t peer_key_length, uint8_t * output, size_t output_size, size_t * output_length);
Parameters
algThe key agreement algorithm to compute: a value of type
psa_algorithm_tsuch thatPSA_ALG_IS_RAW_KEY_AGREEMENT(alg)is true.private_keyIdentifier of the private key to use. It must permit the usage
PSA_KEY_USAGE_DERIVE.peer_keyPublic key of the peer. The peer key must be in the same format that
psa_import_key()accepts for the public key type corresponding to the type ofprivate_key. That is, this function performs the equivalent ofpsa_import_key(...,peer_key,peer_key_length), with key attributes indicating the public key type corresponding to the type ofprivate_key. For example, for ECC keys, this means that peer_key is interpreted as a point on the curve that the private key is on. The standard formats for public keys are documented in the documentation ofpsa_export_public_key().peer_key_lengthSize of
peer_keyin bytes.outputBuffer where the raw shared secret is to be written.
output_sizeSize of the
outputbuffer in bytes. This must be appropriate for the keys:The required output size is
PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(type,bits)wheretypeis the type ofprivate_keyandbitsis the bit-size of eitherprivate_keyor thepeer_key.PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZEevaluates to the maximum output size of any supported raw key agreement algorithm.
output_lengthOn success, the number of bytes that make up the returned output.
Returns: psa_status_t
PSA_SUCCESSSuccess. The first
(*output_length)bytes ofoutputcontain the raw shared secret.PSA_ERROR_BAD_STATEThe library requires initializing by a call to
psa_crypto_init().PSA_ERROR_INVALID_HANDLEprivate_keyis not a valid key identifier.PSA_ERROR_NOT_PERMITTEDprivate_keydoes not have thePSA_KEY_USAGE_DERIVEflag, or it does not permit the requested algorithm.PSA_ERROR_BUFFER_TOO_SMALLThe size of the
outputbuffer is too small.PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE()orPSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZEcan be used to determine a sufficient buffer size.PSA_ERROR_INVALID_ARGUMENTThe following conditions can result in this error:
algis not a key agreement algorithm.private_keyis not compatible withalg.peer_keyis not a valid public key corresponding toprivate_key.
PSA_ERROR_NOT_SUPPORTEDThe following conditions can result in this error:
algis not supported or is not a key agreement algorithm.private_keyis not supported for use withalg.
PSA_ERROR_INSUFFICIENT_MEMORYPSA_ERROR_COMMUNICATION_FAILUREPSA_ERROR_CORRUPTION_DETECTEDPSA_ERROR_STORAGE_FAILUREPSA_ERROR_DATA_CORRUPTPSA_ERROR_DATA_INVALID
Description
Warning
The raw result of a key agreement algorithm such as finite-field Diffie-Hellman or elliptic curve Diffie-Hellman has biases, and is not suitable for use as key material. Instead it is recommended that the result is used as input to a key derivation algorithm. To chain a key agreement with a key derivation, use psa_key_derivation_key_agreement() and other functions from the key derivation interface.
10.9.3. Combining key agreement and key derivation¶
psa_key_derivation_key_agreement (function)¶
Perform a key agreement and use the shared secret as input to a key derivation.
psa_status_t psa_key_derivation_key_agreement(psa_key_derivation_operation_t * operation, psa_key_derivation_step_t step, psa_key_id_t private_key, const uint8_t * peer_key, size_t peer_key_length);
Parameters
operationThe key derivation operation object to use. It must have been set up with
psa_key_derivation_setup()with a key agreement and derivation algorithmalg: a value of typepsa_algorithm_tsuch thatPSA_ALG_IS_KEY_AGREEMENT(alg)is true andPSA_ALG_IS_RAW_KEY_AGREEMENT(alg)is false.The operation must be ready for an input of the type given by
step.stepWhich step the input data is for.
private_keyIdentifier of the private key to use. It must permit the usage
PSA_KEY_USAGE_DERIVE.peer_keyPublic key of the peer. The peer key must be in the same format that
psa_import_key()accepts for the public key type corresponding to the type ofprivate_key. That is, this function performs the equivalent ofpsa_import_key(...,peer_key,peer_key_length), with key attributes indicating the public key type corresponding to the type ofprivate_key. For example, for ECC keys, this means that peer_key is interpreted as a point on the curve that the private key is on. The standard formats for public keys are documented in the documentation ofpsa_export_public_key().peer_key_lengthSize of
peer_keyin bytes.
Returns: psa_status_t
PSA_SUCCESSSuccess.
PSA_ERROR_BAD_STATEThe following conditions can result in this error:
The operation state is not valid for this key agreement
step.The library requires initializing by a call to
psa_crypto_init().
PSA_ERROR_INVALID_HANDLEprivate_keyis not a valid key identifier.PSA_ERROR_NOT_PERMITTEDprivate_keydoes not have thePSA_KEY_USAGE_DERIVEflag, or it does not permit the operation’s algorithm.PSA_ERROR_INVALID_ARGUMENTThe following conditions can result in this error:
The operation’s algorithm is not a key agreement algorithm.
stepdoes not permit an input resulting from a key agreement.private_keyis not compatible with the operation’s algorithm.peer_keyis not a valid public key corresponding toprivate_key.
PSA_ERROR_NOT_SUPPORTEDprivate_keyis not supported for use with the operation’s algorithm.PSA_ERROR_INSUFFICIENT_MEMORYPSA_ERROR_COMMUNICATION_FAILUREPSA_ERROR_CORRUPTION_DETECTEDPSA_ERROR_STORAGE_FAILUREPSA_ERROR_DATA_CORRUPTPSA_ERROR_DATA_INVALID
Description
A key agreement algorithm takes two inputs: a private key private_key, and a public key peer_key. The result of this function is passed as input to the key derivation operation. The output of this key derivation can be extracted by reading from the resulting operation to produce keys and other cryptographic material.
If this function returns an error status, the operation enters an error state and must be aborted by calling psa_key_derivation_abort().
10.9.4. Support macros¶
PSA_ALG_KEY_AGREEMENT_GET_BASE (macro)¶
Get the raw key agreement algorithm from a full key agreement algorithm.
#define PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) /* specification-defined value */
Parameters
algA key agreement algorithm: a value of type
psa_algorithm_tsuch thatPSA_ALG_IS_KEY_AGREEMENT(alg)is true.
Returns
The underlying raw key agreement algorithm if alg is a key agreement algorithm.
Unspecified if alg is not a key agreement algorithm or if it is not supported by the implementation.
Description
See also PSA_ALG_KEY_AGREEMENT() and PSA_ALG_KEY_AGREEMENT_GET_KDF().
PSA_ALG_KEY_AGREEMENT_GET_KDF (macro)¶
Get the key derivation algorithm used in a full key agreement algorithm.
#define PSA_ALG_KEY_AGREEMENT_GET_KDF(alg) /* specification-defined value */
Parameters
algA key agreement algorithm: a value of type
psa_algorithm_tsuch thatPSA_ALG_IS_KEY_AGREEMENT(alg)is true.
Returns
The underlying key derivation algorithm if alg is a key agreement algorithm.
Unspecified if alg is not a key agreement algorithm or if it is not supported by the implementation.
Description
See also PSA_ALG_KEY_AGREEMENT() and PSA_ALG_KEY_AGREEMENT_GET_BASE().
PSA_ALG_IS_RAW_KEY_AGREEMENT (macro)¶
Whether the specified algorithm is a raw key agreement algorithm.
#define PSA_ALG_IS_RAW_KEY_AGREEMENT(alg) /* specification-defined value */
Parameters
algAn algorithm identifier: a value of type
psa_algorithm_t.
Returns
1 if alg is a raw key agreement algorithm, 0 otherwise. This macro can return either 0 or 1 if alg is not a supported algorithm identifier.
Description
A raw key agreement algorithm is one that does not specify a key derivation function. Usually, raw key agreement algorithms are constructed directly with a PSA_ALG_xxx macro while non-raw key agreement algorithms are constructed with PSA_ALG_KEY_AGREEMENT().
The raw key agreement algorithm can be extracted from a full key agreement algorithm identifier using PSA_ALG_KEY_AGREEMENT_GET_BASE().
PSA_ALG_IS_FFDH (macro)¶
Whether the specified algorithm is a finite field Diffie-Hellman algorithm.
#define PSA_ALG_IS_FFDH(alg) /* specification-defined value */
Parameters
algAn algorithm identifier: a value of type
psa_algorithm_t.
Returns
1 if alg is a finite field Diffie-Hellman algorithm, 0 otherwise. This macro can return either 0 or 1 if alg is not a supported key agreement algorithm identifier.
Description
This includes the raw finite field Diffie-Hellman algorithm as well as finite-field Diffie-Hellman followed by any supported key derivation algorithm.
PSA_ALG_IS_ECDH (macro)¶
Whether the specified algorithm is an elliptic curve Diffie-Hellman algorithm.
#define PSA_ALG_IS_ECDH(alg) /* specification-defined value */
Parameters
algAn algorithm identifier: a value of type
psa_algorithm_t.
Returns
1 if alg is an elliptic curve Diffie-Hellman algorithm, 0 otherwise. This macro can return either 0 or 1 if alg is not a supported key agreement algorithm identifier.
Description
This includes the raw elliptic curve Diffie-Hellman algorithm as well as elliptic curve Diffie-Hellman followed by any supporter key derivation algorithm.
PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE (macro)¶
Sufficient output buffer size for psa_raw_key_agreement().
#define PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(key_type, key_bits) \ /* implementation-defined value */
Parameters
key_typeA supported key type.
key_bitsThe size of the key in bits.
Returns
A sufficient output buffer size for the specified key type and size. An implementation can return either 0 or a correct size for a key type and size that it recognizes, but does not support. If the parameters are not valid, the return value is unspecified.
Description
If the size of the output buffer is at least this large, it is guaranteed that psa_raw_key_agreement() will not fail due to an insufficient buffer size. The actual size of the output might be smaller in any given call.
See also PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE.
PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE (macro)¶
Sufficient output buffer size for psa_raw_key_agreement(), for any of the supported key types and key agreement algorithms.
#define PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE \ /* implementation-defined value */
If the size of the output buffer is at least this large, it is guaranteed that psa_raw_key_agreement() will not fail due to an insufficient buffer size.
See also PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE().