diff --git a/include/polarssl/pk.h b/include/polarssl/pk.h index 1309f70da..232e175b1 100644 --- a/include/polarssl/pk.h +++ b/include/polarssl/pk.h @@ -102,6 +102,17 @@ typedef enum { POLARSSL_PK_RSASSA_PSS, } pk_type_t; +/** + * \brief Options for RSASSA-PSS signature verification. + * See \c rsa_rsassa_pss_verify_ext() + */ +typedef struct +{ + md_type_t mgf1_hash_id; + int expected_salt_len; + +} pk_rsassa_pss_options; + /** * \brief Types for interfacing with the debug module */ @@ -307,6 +318,39 @@ int pk_verify( pk_context *ctx, md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len ); +/** + * \brief Verify signature, with options + * + * \param type Signature type to verify + * \param options Pointer to type-specific options, or NULL + * \param ctx PK context to use + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Signature to verify + * \param sig_len Signature length + * + * \return 0 on success (signature is valid), + * POLARSSL_ERR_PK_TYPE_MISMATCH if the PK context can't be + * used for this type of signatures, + * POLARSSL_ERR_PK_SIG_LEN_MISMATCH if the signature is + * valid but its actual length is less than sig_len, + * or a specific error code. + * + * \note If hash_len is 0, then the length associated with md_alg + * is used instead, or an error returned if it is invalid. + * + * \note md_alg may be POLARSSL_MD_NONE, only if hash_len != 0 + * + * \note If type is POLARSSL_PK_RSASSA_PSS, then options must point + * to a pk_rsassa_pss_options structure, + * otherwise it must be NULL. + */ +int pk_verify_ext( pk_type_t type, const void *options, + pk_context *ctx, md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + /** * \brief Make signature * diff --git a/library/pk.c b/library/pk.c index ce171073c..8000c10f4 100644 --- a/library/pk.c +++ b/library/pk.c @@ -188,6 +188,59 @@ int pk_verify( pk_context *ctx, md_type_t md_alg, sig, sig_len ) ); } +/* + * Verify a signature with options + */ +int pk_verify_ext( pk_type_t type, const void *options, + pk_context *ctx, md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( POLARSSL_ERR_PK_BAD_INPUT_DATA ); + + if( ! pk_can_do( ctx, type ) ) + return( POLARSSL_ERR_PK_TYPE_MISMATCH ); + + if( type == POLARSSL_PK_RSASSA_PSS ) + { +#if defined(POLARSSL_RSA_C) && defined(POLARSSL_PKCS1_V21) + int ret; + const pk_rsassa_pss_options *pss_opts; + + if( options == NULL ) + return( POLARSSL_ERR_PK_BAD_INPUT_DATA ); + + pss_opts = (const pk_rsassa_pss_options *) options; + + if( sig_len < pk_get_len( ctx ) ) + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + + ret = rsa_rsassa_pss_verify_ext( pk_rsa( *ctx ), + NULL, NULL, RSA_PUBLIC, + md_alg, hash_len, hash, + pss_opts->mgf1_hash_id, + pss_opts->expected_salt_len, + sig ); + if( ret != 0 ) + return( ret ); + + if( sig_len > pk_get_len( ctx ) ) + return( POLARSSL_ERR_PK_SIG_LEN_MISMATCH ); + + return( 0 ); +#else + return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE ); +#endif + } + + /* General case: no options */ + if( options != NULL ) + return( POLARSSL_ERR_PK_BAD_INPUT_DATA ); + + return( pk_verify( ctx, md_alg, hash, hash_len, sig, sig_len ) ); +} + /* * Make a signature */ diff --git a/library/pk_wrap.c b/library/pk_wrap.c index c0ad10d01..6bfc4d2fe 100644 --- a/library/pk_wrap.c +++ b/library/pk_wrap.c @@ -52,13 +52,13 @@ #define polarssl_free free #endif -/* Used by RSA-alt too */ +#if defined(POLARSSL_RSA_C) static int rsa_can_do( pk_type_t type ) { - return( type == POLARSSL_PK_RSA ); + return( type == POLARSSL_PK_RSA || + type == POLARSSL_PK_RSASSA_PSS ); } -#if defined(POLARSSL_RSA_C) static size_t rsa_get_size( const void *ctx ) { return( 8 * ((const rsa_context *) ctx)->len ); @@ -372,6 +372,11 @@ const pk_info_t ecdsa_info = { * Support for alternative RSA-private implementations */ +static int rsa_alt_can_do( pk_type_t type ) +{ + return( type == POLARSSL_PK_RSA ); +} + static size_t rsa_alt_get_size( const void *ctx ) { const rsa_alt_context *rsa_alt = (const rsa_alt_context *) ctx; @@ -428,7 +433,7 @@ const pk_info_t rsa_alt_info = { POLARSSL_PK_RSA_ALT, "RSA-alt", rsa_alt_get_size, - rsa_can_do, + rsa_alt_can_do, NULL, rsa_alt_sign_wrap, rsa_alt_decrypt_wrap, diff --git a/tests/suites/test_suite_pk.data b/tests/suites/test_suite_pk.data index 974748c6b..c4393d684 100644 --- a/tests/suites/test_suite_pk.data +++ b/tests/suites/test_suite_pk.data @@ -81,3 +81,50 @@ pk_ec_nocrypt:POLARSSL_PK_ECDSA RSA_ALT consistency depends_on:POLARSSL_RSA_C:POLARSSL_PKCS1_V15:POLARSSL_GENPRIME pk_rsa_alt: + +Verify ext RSA #1 (PKCS1 v2.1, salt_len = ANY, OK) +depends_on:POLARSSL_PKCS1_V21:POLARSSL_SHA256_C +pk_rsa_verify_ext_test_vec:"54657374206d657373616765":POLARSSL_MD_SHA256:1024:16:"00dd118a9f99bab068ca2aea3b6a6d5997ed4ec954e40deecea07da01eaae80ec2bb1340db8a128e891324a5c5f5fad8f590d7c8cacbc5fe931dafda1223735279461abaa0572b761631b3a8afe7389b088b63993a0a25ee45d21858bab9931aedd4589a631b37fcf714089f856549f359326dd1e0e86dde52ed66b4a90bda4095":16:"010001":"0d2bdb0456a3d651d5bd48a4204493898f72cf1aaddd71387cc058bc3f4c235ea6be4010fd61b28e1fbb275462b53775c04be9022d38b6a2e0387dddba86a3f8554d2858044a59fddbd594753fc056fe33c8daddb85dc70d164690b1182209ff84824e0be10e35c379f2f378bf176a9f7cb94d95e44d90276a298c8810f741c9":POLARSSL_PK_RSASSA_PSS:POLARSSL_MD_SHA256:RSA_SALT_LEN_ANY:0 + +Verify ext RSA #2 (PKCS1 v2.1, salt_len = ANY, wrong message) +depends_on:POLARSSL_PKCS1_V21:POLARSSL_SHA256_C +pk_rsa_verify_ext_test_vec:"54657374206d657373616766":POLARSSL_MD_SHA256:1024:16:"00dd118a9f99bab068ca2aea3b6a6d5997ed4ec954e40deecea07da01eaae80ec2bb1340db8a128e891324a5c5f5fad8f590d7c8cacbc5fe931dafda1223735279461abaa0572b761631b3a8afe7389b088b63993a0a25ee45d21858bab9931aedd4589a631b37fcf714089f856549f359326dd1e0e86dde52ed66b4a90bda4095":16:"010001":"0d2bdb0456a3d651d5bd48a4204493898f72cf1aaddd71387cc058bc3f4c235ea6be4010fd61b28e1fbb275462b53775c04be9022d38b6a2e0387dddba86a3f8554d2858044a59fddbd594753fc056fe33c8daddb85dc70d164690b1182209ff84824e0be10e35c379f2f378bf176a9f7cb94d95e44d90276a298c8810f741c9":POLARSSL_PK_RSASSA_PSS:POLARSSL_MD_SHA256:RSA_SALT_LEN_ANY:POLARSSL_ERR_RSA_VERIFY_FAILED + +Verify ext RSA #3 (PKCS1 v2.1, salt_len = 0, OK) +depends_on:POLARSSL_PKCS1_V21:POLARSSL_SHA256_C +pk_rsa_verify_ext_test_vec:"54657374206d657373616765":POLARSSL_MD_SHA256:1024:16:"00dd118a9f99bab068ca2aea3b6a6d5997ed4ec954e40deecea07da01eaae80ec2bb1340db8a128e891324a5c5f5fad8f590d7c8cacbc5fe931dafda1223735279461abaa0572b761631b3a8afe7389b088b63993a0a25ee45d21858bab9931aedd4589a631b37fcf714089f856549f359326dd1e0e86dde52ed66b4a90bda4095":16:"010001":"7fc506d26ca3b22922a1ce39faaedd273161b82d9443c56f1a034f131ae4a18cae1474271cb4b66a17d9707ca58b0bdbd3c406b7e65bbcc9bbbce94dc45de807b4989b23b3e4db74ca29298137837eb90cc83d3219249bc7d480fceaf075203a86e54c4ecfa4e312e39f8f69d76534089a36ed9049ca9cfd5ab1db1fa75fe5c8":POLARSSL_PK_RSASSA_PSS:POLARSSL_MD_SHA256:0:0 + +Verify ext RSA #4 (PKCS1 v2.1, salt_len = max, OK) +pk_rsa_verify_ext_test_vec:"54657374206d657373616765":POLARSSL_MD_SHA256:1024:16:"00dd118a9f99bab068ca2aea3b6a6d5997ed4ec954e40deecea07da01eaae80ec2bb1340db8a128e891324a5c5f5fad8f590d7c8cacbc5fe931dafda1223735279461abaa0572b761631b3a8afe7389b088b63993a0a25ee45d21858bab9931aedd4589a631b37fcf714089f856549f359326dd1e0e86dde52ed66b4a90bda4095":16:"010001":"0d2bdb0456a3d651d5bd48a4204493898f72cf1aaddd71387cc058bc3f4c235ea6be4010fd61b28e1fbb275462b53775c04be9022d38b6a2e0387dddba86a3f8554d2858044a59fddbd594753fc056fe33c8daddb85dc70d164690b1182209ff84824e0be10e35c379f2f378bf176a9f7cb94d95e44d90276a298c8810f741c9":POLARSSL_PK_RSASSA_PSS:POLARSSL_MD_SHA256:94:0 + +Verify ext RSA #5 (PKCS1 v2.1, wrong salt_len) +depends_on:POLARSSL_PKCS1_V21:POLARSSL_SHA256_C +pk_rsa_verify_ext_test_vec:"54657374206d657373616765":POLARSSL_MD_SHA256:1024:16:"00dd118a9f99bab068ca2aea3b6a6d5997ed4ec954e40deecea07da01eaae80ec2bb1340db8a128e891324a5c5f5fad8f590d7c8cacbc5fe931dafda1223735279461abaa0572b761631b3a8afe7389b088b63993a0a25ee45d21858bab9931aedd4589a631b37fcf714089f856549f359326dd1e0e86dde52ed66b4a90bda4095":16:"010001":"0d2bdb0456a3d651d5bd48a4204493898f72cf1aaddd71387cc058bc3f4c235ea6be4010fd61b28e1fbb275462b53775c04be9022d38b6a2e0387dddba86a3f8554d2858044a59fddbd594753fc056fe33c8daddb85dc70d164690b1182209ff84824e0be10e35c379f2f378bf176a9f7cb94d95e44d90276a298c8810f741c9":POLARSSL_PK_RSASSA_PSS:POLARSSL_MD_SHA256:32:POLARSSL_ERR_RSA_INVALID_PADDING + +Verify ext RSA #6 (PKCS1 v2.1, MGF1 alg != MSG hash alg) +depends_on:POLARSSL_PKCS1_V21:POLARSSL_SHA256_C +pk_rsa_verify_ext_test_vec:"c0719e9a8d5d838d861dc6f675c899d2b309a3a65bb9fe6b11e5afcbf9a2c0b1":POLARSSL_MD_NONE:1024:16:"00dd118a9f99bab068ca2aea3b6a6d5997ed4ec954e40deecea07da01eaae80ec2bb1340db8a128e891324a5c5f5fad8f590d7c8cacbc5fe931dafda1223735279461abaa0572b761631b3a8afe7389b088b63993a0a25ee45d21858bab9931aedd4589a631b37fcf714089f856549f359326dd1e0e86dde52ed66b4a90bda4095":16:"010001":"0d2bdb0456a3d651d5bd48a4204493898f72cf1aaddd71387cc058bc3f4c235ea6be4010fd61b28e1fbb275462b53775c04be9022d38b6a2e0387dddba86a3f8554d2858044a59fddbd594753fc056fe33c8daddb85dc70d164690b1182209ff84824e0be10e35c379f2f378bf176a9f7cb94d95e44d90276a298c8810f741c9":POLARSSL_PK_RSASSA_PSS:POLARSSL_MD_SHA256:RSA_SALT_LEN_ANY:0 + +Verify ext RSA #7 (PKCS1 v2.1, wrong MGF1 alg != MSG hash alg) +depends_on:POLARSSL_PKCS1_V21:POLARSSL_SHA256_C:POLARSSL_SHA1_C +pk_rsa_verify_ext_test_vec:"c0719e9a8d5d838d861dc6f675c899d2b309a3a65bb9fe6b11e5afcbf9a2c0b1":POLARSSL_MD_NONE:1024:16:"00dd118a9f99bab068ca2aea3b6a6d5997ed4ec954e40deecea07da01eaae80ec2bb1340db8a128e891324a5c5f5fad8f590d7c8cacbc5fe931dafda1223735279461abaa0572b761631b3a8afe7389b088b63993a0a25ee45d21858bab9931aedd4589a631b37fcf714089f856549f359326dd1e0e86dde52ed66b4a90bda4095":16:"010001":"0d2bdb0456a3d651d5bd48a4204493898f72cf1aaddd71387cc058bc3f4c235ea6be4010fd61b28e1fbb275462b53775c04be9022d38b6a2e0387dddba86a3f8554d2858044a59fddbd594753fc056fe33c8daddb85dc70d164690b1182209ff84824e0be10e35c379f2f378bf176a9f7cb94d95e44d90276a298c8810f741c9":POLARSSL_PK_RSASSA_PSS:POLARSSL_MD_SHA1:RSA_SALT_LEN_ANY:POLARSSL_ERR_RSA_INVALID_PADDING + +Verify ext RSA #8 (PKCS1 v2.1, RSASSA-PSS without options) +pk_rsa_verify_ext_test_vec:"54657374206d657373616765":POLARSSL_MD_SHA256:1024:16:"00dd118a9f99bab068ca2aea3b6a6d5997ed4ec954e40deecea07da01eaae80ec2bb1340db8a128e891324a5c5f5fad8f590d7c8cacbc5fe931dafda1223735279461abaa0572b761631b3a8afe7389b088b63993a0a25ee45d21858bab9931aedd4589a631b37fcf714089f856549f359326dd1e0e86dde52ed66b4a90bda4095":16:"010001":"0d2bdb0456a3d651d5bd48a4204493898f72cf1aaddd71387cc058bc3f4c235ea6be4010fd61b28e1fbb275462b53775c04be9022d38b6a2e0387dddba86a3f8554d2858044a59fddbd594753fc056fe33c8daddb85dc70d164690b1182209ff84824e0be10e35c379f2f378bf176a9f7cb94d95e44d90276a298c8810f741c9":POLARSSL_PK_RSASSA_PSS:-1:RSA_SALT_LEN_ANY:POLARSSL_ERR_PK_BAD_INPUT_DATA + +Verify ext RSA #9 (PKCS1 v2.1, RSA with options) +depends_on:POLARSSL_PKCS1_V15:POLARSSL_SHA256_C +pk_rsa_verify_ext_test_vec:"54657374206d657373616765":POLARSSL_MD_SHA256:1024:16:"00dd118a9f99bab068ca2aea3b6a6d5997ed4ec954e40deecea07da01eaae80ec2bb1340db8a128e891324a5c5f5fad8f590d7c8cacbc5fe931dafda1223735279461abaa0572b761631b3a8afe7389b088b63993a0a25ee45d21858bab9931aedd4589a631b37fcf714089f856549f359326dd1e0e86dde52ed66b4a90bda4095":16:"010001":"0d2bdb0456a3d651d5bd48a4204493898f72cf1aaddd71387cc058bc3f4c235ea6be4010fd61b28e1fbb275462b53775c04be9022d38b6a2e0387dddba86a3f8554d2858044a59fddbd594753fc056fe33c8daddb85dc70d164690b1182209ff84824e0be10e35c379f2f378bf176a9f7cb94d95e44d90276a298c8810f741c9":POLARSSL_PK_RSA:POLARSSL_MD_SHA256:RSA_SALT_LEN_ANY:POLARSSL_ERR_PK_BAD_INPUT_DATA + +Verify ext RSA #10 (PKCS1 v2.1, RSA without options) +depends_on:POLARSSL_PKCS1_V15:POLARSSL_SHA256_C +pk_rsa_verify_ext_test_vec:"54657374206d657373616765":POLARSSL_MD_SHA256:1024:16:"00dd118a9f99bab068ca2aea3b6a6d5997ed4ec954e40deecea07da01eaae80ec2bb1340db8a128e891324a5c5f5fad8f590d7c8cacbc5fe931dafda1223735279461abaa0572b761631b3a8afe7389b088b63993a0a25ee45d21858bab9931aedd4589a631b37fcf714089f856549f359326dd1e0e86dde52ed66b4a90bda4095":16:"010001":"0d2bdb0456a3d651d5bd48a4204493898f72cf1aaddd71387cc058bc3f4c235ea6be4010fd61b28e1fbb275462b53775c04be9022d38b6a2e0387dddba86a3f8554d2858044a59fddbd594753fc056fe33c8daddb85dc70d164690b1182209ff84824e0be10e35c379f2f378bf176a9f7cb94d95e44d90276a298c8810f741c9":POLARSSL_PK_RSA:-1:RSA_SALT_LEN_ANY:POLARSSL_ERR_RSA_INVALID_PADDING + +Verify ext RSA #11 (PKCS1 v2.1, asking for ECDSA) +depends_on:POLARSSL_ECDSA_C:POLARSSL_SHA256_C +pk_rsa_verify_ext_test_vec:"54657374206d657373616765":POLARSSL_MD_SHA256:1024:16:"00dd118a9f99bab068ca2aea3b6a6d5997ed4ec954e40deecea07da01eaae80ec2bb1340db8a128e891324a5c5f5fad8f590d7c8cacbc5fe931dafda1223735279461abaa0572b761631b3a8afe7389b088b63993a0a25ee45d21858bab9931aedd4589a631b37fcf714089f856549f359326dd1e0e86dde52ed66b4a90bda4095":16:"010001":"0d2bdb0456a3d651d5bd48a4204493898f72cf1aaddd71387cc058bc3f4c235ea6be4010fd61b28e1fbb275462b53775c04be9022d38b6a2e0387dddba86a3f8554d2858044a59fddbd594753fc056fe33c8daddb85dc70d164690b1182209ff84824e0be10e35c379f2f378bf176a9f7cb94d95e44d90276a298c8810f741c9":POLARSSL_PK_ECDSA:-1:RSA_SALT_LEN_ANY:POLARSSL_ERR_PK_TYPE_MISMATCH + +Verify ext RSA #12 (PKCS1 v1.5, good) +depends_on:POLARSSL_SHA1_C:POLARSSL_PKCS1_V15 +pk_rsa_verify_ext_test_vec:"206ef4bf396c6087f8229ef196fd35f37ccb8de5efcdb238f20d556668f114257a11fbe038464a67830378e62ae9791453953dac1dbd7921837ba98e84e856eb80ed9487e656d0b20c28c8ba5e35db1abbed83ed1c7720a97701f709e3547a4bfcabca9c89c57ad15c3996577a0ae36d7c7b699035242f37954646c1cd5c08ac":POLARSSL_MD_SHA1:1024:16:"e28a13548525e5f36dccb24ecb7cc332cc689dfd64012604c9c7816d72a16c3f5fcdc0e86e7c03280b1c69b586ce0cd8aec722cc73a5d3b730310bf7dfebdc77ce5d94bbc369dc18a2f7b07bd505ab0f82224aef09fdc1e5063234255e0b3c40a52e9e8ae60898eb88a766bdd788fe9493d8fd86bcdd2884d5c06216c65469e5":16:"3":"5abc01f5de25b70867ff0c24e222c61f53c88daf42586fddcd56f3c4588f074be3c328056c063388688b6385a8167957c6e5355a510e005b8a851d69c96b36ec6036644078210e5d7d326f96365ee0648882921492bc7b753eb9c26cdbab37555f210df2ca6fec1b25b463d38b81c0dcea202022b04af5da58aa03d77be949b7":POLARSSL_PK_RSA:-1:RSA_SALT_LEN_ANY:0 + diff --git a/tests/suites/test_suite_pk.function b/tests/suites/test_suite_pk.function index f82ed6748..3da1feb49 100644 --- a/tests/suites/test_suite_pk.function +++ b/tests/suites/test_suite_pk.function @@ -117,6 +117,71 @@ void pk_rsa_verify_test_vec( char *message_hex_string, int digest, } /* END_CASE */ +/* BEGIN_CASE depends_on:POLARSSL_RSA_C */ +void pk_rsa_verify_ext_test_vec( char *message_hex_string, int digest, + int mod, int radix_N, char *input_N, int radix_E, + char *input_E, char *result_hex_str, + int pk_type, int mgf1_hash_id, int salt_len, + int result ) +{ + unsigned char message_str[1000]; + unsigned char hash_result[1000]; + unsigned char result_str[1000]; + rsa_context *rsa; + pk_context pk; + pk_rsassa_pss_options pss_opts; + void *options; + int msg_len; + size_t hash_len; + + pk_init( &pk ); + + memset( message_str, 0x00, 1000 ); + memset( hash_result, 0x00, 1000 ); + memset( result_str, 0x00, 1000 ); + + TEST_ASSERT( pk_init_ctx( &pk, pk_info_from_type( POLARSSL_PK_RSA ) ) == 0 ); + rsa = pk_rsa( pk ); + + rsa->len = mod / 8; + TEST_ASSERT( mpi_read_string( &rsa->N, radix_N, input_N ) == 0 ); + TEST_ASSERT( mpi_read_string( &rsa->E, radix_E, input_E ) == 0 ); + + msg_len = unhexify( message_str, message_hex_string ); + unhexify( result_str, result_hex_str ); + + if( digest != POLARSSL_MD_NONE ) + { + TEST_ASSERT( md( md_info_from_type( digest ), + message_str, msg_len, hash_result ) == 0 ); + hash_len = 0; + } + else + { + memcpy( hash_result, message_str, msg_len ); + hash_len = msg_len; + } + + if( mgf1_hash_id < 0 ) + { + options = NULL; + } + else + { + options = &pss_opts; + + pss_opts.mgf1_hash_id = mgf1_hash_id; + pss_opts.expected_salt_len = salt_len; + } + + TEST_ASSERT( pk_verify_ext( pk_type, options, &pk, + digest, hash_result, hash_len, + result_str, pk_get_len( &pk ) ) == result ); + + pk_free( &pk ); +} +/* END_CASE */ + /* BEGIN_CASE depends_on:POLARSSL_ECDSA_C */ void pk_ec_test_vec( int type, int id, char *key_str, char *hash_str, char * sig_str, int ret )