psa: Move RSA sign/verify hash to the PSA RSA specific file

Signed-off-by: Ronald Cron <ronald.cron@arm.com>
This commit is contained in:
Ronald Cron 2020-12-09 13:34:54 +01:00
parent a99bcc0e17
commit 7bdbca33b2
3 changed files with 291 additions and 209 deletions

View File

@ -3071,207 +3071,6 @@ cleanup:
/* Asymmetric cryptography */
/****************************************************************/
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
/* Decode the hash algorithm from alg and store the mbedtls encoding in
* md_alg. Verify that the hash length is acceptable. */
static psa_status_t psa_rsa_decode_md_type( psa_algorithm_t alg,
size_t hash_length,
mbedtls_md_type_t *md_alg )
{
psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH( alg );
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_psa( hash_alg );
*md_alg = mbedtls_md_get_type( md_info );
/* The Mbed TLS RSA module uses an unsigned int for hash length
* parameters. Validate that it fits so that we don't risk an
* overflow later. */
#if SIZE_MAX > UINT_MAX
if( hash_length > UINT_MAX )
return( PSA_ERROR_INVALID_ARGUMENT );
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN)
/* For PKCS#1 v1.5 signature, if using a hash, the hash length
* must be correct. */
if( PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) &&
alg != PSA_ALG_RSA_PKCS1V15_SIGN_RAW )
{
if( md_info == NULL )
return( PSA_ERROR_NOT_SUPPORTED );
if( mbedtls_md_get_size( md_info ) != hash_length )
return( PSA_ERROR_INVALID_ARGUMENT );
}
#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
/* PSS requires a hash internally. */
if( PSA_ALG_IS_RSA_PSS( alg ) )
{
if( md_info == NULL )
return( PSA_ERROR_NOT_SUPPORTED );
}
#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS */
return( PSA_SUCCESS );
}
static psa_status_t psa_rsa_sign(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
uint8_t *signature, size_t signature_size, size_t *signature_length )
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_rsa_context *rsa = NULL;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_md_type_t md_alg;
status = mbedtls_psa_rsa_load_representation( attributes->core.type,
key_buffer,
key_buffer_size,
&rsa );
if( status != PSA_SUCCESS )
return( status );
status = psa_rsa_decode_md_type( alg, hash_length, &md_alg );
if( status != PSA_SUCCESS )
goto exit;
if( signature_size < mbedtls_rsa_get_len( rsa ) )
{
status = PSA_ERROR_BUFFER_TOO_SMALL;
goto exit;
}
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN)
if( PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) )
{
mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V15,
MBEDTLS_MD_NONE );
ret = mbedtls_rsa_pkcs1_sign( rsa,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE,
MBEDTLS_RSA_PRIVATE,
md_alg,
(unsigned int) hash_length,
hash,
signature );
}
else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
if( PSA_ALG_IS_RSA_PSS( alg ) )
{
mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V21, md_alg );
ret = mbedtls_rsa_rsassa_pss_sign( rsa,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE,
MBEDTLS_RSA_PRIVATE,
MBEDTLS_MD_NONE,
(unsigned int) hash_length,
hash,
signature );
}
else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS */
{
status = PSA_ERROR_INVALID_ARGUMENT;
goto exit;
}
if( ret == 0 )
*signature_length = mbedtls_rsa_get_len( rsa );
status = mbedtls_to_psa_error( ret );
exit:
mbedtls_rsa_free( rsa );
mbedtls_free( rsa );
return( status );
}
static psa_status_t psa_rsa_verify(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
const uint8_t *signature, size_t signature_length )
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_rsa_context *rsa = NULL;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_md_type_t md_alg;
status = mbedtls_psa_rsa_load_representation( attributes->core.type,
key_buffer,
key_buffer_size,
&rsa );
if( status != PSA_SUCCESS )
goto exit;
status = psa_rsa_decode_md_type( alg, hash_length, &md_alg );
if( status != PSA_SUCCESS )
goto exit;
if( signature_length != mbedtls_rsa_get_len( rsa ) )
{
status = PSA_ERROR_INVALID_SIGNATURE;
goto exit;
}
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN)
if( PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) )
{
mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V15,
MBEDTLS_MD_NONE );
ret = mbedtls_rsa_pkcs1_verify( rsa,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE,
MBEDTLS_RSA_PUBLIC,
md_alg,
(unsigned int) hash_length,
hash,
signature );
}
else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
if( PSA_ALG_IS_RSA_PSS( alg ) )
{
mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V21, md_alg );
ret = mbedtls_rsa_rsassa_pss_verify( rsa,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE,
MBEDTLS_RSA_PUBLIC,
MBEDTLS_MD_NONE,
(unsigned int) hash_length,
hash,
signature );
}
else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS */
{
status = PSA_ERROR_INVALID_ARGUMENT;
goto exit;
}
/* Mbed TLS distinguishes "invalid padding" from "valid padding but
* the rest of the signature is invalid". This has little use in
* practice and PSA doesn't report this distinction. */
status = ( ret == MBEDTLS_ERR_RSA_INVALID_PADDING ) ?
PSA_ERROR_INVALID_SIGNATURE :
mbedtls_to_psa_error( ret );
exit:
mbedtls_rsa_free( rsa );
mbedtls_free( rsa );
return( status );
}
#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) ||
* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
/* `ecp` cannot be const because `ecp->grp` needs to be non-const
@ -3387,7 +3186,8 @@ psa_status_t psa_sign_hash_internal(
defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
if( attributes->core.type == PSA_KEY_TYPE_RSA_KEY_PAIR )
{
return( psa_rsa_sign( attributes,
return( mbedtls_psa_rsa_sign_hash(
attributes,
key_buffer, key_buffer_size,
alg, hash, hash_length,
signature, signature_size, signature_length ) );
@ -3510,7 +3310,8 @@ psa_status_t psa_verify_hash_internal(
defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
if( PSA_KEY_TYPE_IS_RSA( attributes->core.type ) )
{
return( psa_rsa_verify( attributes,
return( mbedtls_psa_rsa_verify_hash(
attributes,
key_buffer, key_buffer_size,
alg, hash, hash_length,
signature, signature_length ) );

View File

@ -319,6 +319,212 @@ static psa_status_t rsa_generate_key(
}
#endif /* defined(BUILTIN_KEY_TYPE_RSA_KEY_PAIR) */
/****************************************************************/
/* Sign/verify hashes */
/****************************************************************/
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
/* Decode the hash algorithm from alg and store the mbedtls encoding in
* md_alg. Verify that the hash length is acceptable. */
static psa_status_t psa_rsa_decode_md_type( psa_algorithm_t alg,
size_t hash_length,
mbedtls_md_type_t *md_alg )
{
psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH( alg );
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_psa( hash_alg );
*md_alg = mbedtls_md_get_type( md_info );
/* The Mbed TLS RSA module uses an unsigned int for hash length
* parameters. Validate that it fits so that we don't risk an
* overflow later. */
#if SIZE_MAX > UINT_MAX
if( hash_length > UINT_MAX )
return( PSA_ERROR_INVALID_ARGUMENT );
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN)
/* For PKCS#1 v1.5 signature, if using a hash, the hash length
* must be correct. */
if( PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) &&
alg != PSA_ALG_RSA_PKCS1V15_SIGN_RAW )
{
if( md_info == NULL )
return( PSA_ERROR_NOT_SUPPORTED );
if( mbedtls_md_get_size( md_info ) != hash_length )
return( PSA_ERROR_INVALID_ARGUMENT );
}
#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
/* PSS requires a hash internally. */
if( PSA_ALG_IS_RSA_PSS( alg ) )
{
if( md_info == NULL )
return( PSA_ERROR_NOT_SUPPORTED );
}
#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS */
return( PSA_SUCCESS );
}
psa_status_t mbedtls_psa_rsa_sign_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
uint8_t *signature, size_t signature_size, size_t *signature_length )
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_rsa_context *rsa = NULL;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_md_type_t md_alg;
status = mbedtls_psa_rsa_load_representation( attributes->core.type,
key_buffer,
key_buffer_size,
&rsa );
if( status != PSA_SUCCESS )
return( status );
status = psa_rsa_decode_md_type( alg, hash_length, &md_alg );
if( status != PSA_SUCCESS )
goto exit;
if( signature_size < mbedtls_rsa_get_len( rsa ) )
{
status = PSA_ERROR_BUFFER_TOO_SMALL;
goto exit;
}
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN)
if( PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) )
{
mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V15,
MBEDTLS_MD_NONE );
ret = mbedtls_rsa_pkcs1_sign( rsa,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE,
MBEDTLS_RSA_PRIVATE,
md_alg,
(unsigned int) hash_length,
hash,
signature );
}
else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
if( PSA_ALG_IS_RSA_PSS( alg ) )
{
mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V21, md_alg );
ret = mbedtls_rsa_rsassa_pss_sign( rsa,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE,
MBEDTLS_RSA_PRIVATE,
MBEDTLS_MD_NONE,
(unsigned int) hash_length,
hash,
signature );
}
else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS */
{
status = PSA_ERROR_INVALID_ARGUMENT;
goto exit;
}
if( ret == 0 )
*signature_length = mbedtls_rsa_get_len( rsa );
status = mbedtls_to_psa_error( ret );
exit:
mbedtls_rsa_free( rsa );
mbedtls_free( rsa );
return( status );
}
psa_status_t mbedtls_psa_rsa_verify_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
const uint8_t *signature, size_t signature_length )
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_rsa_context *rsa = NULL;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_md_type_t md_alg;
status = mbedtls_psa_rsa_load_representation( attributes->core.type,
key_buffer,
key_buffer_size,
&rsa );
if( status != PSA_SUCCESS )
goto exit;
status = psa_rsa_decode_md_type( alg, hash_length, &md_alg );
if( status != PSA_SUCCESS )
goto exit;
if( signature_length != mbedtls_rsa_get_len( rsa ) )
{
status = PSA_ERROR_INVALID_SIGNATURE;
goto exit;
}
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN)
if( PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) )
{
mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V15,
MBEDTLS_MD_NONE );
ret = mbedtls_rsa_pkcs1_verify( rsa,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE,
MBEDTLS_RSA_PUBLIC,
md_alg,
(unsigned int) hash_length,
hash,
signature );
}
else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
if( PSA_ALG_IS_RSA_PSS( alg ) )
{
mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V21, md_alg );
ret = mbedtls_rsa_rsassa_pss_verify( rsa,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE,
MBEDTLS_RSA_PUBLIC,
MBEDTLS_MD_NONE,
(unsigned int) hash_length,
hash,
signature );
}
else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS */
{
status = PSA_ERROR_INVALID_ARGUMENT;
goto exit;
}
/* Mbed TLS distinguishes "invalid padding" from "valid padding but
* the rest of the signature is invalid". This has little use in
* practice and PSA doesn't report this distinction. */
status = ( ret == MBEDTLS_ERR_RSA_INVALID_PADDING ) ?
PSA_ERROR_INVALID_SIGNATURE :
mbedtls_to_psa_error( ret );
exit:
mbedtls_rsa_free( rsa );
mbedtls_free( rsa );
return( status );
}
#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) ||
* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) */
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)

