From 7ed29c56f176d3ce4e5d9258da22bd5990cb81d3 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 26 Jun 2018 15:50:08 +0200 Subject: [PATCH 01/15] Rename PSA_ALG_RSA_GET_HASH to PSA_ALG_SIGN_GET_HASH And don't use it for HMAC when there's a perfectly serviceable PSA_ALG_HMAC_HASH. HMAC isn't hash-and-sign. --- include/psa/crypto.h | 58 +++++++++++++++++++++++++++++--------------- library/psa_crypto.c | 2 +- 2 files changed, 40 insertions(+), 20 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 9a1eec96a..90f5b6426 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -632,8 +632,28 @@ typedef uint32_t psa_algorithm_t; (PSA_ALG_RSA_OAEP_MGF1_RAW | ((hash_alg) & PSA_ALG_HASH_MASK)) #define PSA_ALG_IS_RSA_OAEP_MGF1(alg) \ (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_OAEP_MGF1_BASE) -#define PSA_ALG_RSA_GET_HASH(alg) \ - (((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH) +/** Get the hash used by a hash-and-sign signature algorithm. + * + * A hash-and-sign algorithm is a signature algorithm which is + * composed of two phases: first a hashing phase which does not use + * the key and produces a hash of the input message, then a signing + * phase which only uses the hash and the key and not the message + * itself. + * + * \param alg A signature algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_SIGN(alg) is true). + * + * \return The underlying hash algorithm if \p alg is a hash-and-sign + * algorithm. + * \return 0 if \p alg is a signature algorithm that does not + * follow the hash-and-sign structure. + * \return Unspecified if \p alg is not a signature algorithm or + * if it is not supported by the implementation. + */ +#define PSA_ALG_SIGN_GET_HASH(alg) \ + (PSA_ALG_IS_SIGN(alg) ? \ + ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH : \ + 0) #define PSA_ALG_ECDSA_RAW ((psa_algorithm_t)0x10030000) @@ -994,23 +1014,23 @@ typedef struct psa_hash_operation_s psa_hash_operation_t; * An implementation may return either 0 or the correct size * for a hash algorithm that it recognizes, but does not support. */ -#define PSA_HASH_SIZE(alg) \ - ( \ - PSA_ALG_RSA_GET_HASH(alg) == PSA_ALG_MD2 ? 16 : \ - PSA_ALG_RSA_GET_HASH(alg) == PSA_ALG_MD4 ? 16 : \ - PSA_ALG_RSA_GET_HASH(alg) == PSA_ALG_MD5 ? 16 : \ - PSA_ALG_RSA_GET_HASH(alg) == PSA_ALG_RIPEMD160 ? 20 : \ - PSA_ALG_RSA_GET_HASH(alg) == PSA_ALG_SHA_1 ? 20 : \ - PSA_ALG_RSA_GET_HASH(alg) == PSA_ALG_SHA_224 ? 28 : \ - PSA_ALG_RSA_GET_HASH(alg) == PSA_ALG_SHA_256 ? 32 : \ - PSA_ALG_RSA_GET_HASH(alg) == PSA_ALG_SHA_384 ? 48 : \ - PSA_ALG_RSA_GET_HASH(alg) == PSA_ALG_SHA_512 ? 64 : \ - PSA_ALG_RSA_GET_HASH(alg) == PSA_ALG_SHA_512_224 ? 28 : \ - PSA_ALG_RSA_GET_HASH(alg) == PSA_ALG_SHA_512_256 ? 32 : \ - PSA_ALG_RSA_GET_HASH(alg) == PSA_ALG_SHA3_224 ? 28 : \ - PSA_ALG_RSA_GET_HASH(alg) == PSA_ALG_SHA3_256 ? 32 : \ - PSA_ALG_RSA_GET_HASH(alg) == PSA_ALG_SHA3_384 ? 48 : \ - PSA_ALG_RSA_GET_HASH(alg) == PSA_ALG_SHA3_512 ? 64 : \ +#define PSA_HASH_SIZE(alg) \ + ( \ + PSA_ALG_HMAC_HASH(alg) == PSA_ALG_MD2 ? 16 : \ + PSA_ALG_HMAC_HASH(alg) == PSA_ALG_MD4 ? 16 : \ + PSA_ALG_HMAC_HASH(alg) == PSA_ALG_MD5 ? 16 : \ + PSA_ALG_HMAC_HASH(alg) == PSA_ALG_RIPEMD160 ? 20 : \ + PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA_1 ? 20 : \ + PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA_224 ? 28 : \ + PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA_256 ? 32 : \ + PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA_384 ? 48 : \ + PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA_512 ? 64 : \ + PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA_512_224 ? 28 : \ + PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA_512_256 ? 32 : \ + PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA3_224 ? 28 : \ + PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA3_256 ? 32 : \ + PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA3_384 ? 48 : \ + PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA3_512 ? 64 : \ 0) /** Start a multipart hash operation. diff --git a/library/psa_crypto.c b/library/psa_crypto.c index dbeeef6ae..44867dc48 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -1617,7 +1617,7 @@ 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_RSA_GET_HASH( 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 = hash_alg == 0 ? MBEDTLS_MD_NONE : mbedtls_md_get_type( md_info ); if( *md_alg == MBEDTLS_MD_NONE ) From ea4469f8d1dde253f873b226fbe3a9e959c89395 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 28 Jun 2018 13:57:23 +0200 Subject: [PATCH 02/15] Fix parameter name in Doxygen documentation --- include/psa/crypto.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 90f5b6426..8988be105 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -574,11 +574,12 @@ typedef uint32_t psa_algorithm_t; * * For example, `PSA_ALG_HMAC(PSA_ALG_SHA256)` is HMAC-SHA-256. * - * \param alg A hash algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_HASH(alg) is true). + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(alg) is true). * - * \return The corresponding HMAC algorithm. - * \return Unspecified if \p alg is not a hash algorithm. + * \return The corresponding HMAC algorithm. + * \return Unspecified if \p alg is not a supported + * hash algorithm. */ #define PSA_ALG_HMAC(hash_alg) \ (PSA_ALG_HMAC_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) From 9e73ff17d43bf9a88b7d96bbcf24ca4b7e75c55c Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 26 Jun 2018 21:25:40 +0200 Subject: [PATCH 03/15] Add missing parameters to some documentation tests/scripts/doxygen.sh now passes. --- include/psa/crypto.h | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 8988be105..e6911238c 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -1212,13 +1212,18 @@ typedef struct psa_mac_operation_s psa_mac_operation_t; * * This is also the MAC size that psa_mac_verify() expects. * - * \param alg A MAC algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_MAC(alg) is true). + * \param key_type The type of the MAC key. + * \param key_bits The size of the MAC key in bits. + * \param alg A MAC algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_MAC(alg) is true). * - * \return The MAC size for the specified algorithm. - * If the MAC algorithm is not recognized, return 0. - * An implementation may return either 0 or the correct size - * for a MAC algorithm that it recognizes, but does not support. + * \return The MAC size for the specified algorithm with + * the specified key parameters. + * \return 0 if the MAC algorithm is not recognized. + * \return Either 0 or the correct size for a MAC algorithm that + * the implementation recognizes, but does not support. + * \return Unspecified if the key parameters are not consistent + * with the algorithm. */ #define PSA_MAC_FINAL_SIZE(key_type, key_bits, alg) \ (PSA_ALG_IS_HMAC(alg) ? PSA_HASH_SIZE(PSA_ALG_HMAC_HASH(alg)) : \ @@ -1250,6 +1255,7 @@ typedef struct psa_mac_operation_s psa_mac_operation_t; * - A call to psa_mac_finish(), psa_mac_verify() or psa_mac_abort(). * * \param operation The operation object to use. + * \param key Slot containing the key to use for the operation. * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value * such that #PSA_ALG_IS_MAC(alg) is true). * @@ -1326,6 +1332,7 @@ typedef struct psa_cipher_operation_s psa_cipher_operation_t; * - A call to psa_cipher_finish() or psa_cipher_abort(). * * \param operation The operation object to use. + * \param key Slot containing the key to use for the operation. * \param alg The cipher algorithm to compute (\c PSA_ALG_XXX value * such that #PSA_ALG_IS_CIPHER(alg) is true). * @@ -1373,6 +1380,7 @@ psa_status_t psa_encrypt_setup(psa_cipher_operation_t *operation, * - A call to psa_cipher_finish() or psa_cipher_abort(). * * \param operation The operation object to use. + * \param key Slot containing the key to use for the operation. * \param alg The cipher algorithm to compute (\c PSA_ALG_XXX value * such that #PSA_ALG_IS_CIPHER(alg) is true). * From 55bf3d117124f21a28d2b57e0549ab266d1deb78 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 26 Jun 2018 15:53:48 +0200 Subject: [PATCH 04/15] Sort out RSA mechanisms * PSS needs to be parametrized by a hash. * Don't use `_MGF1` in the names of macros for OAEP and PSS. No one ever uses anything else. * Add brief documentation for the RSA signature mechanisms. --- include/psa/crypto.h | 60 ++++++++++++++++++++----- library/psa_crypto.c | 8 ++-- tests/suites/test_suite_psa_crypto.data | 2 +- 3 files changed, 55 insertions(+), 15 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index e6911238c..32e0f3d83 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -621,18 +621,52 @@ typedef uint32_t psa_algorithm_t; #define PSA_ALG_CCM ((psa_algorithm_t)0x06000001) #define PSA_ALG_GCM ((psa_algorithm_t)0x06000002) -#define PSA_ALG_RSA_PKCS1V15_SIGN_RAW ((psa_algorithm_t)0x10010000) -#define PSA_ALG_RSA_PSS_MGF1 ((psa_algorithm_t)0x10020000) -#define PSA_ALG_RSA_PKCS1V15_CRYPT ((psa_algorithm_t)0x12010000) -#define PSA_ALG_RSA_OAEP_MGF1_BASE ((psa_algorithm_t)0x12020000) +#define PSA_ALG_RSA_PKCS1V15_SIGN_BASE ((psa_algorithm_t)0x10020000) +/** RSA PKCS#1 v1.5 signature with hashing. + * + * This is the signature scheme defined by RFC 8017 + * (PKCS#1: RSA Cryptography Specifications) under the name + * RSASSA-PKCS1-v1_5. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(alg) is true). + * + * \return The corresponding RSA PKCS#1 v1.5 signature algorithm. + * \return Unspecified if \p alg is not a supported + * hash algorithm. + */ #define PSA_ALG_RSA_PKCS1V15_SIGN(hash_alg) \ - (PSA_ALG_RSA_PKCS1V15_SIGN_RAW | ((hash_alg) & PSA_ALG_HASH_MASK)) + (PSA_ALG_RSA_PKCS1V15_SIGN_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +/** Raw PKCS#1 v1.5 signature. + * + * The input to this algorithm is the DigestInfo structure used by + * RFC 8017 (PKCS#1: RSA Cryptography Specifications), §9.2 + * steps 3–6. + */ +#define PSA_ALG_RSA_PKCS1V15_SIGN_RAW PSA_ALG_RSA_PKCS1V15_SIGN_BASE #define PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) \ - (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PKCS1V15_SIGN_RAW) -#define PSA_ALG_RSA_OAEP_MGF1(hash_alg) \ - (PSA_ALG_RSA_OAEP_MGF1_RAW | ((hash_alg) & PSA_ALG_HASH_MASK)) -#define PSA_ALG_IS_RSA_OAEP_MGF1(alg) \ - (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_OAEP_MGF1_BASE) + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PKCS1V15_SIGN_BASE) +#define PSA_ALG_RSA_PSS_BASE ((psa_algorithm_t)0x10030000) +/** RSA PSS signature with hashing. + * + * This is the signature scheme defined by RFC 8017 + * (PKCS#1: RSA Cryptography Specifications) under the name + * RSASSA-PSS, with the message generation function MGF1. The specified + * hash algorithm is used to hash the input message, to create the + * salted hash, and for the mask generation. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(alg) is true). + * + * \return The corresponding RSA PSS signature algorithm. + * \return Unspecified if \p alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_RSA_PSS(hash_alg) \ + (PSA_ALG_RSA_PSS_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +#define PSA_ALG_IS_RSA_PSS(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PSS_BASE) + /** Get the hash used by a hash-and-sign signature algorithm. * * A hash-and-sign algorithm is a signature algorithm which is @@ -657,6 +691,12 @@ typedef uint32_t psa_algorithm_t; 0) #define PSA_ALG_ECDSA_RAW ((psa_algorithm_t)0x10030000) +#define PSA_ALG_RSA_PKCS1V15_CRYPT ((psa_algorithm_t)0x12020000) +#define PSA_ALG_RSA_OAEP_BASE ((psa_algorithm_t)0x12030000) +#define PSA_ALG_RSA_OAEP(hash_alg) \ + (PSA_ALG_RSA_OAEP_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +#define PSA_ALG_IS_RSA_OAEP(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_OAEP_BASE) /**@}*/ diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 44867dc48..a4fac648e 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -1690,7 +1690,7 @@ psa_status_t psa_asymmetric_sign( psa_key_slot_t key, else #endif /* MBEDTLS_PKCS1_V15 */ #if defined(MBEDTLS_PKCS1_V21) - if( alg == PSA_ALG_RSA_PSS_MGF1 ) + 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, @@ -1789,7 +1789,7 @@ psa_status_t psa_asymmetric_verify( psa_key_slot_t key, else #endif /* MBEDTLS_PKCS1_V15 */ #if defined(MBEDTLS_PKCS1_V21) - if( alg == PSA_ALG_RSA_PSS_MGF1 ) + 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, @@ -1872,7 +1872,7 @@ psa_status_t psa_asymmetric_encrypt( psa_key_slot_t key, else #endif /* MBEDTLS_PKCS1_V15 */ #if defined(MBEDTLS_PKCS1_V21) - if( PSA_ALG_IS_RSA_OAEP_MGF1( alg ) ) + if( PSA_ALG_IS_RSA_OAEP( alg ) ) { return( PSA_ERROR_NOT_SUPPORTED ); } @@ -1941,7 +1941,7 @@ psa_status_t psa_asymmetric_decrypt( psa_key_slot_t key, else #endif /* MBEDTLS_PKCS1_V15 */ #if defined(MBEDTLS_PKCS1_V21) - if( PSA_ALG_IS_RSA_OAEP_MGF1( alg ) ) + if( PSA_ALG_IS_RSA_OAEP( alg ) ) { return( PSA_ERROR_NOT_SUPPORTED ); } diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index 5bdc718c6..d3186783d 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -503,7 +503,7 @@ PSA signature size: RSA keypair, 1024 bits, PKCS#1 v1.5 SHA-256 signature_size:PSA_KEY_TYPE_RSA_KEYPAIR:1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):128 PSA signature size: RSA keypair, 1024 bits, PSS -signature_size:PSA_KEY_TYPE_RSA_KEYPAIR:1024:PSA_ALG_RSA_PSS_MGF1:128 +signature_size:PSA_KEY_TYPE_RSA_KEYPAIR:1024:PSA_ALG_RSA_PSS( PSA_ALG_SHA_256 ):128 PSA signature size: RSA keypair, 1023 bits, PKCS#1 v1.5 raw signature_size:PSA_KEY_TYPE_RSA_KEYPAIR:1023:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:128 From 08bac713dfb06ae152beaa80b8c8f3d4d5bb69e0 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 26 Jun 2018 16:14:46 +0200 Subject: [PATCH 05/15] Clarify that asymmetric_{sign,verify} operate on a hash --- include/psa/crypto.h | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 32e0f3d83..b67f322f3 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -1715,10 +1715,16 @@ psa_status_t psa_aead_decrypt( psa_key_slot_t key, /** * \brief Sign a hash or short message with a private key. * + * Note that to perform a hash-and-sign signature algorithm, you must + * first calculate the hash by calling psa_hash_start(), psa_hash_update() + * and psa_hash_finish(). Then pass the resulting hash as the \p hash + * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg) + * to determine the hash algorithm to use. + * * \param key Key slot containing an asymmetric key pair. * \param alg A signature algorithm that is compatible with * the type of \c key. - * \param hash The message to sign. + * \param hash The hash or message to sign. * \param hash_length Size of the \c hash buffer in bytes. * \param salt A salt or label, if supported by the signature * algorithm. @@ -1762,11 +1768,18 @@ psa_status_t psa_asymmetric_sign(psa_key_slot_t key, /** * \brief Verify the signature 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_start(), psa_hash_update() + * and psa_hash_finish(). Then pass the resulting hash as the \p hash + * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg) + * to determine the hash algorithm to use. + * * \param key Key slot containing a public key or an * asymmetric key pair. * \param alg A signature algorithm that is compatible with * the type of \c key. - * \param hash The message whose signature is to be verified. + * \param hash The hash or message whose signature is to be + * verified. * \param hash_length Size of the \c hash buffer in bytes. * \param salt A salt or label, if supported by the signature * algorithm. From e9191ff90bb3c3c71a6f73a5159613faf9991a70 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 27 Jun 2018 14:58:41 +0200 Subject: [PATCH 06/15] Add missing const for signature parameter of psa_asymmetric_verify --- include/psa/crypto.h | 2 +- library/psa_crypto.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index b67f322f3..4f1fd7d91 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -1811,7 +1811,7 @@ psa_status_t psa_asymmetric_verify(psa_key_slot_t key, size_t hash_length, const uint8_t *salt, size_t salt_length, - uint8_t *signature, + const uint8_t *signature, size_t signature_size); #define PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(key_type, key_bits, alg) \ diff --git a/library/psa_crypto.c b/library/psa_crypto.c index a4fac648e..c7a44f6a7 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -1741,7 +1741,7 @@ psa_status_t psa_asymmetric_verify( psa_key_slot_t key, size_t hash_length, const uint8_t *salt, size_t salt_length, - uint8_t *signature, + const uint8_t *signature, size_t signature_size ) { key_slot_t *slot; From 526fab0066cb4ab06bf3b291d2a718131010d165 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 27 Jun 2018 18:19:40 +0200 Subject: [PATCH 07/15] Fix parameter name signature_size for psa_asymmetric_verify It should have been signature_length, following our conventions. --- include/psa/crypto.h | 4 ++-- library/psa_crypto.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 4f1fd7d91..62334dd6b 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -1791,7 +1791,7 @@ psa_status_t psa_asymmetric_sign(psa_key_slot_t key, * \param salt_length Size of the \c salt buffer in bytes. * If \c salt is \c NULL, pass 0. * \param signature Buffer containing the signature to verify. - * \param signature_size Size of the \c signature buffer in bytes. + * \param signature_length Size of the \c signature buffer in bytes. * * \retval PSA_SUCCESS * The signature is valid. @@ -1812,7 +1812,7 @@ psa_status_t psa_asymmetric_verify(psa_key_slot_t key, const uint8_t *salt, size_t salt_length, const uint8_t *signature, - size_t signature_size); + size_t signature_length); #define PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(key_type, key_bits, alg) \ (PSA_KEY_TYPE_IS_RSA(key_type) ? \ diff --git a/library/psa_crypto.c b/library/psa_crypto.c index c7a44f6a7..35adbb4ae 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -1742,7 +1742,7 @@ psa_status_t psa_asymmetric_verify( psa_key_slot_t key, const uint8_t *salt, size_t salt_length, const uint8_t *signature, - size_t signature_size ) + size_t signature_length ) { key_slot_t *slot; psa_status_t status; @@ -1768,7 +1768,7 @@ psa_status_t psa_asymmetric_verify( psa_key_slot_t key, if( status != PSA_SUCCESS ) return( status ); - if( signature_size < rsa->len ) + if( signature_length < rsa->len ) return( PSA_ERROR_BUFFER_TOO_SMALL ); #if defined(MBEDTLS_PKCS1_V15) if( PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) ) @@ -1815,7 +1815,7 @@ psa_status_t psa_asymmetric_verify( psa_key_slot_t key, int ret; (void) alg; ret = mbedtls_ecdsa_read_signature( ecdsa, hash, hash_length, - signature, signature_size ); + signature, signature_length ); return( mbedtls_to_psa_error( ret ) ); } else From a81d85b732d077e2fde8745a011cf7f36277e0a2 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 26 Jun 2018 16:10:23 +0200 Subject: [PATCH 08/15] Sort out ECDSA mechanisms * Distinguish randomized ECDSA from deterministic ECDSA. * Deterministic ECDSA needs to be parametrized by a hash. * Randomized ECDSA only uses the hash for the initial hash step, but add ECDSA(hash) algorithms anyway so that all the signature algorithms encode the initial hashing step. * Add brief documentation for the ECDSA signature mechanisms. * Also define DSA signature mechanisms while I'm at it. There were already key types for DSA. --- include/psa/crypto.h | 81 ++++++++++++++++- library/psa_crypto.c | 116 ++++++++++++++++++++---- tests/suites/test_suite_psa_crypto.data | 32 ++++--- 3 files changed, 194 insertions(+), 35 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 62334dd6b..2f972d37d 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -667,6 +667,83 @@ typedef uint32_t psa_algorithm_t; #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(alg) is true). + * + * \return The corresponding DSA signature algorithm. + * \return Unspecified if \p 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) +#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_ECDSA_BASE ((psa_algorithm_t)0x10060000) +/** ECDSA signature with hashing. + * + * This is the ECDSA signature scheme defined by ANSI X9.62, + * 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(alg) is true). + * + * \return The corresponding ECDSA signature algorithm. + * \return Unspecified if \p alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_ECDSA(hash_alg) \ + (PSA_ALG_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +/** ECDSA signature without hashing. + * + * This is the signature scheme defined by ANSI X9.62, + * without specifying a hash algorithm. This algorithm may only be + * used to sign or verify a sequence of bytes that should be an + * already-calculated hash. Note that the input is padded with + * zeros on the left or truncated on the left as required to fit + * the curve size. + */ +#define PSA_ALG_ECDSA_ANY PSA_ALG_ECDSA_BASE +#define PSA_ALG_DETERMINISTIC_ECDSA_BASE ((psa_algorithm_t)0x10070000) +/** Deterministic ECDSA signature with hashing. + * + * This is the deterministic ECDSA signature scheme defined by RFC 6979. + * + * Note that when this algorithm is used for verification, signatures + * made with randomized ECDSA (#PSA_ALG_ECDSA(\c hash_alg)) with the + * same private key are accepted. In other words, + * #PSA_ALG_DETERMINISTIC_ECDSA(\c hash_alg) differs from + * #PSA_ALG_ECDSA(\c hash_alg) only for signature, not for verification. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(alg) is true). + * + * \return The corresponding deterministic ECDSA signature + * algorithm. + * \return Unspecified if \p alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_DETERMINISTIC_ECDSA(hash_alg) \ + (PSA_ALG_DETERMINISTIC_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +#define PSA_ALG_IS_ECDSA(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_DSA_DETERMINISTIC_FLAG) == \ + PSA_ALG_ECDSA_BASE) +#define PSA_ALG_ECDSA_IS_DETERMINISTIC(alg) \ + (((alg) & PSA_ALG_DSA_DETERMINISTIC_FLAG) != 0) + /** Get the hash used by a hash-and-sign signature algorithm. * * A hash-and-sign algorithm is a signature algorithm which is @@ -686,11 +763,11 @@ typedef uint32_t psa_algorithm_t; * if it is not supported by the implementation. */ #define PSA_ALG_SIGN_GET_HASH(alg) \ - (PSA_ALG_IS_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) ? \ ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH : \ 0) -#define PSA_ALG_ECDSA_RAW ((psa_algorithm_t)0x10030000) #define PSA_ALG_RSA_PKCS1V15_CRYPT ((psa_algorithm_t)0x12020000) #define PSA_ALG_RSA_OAEP_BASE ((psa_algorithm_t)0x12030000) #define PSA_ALG_RSA_OAEP(hash_alg) \ diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 35adbb4ae..ffc587a1e 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -40,6 +40,8 @@ #include "mbedtls/arc4.h" #include "mbedtls/asn1.h" +#include "mbedtls/asn1write.h" +#include "mbedtls/bignum.h" #include "mbedtls/blowfish.h" #include "mbedtls/camellia.h" #include "mbedtls/cipher.h" @@ -1637,6 +1639,74 @@ static psa_status_t psa_rsa_decode_md_type( psa_algorithm_t alg, return( PSA_SUCCESS ); } +#if defined(MBEDTLS_ECDSA_C) +/* Temporary copy from ecdsa.c */ +static int ecdsa_signature_to_asn1( const mbedtls_mpi *r, const mbedtls_mpi *s, + unsigned char *sig, size_t *slen ) +{ + int ret; + unsigned char buf[MBEDTLS_ECDSA_MAX_LEN]; + unsigned char *p = buf + sizeof( buf ); + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, s ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, r ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &p, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &p, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); + + memcpy( sig, p, len ); + *slen = len; + + return( 0 ); +} + +/* `ecp` cannot be const because `ecp->grp` needs to be non-const + * for mbedtls_ecdsa_sign() and mbedtls_ecdsa_sign_det() + * (even though these functions don't modify it). */ +static psa_status_t psa_ecdsa_sign( mbedtls_ecp_keypair *ecp, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length ) +{ + int ret; + mbedtls_mpi r, s; + mbedtls_mpi_init( &r ); + mbedtls_mpi_init( &s ); + + if( signature_size < PSA_ECDSA_SIGNATURE_SIZE( ecp->grp.pbits ) ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + + if( PSA_ALG_DSA_IS_DETERMINISTIC( 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 ); + mbedtls_md_type_t md_alg = mbedtls_md_get_type( md_info ); + MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign_det( &ecp->grp, &r, &s, &ecp->d, + hash, hash_length, + md_alg ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ecp->grp, &r, &s, &ecp->d, + hash, hash_length, + mbedtls_ctr_drbg_random, + &global_data.ctr_drbg ) ); + } + MBEDTLS_MPI_CHK( ecdsa_signature_to_asn1( &r, &s, + signature, signature_length ) ); + +cleanup: + mbedtls_mpi_free( &r ); + mbedtls_mpi_free( &s ); + return( mbedtls_to_psa_error( ret ) ); +} +#endif /* MBEDTLS_ECDSA_C */ + psa_status_t psa_asymmetric_sign( psa_key_slot_t key, psa_algorithm_t alg, const uint8_t *hash, @@ -1714,19 +1784,19 @@ psa_status_t psa_asymmetric_sign( psa_key_slot_t key, #if defined(MBEDTLS_ECP_C) if( PSA_KEY_TYPE_IS_ECC( slot->type ) ) { - mbedtls_ecp_keypair *ecdsa = slot->data.ecp; - int ret; - const mbedtls_md_info_t *md_info; - mbedtls_md_type_t md_alg; - if( signature_size < PSA_ECDSA_SIGNATURE_SIZE( ecdsa->grp.pbits ) ) - return( PSA_ERROR_BUFFER_TOO_SMALL ); - md_info = mbedtls_md_info_from_psa( alg ); - md_alg = mbedtls_md_get_type( md_info ); - ret = mbedtls_ecdsa_write_signature( ecdsa, md_alg, hash, hash_length, - signature, signature_length, - mbedtls_ctr_drbg_random, - &global_data.ctr_drbg ); - return( mbedtls_to_psa_error( ret ) ); +#if defined(MBEDTLS_ECDSA_C) + if( PSA_ALG_IS_ECDSA( alg ) ) + status = psa_ecdsa_sign( slot->data.ecp, + alg, + hash, hash_length, + signature, signature_size, + signature_length ); + else +#endif /* defined(MBEDTLS_ECDSA_C) */ + { + return( PSA_ERROR_INVALID_ARGUMENT ); + } + return( status ); } else #endif /* defined(MBEDTLS_ECP_C) */ @@ -1811,12 +1881,20 @@ psa_status_t psa_asymmetric_verify( psa_key_slot_t key, #if defined(MBEDTLS_ECP_C) if( PSA_KEY_TYPE_IS_ECC( slot->type ) ) { - mbedtls_ecp_keypair *ecdsa = slot->data.ecp; - int ret; - (void) alg; - ret = mbedtls_ecdsa_read_signature( ecdsa, hash, hash_length, - signature, signature_length ); - return( mbedtls_to_psa_error( ret ) ); +#if defined(MBEDTLS_ECDSA_C) + if( PSA_ALG_IS_ECDSA( alg ) ) + { + int ret; + ret = mbedtls_ecdsa_read_signature( slot->data.ecp, + hash, hash_length, + signature, signature_length ); + return( mbedtls_to_psa_error( ret ) ); + } + else +#endif /* defined(MBEDTLS_ECDSA_C) */ + { + return( PSA_ERROR_INVALID_ARGUMENT ); + } } else #endif /* defined(MBEDTLS_ECP_C) */ diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index d3186783d..17e3a5538 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -111,11 +111,11 @@ import_export_public_key:"2b7e151628aed2a6abf7158809cf4f3c":PSA_KEY_TYPE_AES:PSA PSA import/export EC secp256r1: good depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED -import_export:"3077020101042049c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eeea00a06082a8648ce3d030107a144034200047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45":PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):PSA_ALG_ECDSA_RAW:PSA_KEY_USAGE_EXPORT:256:0:PSA_SUCCESS:1 +import_export:"3077020101042049c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eeea00a06082a8648ce3d030107a144034200047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45":PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):PSA_ALG_ECDSA_ANY:PSA_KEY_USAGE_EXPORT:256:0:PSA_SUCCESS:1 PSA import/export EC secp384r1: good depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED -import_export:"3081a402010104303f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76aa00706052b81040022a16403620004d9c662b50ba29ca47990450e043aeaf4f0c69b15676d112f622a71c93059af999691c5680d2b44d111579db12f4a413a2ed5c45fcfb67b5b63e00b91ebe59d09a6b1ac2c0c4282aa12317ed5914f999bc488bb132e8342cc36f2ca5e3379c747":PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP384R1):PSA_ALG_ECDSA_RAW:PSA_KEY_USAGE_EXPORT:384:0:PSA_SUCCESS:1 +import_export:"3081a402010104303f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76aa00706052b81040022a16403620004d9c662b50ba29ca47990450e043aeaf4f0c69b15676d112f622a71c93059af999691c5680d2b44d111579db12f4a413a2ed5c45fcfb67b5b63e00b91ebe59d09a6b1ac2c0c4282aa12317ed5914f999bc488bb132e8342cc36f2ca5e3379c747":PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP384R1):PSA_ALG_ECDSA_ANY:PSA_KEY_USAGE_EXPORT:384:0:PSA_SUCCESS:1 PSA import EC keypair secp384r1: valid key but wrong curve (secp256r1) depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED @@ -518,9 +518,9 @@ sign_deterministic:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84 PSA sign: RSA PKCS#1 v1.5 SHA-256 sign_deterministic:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"a73664d55b39c7ea6c1e5b5011724a11e1d7073d3a68f48c836fad153a1d91b6abdbc8f69da13b206cc96af6363b114458b026af14b24fab8929ed634c6a2acace0bcc62d9bb6a984afbcbfcd3a0608d32a2bae535b9cd1ecdf9dd281db1e0025c3bfb5512963ec3b98ddaa69e38bc3c84b1b61a04e5648640856aacc6fc7311" -PSA sign: ECDSA SECP256R1 SHA-256 +PSA sign: deterministic ECDSA SECP256R1 SHA-256 depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_DETERMINISTIC -sign_deterministic:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_SHA_256:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"304502206a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151022100ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f" +sign_deterministic:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"304502206a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151022100ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f" PSA sign: RSA PKCS#1 v1.5 SHA-256, wrong hash size sign_fail:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015":128:PSA_ERROR_INVALID_ARGUMENT @@ -528,13 +528,13 @@ sign_fail:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5 PSA sign: RSA PKCS#1 v1.5 SHA-256, output buffer too small sign_fail:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":127:PSA_ERROR_BUFFER_TOO_SMALL -PSA sign: ECDSA SECP256R1 SHA-256, output buffer too small +PSA sign: deterministic ECDSA SECP256R1 SHA-256, output buffer too small depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED -sign_fail:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_SHA_256:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":10:PSA_ERROR_BUFFER_TOO_SMALL +sign_fail:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":10:PSA_ERROR_BUFFER_TOO_SMALL -PSA sign: ECDSA SECP256R1, invalid hash +PSA sign: deterministic ECDSA SECP256R1, invalid hash depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_DETERMINISTIC -sign_fail:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":0:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":72:PSA_ERROR_INVALID_ARGUMENT +sign_fail:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_DETERMINISTIC_ECDSA( 0 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":72:PSA_ERROR_INVALID_ARGUMENT PSA verify: RSA PKCS#1 v1.5 SHA-256, good signature depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15 @@ -548,9 +548,13 @@ PSA verify: RSA PKCS#1 v1.5 SHA-256, wrong signature depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15 asymmetric_verify_fail:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"111164d55b39c7ea6c1e5b5011724a11e1d7073d3a68f48c836fad153a1d91b6abdbc8f69da13b206cc96af6363b114458b026af14b24fab8929ed634c6a2acace0bcc62d9bb6a984afbcbfcd3a0608d32a2bae535b9cd1ecdf9dd281db1e0025c3bfb5512963ec3b98ddaa69e38bc3c84b1b61a04e5648640856aacc6fc7311":PSA_ERROR_INVALID_SIGNATURE -PSA verify: ECDSA SECP256R1 SHA-256 +PSA verify: ECDSA SECP256R1, good depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED -asymmetric_verify:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_SHA_256:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"304502206a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151022100ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f" +asymmetric_verify:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"304502206a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151022100ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f" + +PSA verify: ECDSA SECP256R1, wrong signature +depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED +asymmetric_verify_fail:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"304502206a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151022100ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50e":PSA_ERROR_INVALID_SIGNATURE PSA encrypt-decrypt: RSA PKCS#1 v1.5 vector #1 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15 @@ -662,9 +666,9 @@ depends_on:MBEDTLS_RSA_C generate_key:PSA_KEY_TYPE_RSA_KEYPAIR:512:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_SUCCESS PSA generate key: ECC, SECP256R1, good -depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED -generate_key:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):256:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY:PSA_ALG_ECDSA_RAW | PSA_ALG_SHA_256:PSA_SUCCESS +depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_C +generate_key:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):256:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY:PSA_ALG_ECDSA_ANY:PSA_SUCCESS PSA generate key: ECC, SECP256R1, incorrect bit size -depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED -generate_key:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):128:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY:PSA_ALG_ECDSA_RAW:PSA_ERROR_INVALID_ARGUMENT +depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_C +generate_key:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):128:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY:PSA_ALG_ECDSA_ANY:PSA_ERROR_INVALID_ARGUMENT From a680c7a9fcf7765dd35a177e9b6ddd607520ab3f Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 26 Jun 2018 16:12:43 +0200 Subject: [PATCH 09/15] Add import-and-exercise tests for some signature algorithms --- tests/suites/test_suite_psa_crypto.data | 12 ++++ tests/suites/test_suite_psa_crypto.function | 61 +++++++++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index 17e3a5538..2f9035438 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -511,6 +511,18 @@ signature_size:PSA_KEY_TYPE_RSA_KEYPAIR:1023:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:128 PSA signature size: RSA keypair, 1025 bits, PKCS#1 v1.5 raw signature_size:PSA_KEY_TYPE_RSA_KEYPAIR:1025:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:129 +PSA import/exercise RSA keypair, PKCS#1 v1.5 raw +depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C +import_and_exercise_key:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEYPAIR:1024:PSA_ALG_RSA_PKCS1V15_SIGN_RAW + +PSA import/exercise: ECP SECP256R1 keypair, ECDSA +depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_C +import_and_exercise_key:"3077020101042049c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eeea00a06082a8648ce3d030107a144034200047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45":PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):256:PSA_ALG_ECDSA_ANY + +PSA import/exercise: ECP SECP256R1 keypair, deterministic ECDSA +depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_C:MBEDTLS_ECDSA_DETERMINISTIC:MBEDTLS_SHA256_C +import_and_exercise_key:"3077020101042049c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eeea00a06082a8648ce3d030107a144034200047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45":PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):256:PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ) + PSA sign: RSA PKCS#1 v1.5, raw depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15 sign_deterministic:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN_RAW:"616263":"2c7744983f023ac7bb1c55529d83ed11a76a7898a1bb5ce191375a4aa7495a633d27879ff58eba5a57371c34feb1180e8b850d552476ebb5634df620261992f12ebee9097041dbbea85a42d45b344be5073ceb772ffc604954b9158ba81ec3dc4d9d65e3ab7aa318165f38c36f841f1c69cb1cfa494aa5cbb4d6c0efbafb043a" diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index 6bcc65f31..446af5a19 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -476,6 +476,67 @@ exit: } /* END_CASE */ +/* BEGIN_CASE */ +void import_and_exercise_key( data_t *data, + int type_arg, + int bits_arg, + int alg_arg ) +{ + int slot = 1; + psa_key_type_t type = type_arg; + size_t bits = bits_arg; + psa_algorithm_t alg = alg_arg; + psa_key_usage_t usage = + ( PSA_ALG_IS_MAC( alg ) || PSA_ALG_IS_SIGN( alg ) ? + ( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ? + PSA_KEY_USAGE_VERIFY : + PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY ) : + PSA_ALG_IS_CIPHER( alg ) || PSA_ALG_IS_AEAD( alg ) || + PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) ? + ( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ? + PSA_KEY_USAGE_ENCRYPT : + PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT ) : + 0 ); + psa_key_policy_t policy; + psa_key_type_t got_type; + size_t got_bits; + psa_status_t status; + + TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + + psa_key_policy_init( &policy ); + psa_key_policy_set_usage( &policy, usage, alg ); + TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS ); + + /* Import the key */ + status = psa_import_key( slot, type, data->x, data->len ); + TEST_ASSERT( status == PSA_SUCCESS ); + + /* Test the key information */ + TEST_ASSERT( psa_get_key_information( slot, + &got_type, + &got_bits ) == PSA_SUCCESS ); + TEST_ASSERT( got_type == type ); + TEST_ASSERT( got_bits == bits ); + + /* Do something with the key according to its type and permitted usage. */ + if( PSA_ALG_IS_MAC( alg ) ) + exercise_mac_key( slot, usage, alg ); + else if( PSA_ALG_IS_CIPHER( alg ) ) + exercise_cipher_key( slot, usage, alg ); + else if( PSA_ALG_IS_AEAD( alg ) ) + exercise_aead_key( slot, usage, alg ); + else if( PSA_ALG_IS_SIGN( alg ) ) + exercise_signature_key( slot, usage, alg ); + else if( PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) ) + exercise_asymmetric_encryption_key( slot, usage, alg ); + +exit: + psa_destroy_key( slot ); + mbedtls_psa_crypto_free( ); +} +/* END_CASE */ + /* BEGIN_CASE */ void key_policy( int usage_arg, int alg_arg ) { From ca45c35e65818ec2e2c13291053d2f7a20e709a0 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 26 Jun 2018 16:13:09 +0200 Subject: [PATCH 10/15] Fix exercise_signature_key for ECDSA mbedtls_ecdsa_verify fails when the input is all-bits-zero (mbedtls issue #1792). Use a different input. --- tests/suites/test_suite_psa_crypto.function | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index 446af5a19..cb6da7f44 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -189,7 +189,7 @@ static int exercise_signature_key( psa_key_slot_t key, psa_key_usage_t usage, psa_algorithm_t alg ) { - unsigned char payload[16] = {0}; + unsigned char payload[16] = {1}; size_t payload_length = sizeof( payload ); unsigned char signature[256] = {0}; size_t signature_length = sizeof( signature ); From eae6eee24c1c09839efcbaf38669073fc6239fa9 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 28 Jun 2018 13:56:01 +0200 Subject: [PATCH 11/15] Change ECDSA signature representation to r||s Change the representation of an ECDSA signature from the ASN.1 DER encoding used in TLS and X.509, to the concatenation of r and s in big-endian order with a fixed size. A fixed size helps memory and buffer management and this representation is generally easier to use for anything that doesn't require the ASN.1 representation. This is the same representation as PKCS#11 (Cryptoki) except that PKCS#11 allows r and s to be truncated (both to the same length), which complicates the implementation and negates the advantage of a fixed-size representation. --- include/psa/crypto.h | 39 ++++------- library/psa_crypto.c | 86 +++++++++++++++---------- tests/suites/test_suite_psa_crypto.data | 14 ++-- 3 files changed, 75 insertions(+), 64 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 2f972d37d..dcf1ba227 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -698,6 +698,12 @@ typedef uint32_t psa_algorithm_t; * This is the ECDSA signature scheme defined by ANSI X9.62, * with a random per-message secret number (*k*). * + * The representation of the signature as a byte string consists of + * the concatentation of the signature values *r* and *s*. Each of + * *r* and *s* is encoded as an *N*-octet string, where *N* is the length + * of the base point of the curve in octets. Each value is represented + * in big-endian order (most significant octet first). + * * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_HASH(alg) is true). * @@ -709,7 +715,7 @@ typedef uint32_t psa_algorithm_t; (PSA_ALG_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) /** ECDSA signature without hashing. * - * This is the signature scheme defined by ANSI X9.62, + * This is the same signature scheme as #PSA_ALG_ECDSA(), but * without specifying a hash algorithm. This algorithm may only be * used to sign or verify a sequence of bytes that should be an * already-calculated hash. Note that the input is padded with @@ -722,6 +728,8 @@ typedef uint32_t psa_algorithm_t; * * This is the deterministic ECDSA signature scheme defined by RFC 6979. * + * The representation of a signature is the same as with #PSA_ALG_ECDSA(). + * * Note that when this algorithm is used for verification, signatures * made with randomized ECDSA (#PSA_ALG_ECDSA(\c hash_alg)) with the * same private key are accepted. In other words, @@ -1728,34 +1736,15 @@ psa_status_t psa_aead_decrypt( psa_key_slot_t key, */ /** - * \brief Maximum ECDSA signature size for a given curve bit size + * \brief ECDSA signature size for a given curve bit size * - * \param curve_bits Curve size in bits - * \return Maximum signature size in bytes + * \param curve_bits Curve size in bits. + * \return Signature size in bytes. * * \note This macro returns a compile-time constant if its argument is one. - * - * \warning This macro may evaluate its argument multiple times. */ -/* - * RFC 4492 page 20: - * - * Ecdsa-Sig-Value ::= SEQUENCE { - * r INTEGER, - * s INTEGER - * } - * - * Size is at most - * 1 (tag) + 1 (len) + 1 (initial 0) + curve_bytes for each of r and s, - * twice that + 1 (tag) + 2 (len) for the sequence - * (assuming curve_bytes is less than 126 for r and s, - * and less than 124 (total len <= 255) for the sequence) - */ -#define PSA_ECDSA_SIGNATURE_SIZE(curve_bits) \ - ( /*T,L of SEQUENCE*/ ((curve_bits) >= 61 * 8 ? 3 : 2) + \ - /*T,L of r,s*/ 2 * (((curve_bits) >= 127 * 8 ? 3 : 2) + \ - /*V of r,s*/ ((curve_bits) + 8) / 8)) - +#define PSA_ECDSA_SIGNATURE_SIZE(curve_bits) \ + (PSA_BITS_TO_BYTES(curve_bits) * 2) /** Safe signature buffer size for psa_asymmetric_sign(). * diff --git a/library/psa_crypto.c b/library/psa_crypto.c index ffc587a1e..9454f478c 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -40,7 +40,6 @@ #include "mbedtls/arc4.h" #include "mbedtls/asn1.h" -#include "mbedtls/asn1write.h" #include "mbedtls/bignum.h" #include "mbedtls/blowfish.h" #include "mbedtls/camellia.h" @@ -1640,28 +1639,6 @@ static psa_status_t psa_rsa_decode_md_type( psa_algorithm_t alg, } #if defined(MBEDTLS_ECDSA_C) -/* Temporary copy from ecdsa.c */ -static int ecdsa_signature_to_asn1( const mbedtls_mpi *r, const mbedtls_mpi *s, - unsigned char *sig, size_t *slen ) -{ - int ret; - unsigned char buf[MBEDTLS_ECDSA_MAX_LEN]; - unsigned char *p = buf + sizeof( buf ); - size_t len = 0; - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, s ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, r ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &p, buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &p, buf, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); - - memcpy( sig, p, len ); - *slen = len; - - return( 0 ); -} - /* `ecp` cannot be const because `ecp->grp` needs to be non-const * for mbedtls_ecdsa_sign() and mbedtls_ecdsa_sign_det() * (even though these functions don't modify it). */ @@ -1675,11 +1652,16 @@ static psa_status_t psa_ecdsa_sign( mbedtls_ecp_keypair *ecp, { int ret; mbedtls_mpi r, s; + size_t curve_bytes = PSA_BITS_TO_BYTES( ecp->grp.pbits ); mbedtls_mpi_init( &r ); mbedtls_mpi_init( &s ); - if( signature_size < PSA_ECDSA_SIGNATURE_SIZE( ecp->grp.pbits ) ) - return( PSA_ERROR_BUFFER_TOO_SMALL ); + *signature_length = 0; + if( signature_size < 2 * curve_bytes ) + { + ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; + goto cleanup; + } if( PSA_ALG_DSA_IS_DETERMINISTIC( alg ) ) { @@ -1697,8 +1679,48 @@ static psa_status_t psa_ecdsa_sign( mbedtls_ecp_keypair *ecp, mbedtls_ctr_drbg_random, &global_data.ctr_drbg ) ); } - MBEDTLS_MPI_CHK( ecdsa_signature_to_asn1( &r, &s, - signature, signature_length ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &r, + signature, + curve_bytes ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &s, + signature + curve_bytes, + curve_bytes ) ); + +cleanup: + mbedtls_mpi_free( &r ); + mbedtls_mpi_free( &s ); + if( ret == 0 ) + *signature_length = 2 * curve_bytes; + memset( signature + *signature_length, 0, + signature_size - *signature_length ); + return( mbedtls_to_psa_error( ret ) ); +} + +static psa_status_t psa_ecdsa_verify( mbedtls_ecp_keypair *ecp, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length ) +{ + int ret; + mbedtls_mpi r, s; + size_t curve_bytes = PSA_BITS_TO_BYTES( ecp->grp.pbits ); + mbedtls_mpi_init( &r ); + mbedtls_mpi_init( &s ); + + if( signature_length != 2 * curve_bytes ) + return( PSA_ERROR_INVALID_SIGNATURE ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, + signature, + curve_bytes ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &s, + signature + curve_bytes, + curve_bytes ) ); + + ret = mbedtls_ecdsa_verify( &ecp->grp, hash, hash_length, + &ecp->Q, &r, &s ); cleanup: mbedtls_mpi_free( &r ); @@ -1883,13 +1905,9 @@ psa_status_t psa_asymmetric_verify( psa_key_slot_t key, { #if defined(MBEDTLS_ECDSA_C) if( PSA_ALG_IS_ECDSA( alg ) ) - { - int ret; - ret = mbedtls_ecdsa_read_signature( slot->data.ecp, - hash, hash_length, - signature, signature_length ); - return( mbedtls_to_psa_error( ret ) ); - } + return( psa_ecdsa_verify( slot->data.ecp, + hash, hash_length, + signature, signature_length ) ); else #endif /* defined(MBEDTLS_ECDSA_C) */ { diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index 2f9035438..1181fcd92 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -532,7 +532,7 @@ sign_deterministic:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84 PSA sign: deterministic ECDSA SECP256R1 SHA-256 depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_DETERMINISTIC -sign_deterministic:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"304502206a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151022100ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f" +sign_deterministic:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f" PSA sign: RSA PKCS#1 v1.5 SHA-256, wrong hash size sign_fail:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015":128:PSA_ERROR_INVALID_ARGUMENT @@ -542,7 +542,7 @@ sign_fail:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5 PSA sign: deterministic ECDSA SECP256R1 SHA-256, output buffer too small depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED -sign_fail:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":10:PSA_ERROR_BUFFER_TOO_SMALL +sign_fail:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":63:PSA_ERROR_BUFFER_TOO_SMALL PSA sign: deterministic ECDSA SECP256R1, invalid hash depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_DETERMINISTIC @@ -562,11 +562,15 @@ asymmetric_verify_fail:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396 PSA verify: ECDSA SECP256R1, good depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED -asymmetric_verify:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"304502206a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151022100ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f" +asymmetric_verify:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f" -PSA verify: ECDSA SECP256R1, wrong signature +PSA verify: ECDSA SECP256R1, wrong signature size (correct but ASN1-encoded) depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED -asymmetric_verify_fail:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"304502206a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151022100ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50e":PSA_ERROR_INVALID_SIGNATURE +asymmetric_verify_fail:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"304502206a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151022100ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":PSA_ERROR_INVALID_SIGNATURE + +PSA verify: ECDSA SECP256R1, wrong signature of correct size +depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED +asymmetric_verify_fail:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50e":PSA_ERROR_INVALID_SIGNATURE PSA encrypt-decrypt: RSA PKCS#1 v1.5 vector #1 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15 From d35a1cce7f20b3d6a28813961e46331e3e371d4d Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 26 Jun 2018 21:26:10 +0200 Subject: [PATCH 12/15] Correct the documentation of mem_is_zero --- tests/suites/test_suite_psa_crypto.function | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index cb6da7f44..2fba85414 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -11,7 +11,7 @@ /** An invalid export length that will never be set by psa_export_key(). */ static const size_t INVALID_EXPORT_LENGTH = ~0U; -/** Test if a buffer is not all-bits zero. +/** Test if a buffer is all-bits zero. * * \param buffer Pointer to the beginning of the buffer. * \param size Size of the buffer in bytes. From 2b450e3a01e138598e31dbb0c0f8b8a4182e92f7 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 27 Jun 2018 15:42:46 +0200 Subject: [PATCH 13/15] Factor RSA sign/verify code into its own functions This makes the functions smaller and makes error paths easier to read. --- library/psa_crypto.c | 219 ++++++++++++++++++++++++------------------- 1 file changed, 125 insertions(+), 94 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 9454f478c..cb2a4f271 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -1612,6 +1612,7 @@ psa_status_t psa_mac_verify( psa_mac_operation_t *operation, /* Asymmetric cryptography */ /****************************************************************/ +#if defined(MBEDTLS_RSA_C) /* Decode the hash algorithm from alg and store the mbedtls encoding in * md_alg. Verify that the hash length is consistent. */ static psa_status_t psa_rsa_decode_md_type( psa_algorithm_t alg, @@ -1638,6 +1639,115 @@ static psa_status_t psa_rsa_decode_md_type( psa_algorithm_t alg, return( PSA_SUCCESS ); } +static psa_status_t psa_rsa_sign( mbedtls_rsa_context *rsa, + 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; + int ret; + mbedtls_md_type_t md_alg; + + status = psa_rsa_decode_md_type( alg, hash_length, &md_alg ); + if( status != PSA_SUCCESS ) + return( status ); + + if( signature_size < rsa->len ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + +#if defined(MBEDTLS_PKCS1_V15) + 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_ctr_drbg_random, + &global_data.ctr_drbg, + MBEDTLS_RSA_PRIVATE, + md_alg, hash_length, hash, + signature ); + } + else +#endif /* MBEDTLS_PKCS1_V15 */ +#if defined(MBEDTLS_PKCS1_V21) + 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_ctr_drbg_random, + &global_data.ctr_drbg, + MBEDTLS_RSA_PRIVATE, + md_alg, hash_length, hash, + signature ); + } + else +#endif /* MBEDTLS_PKCS1_V21 */ + { + return( PSA_ERROR_INVALID_ARGUMENT ); + } + + if( ret == 0 ) + *signature_length = rsa->len; + return( mbedtls_to_psa_error( ret ) ); +} + +static psa_status_t psa_rsa_verify( mbedtls_rsa_context *rsa, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length ) +{ + psa_status_t status; + int ret; + mbedtls_md_type_t md_alg; + + status = psa_rsa_decode_md_type( alg, hash_length, &md_alg ); + if( status != PSA_SUCCESS ) + return( status ); + + if( signature_length < rsa->len ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + +#if defined(MBEDTLS_PKCS1_V15) + 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_ctr_drbg_random, + &global_data.ctr_drbg, + MBEDTLS_RSA_PUBLIC, + md_alg, + hash_length, + hash, + signature ); + } + else +#endif /* MBEDTLS_PKCS1_V15 */ +#if defined(MBEDTLS_PKCS1_V21) + 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_ctr_drbg_random, + &global_data.ctr_drbg, + MBEDTLS_RSA_PUBLIC, + md_alg, hash_length, hash, + signature ); + } + else +#endif /* MBEDTLS_PKCS1_V21 */ + { + return( PSA_ERROR_INVALID_ARGUMENT ); + } + return( mbedtls_to_psa_error( ret ) ); +} +#endif /* MBEDTLS_RSA_C */ + #if defined(MBEDTLS_ECDSA_C) /* `ecp` cannot be const because `ecp->grp` needs to be non-const * for mbedtls_ecdsa_sign() and mbedtls_ecdsa_sign_det() @@ -1740,7 +1850,6 @@ psa_status_t psa_asymmetric_sign( psa_key_slot_t key, size_t *signature_length ) { key_slot_t *slot; - psa_status_t status; *signature_length = 0; (void) salt; (void) salt_length; @@ -1758,48 +1867,11 @@ psa_status_t psa_asymmetric_sign( psa_key_slot_t key, #if defined(MBEDTLS_RSA_C) if( slot->type == PSA_KEY_TYPE_RSA_KEYPAIR ) { - mbedtls_rsa_context *rsa = slot->data.rsa; - int ret; - mbedtls_md_type_t md_alg; - status = psa_rsa_decode_md_type( alg, hash_length, &md_alg ); - if( status != PSA_SUCCESS ) - return( status ); - - if( signature_size < rsa->len ) - return( PSA_ERROR_BUFFER_TOO_SMALL ); -#if defined(MBEDTLS_PKCS1_V15) - 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_ctr_drbg_random, - &global_data.ctr_drbg, - MBEDTLS_RSA_PRIVATE, - md_alg, hash_length, hash, - signature ); - } - else -#endif /* MBEDTLS_PKCS1_V15 */ -#if defined(MBEDTLS_PKCS1_V21) - 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_ctr_drbg_random, - &global_data.ctr_drbg, - MBEDTLS_RSA_PRIVATE, - md_alg, hash_length, hash, - signature ); - } - else -#endif /* MBEDTLS_PKCS1_V21 */ - { - return( PSA_ERROR_INVALID_ARGUMENT ); - } - if( ret == 0 ) - *signature_length = rsa->len; - return( mbedtls_to_psa_error( ret ) ); + return( psa_rsa_sign( slot->data.rsa, + alg, + hash, hash_length, + signature, signature_size, + signature_length ) ); } else #endif /* defined(MBEDTLS_RSA_C) */ @@ -1808,17 +1880,16 @@ psa_status_t psa_asymmetric_sign( psa_key_slot_t key, { #if defined(MBEDTLS_ECDSA_C) if( PSA_ALG_IS_ECDSA( alg ) ) - status = psa_ecdsa_sign( slot->data.ecp, - alg, - hash, hash_length, - signature, signature_size, - signature_length ); + return( psa_ecdsa_sign( slot->data.ecp, + alg, + hash, hash_length, + signature, signature_size, + signature_length ) ); else #endif /* defined(MBEDTLS_ECDSA_C) */ { return( PSA_ERROR_INVALID_ARGUMENT ); } - return( status ); } else #endif /* defined(MBEDTLS_ECP_C) */ @@ -1837,7 +1908,7 @@ psa_status_t psa_asymmetric_verify( psa_key_slot_t key, size_t signature_length ) { key_slot_t *slot; - psa_status_t status; + (void) salt; (void) salt_length; @@ -1853,50 +1924,10 @@ psa_status_t psa_asymmetric_verify( psa_key_slot_t key, if( slot->type == PSA_KEY_TYPE_RSA_KEYPAIR || slot->type == PSA_KEY_TYPE_RSA_PUBLIC_KEY ) { - mbedtls_rsa_context *rsa = slot->data.rsa; - int ret; - mbedtls_md_type_t md_alg; - status = psa_rsa_decode_md_type( alg, hash_length, &md_alg ); - if( status != PSA_SUCCESS ) - return( status ); - - if( signature_length < rsa->len ) - return( PSA_ERROR_BUFFER_TOO_SMALL ); -#if defined(MBEDTLS_PKCS1_V15) - 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_ctr_drbg_random, - &global_data.ctr_drbg, - MBEDTLS_RSA_PUBLIC, - md_alg, - hash_length, - hash, - signature ); - - } - else -#endif /* MBEDTLS_PKCS1_V15 */ -#if defined(MBEDTLS_PKCS1_V21) - 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_ctr_drbg_random, - &global_data.ctr_drbg, - MBEDTLS_RSA_PUBLIC, - md_alg, hash_length, hash, - signature ); - } - else -#endif /* MBEDTLS_PKCS1_V21 */ - { - return( PSA_ERROR_INVALID_ARGUMENT ); - } - return( mbedtls_to_psa_error( ret ) ); + return( psa_rsa_verify( slot->data.rsa, + alg, + hash, hash_length, + signature, signature_length ) ); } else #endif /* defined(MBEDTLS_RSA_C) */ From a26ff6a290ff8b8bfbc836f0fd54bc7e55306e0f Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 28 Jun 2018 12:21:19 +0200 Subject: [PATCH 14/15] psa_asymmetric_sign: consistently fill unused output with '!' Fill the unused part of the output buffer with '!', for consistency with hash and mac. On error, set the output length to the output buffer size and fill the output buffer with '!', again for consistency with hash and mac. This way an invalid output is more visible in a memory dump. Restructure the error paths so that there is a single place where the unused part of the output buffer is filled. Also remove a redundant initialization of *signature_length to 0. --- library/psa_crypto.c | 64 ++++++++++++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 20 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index cb2a4f271..1d8eb506d 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -1766,7 +1766,6 @@ static psa_status_t psa_ecdsa_sign( mbedtls_ecp_keypair *ecp, mbedtls_mpi_init( &r ); mbedtls_mpi_init( &s ); - *signature_length = 0; if( signature_size < 2 * curve_bytes ) { ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; @@ -1802,8 +1801,6 @@ cleanup: mbedtls_mpi_free( &s ); if( ret == 0 ) *signature_length = 2 * curve_bytes; - memset( signature + *signature_length, 0, - signature_size - *signature_length ); return( mbedtls_to_psa_error( ret ) ); } @@ -1850,28 +1847,43 @@ psa_status_t psa_asymmetric_sign( psa_key_slot_t key, size_t *signature_length ) { key_slot_t *slot; - *signature_length = 0; + psa_status_t status; + + *signature_length = signature_size; + (void) salt; (void) salt_length; if( key == 0 || key > PSA_KEY_SLOT_COUNT ) - return( PSA_ERROR_EMPTY_SLOT ); + { + status = PSA_ERROR_EMPTY_SLOT; + goto exit; + } slot = &global_data.key_slots[key]; if( slot->type == PSA_KEY_TYPE_NONE ) - return( PSA_ERROR_EMPTY_SLOT ); + { + status = PSA_ERROR_EMPTY_SLOT; + goto exit; + } if( ! PSA_KEY_TYPE_IS_KEYPAIR( slot->type ) ) - return( PSA_ERROR_INVALID_ARGUMENT ); + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } if( ! ( slot->policy.usage & PSA_KEY_USAGE_SIGN ) ) - return( PSA_ERROR_NOT_PERMITTED ); + { + status = PSA_ERROR_NOT_PERMITTED; + goto exit; + } #if defined(MBEDTLS_RSA_C) if( slot->type == PSA_KEY_TYPE_RSA_KEYPAIR ) { - return( psa_rsa_sign( slot->data.rsa, - alg, - hash, hash_length, - signature, signature_size, - signature_length ) ); + status = psa_rsa_sign( slot->data.rsa, + alg, + hash, hash_length, + signature, signature_size, + signature_length ); } else #endif /* defined(MBEDTLS_RSA_C) */ @@ -1880,22 +1892,34 @@ psa_status_t psa_asymmetric_sign( psa_key_slot_t key, { #if defined(MBEDTLS_ECDSA_C) if( PSA_ALG_IS_ECDSA( alg ) ) - return( psa_ecdsa_sign( slot->data.ecp, - alg, - hash, hash_length, - signature, signature_size, - signature_length ) ); + status = psa_ecdsa_sign( slot->data.ecp, + alg, + hash, hash_length, + signature, signature_size, + signature_length ); else #endif /* defined(MBEDTLS_ECDSA_C) */ { - return( PSA_ERROR_INVALID_ARGUMENT ); + status = PSA_ERROR_INVALID_ARGUMENT; } } else #endif /* defined(MBEDTLS_ECP_C) */ { - return( PSA_ERROR_NOT_SUPPORTED ); + status = PSA_ERROR_NOT_SUPPORTED; } + +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 mac + * (barring an attack on the mac 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 ); + return( status ); } psa_status_t psa_asymmetric_verify( psa_key_slot_t key, From 860ce9d9e53c700cdc20819fd70bae46d9262932 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 28 Jun 2018 12:23:00 +0200 Subject: [PATCH 15/15] Document what the signature tests are doing a bit better Add a check that the purported output length is less than the buffer size in sign_fail. --- tests/suites/test_suite_psa_crypto.function | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index 2fba85414..1959e13d0 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -1589,17 +1589,21 @@ void sign_deterministic( int key_type_arg, data_t *key_data, NULL, &key_bits ) == PSA_SUCCESS ); + /* Allocate a buffer which has the size advertized by the + * library. */ signature_size = PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE( key_type, key_bits, alg ); TEST_ASSERT( signature_size != 0 ); signature = mbedtls_calloc( 1, signature_size ); TEST_ASSERT( signature != NULL ); + /* Perform the signature. */ TEST_ASSERT( psa_asymmetric_sign( slot, alg, input_data->x, input_data->len, NULL, 0, signature, signature_size, &signature_length ) == PSA_SUCCESS ); + /* Verify that the signature is correct. */ TEST_ASSERT( signature_length == output_data->len ); TEST_ASSERT( memcmp( signature, output_data->x, output_data->len ) == 0 ); @@ -1614,11 +1618,12 @@ exit: /* BEGIN_CASE */ void sign_fail( int key_type_arg, data_t *key_data, int alg_arg, data_t *input_data, - int signature_size, int expected_status_arg ) + int signature_size_arg, int expected_status_arg ) { int slot = 1; psa_key_type_t key_type = key_type_arg; psa_algorithm_t alg = alg_arg; + size_t signature_size = signature_size_arg; psa_status_t actual_status; psa_status_t expected_status = expected_status_arg; unsigned char *signature = NULL; @@ -1649,7 +1654,11 @@ void sign_fail( int key_type_arg, data_t *key_data, signature, signature_size, &signature_length ); TEST_ASSERT( actual_status == expected_status ); - TEST_ASSERT( signature_length == 0 ); + /* The value of *signature_length is unspecified on error, but + * whatever it is, it should be less than signature_size, so that + * if the caller tries to read *signature_length bytes without + * checking the error code then they don't overflow a buffer. */ + TEST_ASSERT( signature_length <= signature_size ); exit: psa_destroy_key( slot );