mirror of
https://github.com/yuzu-emu/mbedtls.git
synced 2024-11-22 22:05:42 +01:00
Implement psa_sign_message and psa_verify_message functions
Signed-off-by: gabor-mezei-arm <gabor.mezei@arm.com>
This commit is contained in:
parent
0ac7dbcfdc
commit
e8efa3911c
@ -2889,6 +2889,123 @@ psa_status_t psa_aead_abort(psa_aead_operation_t *operation);
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Sign a message with a private key. For hash-and-sign algorithms,
|
||||
* this includes the hashing step.
|
||||
*
|
||||
* \note To perform a multi-part hash-and-sign signature algorithm, first use
|
||||
* a multi-part hash operation and then pass the resulting hash to
|
||||
* psa_sign_hash(). PSA_ALG_GET_HASH(\p alg) can be used to determine the
|
||||
* hash algorithm to use.
|
||||
*
|
||||
* \param[in] key Identifier of the key to use for the operation.
|
||||
* It must be an asymmetric key pair. The key must
|
||||
* allow the usage #PSA_KEY_USAGE_SIGN_MESSAGE.
|
||||
* \param[in] alg An asymmetric signature algorithm (PSA_ALG_XXX
|
||||
* value such that #PSA_ALG_IS_SIGN_MESSAGE(\p alg)
|
||||
* is true), that is compatible with the type of
|
||||
* \p key.
|
||||
* \param[in] input The input message to sign.
|
||||
* \param[in] input_length Size of the \p input buffer in bytes.
|
||||
* \param[out] signature Buffer where the signature is to be written.
|
||||
* \param[in] signature_size Size of the \p signature buffer in bytes. This
|
||||
* must be appropriate for the selected
|
||||
* algorithm and key:
|
||||
* - The required signature size is
|
||||
* #PSA_SIGN_OUTPUT_SIZE(key_type, key_bits, \p alg)
|
||||
* where key_type and key_bits are the type and
|
||||
* bit-size respectively of key.
|
||||
* - #PSA_SIGNATURE_MAX_SIZE evaluates to the
|
||||
* maximum signature size of any supported
|
||||
* signature algorithm.
|
||||
* \param[out] signature_length On success, the number of bytes that make up
|
||||
* the returned signature value.
|
||||
*
|
||||
* \retval #PSA_SUCCESS
|
||||
* \retval #PSA_ERROR_INVALID_HANDLE
|
||||
* \retval #PSA_ERROR_NOT_PERMITTED
|
||||
* The key does not have the #PSA_KEY_USAGE_SIGN_MESSAGE flag,
|
||||
* or it does not permit the requested algorithm.
|
||||
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
|
||||
* The size of the \p signature buffer is too small. You can
|
||||
* determine a sufficient buffer size by calling
|
||||
* #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg)
|
||||
* where \c key_type and \c key_bits are the type and bit-size
|
||||
* respectively of \p key.
|
||||
* \retval #PSA_ERROR_NOT_SUPPORTED
|
||||
* \retval #PSA_ERROR_INVALID_ARGUMENT
|
||||
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
|
||||
* \retval #PSA_ERROR_COMMUNICATION_FAILURE
|
||||
* \retval #PSA_ERROR_HARDWARE_FAILURE
|
||||
* \retval #PSA_ERROR_CORRUPTION_DETECTED
|
||||
* \retval #PSA_ERROR_STORAGE_FAILURE
|
||||
* \retval #PSA_ERROR_DATA_CORRUPT
|
||||
* \retval #PSA_ERROR_DATA_INVALID
|
||||
* \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
|
||||
* \retval #PSA_ERROR_BAD_STATE
|
||||
* The library has not been previously initialized by psa_crypto_init().
|
||||
* It is implementation-dependent whether a failure to initialize
|
||||
* results in this error code.
|
||||
*/
|
||||
psa_status_t psa_sign_message( mbedtls_svc_key_id_t key,
|
||||
psa_algorithm_t alg,
|
||||
const uint8_t * input,
|
||||
size_t input_length,
|
||||
uint8_t * signature,
|
||||
size_t signature_size,
|
||||
size_t * signature_length );
|
||||
|
||||
/** \brief Verify the signature of a message with a public key, using
|
||||
* a hash-and-sign verification algorithm.
|
||||
*
|
||||
* \note To perform a multi-part hash-and-sign signature verification
|
||||
* algorithm, first use a multi-part hash operation to hash the message
|
||||
* and then pass the resulting hash to psa_verify_hash().
|
||||
* PSA_ALG_GET_HASH(\p alg) can be used to determine the hash algorithm
|
||||
* to use.
|
||||
*
|
||||
* \param[in] key Identifier of the key to use for the operation.
|
||||
* It must be a public key or an asymmetric key
|
||||
* pair. The key must allow the usage
|
||||
* #PSA_KEY_USAGE_VERIFY_MESSAGE.
|
||||
* \param[in] alg An asymmetric signature algorithm (PSA_ALG_XXX
|
||||
* value such that #PSA_ALG_IS_SIGN_MESSAGE(\p alg)
|
||||
* is true), that is compatible with the type of
|
||||
* \p key.
|
||||
* \param[in] input The message whose signature is to be verified.
|
||||
* \param[in] input_length Size of the \p input buffer in bytes.
|
||||
* \param[out] signature Buffer containing the signature to verify.
|
||||
* \param[in] signature_length Size of the \p signature buffer in bytes.
|
||||
*
|
||||
* \retval #PSA_SUCCESS
|
||||
* \retval #PSA_ERROR_INVALID_HANDLE
|
||||
* \retval #PSA_ERROR_NOT_PERMITTED
|
||||
* The key does not have the #PSA_KEY_USAGE_SIGN_MESSAGE flag,
|
||||
* or it does not permit the requested algorithm.
|
||||
* \retval #PSA_ERROR_INVALID_SIGNATURE
|
||||
* The calculation was performed successfully, but the passed signature
|
||||
* is not a valid signature.
|
||||
* \retval #PSA_ERROR_NOT_SUPPORTED
|
||||
* \retval #PSA_ERROR_INVALID_ARGUMENT
|
||||
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
|
||||
* \retval #PSA_ERROR_COMMUNICATION_FAILURE
|
||||
* \retval #PSA_ERROR_HARDWARE_FAILURE
|
||||
* \retval #PSA_ERROR_CORRUPTION_DETECTED
|
||||
* \retval #PSA_ERROR_STORAGE_FAILURE
|
||||
* \retval #PSA_ERROR_DATA_CORRUPT
|
||||
* \retval #PSA_ERROR_DATA_INVALID
|
||||
* \retval #PSA_ERROR_BAD_STATE
|
||||
* The library has not been previously initialized by psa_crypto_init().
|
||||
* It is implementation-dependent whether a failure to initialize
|
||||
* results in this error code.
|
||||
*/
|
||||
psa_status_t psa_verify_message( mbedtls_svc_key_id_t key,
|
||||
psa_algorithm_t alg,
|
||||
const uint8_t * input,
|
||||
size_t input_length,
|
||||
const uint8_t * signature,
|
||||
size_t signature_length );
|
||||
|
||||
/**
|
||||
* \brief Sign a hash or short message with a private key.
|
||||
*
|
||||
@ -2942,7 +3059,7 @@ psa_status_t psa_sign_hash(mbedtls_svc_key_id_t key,
|
||||
size_t *signature_length);
|
||||
|
||||
/**
|
||||
* \brief Verify the signature a hash or short message using a public key.
|
||||
* \brief Verify the signature of a hash or short message using a public key.
|
||||
*
|
||||
* Note that to perform a hash-and-sign signature algorithm, you must
|
||||
* first calculate the hash by calling psa_hash_setup(), psa_hash_update()
|
||||
|
@ -1487,6 +1487,23 @@
|
||||
PSA_ALG_IS_ECDSA(alg) || PSA_ALG_IS_HASH_EDDSA(alg) || \
|
||||
PSA_ALG_IS_VENDOR_HASH_AND_SIGN(alg))
|
||||
|
||||
|
||||
/** Whether the specified algorithm is a signature algorithm that can be used
|
||||
* with psa_sign_message() and psa_verify_message().
|
||||
*
|
||||
* \param alg An algorithm identifier (value of type #psa_algorithm_t).
|
||||
*
|
||||
* \return 1 if alg is a signature algorithm that can be used to sign a
|
||||
* message. 0 if alg is a signature algorithm that can only be used
|
||||
* to sign an already-calculated hash. 0 if alg is not a signature
|
||||
* algorithm. This macro can return either 0 or 1 if alg is not a
|
||||
* supported algorithm identifier.
|
||||
*/
|
||||
#define PSA_ALG_IS_SIGN_MESSAGE(alg) \
|
||||
(PSA_ALG_IS_RSA_PSS(alg) || PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || \
|
||||
PSA_ALG_IS_ECDSA(alg) || PSA_ALG_IS_HASH_EDDSA(alg) || \
|
||||
PSA_ALG_IS_VENDOR_HASH_AND_SIGN(alg))
|
||||
|
||||
/** Get the hash used by a hash-and-sign signature algorithm.
|
||||
*
|
||||
* A hash-and-sign algorithm is a signature algorithm which is
|
||||
@ -2063,6 +2080,26 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key )
|
||||
*/
|
||||
#define PSA_KEY_USAGE_DECRYPT ((psa_key_usage_t)0x00000200)
|
||||
|
||||
/** Whether the key may be used to sign a message.
|
||||
*
|
||||
* This flag allows the key to be used for a MAC calculation operation or for
|
||||
* an asymmetric message signature operation, if otherwise permitted by the
|
||||
* key’s type and policy.
|
||||
*
|
||||
* For a key pair, this concerns the private key.
|
||||
*/
|
||||
#define PSA_KEY_USAGE_SIGN_MESSAGE ((psa_key_usage_t)0x00000400)
|
||||
|
||||
/** Whether the key may be used to verify a message.
|
||||
*
|
||||
* This flag allows the key to be used for a MAC verification operation or for
|
||||
* an asymmetric message signature verification operation, if otherwise
|
||||
* permitted by the key’s type and policy.
|
||||
*
|
||||
* For a key pair, this concerns the public key.
|
||||
*/
|
||||
#define PSA_KEY_USAGE_VERIFY_MESSAGE ((psa_key_usage_t)0x00000800)
|
||||
|
||||
/** Whether the key may be used to sign a message.
|
||||
*
|
||||
* This flag allows the key to be used for a MAC calculation operation
|
||||
|
@ -1556,6 +1556,8 @@ static psa_status_t psa_validate_key_policy( const psa_key_policy_t *policy )
|
||||
PSA_KEY_USAGE_COPY |
|
||||
PSA_KEY_USAGE_ENCRYPT |
|
||||
PSA_KEY_USAGE_DECRYPT |
|
||||
PSA_KEY_USAGE_SIGN_MESSAGE |
|
||||
PSA_KEY_USAGE_VERIFY_MESSAGE |
|
||||
PSA_KEY_USAGE_SIGN_HASH |
|
||||
PSA_KEY_USAGE_VERIFY_HASH |
|
||||
PSA_KEY_USAGE_DERIVE ) ) != 0 )
|
||||
@ -2840,6 +2842,140 @@ cleanup:
|
||||
/* Asymmetric cryptography */
|
||||
/****************************************************************/
|
||||
|
||||
psa_status_t psa_sign_message( mbedtls_svc_key_id_t key,
|
||||
psa_algorithm_t alg,
|
||||
const uint8_t * input,
|
||||
size_t input_length,
|
||||
uint8_t * signature,
|
||||
size_t signature_size,
|
||||
size_t * signature_length )
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
psa_key_slot_t *slot;
|
||||
size_t hash_length;
|
||||
uint8_t hash[PSA_HASH_MAX_SIZE];
|
||||
|
||||
*signature_length = 0;
|
||||
|
||||
if( ! PSA_ALG_IS_SIGN_MESSAGE( alg ) )
|
||||
return( PSA_ERROR_INVALID_ARGUMENT );
|
||||
|
||||
if ( ! PSA_ALG_IS_HASH( PSA_ALG_SIGN_GET_HASH( alg ) ) )
|
||||
return( PSA_ERROR_INVALID_ARGUMENT );
|
||||
|
||||
/* Immediately reject a zero-length signature buffer. This guarantees
|
||||
* that signature must be a valid pointer. (On the other hand, the hash
|
||||
* buffer can in principle be empty since it doesn't actually have
|
||||
* to be a hash.) */
|
||||
if( signature_size == 0 )
|
||||
return( PSA_ERROR_BUFFER_TOO_SMALL );
|
||||
|
||||
status = psa_get_and_lock_key_slot_with_policy( key, &slot,
|
||||
PSA_KEY_USAGE_SIGN_MESSAGE,
|
||||
alg );
|
||||
if( status != PSA_SUCCESS )
|
||||
goto exit;
|
||||
|
||||
if( ! PSA_KEY_TYPE_IS_KEY_PAIR( slot->attr.type ) )
|
||||
{
|
||||
status = PSA_ERROR_INVALID_ARGUMENT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
psa_key_attributes_t attributes = {
|
||||
.core = slot->attr
|
||||
};
|
||||
|
||||
status = psa_driver_wrapper_hash_compute( PSA_ALG_SIGN_GET_HASH( alg ),
|
||||
input, input_length,
|
||||
hash, sizeof( hash ),
|
||||
&hash_length );
|
||||
|
||||
if( status != PSA_SUCCESS )
|
||||
{
|
||||
memset( hash, 0, sizeof( hash ) );
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = psa_driver_wrapper_sign_hash(
|
||||
&attributes, slot->key.data, slot->key.bytes,
|
||||
alg, hash, hash_length,
|
||||
signature, signature_size, signature_length );
|
||||
|
||||
memset( hash, 0, hash_length );
|
||||
|
||||
exit:
|
||||
/* Fill the unused part of the output buffer (the whole buffer on error,
|
||||
* the trailing part on success) with something that isn't a valid signature
|
||||
* (barring an attack on the signature and deliberately-crafted input),
|
||||
* in case the caller doesn't check the return status properly. */
|
||||
if( status == PSA_SUCCESS )
|
||||
memset( signature + *signature_length, '!',
|
||||
signature_size - *signature_length );
|
||||
else
|
||||
memset( signature, '!', signature_size );
|
||||
/* If signature_size is 0 then we have nothing to do. We must not call
|
||||
* memset because signature may be NULL in this case. */
|
||||
|
||||
unlock_status = psa_unlock_key_slot( slot );
|
||||
|
||||
return( ( status == PSA_SUCCESS ) ? unlock_status : status );
|
||||
}
|
||||
|
||||
psa_status_t psa_verify_message( mbedtls_svc_key_id_t key,
|
||||
psa_algorithm_t alg,
|
||||
const uint8_t * input,
|
||||
size_t input_length,
|
||||
const uint8_t * signature,
|
||||
size_t signature_length )
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
psa_key_slot_t *slot;
|
||||
size_t hash_length;
|
||||
uint8_t hash[PSA_HASH_MAX_SIZE];
|
||||
|
||||
if( ! PSA_ALG_IS_SIGN_MESSAGE( alg ) )
|
||||
return( PSA_ERROR_INVALID_ARGUMENT );
|
||||
|
||||
if ( ! PSA_ALG_IS_HASH( PSA_ALG_SIGN_GET_HASH( alg ) ) )
|
||||
return( PSA_ERROR_INVALID_ARGUMENT );
|
||||
|
||||
status = psa_get_and_lock_key_slot_with_policy( key, &slot,
|
||||
PSA_KEY_USAGE_VERIFY_MESSAGE,
|
||||
alg );
|
||||
if( status != PSA_SUCCESS )
|
||||
return( status );
|
||||
|
||||
psa_key_attributes_t attributes = {
|
||||
.core = slot->attr
|
||||
};
|
||||
|
||||
status = psa_driver_wrapper_hash_compute( PSA_ALG_SIGN_GET_HASH( alg ),
|
||||
input, input_length,
|
||||
hash, sizeof( hash ),
|
||||
&hash_length );
|
||||
|
||||
if( status != PSA_SUCCESS )
|
||||
{
|
||||
memset( hash, 0, sizeof( hash ) );
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = psa_driver_wrapper_verify_hash(
|
||||
&attributes, slot->key.data, slot->key.bytes,
|
||||
alg, hash, hash_length,
|
||||
signature, signature_length );
|
||||
|
||||
memset( hash, 0, hash_length );
|
||||
|
||||
exit:
|
||||
unlock_status = psa_unlock_key_slot( slot );
|
||||
|
||||
return( ( status == PSA_SUCCESS ) ? unlock_status : status );
|
||||
}
|
||||
|
||||
psa_status_t psa_sign_hash_internal(
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key_buffer, size_t key_buffer_size,
|
||||
|
@ -394,6 +394,13 @@ static int psa_snprint_key_usage(char *buffer, size_t buffer_size,
|
||||
append(&buffer, buffer_size, &required_size, "PSA_KEY_USAGE_SIGN_HASH", 23);
|
||||
usage ^= PSA_KEY_USAGE_SIGN_HASH;
|
||||
}
|
||||
if (usage & PSA_KEY_USAGE_SIGN_MESSAGE) {
|
||||
if (required_size != 0) {
|
||||
append(&buffer, buffer_size, &required_size, " | ", 3);
|
||||
}
|
||||
append(&buffer, buffer_size, &required_size, "PSA_KEY_USAGE_SIGN_MESSAGE", 26);
|
||||
usage ^= PSA_KEY_USAGE_SIGN_MESSAGE;
|
||||
}
|
||||
if (usage & PSA_KEY_USAGE_VERIFY_HASH) {
|
||||
if (required_size != 0) {
|
||||
append(&buffer, buffer_size, &required_size, " | ", 3);
|
||||
@ -401,6 +408,13 @@ static int psa_snprint_key_usage(char *buffer, size_t buffer_size,
|
||||
append(&buffer, buffer_size, &required_size, "PSA_KEY_USAGE_VERIFY_HASH", 25);
|
||||
usage ^= PSA_KEY_USAGE_VERIFY_HASH;
|
||||
}
|
||||
if (usage & PSA_KEY_USAGE_VERIFY_MESSAGE) {
|
||||
if (required_size != 0) {
|
||||
append(&buffer, buffer_size, &required_size, " | ", 3);
|
||||
}
|
||||
append(&buffer, buffer_size, &required_size, "PSA_KEY_USAGE_VERIFY_MESSAGE", 28);
|
||||
usage ^= PSA_KEY_USAGE_VERIFY_MESSAGE;
|
||||
}
|
||||
if (usage != 0) {
|
||||
if (required_size != 0) {
|
||||
append(&buffer, buffer_size, &required_size, " | ", 3);
|
||||
|
Loading…
Reference in New Issue
Block a user