diff options
author | wtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-28 17:46:53 +0000 |
---|---|---|
committer | wtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-28 17:46:53 +0000 |
commit | 9b898661f246b337e278343318b7eea0c2c0ca20 (patch) | |
tree | 4243f662fd6c35aac49a2668d9723bd158ab42ed | |
parent | 6aec09b8ad4dd6dcd11babae85322d5208a464c6 (diff) | |
download | chromium_src-9b898661f246b337e278343318b7eea0c2c0ca20.zip chromium_src-9b898661f246b337e278343318b7eea0c2c0ca20.tar.gz chromium_src-9b898661f246b337e278343318b7eea0c2c0ca20.tar.bz2 |
Add SignatureVerifier::VerifyInitRSAPSS for verifying RSA-PSS signatures.
Change the OpenSSL-based SignatureVerifier to use EVP_DigestVerifyInit
instead of EVP_VerifyInit_ex.
Copy the PSS padding verification code from NSS to the NSS-based
SignatureVerifier because the RSA-PSS code in the NSS softoken isn't
exposed via the NSS PK11_ or VFY_ functions yet.
R=agl@chromium.org,rsleevi@chromium.org
BUG=none
TEST=to be added to net_unittests via testing net::quic::ProofVerifier.
Review URL: https://chromiumcodereview.appspot.com/17776003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@209178 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | crypto/crypto.gyp | 2 | ||||
-rw-r--r-- | crypto/signature_verifier.h | 60 | ||||
-rw-r--r-- | crypto/signature_verifier_nss.cc | 140 | ||||
-rw-r--r-- | crypto/signature_verifier_openssl.cc | 99 | ||||
-rw-r--r-- | crypto/signature_verifier_unittest.cc | 879 | ||||
-rw-r--r-- | crypto/third_party/nss/README.chromium | 4 | ||||
-rw-r--r-- | crypto/third_party/nss/chromium-nss.h | 9 | ||||
-rw-r--r-- | crypto/third_party/nss/rsawrapr.c | 160 |
8 files changed, 1315 insertions, 38 deletions
diff --git a/crypto/crypto.gyp b/crypto/crypto.gyp index f6ac0f8..e2ac853 100644 --- a/crypto/crypto.gyp +++ b/crypto/crypto.gyp @@ -139,6 +139,7 @@ 'third_party/nss/chromium-nss.h', 'third_party/nss/chromium-sha256.h', 'third_party/nss/pk11akey.cc', + 'third_party/nss/rsawrapr.c', 'third_party/nss/secsign.cc', 'third_party/nss/sha512.cc', ], @@ -234,6 +235,7 @@ 'third_party/nss/chromium-blapit.h', 'third_party/nss/chromium-nss.h', 'third_party/nss/pk11akey.cc', + 'third_party/nss/rsawrapr.c', 'third_party/nss/secsign.cc', ], }, diff --git a/crypto/signature_verifier.h b/crypto/signature_verifier.h index 505ed0c..93591d2 100644 --- a/crypto/signature_verifier.h +++ b/crypto/signature_verifier.h @@ -12,7 +12,12 @@ #include "base/basictypes.h" #include "crypto/crypto_export.h" -#if !defined(USE_OPENSSL) +#if defined(USE_OPENSSL) +typedef struct env_md_st EVP_MD; +typedef struct evp_pkey_ctx_st EVP_PKEY_CTX; +#else +typedef struct HASHContextStr HASHContext; +typedef struct SECKEYPublicKeyStr SECKEYPublicKey; typedef struct VFYContextStr VFYContext; #endif @@ -22,6 +27,12 @@ namespace crypto { // (as opposed to a certificate). class CRYPTO_EXPORT SignatureVerifier { public: + // The set of supported hash functions. Extend as required. + enum HashAlgorithm { + SHA1, + SHA256, + }; + SignatureVerifier(); ~SignatureVerifier(); @@ -29,6 +40,7 @@ class CRYPTO_EXPORT SignatureVerifier { // Initiates a signature verification operation. This should be followed // by one or more VerifyUpdate calls and a VerifyFinal call. + // NOTE: for RSA-PSS signatures, use VerifyInitRSAPSS instead. // // The signature algorithm is specified as a DER encoded ASN.1 // AlgorithmIdentifier structure: @@ -38,7 +50,7 @@ class CRYPTO_EXPORT SignatureVerifier { // // The signature is encoded according to the signature algorithm, but it // must not be further encoded in an ASN.1 BIT STRING. - // Note: An RSA signatures is actually a big integer. It must be in the + // Note: An RSA signature is actually a big integer. It must be in // big-endian byte order. // // The public key is specified as a DER encoded ASN.1 SubjectPublicKeyInfo @@ -54,6 +66,30 @@ class CRYPTO_EXPORT SignatureVerifier { const uint8* public_key_info, int public_key_info_len); + // Initiates a RSA-PSS signature verification operation. This should be + // followed by one or more VerifyUpdate calls and a VerifyFinal call. + // + // The RSA-PSS signature algorithm parameters are specified with the + // |hash_alg|, |mask_hash_alg|, and |salt_len| arguments. + // + // An RSA-PSS signature is a nonnegative integer encoded as a byte string + // (of the same length as the RSA modulus) in big-endian byte order. It + // must not be further encoded in an ASN.1 BIT STRING. + // + // The public key is specified as a DER encoded ASN.1 SubjectPublicKeyInfo + // structure, which contains not only the public key but also its type + // (algorithm): + // SubjectPublicKeyInfo ::= SEQUENCE { + // algorithm AlgorithmIdentifier, + // subjectPublicKey BIT STRING } + bool VerifyInitRSAPSS(HashAlgorithm hash_alg, + HashAlgorithm mask_hash_alg, + int salt_len, + const uint8* signature, + int signature_len, + const uint8* public_key_info, + int public_key_info_len); + // Feeds a piece of the data to the signature verifier. void VerifyUpdate(const uint8* data_part, int data_part_len); @@ -73,6 +109,18 @@ class CRYPTO_EXPORT SignatureVerifier { // int public_key_info_len); private: +#if defined(USE_OPENSSL) + bool CommonInit(const EVP_MD* digest, + const uint8* signature, + int signature_len, + const uint8* public_key_info, + int public_key_info_len, + EVP_PKEY_CTX** pkey_ctx); +#else + static SECKEYPublicKey* DecodePublicKeyInfo(const uint8* public_key_info, + int public_key_info_len); +#endif + void Reset(); std::vector<uint8> signature_; @@ -81,7 +129,15 @@ class CRYPTO_EXPORT SignatureVerifier { struct VerifyContext; VerifyContext* verify_context_; #else + // Used for all signature types except RSA-PSS. VFYContext* vfy_context_; + + // Used for RSA-PSS signatures. + HashAlgorithm hash_alg_; + HashAlgorithm mask_hash_alg_; + unsigned int salt_len_; + SECKEYPublicKey* public_key_; + HASHContext* hash_context_; #endif }; diff --git a/crypto/signature_verifier_nss.cc b/crypto/signature_verifier_nss.cc index 662e8f2..69b0f82 100644 --- a/crypto/signature_verifier_nss.cc +++ b/crypto/signature_verifier_nss.cc @@ -6,14 +6,66 @@ #include <cryptohi.h> #include <keyhi.h> +#include <pk11pub.h> +#include <secerr.h> +#include <sechash.h> #include <stdlib.h> #include "base/logging.h" #include "crypto/nss_util.h" +#include "crypto/third_party/nss/chromium-nss.h" namespace crypto { -SignatureVerifier::SignatureVerifier() : vfy_context_(NULL) { +namespace { + +HASH_HashType ToNSSHashType(SignatureVerifier::HashAlgorithm hash_alg) { + switch (hash_alg) { + case SignatureVerifier::SHA1: + return HASH_AlgSHA1; + case SignatureVerifier::SHA256: + return HASH_AlgSHA256; + } + return HASH_AlgNULL; +} + +SECStatus VerifyRSAPSS_End(SECKEYPublicKey* public_key, + HASHContext* hash_context, + HASH_HashType mask_hash_alg, + unsigned int salt_len, + const unsigned char* signature, + unsigned int signature_len) { + unsigned int hash_len = hash_context->hashobj->length; + std::vector<unsigned char> hash(hash_len); + HASH_End(hash_context, &hash[0], &hash_len, hash.size()); + + unsigned int modulus_len = SECKEY_PublicKeyStrength(public_key); + if (signature_len != modulus_len) { + PORT_SetError(SEC_ERROR_BAD_SIGNATURE); + return SECFailure; + } + std::vector<unsigned char> enc(signature_len); + SECStatus rv = PK11_PubEncryptRaw(public_key, &enc[0], + const_cast<unsigned char*>(signature), + signature_len, NULL); + if (rv != SECSuccess) { + LOG(WARNING) << "PK11_PubEncryptRaw failed"; + return rv; + } + return emsa_pss_verify(&hash[0], &enc[0], enc.size(), + hash_context->hashobj->type, mask_hash_alg, + salt_len); +} + +} // namespace + +SignatureVerifier::SignatureVerifier() + : vfy_context_(NULL), + hash_alg_(SHA1), + mask_hash_alg_(SHA1), + salt_len_(0), + public_key_(NULL), + hash_context_(NULL) { EnsureNSSInit(); } @@ -27,18 +79,13 @@ bool SignatureVerifier::VerifyInit(const uint8* signature_algorithm, int signature_len, const uint8* public_key_info, int public_key_info_len) { + if (vfy_context_ || hash_context_) + return false; + signature_.assign(signature, signature + signature_len); - CERTSubjectPublicKeyInfo* spki = NULL; - SECItem spki_der; - spki_der.type = siBuffer; - spki_der.data = const_cast<uint8*>(public_key_info); - spki_der.len = public_key_info_len; - spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_der); - if (!spki) - return false; - SECKEYPublicKey* public_key = SECKEY_ExtractPublicKey(spki); - SECKEY_DestroySubjectPublicKeyInfo(spki); // Done with spki. + SECKEYPublicKey* public_key = DecodePublicKeyInfo(public_key_info, + public_key_info_len); if (!public_key) return false; @@ -88,14 +135,54 @@ bool SignatureVerifier::VerifyInit(const uint8* signature_algorithm, return true; } +bool SignatureVerifier::VerifyInitRSAPSS(HashAlgorithm hash_alg, + HashAlgorithm mask_hash_alg, + int salt_len, + const uint8* signature, + int signature_len, + const uint8* public_key_info, + int public_key_info_len) { + if (vfy_context_ || hash_context_) + return false; + + signature_.assign(signature, signature + signature_len); + + SECKEYPublicKey* public_key = DecodePublicKeyInfo(public_key_info, + public_key_info_len); + if (!public_key) + return false; + + public_key_ = public_key; + hash_alg_ = hash_alg; + mask_hash_alg_ = mask_hash_alg; + salt_len_ = salt_len; + hash_context_ = HASH_Create(ToNSSHashType(hash_alg_)); + if (!hash_context_) + return false; + HASH_Begin(hash_context_); + return true; +} + void SignatureVerifier::VerifyUpdate(const uint8* data_part, int data_part_len) { - SECStatus rv = VFY_Update(vfy_context_, data_part, data_part_len); - DCHECK_EQ(SECSuccess, rv); + if (vfy_context_) { + SECStatus rv = VFY_Update(vfy_context_, data_part, data_part_len); + DCHECK_EQ(SECSuccess, rv); + } else { + HASH_Update(hash_context_, data_part, data_part_len); + } } bool SignatureVerifier::VerifyFinal() { - SECStatus rv = VFY_End(vfy_context_); + SECStatus rv; + if (vfy_context_) { + rv = VFY_End(vfy_context_); + } else { + rv = VerifyRSAPSS_End(public_key_, hash_context_, + ToNSSHashType(mask_hash_alg_), salt_len_, + signature_.data(), + signature_.size()); + } Reset(); // If signature verification fails, the error code is @@ -103,11 +190,36 @@ bool SignatureVerifier::VerifyFinal() { return (rv == SECSuccess); } +// static +SECKEYPublicKey* SignatureVerifier::DecodePublicKeyInfo( + const uint8* public_key_info, + int public_key_info_len) { + CERTSubjectPublicKeyInfo* spki = NULL; + SECItem spki_der; + spki_der.type = siBuffer; + spki_der.data = const_cast<uint8*>(public_key_info); + spki_der.len = public_key_info_len; + spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_der); + if (!spki) + return NULL; + SECKEYPublicKey* public_key = SECKEY_ExtractPublicKey(spki); + SECKEY_DestroySubjectPublicKeyInfo(spki); // Done with spki. + return public_key; +} + void SignatureVerifier::Reset() { if (vfy_context_) { VFY_DestroyContext(vfy_context_, PR_TRUE); vfy_context_ = NULL; } + if (hash_context_) { + HASH_Destroy(hash_context_); + hash_context_ = NULL; + } + if (public_key_) { + SECKEY_DestroyPublicKey(public_key_); + public_key_ = NULL; + } signature_.clear(); } diff --git a/crypto/signature_verifier_openssl.cc b/crypto/signature_verifier_openssl.cc index cab45db..1e71339 100644 --- a/crypto/signature_verifier_openssl.cc +++ b/crypto/signature_verifier_openssl.cc @@ -16,8 +16,21 @@ namespace crypto { +namespace { + +const EVP_MD* ToOpenSSLDigest(SignatureVerifier::HashAlgorithm hash_alg) { + switch (hash_alg) { + case SignatureVerifier::SHA1: + return EVP_sha1(); + case SignatureVerifier::SHA256: + return EVP_sha256(); + } + return EVP_md_null(); +} + +} // namespace + struct SignatureVerifier::VerifyContext { - ScopedOpenSSL<EVP_PKEY, EVP_PKEY_free> public_key; ScopedOpenSSL<EVP_MD_CTX, EVP_MD_CTX_destroy> ctx; }; @@ -35,33 +48,44 @@ bool SignatureVerifier::VerifyInit(const uint8* signature_algorithm, int signature_len, const uint8* public_key_info, int public_key_info_len) { - DCHECK(!verify_context_); - verify_context_ = new VerifyContext; OpenSSLErrStackTracer err_tracer(FROM_HERE); - ScopedOpenSSL<X509_ALGOR, X509_ALGOR_free> algorithm( d2i_X509_ALGOR(NULL, &signature_algorithm, signature_algorithm_len)); if (!algorithm.get()) return false; - const EVP_MD* digest = EVP_get_digestbyobj(algorithm.get()->algorithm); - DCHECK(digest); + if (!digest) + return false; - signature_.assign(signature, signature + signature_len); + return CommonInit(digest, signature, signature_len, public_key_info, + public_key_info_len, NULL); +} - // BIO_new_mem_buf is not const aware, but it does not modify the buffer. - char* data = reinterpret_cast<char*>(const_cast<uint8*>(public_key_info)); - ScopedOpenSSL<BIO, BIO_free_all> bio(BIO_new_mem_buf(data, - public_key_info_len)); - if (!bio.get()) - return false; +bool SignatureVerifier::VerifyInitRSAPSS(HashAlgorithm hash_alg, + HashAlgorithm mask_hash_alg, + int salt_len, + const uint8* signature, + int signature_len, + const uint8* public_key_info, + int public_key_info_len) { + OpenSSLErrStackTracer err_tracer(FROM_HERE); + const EVP_MD* digest = ToOpenSSLDigest(hash_alg); + DCHECK(digest); - verify_context_->public_key.reset(d2i_PUBKEY_bio(bio.get(), NULL)); - if (!verify_context_->public_key.get()) + EVP_PKEY_CTX* pkey_ctx; + if (!CommonInit(digest, signature, signature_len, public_key_info, + public_key_info_len, &pkey_ctx)) { return false; + } - verify_context_->ctx.reset(EVP_MD_CTX_create()); - int rv = EVP_VerifyInit_ex(verify_context_->ctx.get(), digest, NULL); + int rv = EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING); + if (rv != 1) + return false; + rv = EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, + ToOpenSSLDigest(mask_hash_alg)); + if (rv != 1) + return false; + rv = EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, salt_len); return rv == 1; } @@ -69,22 +93,53 @@ void SignatureVerifier::VerifyUpdate(const uint8* data_part, int data_part_len) { DCHECK(verify_context_); OpenSSLErrStackTracer err_tracer(FROM_HERE); - int rv = EVP_VerifyUpdate(verify_context_->ctx.get(), - data_part, data_part_len); + int rv = EVP_DigestVerifyUpdate(verify_context_->ctx.get(), + data_part, data_part_len); DCHECK_EQ(rv, 1); } bool SignatureVerifier::VerifyFinal() { DCHECK(verify_context_); OpenSSLErrStackTracer err_tracer(FROM_HERE); - int rv = EVP_VerifyFinal(verify_context_->ctx.get(), - vector_as_array(&signature_), signature_.size(), - verify_context_->public_key.get()); + int rv = EVP_DigestVerifyFinal(verify_context_->ctx.get(), + vector_as_array(&signature_), + signature_.size()); DCHECK_GE(rv, 0); Reset(); return rv == 1; } +bool SignatureVerifier::CommonInit(const EVP_MD* digest, + const uint8* signature, + int signature_len, + const uint8* public_key_info, + int public_key_info_len, + EVP_PKEY_CTX** pkey_ctx) { + if (verify_context_) + return false; + + verify_context_ = new VerifyContext; + + signature_.assign(signature, signature + signature_len); + + // BIO_new_mem_buf is not const aware, but it does not modify the buffer. + char* data = reinterpret_cast<char*>(const_cast<uint8*>(public_key_info)); + ScopedOpenSSL<BIO, BIO_free_all> bio(BIO_new_mem_buf(data, + public_key_info_len)); + if (!bio.get()) + return false; + + ScopedOpenSSL<EVP_PKEY, EVP_PKEY_free> public_key( + d2i_PUBKEY_bio(bio.get(), NULL)); + if (!public_key.get()) + return false; + + verify_context_->ctx.reset(EVP_MD_CTX_create()); + int rv = EVP_DigestVerifyInit(verify_context_->ctx.get(), pkey_ctx, + digest, NULL, public_key.get()); + return rv == 1; +} + void SignatureVerifier::Reset() { delete verify_context_; verify_context_ = NULL; diff --git a/crypto/signature_verifier_unittest.cc b/crypto/signature_verifier_unittest.cc index 360afa9..3329799 100644 --- a/crypto/signature_verifier_unittest.cc +++ b/crypto/signature_verifier_unittest.cc @@ -257,3 +257,882 @@ TEST(SignatureVerifierTest, BasicTest) { EXPECT_FALSE(ok); } } + +////////////////////////////////////////////////////////////////////// +// +// RSA-PSS signature verification known answer test +// +////////////////////////////////////////////////////////////////////// + +// The following RSA-PSS signature test vectors come from the pss-vect.txt +// file downloaded from +// ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip. +// +// For each key, 6 random messages of length between 1 and 256 octets have +// been RSASSA-PSS signed. +// +// Hash function: SHA-1 +// Mask generation function: MGF1 with SHA-1 +// Salt length: 20 octets + +// Example 1: A 1024-bit RSA Key Pair" + +// RSA modulus n: +static const char rsa_modulus_n_1[] = + "a5 6e 4a 0e 70 10 17 58 9a 51 87 dc 7e a8 41 d1 " + "56 f2 ec 0e 36 ad 52 a4 4d fe b1 e6 1f 7a d9 91 " + "d8 c5 10 56 ff ed b1 62 b4 c0 f2 83 a1 2a 88 a3 " + "94 df f5 26 ab 72 91 cb b3 07 ce ab fc e0 b1 df " + "d5 cd 95 08 09 6d 5b 2b 8b 6d f5 d6 71 ef 63 77 " + "c0 92 1c b2 3c 27 0a 70 e2 59 8e 6f f8 9d 19 f1 " + "05 ac c2 d3 f0 cb 35 f2 92 80 e1 38 6b 6f 64 c4 " + "ef 22 e1 e1 f2 0d 0c e8 cf fb 22 49 bd 9a 21 37 "; +// RSA public exponent e: " +static const char rsa_public_exponent_e_1[] = + "01 00 01 "; + +// RSASSA-PSS Signature Example 1.1 +// Message to be signed: +static const char message_1_1[] = + "cd c8 7d a2 23 d7 86 df 3b 45 e0 bb bc 72 13 26 " + "d1 ee 2a f8 06 cc 31 54 75 cc 6f 0d 9c 66 e1 b6 " + "23 71 d4 5c e2 39 2e 1a c9 28 44 c3 10 10 2f 15 " + "6a 0d 8d 52 c1 f4 c4 0b a3 aa 65 09 57 86 cb 76 " + "97 57 a6 56 3b a9 58 fe d0 bc c9 84 e8 b5 17 a3 " + "d5 f5 15 b2 3b 8a 41 e7 4a a8 67 69 3f 90 df b0 " + "61 a6 e8 6d fa ae e6 44 72 c0 0e 5f 20 94 57 29 " + "cb eb e7 7f 06 ce 78 e0 8f 40 98 fb a4 1f 9d 61 " + "93 c0 31 7e 8b 60 d4 b6 08 4a cb 42 d2 9e 38 08 " + "a3 bc 37 2d 85 e3 31 17 0f cb f7 cc 72 d0 b7 1c " + "29 66 48 b3 a4 d1 0f 41 62 95 d0 80 7a a6 25 ca " + "b2 74 4f d9 ea 8f d2 23 c4 25 37 02 98 28 bd 16 " + "be 02 54 6f 13 0f d2 e3 3b 93 6d 26 76 e0 8a ed " + "1b 73 31 8b 75 0a 01 67 d0 "; +// Salt: +static const char salt_1_1[] = + "de e9 59 c7 e0 64 11 36 14 20 ff 80 18 5e d5 7f " + "3e 67 76 af "; +// Signature: +static const char signature_1_1[] = + "90 74 30 8f b5 98 e9 70 1b 22 94 38 8e 52 f9 71 " + "fa ac 2b 60 a5 14 5a f1 85 df 52 87 b5 ed 28 87 " + "e5 7c e7 fd 44 dc 86 34 e4 07 c8 e0 e4 36 0b c2 " + "26 f3 ec 22 7f 9d 9e 54 63 8e 8d 31 f5 05 12 15 " + "df 6e bb 9c 2f 95 79 aa 77 59 8a 38 f9 14 b5 b9 " + "c1 bd 83 c4 e2 f9 f3 82 a0 d0 aa 35 42 ff ee 65 " + "98 4a 60 1b c6 9e b2 8d eb 27 dc a1 2c 82 c2 d4 " + "c3 f6 6c d5 00 f1 ff 2b 99 4d 8a 4e 30 cb b3 3c "; + +// RSASSA-PSS Signature Example 1.2 +// Message to be signed: +static const char message_1_2[] = + "85 13 84 cd fe 81 9c 22 ed 6c 4c cb 30 da eb 5c " + "f0 59 bc 8e 11 66 b7 e3 53 0c 4c 23 3e 2b 5f 8f " + "71 a1 cc a5 82 d4 3e cc 72 b1 bc a1 6d fc 70 13 " + "22 6b 9e "; +// Salt: +static const char salt_1_2[] = + "ef 28 69 fa 40 c3 46 cb 18 3d ab 3d 7b ff c9 8f " + "d5 6d f4 2d "; +// Signature: +static const char signature_1_2[] = + "3e f7 f4 6e 83 1b f9 2b 32 27 41 42 a5 85 ff ce " + "fb dc a7 b3 2a e9 0d 10 fb 0f 0c 72 99 84 f0 4e " + "f2 9a 9d f0 78 07 75 ce 43 73 9b 97 83 83 90 db " + "0a 55 05 e6 3d e9 27 02 8d 9d 29 b2 19 ca 2c 45 " + "17 83 25 58 a5 5d 69 4a 6d 25 b9 da b6 60 03 c4 " + "cc cd 90 78 02 19 3b e5 17 0d 26 14 7d 37 b9 35 " + "90 24 1b e5 1c 25 05 5f 47 ef 62 75 2c fb e2 14 " + "18 fa fe 98 c2 2c 4d 4d 47 72 4f db 56 69 e8 43 "; + +// RSASSA-PSS Signature Example 1.3 +// Message to be signed: +static const char message_1_3[] = + "a4 b1 59 94 17 61 c4 0c 6a 82 f2 b8 0d 1b 94 f5 " + "aa 26 54 fd 17 e1 2d 58 88 64 67 9b 54 cd 04 ef " + "8b d0 30 12 be 8d c3 7f 4b 83 af 79 63 fa ff 0d " + "fa 22 54 77 43 7c 48 01 7f f2 be 81 91 cf 39 55 " + "fc 07 35 6e ab 3f 32 2f 7f 62 0e 21 d2 54 e5 db " + "43 24 27 9f e0 67 e0 91 0e 2e 81 ca 2c ab 31 c7 " + "45 e6 7a 54 05 8e b5 0d 99 3c db 9e d0 b4 d0 29 " + "c0 6d 21 a9 4c a6 61 c3 ce 27 fa e1 d6 cb 20 f4 " + "56 4d 66 ce 47 67 58 3d 0e 5f 06 02 15 b5 90 17 " + "be 85 ea 84 89 39 12 7b d8 c9 c4 d4 7b 51 05 6c " + "03 1c f3 36 f1 7c 99 80 f3 b8 f5 b9 b6 87 8e 8b " + "79 7a a4 3b 88 26 84 33 3e 17 89 3f e9 ca a6 aa " + "29 9f 7e d1 a1 8e e2 c5 48 64 b7 b2 b9 9b 72 61 " + "8f b0 25 74 d1 39 ef 50 f0 19 c9 ee f4 16 97 13 " + "38 e7 d4 70 "; +// Salt: +static const char salt_1_3[] = + "71 0b 9c 47 47 d8 00 d4 de 87 f1 2a fd ce 6d f1 " + "81 07 cc 77 "; +// Signature: +static const char signature_1_3[] = + "66 60 26 fb a7 1b d3 e7 cf 13 15 7c c2 c5 1a 8e " + "4a a6 84 af 97 78 f9 18 49 f3 43 35 d1 41 c0 01 " + "54 c4 19 76 21 f9 62 4a 67 5b 5a bc 22 ee 7d 5b " + "aa ff aa e1 c9 ba ca 2c c3 73 b3 f3 3e 78 e6 14 " + "3c 39 5a 91 aa 7f ac a6 64 eb 73 3a fd 14 d8 82 " + "72 59 d9 9a 75 50 fa ca 50 1e f2 b0 4e 33 c2 3a " + "a5 1f 4b 9e 82 82 ef db 72 8c c0 ab 09 40 5a 91 " + "60 7c 63 69 96 1b c8 27 0d 2d 4f 39 fc e6 12 b1 "; + +// RSASSA-PSS Signature Example 1.4 +// Message to be signed: +static const char message_1_4[] = + "bc 65 67 47 fa 9e af b3 f0 "; +// Salt: +static const char salt_1_4[] = + "05 6f 00 98 5d e1 4d 8e f5 ce a9 e8 2f 8c 27 be " + "f7 20 33 5e "; +// Signature: +static const char signature_1_4[] = + "46 09 79 3b 23 e9 d0 93 62 dc 21 bb 47 da 0b 4f " + "3a 76 22 64 9a 47 d4 64 01 9b 9a ea fe 53 35 9c " + "17 8c 91 cd 58 ba 6b cb 78 be 03 46 a7 bc 63 7f " + "4b 87 3d 4b ab 38 ee 66 1f 19 96 34 c5 47 a1 ad " + "84 42 e0 3d a0 15 b1 36 e5 43 f7 ab 07 c0 c1 3e " + "42 25 b8 de 8c ce 25 d4 f6 eb 84 00 f8 1f 7e 18 " + "33 b7 ee 6e 33 4d 37 09 64 ca 79 fd b8 72 b4 d7 " + "52 23 b5 ee b0 81 01 59 1f b5 32 d1 55 a6 de 87 "; + +// RSASSA-PSS Signature Example 1.5 +// Message to be signed: +static const char message_1_5[] = + "b4 55 81 54 7e 54 27 77 0c 76 8e 8b 82 b7 55 64 " + "e0 ea 4e 9c 32 59 4d 6b ff 70 65 44 de 0a 87 76 " + "c7 a8 0b 45 76 55 0e ee 1b 2a ca bc 7e 8b 7d 3e " + "f7 bb 5b 03 e4 62 c1 10 47 ea dd 00 62 9a e5 75 " + "48 0a c1 47 0f e0 46 f1 3a 2b f5 af 17 92 1d c4 " + "b0 aa 8b 02 be e6 33 49 11 65 1d 7f 85 25 d1 0f " + "32 b5 1d 33 be 52 0d 3d df 5a 70 99 55 a3 df e7 " + "82 83 b9 e0 ab 54 04 6d 15 0c 17 7f 03 7f dc cc " + "5b e4 ea 5f 68 b5 e5 a3 8c 9d 7e dc cc c4 97 5f " + "45 5a 69 09 b4 "; +// Salt: +static const char salt_1_5[] = + "80 e7 0f f8 6a 08 de 3e c6 09 72 b3 9b 4f bf dc " + "ea 67 ae 8e "; +// Signature: +static const char signature_1_5[] = + "1d 2a ad 22 1c a4 d3 1d df 13 50 92 39 01 93 98 " + "e3 d1 4b 32 dc 34 dc 5a f4 ae ae a3 c0 95 af 73 " + "47 9c f0 a4 5e 56 29 63 5a 53 a0 18 37 76 15 b1 " + "6c b9 b1 3b 3e 09 d6 71 eb 71 e3 87 b8 54 5c 59 " + "60 da 5a 64 77 6e 76 8e 82 b2 c9 35 83 bf 10 4c " + "3f db 23 51 2b 7b 4e 89 f6 33 dd 00 63 a5 30 db " + "45 24 b0 1c 3f 38 4c 09 31 0e 31 5a 79 dc d3 d6 " + "84 02 2a 7f 31 c8 65 a6 64 e3 16 97 8b 75 9f ad "; + +// RSASSA-PSS Signature Example 1.6 +// Message to be signed: +static const char message_1_6[] = + "10 aa e9 a0 ab 0b 59 5d 08 41 20 7b 70 0d 48 d7 " + "5f ae dd e3 b7 75 cd 6b 4c c8 8a e0 6e 46 94 ec " + "74 ba 18 f8 52 0d 4f 5e a6 9c bb e7 cc 2b eb a4 " + "3e fd c1 02 15 ac 4e b3 2d c3 02 a1 f5 3d c6 c4 " + "35 22 67 e7 93 6c fe bf 7c 8d 67 03 57 84 a3 90 " + "9f a8 59 c7 b7 b5 9b 8e 39 c5 c2 34 9f 18 86 b7 " + "05 a3 02 67 d4 02 f7 48 6a b4 f5 8c ad 5d 69 ad " + "b1 7a b8 cd 0c e1 ca f5 02 5a f4 ae 24 b1 fb 87 " + "94 c6 07 0c c0 9a 51 e2 f9 91 13 11 e3 87 7d 00 " + "44 c7 1c 57 a9 93 39 50 08 80 6b 72 3a c3 83 73 " + "d3 95 48 18 18 52 8c 1e 70 53 73 92 82 05 35 29 " + "51 0e 93 5c d0 fa 77 b8 fa 53 cc 2d 47 4b d4 fb " + "3c c5 c6 72 d6 ff dc 90 a0 0f 98 48 71 2c 4b cf " + "e4 6c 60 57 36 59 b1 1e 64 57 e8 61 f0 f6 04 b6 " + "13 8d 14 4f 8c e4 e2 da 73 "; +// Salt: +static const char salt_1_6[] = + "a8 ab 69 dd 80 1f 00 74 c2 a1 fc 60 64 98 36 c6 " + "16 d9 96 81 "; +// Signature: +static const char signature_1_6[] = + "2a 34 f6 12 5e 1f 6b 0b f9 71 e8 4f bd 41 c6 32 " + "be 8f 2c 2a ce 7d e8 b6 92 6e 31 ff 93 e9 af 98 " + "7f bc 06 e5 1e 9b e1 4f 51 98 f9 1f 3f 95 3b d6 " + "7d a6 0a 9d f5 97 64 c3 dc 0f e0 8e 1c be f0 b7 " + "5f 86 8d 10 ad 3f ba 74 9f ef 59 fb 6d ac 46 a0 " + "d6 e5 04 36 93 31 58 6f 58 e4 62 8f 39 aa 27 89 " + "82 54 3b c0 ee b5 37 dc 61 95 80 19 b3 94 fb 27 " + "3f 21 58 58 a0 a0 1a c4 d6 50 b9 55 c6 7f 4c 58 "; + +// Example 9: A 1536-bit RSA Key Pair + +// RSA modulus n: +static const char rsa_modulus_n_9[] = + "e6 bd 69 2a c9 66 45 79 04 03 fd d0 f5 be b8 b9 " + "bf 92 ed 10 00 7f c3 65 04 64 19 dd 06 c0 5c 5b " + "5b 2f 48 ec f9 89 e4 ce 26 91 09 97 9c bb 40 b4 " + "a0 ad 24 d2 24 83 d1 ee 31 5a d4 cc b1 53 42 68 " + "35 26 91 c5 24 f6 dd 8e 6c 29 d2 24 cf 24 69 73 " + "ae c8 6c 5b f6 b1 40 1a 85 0d 1b 9a d1 bb 8c bc " + "ec 47 b0 6f 0f 8c 7f 45 d3 fc 8f 31 92 99 c5 43 " + "3d db c2 b3 05 3b 47 de d2 ec d4 a4 ca ef d6 14 " + "83 3d c8 bb 62 2f 31 7e d0 76 b8 05 7f e8 de 3f " + "84 48 0a d5 e8 3e 4a 61 90 4a 4f 24 8f b3 97 02 " + "73 57 e1 d3 0e 46 31 39 81 5c 6f d4 fd 5a c5 b8 " + "17 2a 45 23 0e cb 63 18 a0 4f 14 55 d8 4e 5a 8b "; +// RSA public exponent e: +static const char rsa_public_exponent_e_9[] = + "01 00 01 "; + +// RSASSA-PSS Signature Example 9.1 +// Message to be signed: +static const char message_9_1[] = + "a8 8e 26 58 55 e9 d7 ca 36 c6 87 95 f0 b3 1b 59 " + "1c d6 58 7c 71 d0 60 a0 b3 f7 f3 ea ef 43 79 59 " + "22 02 8b c2 b6 ad 46 7c fc 2d 7f 65 9c 53 85 aa " + "70 ba 36 72 cd de 4c fe 49 70 cc 79 04 60 1b 27 " + "88 72 bf 51 32 1c 4a 97 2f 3c 95 57 0f 34 45 d4 " + "f5 79 80 e0 f2 0d f5 48 46 e6 a5 2c 66 8f 12 88 " + "c0 3f 95 00 6e a3 2f 56 2d 40 d5 2a f9 fe b3 2f " + "0f a0 6d b6 5b 58 8a 23 7b 34 e5 92 d5 5c f9 79 " + "f9 03 a6 42 ef 64 d2 ed 54 2a a8 c7 7d c1 dd 76 " + "2f 45 a5 93 03 ed 75 e5 41 ca 27 1e 2b 60 ca 70 " + "9e 44 fa 06 61 13 1e 8d 5d 41 63 fd 8d 39 85 66 " + "ce 26 de 87 30 e7 2f 9c ca 73 76 41 c2 44 15 94 " + "20 63 70 28 df 0a 18 07 9d 62 08 ea 8b 47 11 a2 " + "c7 50 f5 "; +// Salt: +static const char salt_9_1[] = + "c0 a4 25 31 3d f8 d7 56 4b d2 43 4d 31 15 23 d5 " + "25 7e ed 80 "; +// Signature: +static const char signature_9_1[] = + "58 61 07 22 6c 3c e0 13 a7 c8 f0 4d 1a 6a 29 59 " + "bb 4b 8e 20 5b a4 3a 27 b5 0f 12 41 11 bc 35 ef " + "58 9b 03 9f 59 32 18 7c b6 96 d7 d9 a3 2c 0c 38 " + "30 0a 5c dd a4 83 4b 62 d2 eb 24 0a f3 3f 79 d1 " + "3d fb f0 95 bf 59 9e 0d 96 86 94 8c 19 64 74 7b " + "67 e8 9c 9a ba 5c d8 50 16 23 6f 56 6c c5 80 2c " + "b1 3e ad 51 bc 7c a6 be f3 b9 4d cb db b1 d5 70 " + "46 97 71 df 0e 00 b1 a8 a0 67 77 47 2d 23 16 27 " + "9e da e8 64 74 66 8d 4e 1e ff f9 5f 1d e6 1c 60 " + "20 da 32 ae 92 bb f1 65 20 fe f3 cf 4d 88 f6 11 " + "21 f2 4b bd 9f e9 1b 59 ca f1 23 5b 2a 93 ff 81 " + "fc 40 3a dd f4 eb de a8 49 34 a9 cd af 8e 1a 9e "; + +// RSASSA-PSS Signature Example 9.2 +// Message to be signed: +static const char message_9_2[] = + "c8 c9 c6 af 04 ac da 41 4d 22 7e f2 3e 08 20 c3 " + "73 2c 50 0d c8 72 75 e9 5b 0d 09 54 13 99 3c 26 " + "58 bc 1d 98 85 81 ba 87 9c 2d 20 1f 14 cb 88 ce " + "d1 53 a0 19 69 a7 bf 0a 7b e7 9c 84 c1 48 6b c1 " + "2b 3f a6 c5 98 71 b6 82 7c 8c e2 53 ca 5f ef a8 " + "a8 c6 90 bf 32 6e 8e 37 cd b9 6d 90 a8 2e ba b6 " + "9f 86 35 0e 18 22 e8 bd 53 6a 2e "; +// Salt: +static const char salt_9_2[] = + "b3 07 c4 3b 48 50 a8 da c2 f1 5f 32 e3 78 39 ef " + "8c 5c 0e 91 "; +// Signature: +static const char signature_9_2[] = + "80 b6 d6 43 25 52 09 f0 a4 56 76 38 97 ac 9e d2 " + "59 d4 59 b4 9c 28 87 e5 88 2e cb 44 34 cf d6 6d " + "d7 e1 69 93 75 38 1e 51 cd 7f 55 4f 2c 27 17 04 " + "b3 99 d4 2b 4b e2 54 0a 0e ca 61 95 1f 55 26 7f " + "7c 28 78 c1 22 84 2d ad b2 8b 01 bd 5f 8c 02 5f " + "7e 22 84 18 a6 73 c0 3d 6b c0 c7 36 d0 a2 95 46 " + "bd 67 f7 86 d9 d6 92 cc ea 77 8d 71 d9 8c 20 63 " + "b7 a7 10 92 18 7a 4d 35 af 10 81 11 d8 3e 83 ea " + "e4 6c 46 aa 34 27 7e 06 04 45 89 90 37 88 f1 d5 " + "e7 ce e2 5f b4 85 e9 29 49 11 88 14 d6 f2 c3 ee " + "36 14 89 01 6f 32 7f b5 bc 51 7e b5 04 70 bf fa " + "1a fa 5f 4c e9 aa 0c e5 b8 ee 19 bf 55 01 b9 58 "; + +// RSASSA-PSS Signature Example 9.3 +// Message to be signed: +static const char message_9_3[] = + "0a fa d4 2c cd 4f c6 06 54 a5 50 02 d2 28 f5 2a " + "4a 5f e0 3b 8b bb 08 ca 82 da ca 55 8b 44 db e1 " + "26 6e 50 c0 e7 45 a3 6d 9d 29 04 e3 40 8a bc d1 " + "fd 56 99 94 06 3f 4a 75 cc 72 f2 fe e2 a0 cd 89 " + "3a 43 af 1c 5b 8b 48 7d f0 a7 16 10 02 4e 4f 6d " + "df 9f 28 ad 08 13 c1 aa b9 1b cb 3c 90 64 d5 ff " + "74 2d ef fe a6 57 09 41 39 36 9e 5e a6 f4 a9 63 " + "19 a5 cc 82 24 14 5b 54 50 62 75 8f ef d1 fe 34 " + "09 ae 16 92 59 c6 cd fd 6b 5f 29 58 e3 14 fa ec " + "be 69 d2 ca ce 58 ee 55 17 9a b9 b3 e6 d1 ec c1 " + "4a 55 7c 5f eb e9 88 59 52 64 fc 5d a1 c5 71 46 " + "2e ca 79 8a 18 a1 a4 94 0c da b4 a3 e9 20 09 cc " + "d4 2e 1e 94 7b 13 14 e3 22 38 a2 de ce 7d 23 a8 " + "9b 5b 30 c7 51 fd 0a 4a 43 0d 2c 54 85 94 "; +// Salt: +static const char salt_9_3[] = + "9a 2b 00 7e 80 97 8b bb 19 2c 35 4e b7 da 9a ed " + "fc 74 db f5 "; +// Signature: +static const char signature_9_3[] = + "48 44 08 f3 89 8c d5 f5 34 83 f8 08 19 ef bf 27 " + "08 c3 4d 27 a8 b2 a6 fa e8 b3 22 f9 24 02 37 f9 " + "81 81 7a ca 18 46 f1 08 4d aa 6d 7c 07 95 f6 e5 " + "bf 1a f5 9c 38 e1 85 84 37 ce 1f 7e c4 19 b9 8c " + "87 36 ad f6 dd 9a 00 b1 80 6d 2b d3 ad 0a 73 77 " + "5e 05 f5 2d fe f3 a5 9a b4 b0 81 43 f0 df 05 cd " + "1a d9 d0 4b ec ec a6 da a4 a2 12 98 03 e2 00 cb " + "c7 77 87 ca f4 c1 d0 66 3a 6c 59 87 b6 05 95 20 " + "19 78 2c af 2e c1 42 6d 68 fb 94 ed 1d 4b e8 16 " + "a7 ed 08 1b 77 e6 ab 33 0b 3f fc 07 38 20 fe cd " + "e3 72 7f cb e2 95 ee 61 a0 50 a3 43 65 86 37 c3 " + "fd 65 9c fb 63 73 6d e3 2d 9f 90 d3 c2 f6 3e ca "; + +// RSASSA-PSS Signature Example 9.4 +// Message to be signed: +static const char message_9_4[] = + "1d fd 43 b4 6c 93 db 82 62 9b da e2 bd 0a 12 b8 " + "82 ea 04 c3 b4 65 f5 cf 93 02 3f 01 05 96 26 db " + "be 99 f2 6b b1 be 94 9d dd d1 6d c7 f3 de bb 19 " + "a1 94 62 7f 0b 22 44 34 df 7d 87 00 e9 e9 8b 06 " + "e3 60 c1 2f db e3 d1 9f 51 c9 68 4e b9 08 9e cb " + "b0 a2 f0 45 03 99 d3 f5 9e ac 72 94 08 5d 04 4f " + "53 93 c6 ce 73 74 23 d8 b8 6c 41 53 70 d3 89 e3 " + "0b 9f 0a 3c 02 d2 5d 00 82 e8 ad 6f 3f 1e f2 4a " + "45 c3 cf 82 b3 83 36 70 63 a4 d4 61 3e 42 64 f0 " + "1b 2d ac 2e 5a a4 20 43 f8 fb 5f 69 fa 87 1d 14 " + "fb 27 3e 76 7a 53 1c 40 f0 2f 34 3b c2 fb 45 a0 " + "c7 e0 f6 be 25 61 92 3a 77 21 1d 66 a6 e2 db b4 " + "3c 36 63 50 be ae 22 da 3a c2 c1 f5 07 70 96 fc " + "b5 c4 bf 25 5f 75 74 35 1a e0 b1 e1 f0 36 32 81 " + "7c 08 56 d4 a8 ba 97 af bd c8 b8 58 55 40 2b c5 " + "69 26 fc ec 20 9f 9e a8 "; +// Salt: +static const char salt_9_4[] = + "70 f3 82 bd df 4d 5d 2d d8 8b 3b c7 b7 30 8b e6 " + "32 b8 40 45 "; +// Signature: +static const char signature_9_4[] = + "84 eb eb 48 1b e5 98 45 b4 64 68 ba fb 47 1c 01 " + "12 e0 2b 23 5d 84 b5 d9 11 cb d1 92 6e e5 07 4a " + "e0 42 44 95 cb 20 e8 23 08 b8 eb b6 5f 41 9a 03 " + "fb 40 e7 2b 78 98 1d 88 aa d1 43 05 36 85 17 2c " + "97 b2 9c 8b 7b f0 ae 73 b5 b2 26 3c 40 3d a0 ed " + "2f 80 ff 74 50 af 78 28 eb 8b 86 f0 02 8b d2 a8 " + "b1 76 a4 d2 28 cc ce a1 83 94 f2 38 b0 9f f7 58 " + "cc 00 bc 04 30 11 52 35 57 42 f2 82 b5 4e 66 3a " + "91 9e 70 9d 8d a2 4a de 55 00 a7 b9 aa 50 22 6e " + "0c a5 29 23 e6 c2 d8 60 ec 50 ff 48 0f a5 74 77 " + "e8 2b 05 65 f4 37 9f 79 c7 72 d5 c2 da 80 af 9f " + "bf 32 5e ce 6f c2 0b 00 96 16 14 be e8 9a 18 3e "; + +// RSASSA-PSS Signature Example 9.5 +// Message to be signed: +static const char message_9_5[] = + "1b dc 6e 7c 98 fb 8c f5 4e 9b 09 7b 66 a8 31 e9 " + "cf e5 2d 9d 48 88 44 8e e4 b0 97 80 93 ba 1d 7d " + "73 ae 78 b3 a6 2b a4 ad 95 cd 28 9c cb 9e 00 52 " + "26 bb 3d 17 8b cc aa 82 1f b0 44 a4 e2 1e e9 76 " + "96 c1 4d 06 78 c9 4c 2d ae 93 b0 ad 73 92 22 18 " + "55 3d aa 7e 44 eb e5 77 25 a7 a4 5c c7 2b 9b 21 " + "38 a6 b1 7c 8d b4 11 ce 82 79 ee 12 41 af f0 a8 " + "be c6 f7 7f 87 ed b0 c6 9c b2 72 36 e3 43 5a 80 " + "0b 19 2e 4f 11 e5 19 e3 fe 30 fc 30 ea cc ca 4f " + "bb 41 76 90 29 bf 70 8e 81 7a 9e 68 38 05 be 67 " + "fa 10 09 84 68 3b 74 83 8e 3b cf fa 79 36 6e ed " + "1d 48 1c 76 72 91 18 83 8f 31 ba 8a 04 8a 93 c1 " + "be 44 24 59 8e 8d f6 32 8b 7a 77 88 0a 3f 9c 7e " + "2e 8d fc a8 eb 5a 26 fb 86 bd c5 56 d4 2b be 01 " + "d9 fa 6e d8 06 46 49 1c 93 41 "; +// Salt: +static const char salt_9_5[] = + "d6 89 25 7a 86 ef fa 68 21 2c 5e 0c 61 9e ca 29 " + "5f b9 1b 67 "; +// Signature: +static const char signature_9_5[] = + "82 10 2d f8 cb 91 e7 17 99 19 a0 4d 26 d3 35 d6 " + "4f bc 2f 87 2c 44 83 39 43 24 1d e8 45 48 10 27 " + "4c df 3d b5 f4 2d 42 3d b1 52 af 71 35 f7 01 42 " + "0e 39 b4 94 a6 7c bf d1 9f 91 19 da 23 3a 23 da " + "5c 64 39 b5 ba 0d 2b c3 73 ee e3 50 70 01 37 8d " + "4a 40 73 85 6b 7f e2 ab a0 b5 ee 93 b2 7f 4a fe " + "c7 d4 d1 20 92 1c 83 f6 06 76 5b 02 c1 9e 4d 6a " + "1a 3b 95 fa 4c 42 29 51 be 4f 52 13 10 77 ef 17 " + "17 97 29 cd df bd b5 69 50 db ac ee fe 78 cb 16 " + "64 0a 09 9e a5 6d 24 38 9e ef 10 f8 fe cb 31 ba " + "3e a3 b2 27 c0 a8 66 98 bb 89 e3 e9 36 39 05 bf " + "22 77 7b 2a 3a a5 21 b6 5b 4c ef 76 d8 3b de 4c "; + +// RSASSA-PSS Signature Example 9.6 +// Message to be signed: +static const char message_9_6[] = + "88 c7 a9 f1 36 04 01 d9 0e 53 b1 01 b6 1c 53 25 " + "c3 c7 5d b1 b4 11 fb eb 8e 83 0b 75 e9 6b 56 67 " + "0a d2 45 40 4e 16 79 35 44 ee 35 4b c6 13 a9 0c " + "c9 84 87 15 a7 3d b5 89 3e 7f 6d 27 98 15 c0 c1 " + "de 83 ef 8e 29 56 e3 a5 6e d2 6a 88 8d 7a 9c dc " + "d0 42 f4 b1 6b 7f a5 1e f1 a0 57 36 62 d1 6a 30 " + "2d 0e c5 b2 85 d2 e0 3a d9 65 29 c8 7b 3d 37 4d " + "b3 72 d9 5b 24 43 d0 61 b6 b1 a3 50 ba 87 80 7e " + "d0 83 af d1 eb 05 c3 f5 2f 4e ba 5e d2 22 77 14 " + "fd b5 0b 9d 9d 9d d6 81 4f 62 f6 27 2f cd 5c db " + "ce 7a 9e f7 97 "; +// Salt: +static const char salt_9_6[] = + "c2 5f 13 bf 67 d0 81 67 1a 04 81 a1 f1 82 0d 61 " + "3b ba 22 76 "; +// Signature: +static const char signature_9_6[] = + "a7 fd b0 d2 59 16 5c a2 c8 8d 00 bb f1 02 8a 86 " + "7d 33 76 99 d0 61 19 3b 17 a9 64 8e 14 cc bb aa " + "de ac aa cd ec 81 5e 75 71 29 4e bb 8a 11 7a f2 " + "05 fa 07 8b 47 b0 71 2c 19 9e 3a d0 51 35 c5 04 " + "c2 4b 81 70 51 15 74 08 02 48 79 92 ff d5 11 d4 " + "af c6 b8 54 49 1e b3 f0 dd 52 31 39 54 2f f1 5c " + "31 01 ee 85 54 35 17 c6 a3 c7 94 17 c6 7e 2d d9 " + "aa 74 1e 9a 29 b0 6d cb 59 3c 23 36 b3 67 0a e3 " + "af ba c7 c3 e7 6e 21 54 73 e8 66 e3 38 ca 24 4d " + "e0 0b 62 62 4d 6b 94 26 82 2c ea e9 f8 cc 46 08 " + "95 f4 12 50 07 3f d4 5c 5a 1e 7b 42 5c 20 4a 42 " + "3a 69 91 59 f6 90 3e 71 0b 37 a7 bb 2b c8 04 9f "; + +// Example 10: A 2048-bit RSA Key Pair + +// RSA modulus n: +static const char rsa_modulus_n_10[] = + "a5 dd 86 7a c4 cb 02 f9 0b 94 57 d4 8c 14 a7 70 " + "ef 99 1c 56 c3 9c 0e c6 5f d1 1a fa 89 37 ce a5 " + "7b 9b e7 ac 73 b4 5c 00 17 61 5b 82 d6 22 e3 18 " + "75 3b 60 27 c0 fd 15 7b e1 2f 80 90 fe e2 a7 ad " + "cd 0e ef 75 9f 88 ba 49 97 c7 a4 2d 58 c9 aa 12 " + "cb 99 ae 00 1f e5 21 c1 3b b5 43 14 45 a8 d5 ae " + "4f 5e 4c 7e 94 8a c2 27 d3 60 40 71 f2 0e 57 7e " + "90 5f be b1 5d fa f0 6d 1d e5 ae 62 53 d6 3a 6a " + "21 20 b3 1a 5d a5 da bc 95 50 60 0e 20 f2 7d 37 " + "39 e2 62 79 25 fe a3 cc 50 9f 21 df f0 4e 6e ea " + "45 49 c5 40 d6 80 9f f9 30 7e ed e9 1f ff 58 73 " + "3d 83 85 a2 37 d6 d3 70 5a 33 e3 91 90 09 92 07 " + "0d f7 ad f1 35 7c f7 e3 70 0c e3 66 7d e8 3f 17 " + "b8 df 17 78 db 38 1d ce 09 cb 4a d0 58 a5 11 00 " + "1a 73 81 98 ee 27 cf 55 a1 3b 75 45 39 90 65 82 " + "ec 8b 17 4b d5 8d 5d 1f 3d 76 7c 61 37 21 ae 05 "; +// RSA public exponent e: +static const char rsa_public_exponent_e_10[] = + "01 00 01 "; + +// RSASSA-PSS Signature Example 10.1 +// Message to be signed: +static const char message_10_1[] = + "88 31 77 e5 12 6b 9b e2 d9 a9 68 03 27 d5 37 0c " + "6f 26 86 1f 58 20 c4 3d a6 7a 3a d6 09 "; +// Salt: +static const char salt_10_1[] = + "04 e2 15 ee 6f f9 34 b9 da 70 d7 73 0c 87 34 ab " + "fc ec de 89 "; +// Signature: +static const char signature_10_1[] = + "82 c2 b1 60 09 3b 8a a3 c0 f7 52 2b 19 f8 73 54 " + "06 6c 77 84 7a bf 2a 9f ce 54 2d 0e 84 e9 20 c5 " + "af b4 9f fd fd ac e1 65 60 ee 94 a1 36 96 01 14 " + "8e ba d7 a0 e1 51 cf 16 33 17 91 a5 72 7d 05 f2 " + "1e 74 e7 eb 81 14 40 20 69 35 d7 44 76 5a 15 e7 " + "9f 01 5c b6 6c 53 2c 87 a6 a0 59 61 c8 bf ad 74 " + "1a 9a 66 57 02 28 94 39 3e 72 23 73 97 96 c0 2a " + "77 45 5d 0f 55 5b 0e c0 1d df 25 9b 62 07 fd 0f " + "d5 76 14 ce f1 a5 57 3b aa ff 4e c0 00 69 95 16 " + "59 b8 5f 24 30 0a 25 16 0c a8 52 2d c6 e6 72 7e " + "57 d0 19 d7 e6 36 29 b8 fe 5e 89 e2 5c c1 5b eb " + "3a 64 75 77 55 92 99 28 0b 9b 28 f7 9b 04 09 00 " + "0b e2 5b bd 96 40 8b a3 b4 3c c4 86 18 4d d1 c8 " + "e6 25 53 fa 1a f4 04 0f 60 66 3d e7 f5 e4 9c 04 " + "38 8e 25 7f 1c e8 9c 95 da b4 8a 31 5d 9b 66 b1 " + "b7 62 82 33 87 6f f2 38 52 30 d0 70 d0 7e 16 66 "; + +// RSASSA-PSS Signature Example 10.2 +// Message to be signed: +static const char message_10_2[] = + "dd 67 0a 01 46 58 68 ad c9 3f 26 13 19 57 a5 0c " + "52 fb 77 7c db aa 30 89 2c 9e 12 36 11 64 ec 13 " + "97 9d 43 04 81 18 e4 44 5d b8 7b ee 58 dd 98 7b " + "34 25 d0 20 71 d8 db ae 80 70 8b 03 9d bb 64 db " + "d1 de 56 57 d9 fe d0 c1 18 a5 41 43 74 2e 0f f3 " + "c8 7f 74 e4 58 57 64 7a f3 f7 9e b0 a1 4c 9d 75 " + "ea 9a 1a 04 b7 cf 47 8a 89 7a 70 8f d9 88 f4 8e " + "80 1e db 0b 70 39 df 8c 23 bb 3c 56 f4 e8 21 ac "; +// Salt: +static const char salt_10_2[] = + "8b 2b dd 4b 40 fa f5 45 c7 78 dd f9 bc 1a 49 cb " + "57 f9 b7 1b "; +// Signature: +static const char signature_10_2[] = + "14 ae 35 d9 dd 06 ba 92 f7 f3 b8 97 97 8a ed 7c " + "d4 bf 5f f0 b5 85 a4 0b d4 6c e1 b4 2c d2 70 30 " + "53 bb 90 44 d6 4e 81 3d 8f 96 db 2d d7 00 7d 10 " + "11 8f 6f 8f 84 96 09 7a d7 5e 1f f6 92 34 1b 28 " + "92 ad 55 a6 33 a1 c5 5e 7f 0a 0a d5 9a 0e 20 3a " + "5b 82 78 ae c5 4d d8 62 2e 28 31 d8 71 74 f8 ca " + "ff 43 ee 6c 46 44 53 45 d8 4a 59 65 9b fb 92 ec " + "d4 c8 18 66 86 95 f3 47 06 f6 68 28 a8 99 59 63 " + "7f 2b f3 e3 25 1c 24 bd ba 4d 4b 76 49 da 00 22 " + "21 8b 11 9c 84 e7 9a 65 27 ec 5b 8a 5f 86 1c 15 " + "99 52 e2 3e c0 5e 1e 71 73 46 fa ef e8 b1 68 68 " + "25 bd 2b 26 2f b2 53 10 66 c0 de 09 ac de 2e 42 " + "31 69 07 28 b5 d8 5e 11 5a 2f 6b 92 b7 9c 25 ab " + "c9 bd 93 99 ff 8b cf 82 5a 52 ea 1f 56 ea 76 dd " + "26 f4 3b aa fa 18 bf a9 2a 50 4c bd 35 69 9e 26 " + "d1 dc c5 a2 88 73 85 f3 c6 32 32 f0 6f 32 44 c3 "; + +// RSASSA-PSS Signature Example 10.3 +// Message to be signed: +static const char message_10_3[] = + "48 b2 b6 a5 7a 63 c8 4c ea 85 9d 65 c6 68 28 4b " + "08 d9 6b dc aa be 25 2d b0 e4 a9 6c b1 ba c6 01 " + "93 41 db 6f be fb 8d 10 6b 0e 90 ed a6 bc c6 c6 " + "26 2f 37 e7 ea 9c 7e 5d 22 6b d7 df 85 ec 5e 71 " + "ef ff 2f 54 c5 db 57 7f f7 29 ff 91 b8 42 49 1d " + "e2 74 1d 0c 63 16 07 df 58 6b 90 5b 23 b9 1a f1 " + "3d a1 23 04 bf 83 ec a8 a7 3e 87 1f f9 db "; +// Salt: +static const char salt_10_3[] = + "4e 96 fc 1b 39 8f 92 b4 46 71 01 0c 0d c3 ef d6 " + "e2 0c 2d 73 "; +// Signature: +static const char signature_10_3[] = + "6e 3e 4d 7b 6b 15 d2 fb 46 01 3b 89 00 aa 5b bb " + "39 39 cf 2c 09 57 17 98 70 42 02 6e e6 2c 74 c5 " + "4c ff d5 d7 d5 7e fb bf 95 0a 0f 5c 57 4f a0 9d " + "3f c1 c9 f5 13 b0 5b 4f f5 0d d8 df 7e df a2 01 " + "02 85 4c 35 e5 92 18 01 19 a7 0c e5 b0 85 18 2a " + "a0 2d 9e a2 aa 90 d1 df 03 f2 da ae 88 5b a2 f5 " + "d0 5a fd ac 97 47 6f 06 b9 3b 5b c9 4a 1a 80 aa " + "91 16 c4 d6 15 f3 33 b0 98 89 2b 25 ff ac e2 66 " + "f5 db 5a 5a 3b cc 10 a8 24 ed 55 aa d3 5b 72 78 " + "34 fb 8c 07 da 28 fc f4 16 a5 d9 b2 22 4f 1f 8b " + "44 2b 36 f9 1e 45 6f de a2 d7 cf e3 36 72 68 de " + "03 07 a4 c7 4e 92 41 59 ed 33 39 3d 5e 06 55 53 " + "1c 77 32 7b 89 82 1b de df 88 01 61 c7 8c d4 19 " + "6b 54 19 f7 ac c3 f1 3e 5e bf 16 1b 6e 7c 67 24 " + "71 6c a3 3b 85 c2 e2 56 40 19 2a c2 85 96 51 d5 " + "0b de 7e b9 76 e5 1c ec 82 8b 98 b6 56 3b 86 bb "; + +// RSASSA-PSS Signature Example 10.4 +// Message to be signed: +static const char message_10_4[] = + "0b 87 77 c7 f8 39 ba f0 a6 4b bb db c5 ce 79 75 " + "5c 57 a2 05 b8 45 c1 74 e2 d2 e9 05 46 a0 89 c4 " + "e6 ec 8a df fa 23 a7 ea 97 ba e6 b6 5d 78 2b 82 " + "db 5d 2b 5a 56 d2 2a 29 a0 5e 7c 44 33 e2 b8 2a " + "62 1a bb a9 0a dd 05 ce 39 3f c4 8a 84 05 42 45 " + "1a "; +// Salt: +static const char salt_10_4[] = + "c7 cd 69 8d 84 b6 51 28 d8 83 5e 3a 8b 1e b0 e0 " + "1c b5 41 ec "; +// Signature: +static const char signature_10_4[] = + "34 04 7f f9 6c 4d c0 dc 90 b2 d4 ff 59 a1 a3 61 " + "a4 75 4b 25 5d 2e e0 af 7d 8b f8 7c 9b c9 e7 dd " + "ee de 33 93 4c 63 ca 1c 0e 3d 26 2c b1 45 ef 93 " + "2a 1f 2c 0a 99 7a a6 a3 4f 8e ae e7 47 7d 82 cc " + "f0 90 95 a6 b8 ac ad 38 d4 ee c9 fb 7e ab 7a d0 " + "2d a1 d1 1d 8e 54 c1 82 5e 55 bf 58 c2 a2 32 34 " + "b9 02 be 12 4f 9e 90 38 a8 f6 8f a4 5d ab 72 f6 " + "6e 09 45 bf 1d 8b ac c9 04 4c 6f 07 09 8c 9f ce " + "c5 8a 3a ab 10 0c 80 51 78 15 5f 03 0a 12 4c 45 " + "0e 5a cb da 47 d0 e4 f1 0b 80 a2 3f 80 3e 77 4d " + "02 3b 00 15 c2 0b 9f 9b be 7c 91 29 63 38 d5 ec " + "b4 71 ca fb 03 20 07 b6 7a 60 be 5f 69 50 4a 9f " + "01 ab b3 cb 46 7b 26 0e 2b ce 86 0b e8 d9 5b f9 " + "2c 0c 8e 14 96 ed 1e 52 85 93 a4 ab b6 df 46 2d " + "de 8a 09 68 df fe 46 83 11 68 57 a2 32 f5 eb f6 " + "c8 5b e2 38 74 5a d0 f3 8f 76 7a 5f db f4 86 fb "; + +// RSASSA-PSS Signature Example 10.5 +// Message to be signed: +static const char message_10_5[] = + "f1 03 6e 00 8e 71 e9 64 da dc 92 19 ed 30 e1 7f " + "06 b4 b6 8a 95 5c 16 b3 12 b1 ed df 02 8b 74 97 " + "6b ed 6b 3f 6a 63 d4 e7 78 59 24 3c 9c cc dc 98 " + "01 65 23 ab b0 24 83 b3 55 91 c3 3a ad 81 21 3b " + "b7 c7 bb 1a 47 0a ab c1 0d 44 25 6c 4d 45 59 d9 " + "16 "; +// Salt: +static const char salt_10_5[] = + "ef a8 bf f9 62 12 b2 f4 a3 f3 71 a1 0d 57 41 52 " + "65 5f 5d fb "; +// Signature: +static const char signature_10_5[] = + "7e 09 35 ea 18 f4 d6 c1 d1 7c e8 2e b2 b3 83 6c " + "55 b3 84 58 9c e1 9d fe 74 33 63 ac 99 48 d1 f3 " + "46 b7 bf dd fe 92 ef d7 8a db 21 fa ef c8 9a de " + "42 b1 0f 37 40 03 fe 12 2e 67 42 9a 1c b8 cb d1 " + "f8 d9 01 45 64 c4 4d 12 01 16 f4 99 0f 1a 6e 38 " + "77 4c 19 4b d1 b8 21 32 86 b0 77 b0 49 9d 2e 7b " + "3f 43 4a b1 22 89 c5 56 68 4d ee d7 81 31 93 4b " + "b3 dd 65 37 23 6f 7c 6f 3d cb 09 d4 76 be 07 72 " + "1e 37 e1 ce ed 9b 2f 7b 40 68 87 bd 53 15 73 05 " + "e1 c8 b4 f8 4d 73 3b c1 e1 86 fe 06 cc 59 b6 ed " + "b8 f4 bd 7f fe fd f4 f7 ba 9c fb 9d 57 06 89 b5 " + "a1 a4 10 9a 74 6a 69 08 93 db 37 99 25 5a 0c b9 " + "21 5d 2d 1c d4 90 59 0e 95 2e 8c 87 86 aa 00 11 " + "26 52 52 47 0c 04 1d fb c3 ee c7 c3 cb f7 1c 24 " + "86 9d 11 5c 0c b4 a9 56 f5 6d 53 0b 80 ab 58 9a " + "cf ef c6 90 75 1d df 36 e8 d3 83 f8 3c ed d2 cc "; + +// RSASSA-PSS Signature Example 10.6 +// Message to be signed: +static const char message_10_6[] = + "25 f1 08 95 a8 77 16 c1 37 45 0b b9 51 9d fa a1 " + "f2 07 fa a9 42 ea 88 ab f7 1e 9c 17 98 00 85 b5 " + "55 ae ba b7 62 64 ae 2a 3a b9 3c 2d 12 98 11 91 " + "dd ac 6f b5 94 9e b3 6a ee 3c 5d a9 40 f0 07 52 " + "c9 16 d9 46 08 fa 7d 97 ba 6a 29 15 b6 88 f2 03 " + "23 d4 e9 d9 68 01 d8 9a 72 ab 58 92 dc 21 17 c0 " + "74 34 fc f9 72 e0 58 cf 8c 41 ca 4b 4f f5 54 f7 " + "d5 06 8a d3 15 5f ce d0 f3 12 5b c0 4f 91 93 37 " + "8a 8f 5c 4c 3b 8c b4 dd 6d 1c c6 9d 30 ec ca 6e " + "aa 51 e3 6a 05 73 0e 9e 34 2e 85 5b af 09 9d ef " + "b8 af d7 "; +// Salt: +static const char salt_10_6[] = + "ad 8b 15 23 70 36 46 22 4b 66 0b 55 08 85 91 7c " + "a2 d1 df 28 "; +// Signature: +static const char signature_10_6[] = + "6d 3b 5b 87 f6 7e a6 57 af 21 f7 54 41 97 7d 21 " + "80 f9 1b 2c 5f 69 2d e8 29 55 69 6a 68 67 30 d9 " + "b9 77 8d 97 07 58 cc b2 60 71 c2 20 9f fb d6 12 " + "5b e2 e9 6e a8 1b 67 cb 9b 93 08 23 9f da 17 f7 " + "b2 b6 4e cd a0 96 b6 b9 35 64 0a 5a 1c b4 2a 91 " + "55 b1 c9 ef 7a 63 3a 02 c5 9f 0d 6e e5 9b 85 2c " + "43 b3 50 29 e7 3c 94 0f f0 41 0e 8f 11 4e ed 46 " + "bb d0 fa e1 65 e4 2b e2 52 8a 40 1c 3b 28 fd 81 " + "8e f3 23 2d ca 9f 4d 2a 0f 51 66 ec 59 c4 23 96 " + "d6 c1 1d bc 12 15 a5 6f a1 71 69 db 95 75 34 3e " + "f3 4f 9d e3 2a 49 cd c3 17 49 22 f2 29 c2 3e 18 " + "e4 5d f9 35 31 19 ec 43 19 ce dc e7 a1 7c 64 08 " + "8c 1f 6f 52 be 29 63 41 00 b3 91 9d 38 f3 d1 ed " + "94 e6 89 1e 66 a7 3b 8f b8 49 f5 87 4d f5 94 59 " + "e2 98 c7 bb ce 2e ee 78 2a 19 5a a6 6f e2 d0 73 " + "2b 25 e5 95 f5 7d 3e 06 1b 1f c3 e4 06 3b f9 8f "; + +struct SignatureExample { + const char* message; + const char* salt; + const char* signature; +}; + +struct PSSTestVector { + const char* modulus_n; + const char* public_exponent_e; + SignatureExample example[6]; +}; + +static const PSSTestVector pss_test[] = { + { + rsa_modulus_n_1, + rsa_public_exponent_e_1, + { + { message_1_1, salt_1_1, signature_1_1 }, + { message_1_2, salt_1_2, signature_1_2 }, + { message_1_3, salt_1_3, signature_1_3 }, + { message_1_4, salt_1_4, signature_1_4 }, + { message_1_5, salt_1_5, signature_1_5 }, + { message_1_6, salt_1_6, signature_1_6 }, + } + }, + { + rsa_modulus_n_9, + rsa_public_exponent_e_9, + { + { message_9_1, salt_9_1, signature_9_1 }, + { message_9_2, salt_9_2, signature_9_2 }, + { message_9_3, salt_9_3, signature_9_3 }, + { message_9_4, salt_9_4, signature_9_4 }, + { message_9_5, salt_9_5, signature_9_5 }, + { message_9_6, salt_9_6, signature_9_6 }, + } + }, + { + rsa_modulus_n_10, + rsa_public_exponent_e_10, + { + { message_10_1, salt_10_1, signature_10_1 }, + { message_10_2, salt_10_2, signature_10_2 }, + { message_10_3, salt_10_3, signature_10_3 }, + { message_10_4, salt_10_4, signature_10_4 }, + { message_10_5, salt_10_5, signature_10_5 }, + { message_10_6, salt_10_6, signature_10_6 }, + } + }, +}; + +static uint8 HexDigitValue(char digit) { + if ('0' <= digit && digit <= '9') + return digit - '0'; + if ('a' <= digit && digit <= 'f') + return digit - 'a' + 10; + return digit - 'A' + 10; +} + +static bool DecodeTestInput(const char* in, std::vector<uint8>* out) { + out->clear(); + while (in[0] != '\0') { + if (!isxdigit(in[0]) || !isxdigit(in[1]) || in[2] != ' ') + return false; + uint8 octet = HexDigitValue(in[0]) * 16 + HexDigitValue(in[1]); + out->push_back(octet); + in += 3; + } + return true; +} + +static bool EncodeRSAPublicKey(const std::vector<uint8>& modulus_n, + const std::vector<uint8>& public_exponent_e, + std::vector<uint8>* public_key_info) { + // The public key is specified as the following ASN.1 structure: + // SubjectPublicKeyInfo ::= SEQUENCE { + // algorithm AlgorithmIdentifier, + // subjectPublicKey BIT STRING } + // + // The signature algorithm is specified as the following ASN.1 structure: + // AlgorithmIdentifier ::= SEQUENCE { + // algorithm OBJECT IDENTIFIER, + // parameters ANY DEFINED BY algorithm OPTIONAL } + // + // An RSA public key is specified as the following ASN.1 structure: + // RSAPublicKey ::= SEQUENCE { + // modulus INTEGER, -- n + // publicExponent INTEGER -- e + // } + static const uint8 kIntegerTag = 0x02; + static const uint8 kBitStringTag = 0x03; + static const uint8 kSequenceTag = 0x30; + public_key_info->clear(); + + // Encode the public exponent e as an INTEGER. + public_key_info->insert(public_key_info->begin(), + public_exponent_e.begin(), + public_exponent_e.end()); + uint8 length = public_exponent_e.size(); + public_key_info->insert(public_key_info->begin(), length); + public_key_info->insert(public_key_info->begin(), kIntegerTag); + + // Encode the modulus n as an INTEGER. + public_key_info->insert(public_key_info->begin(), + modulus_n.begin(), modulus_n.end()); + uint16 length16 = modulus_n.size(); + if (modulus_n[0] & 0x80) { + public_key_info->insert(public_key_info->begin(), 0x00); + length16++; + } + public_key_info->insert(public_key_info->begin(), length16 & 0xff); + public_key_info->insert(public_key_info->begin(), (length16 >> 8) & 0xff); + public_key_info->insert(public_key_info->begin(), 0x82); + public_key_info->insert(public_key_info->begin(), kIntegerTag); + + // Encode the RSAPublicKey SEQUENCE. + length16 = public_key_info->size(); + public_key_info->insert(public_key_info->begin(), length16 & 0xff); + public_key_info->insert(public_key_info->begin(), (length16 >> 8) & 0xff); + public_key_info->insert(public_key_info->begin(), 0x82); + public_key_info->insert(public_key_info->begin(), kSequenceTag); + + // Encode the BIT STRING. + // Number of unused bits. + public_key_info->insert(public_key_info->begin(), 0x00); + length16 = public_key_info->size(); + public_key_info->insert(public_key_info->begin(), length16 & 0xff); + public_key_info->insert(public_key_info->begin(), (length16 >> 8) & 0xff); + public_key_info->insert(public_key_info->begin(), 0x82); + public_key_info->insert(public_key_info->begin(), kBitStringTag); + + // Encode the AlgorithmIdentifier. + static const uint8 algorithm[] = { + 0x30, 0x0d, // a SEQUENCE of length 13 + 0x06, 0x09, // an OBJECT IDENTIFIER of length 9 + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, + 0x05, 0x00, + }; + public_key_info->insert(public_key_info->begin(), + algorithm, algorithm + sizeof(algorithm)); + + // Encode the outermost SEQUENCE. + length16 = public_key_info->size(); + public_key_info->insert(public_key_info->begin(), length16 & 0xff); + public_key_info->insert(public_key_info->begin(), (length16 >> 8) & 0xff); + public_key_info->insert(public_key_info->begin(), 0x82); + public_key_info->insert(public_key_info->begin(), kSequenceTag); + + return true; +} + +TEST(SignatureVerifierTest, VerifyRSAPSS) { + for (unsigned int i = 0; i < arraysize(pss_test); i++) { + std::vector<uint8> modulus_n; + std::vector<uint8> public_exponent_e; + ASSERT_TRUE(DecodeTestInput(pss_test[i].modulus_n, &modulus_n)); + ASSERT_TRUE(DecodeTestInput(pss_test[i].public_exponent_e, + &public_exponent_e)); + std::vector<uint8> public_key_info; + ASSERT_TRUE(EncodeRSAPublicKey(modulus_n, public_exponent_e, + &public_key_info)); + + for (unsigned int j = 0; j < arraysize(pss_test[i].example); j++) { + std::vector<uint8> message; + std::vector<uint8> salt; + std::vector<uint8> signature; + ASSERT_TRUE(DecodeTestInput(pss_test[i].example[j].message, &message)); + ASSERT_TRUE(DecodeTestInput(pss_test[i].example[j].salt, &salt)); + ASSERT_TRUE(DecodeTestInput(pss_test[i].example[j].signature, + &signature)); + + crypto::SignatureVerifier verifier; + bool ok; + + // Positive test. + ok = verifier.VerifyInitRSAPSS(crypto::SignatureVerifier::SHA1, + crypto::SignatureVerifier::SHA1, + salt.size(), + &signature[0], signature.size(), + &public_key_info[0], + public_key_info.size()); + ASSERT_TRUE(ok); + verifier.VerifyUpdate(&message[0], message.size()); + ok = verifier.VerifyFinal(); + EXPECT_TRUE(ok); + + // Modify the first byte of the message. + ok = verifier.VerifyInitRSAPSS(crypto::SignatureVerifier::SHA1, + crypto::SignatureVerifier::SHA1, + salt.size(), + &signature[0], signature.size(), + &public_key_info[0], + public_key_info.size()); + ASSERT_TRUE(ok); + message[0] += 1; + verifier.VerifyUpdate(&message[0], message.size()); + message[0] -= 1; + ok = verifier.VerifyFinal(); + EXPECT_FALSE(ok); + + // Truncate the message. + ASSERT_FALSE(message.empty()); + ok = verifier.VerifyInitRSAPSS(crypto::SignatureVerifier::SHA1, + crypto::SignatureVerifier::SHA1, + salt.size(), + &signature[0], signature.size(), + &public_key_info[0], + public_key_info.size()); + ASSERT_TRUE(ok); + verifier.VerifyUpdate(&message[0], message.size() - 1); + ok = verifier.VerifyFinal(); + EXPECT_FALSE(ok); + + // Corrupt the signature. + signature[0] += 1; + ok = verifier.VerifyInitRSAPSS(crypto::SignatureVerifier::SHA1, + crypto::SignatureVerifier::SHA1, + salt.size(), + &signature[0], signature.size(), + &public_key_info[0], + public_key_info.size()); + signature[0] -= 1; + ASSERT_TRUE(ok); + verifier.VerifyUpdate(&message[0], message.size()); + ok = verifier.VerifyFinal(); + EXPECT_FALSE(ok); + } + } +} diff --git a/crypto/third_party/nss/README.chromium b/crypto/third_party/nss/README.chromium index f0bb87b..1a63665 100644 --- a/crypto/third_party/nss/README.chromium +++ b/crypto/third_party/nss/README.chromium @@ -12,3 +12,7 @@ In blapi.h and sha512.cc, replaced uint32 by unsigned int so that they can be compiled with -DNO_NSPR_10_SUPPORT. NO_NSPR_10_SUPPORT turns off the definition of the NSPR 1.0 types int8 - int64 and uint8 - uint64 to avoid conflict with the same-named types defined in "base/basictypes.h". + +rsawrapr.c is copied from nss/lib/softoken/rsawrapr.c, with +HASH_GetRawHashObject changed to HASH_GetHashObject. It contains the +emsa_pss_verify function for verifying RSA-PSS signatures. diff --git a/crypto/third_party/nss/chromium-nss.h b/crypto/third_party/nss/chromium-nss.h index 5ef28e3..437e6bd 100644 --- a/crypto/third_party/nss/chromium-nss.h +++ b/crypto/third_party/nss/chromium-nss.h @@ -39,11 +39,20 @@ // This file contains some functions we borrowed from NSS. +#include <prtypes.h> +#include <hasht.h> #include <keyhi.h> #include <secmod.h> #include "crypto/crypto_export.h" +extern "C" SECStatus emsa_pss_verify(const unsigned char *mHash, + const unsigned char *em, + unsigned int emLen, + HASH_HashType hashAlg, + HASH_HashType maskHashAlg, + unsigned int sLen); + // Like PK11_ImportEncryptedPrivateKeyInfo, but hardcoded for EC, and returns // the SECKEYPrivateKey. // See https://bugzilla.mozilla.org/show_bug.cgi?id=211546 diff --git a/crypto/third_party/nss/rsawrapr.c b/crypto/third_party/nss/rsawrapr.c new file mode 100644 index 0000000..73e498f --- /dev/null +++ b/crypto/third_party/nss/rsawrapr.c @@ -0,0 +1,160 @@ +/* + * PKCS#1 encoding and decoding functions. + * This file is believed to contain no code licensed from other parties. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "seccomon.h" +#include "secerr.h" +#include "sechash.h" + +/* Needed for RSA-PSS functions */ +static const unsigned char eightZeros[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + +/* + * Mask generation function MGF1 as defined in PKCS #1 v2.1 / RFC 3447. + */ +static SECStatus +MGF1(HASH_HashType hashAlg, unsigned char *mask, unsigned int maskLen, + const unsigned char *mgfSeed, unsigned int mgfSeedLen) +{ + unsigned int digestLen; + PRUint32 counter, rounds; + unsigned char *tempHash, *temp; + const SECHashObject *hash; + void *hashContext; + unsigned char C[4]; + + hash = HASH_GetHashObject(hashAlg); + if (hash == NULL) + return SECFailure; + + hashContext = (*hash->create)(); + rounds = (maskLen + hash->length - 1) / hash->length; + for (counter = 0; counter < rounds; counter++) { + C[0] = (unsigned char)((counter >> 24) & 0xff); + C[1] = (unsigned char)((counter >> 16) & 0xff); + C[2] = (unsigned char)((counter >> 8) & 0xff); + C[3] = (unsigned char)(counter & 0xff); + + /* This could be optimized when the clone functions in + * rawhash.c are implemented. */ + (*hash->begin)(hashContext); + (*hash->update)(hashContext, mgfSeed, mgfSeedLen); + (*hash->update)(hashContext, C, sizeof C); + + tempHash = mask + counter * hash->length; + if (counter != (rounds-1)) { + (*hash->end)(hashContext, tempHash, &digestLen, hash->length); + } else { /* we're in the last round and need to cut the hash */ + temp = (unsigned char *)PORT_Alloc(hash->length); + (*hash->end)(hashContext, temp, &digestLen, hash->length); + PORT_Memcpy(tempHash, temp, maskLen - counter * hash->length); + PORT_Free(temp); + } + } + (*hash->destroy)(hashContext, PR_TRUE); + + return SECSuccess; +} + +/* + * Verify a RSA-PSS signature. + * Described in RFC 3447, section 9.1.2. + * We use mHash instead of M as input. + * emBits from the RFC is just modBits - 1, see section 8.1.2. + * We only support MGF1 as the MGF. + * + * NOTE: this code assumes modBits is a multiple of 8. + */ +SECStatus +emsa_pss_verify(const unsigned char *mHash, + const unsigned char *em, unsigned int emLen, + HASH_HashType hashAlg, HASH_HashType maskHashAlg, + unsigned int sLen) +{ + const SECHashObject *hash; + void *hash_context; + unsigned char *db; + unsigned char *H_; /* H' from the RFC */ + unsigned int i, dbMaskLen; + SECStatus rv; + + hash = HASH_GetHashObject(hashAlg); + dbMaskLen = emLen - hash->length - 1; + + /* Step 3 + 4 + 6 */ + if ((emLen < (hash->length + sLen + 2)) || + (em[emLen - 1] != 0xbc) || + ((em[0] & 0x80) != 0)) { + PORT_SetError(SEC_ERROR_BAD_SIGNATURE); + return SECFailure; + } + + /* Step 7 */ + db = (unsigned char *)PORT_Alloc(dbMaskLen); + if (db == NULL) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + return SECFailure; + } + /* &em[dbMaskLen] points to H, used as mgfSeed */ + MGF1(maskHashAlg, db, dbMaskLen, &em[dbMaskLen], hash->length); + + /* Step 8 */ + for (i = 0; i < dbMaskLen; i++) { + db[i] ^= em[i]; + } + + /* Step 9 */ + db[0] &= 0x7f; + + /* Step 10 */ + for (i = 0; i < (dbMaskLen - sLen - 1); i++) { + if (db[i] != 0) { + PORT_Free(db); + PORT_SetError(SEC_ERROR_BAD_SIGNATURE); + return SECFailure; + } + } + if (db[dbMaskLen - sLen - 1] != 0x01) { + PORT_Free(db); + PORT_SetError(SEC_ERROR_BAD_SIGNATURE); + return SECFailure; + } + + /* Step 12 + 13 */ + H_ = (unsigned char *)PORT_Alloc(hash->length); + if (H_ == NULL) { + PORT_Free(db); + PORT_SetError(SEC_ERROR_NO_MEMORY); + return SECFailure; + } + hash_context = (*hash->create)(); + if (hash_context == NULL) { + PORT_Free(db); + PORT_Free(H_); + PORT_SetError(SEC_ERROR_NO_MEMORY); + return SECFailure; + } + (*hash->begin)(hash_context); + (*hash->update)(hash_context, eightZeros, 8); + (*hash->update)(hash_context, mHash, hash->length); + (*hash->update)(hash_context, &db[dbMaskLen - sLen], sLen); + (*hash->end)(hash_context, H_, &i, hash->length); + (*hash->destroy)(hash_context, PR_TRUE); + + PORT_Free(db); + + /* Step 14 */ + if (PORT_Memcmp(H_, &em[dbMaskLen], hash->length) != 0) { + PORT_SetError(SEC_ERROR_BAD_SIGNATURE); + rv = SECFailure; + } else { + rv = SECSuccess; + } + + PORT_Free(H_); + return rv; +} |