View File

@ -137,6 +137,81 @@ psa_status_t mbedtls_psa_rsa_generate_key(
const psa_key_attributes_t *attributes,
uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length );
/** Sign an already-calculated hash with an RSA private key.
*
* \note The signature of this function is that of a PSA driver
* sign_hash entry point. This function behaves as a sign_hash
* entry point as defined in the PSA driver interface specification for
* transparent drivers.
*
* \param[in] attributes The attributes of the RSA key to use for the
* operation.
* \param[in] key_buffer The buffer containing the RSA key context.
* format.
* \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes.
* \param[in] alg A signature algorithm that is compatible with
* an RSA key.
* \param[in] hash The hash or message to sign.
* \param[in] hash_length Size of the \p hash 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.
* \param[out] signature_length On success, the number of bytes
* that make up the returned signature value.
*
* \retval #PSA_SUCCESS
* \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 PSA_KEY_TYPE_RSA_KEY_PAIR, \c key_bits,
* \p alg) where \c key_bits is the bit-size of the RSA key.
* \retval #PSA_ERROR_NOT_SUPPORTED
* \retval #PSA_ERROR_INVALID_ARGUMENT
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
* \retval #PSA_ERROR_CORRUPTION_DETECTED
* \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
*/
psa_status_t mbedtls_psa_rsa_sign_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
uint8_t *signature, size_t signature_size, size_t *signature_length );
/**
* \brief Verify the signature a hash or short message using a public RSA key.
*
* \note The signature of this function is that of a PSA driver
* verify_hash entry point. This function behaves as a verify_hash
* entry point as defined in the PSA driver interface specification for
* transparent drivers.
*
* \param[in] attributes The attributes of the RSA key to use for the
* operation.
* \param[in] key_buffer The buffer containing the RSA key context.
* format.
* \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes.
* \param[in] alg A signature algorithm that is compatible with
* an RSA key.
* \param[in] hash The hash or message whose signature is to be
* verified.
* \param[in] hash_length Size of the \p hash buffer in bytes.
* \param[in] signature Buffer containing the signature to verify.
* \param[in] signature_length Size of the \p signature buffer in bytes.
*
* \retval #PSA_SUCCESS
* The signature is valid.
* \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
*/
psa_status_t mbedtls_psa_rsa_verify_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
const uint8_t *signature, size_t signature_length );
/*
* BEYOND THIS POINT, TEST DRIVER ENTRY POINTS ONLY.
*/