diff options
author | davidben <davidben@chromium.org> | 2014-11-10 16:13:13 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-11-11 00:13:48 +0000 |
commit | 40af916dfb14ca12890e3a7cf8b50d8e62c69695 (patch) | |
tree | 5b870f1349f77e8ebac518c57e04b114eab35d81 /crypto | |
parent | 991bb31434938a71af3cbb3e080cfea6a0240009 (diff) | |
download | chromium_src-40af916dfb14ca12890e3a7cf8b50d8e62c69695.zip chromium_src-40af916dfb14ca12890e3a7cf8b50d8e62c69695.tar.gz chromium_src-40af916dfb14ca12890e3a7cf8b50d8e62c69695.tar.bz2 |
Check trailing data when parsing ASN.1.
Properly check that the entire buffer was consumed. d2i_* may process only a
prefix of its input. In addition, don't bother using a memory BIO when the
buffer can be parsed directly.
This aligns the NSS and OpenSSL port's behavior in most places:
SEC_QuickDERDecodeItem fails with SEC_ERROR_EXTRA_INPUT if there is excess data.
Add tests. Both for testing and to verify this is the NSS port's behavior.
For a PKCS #8 PrivateKeyInfo, NSS will silently accept trailing data. Fix
WebCrypto in NSS to align with the spec. RSAPrivateKey is left for a follow-up. (This includes an NSS roll to pick up a symbol export.)
BUG=430200
Review URL: https://codereview.chromium.org/685063007
Cr-Commit-Position: refs/heads/master@{#303546}
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/rsa_private_key_nss.cc | 3 | ||||
-rw-r--r-- | crypto/rsa_private_key_openssl.cc | 16 | ||||
-rw-r--r-- | crypto/signature_verifier_openssl.cc | 13 | ||||
-rw-r--r-- | crypto/signature_verifier_unittest.cc | 20 |
4 files changed, 36 insertions, 16 deletions
diff --git a/crypto/rsa_private_key_nss.cc b/crypto/rsa_private_key_nss.cc index 078544d..0065875 100644 --- a/crypto/rsa_private_key_nss.cc +++ b/crypto/rsa_private_key_nss.cc @@ -285,6 +285,9 @@ RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfoWithParams( // and signature generation. const unsigned int key_usage = KU_KEY_ENCIPHERMENT | KU_DATA_ENCIPHERMENT | KU_DIGITAL_SIGNATURE; + // TODO(davidben): PK11_ImportDERPrivateKeyInfoAndReturnKey calls NSS's + // SEC_ASN1DecodeItem which does not enforce that there is no trailing + // data. SECStatus rv = PK11_ImportDERPrivateKeyInfoAndReturnKey( slot, &der_private_key_info, NULL, NULL, permanent, sensitive, key_usage, &result->key_, NULL); diff --git a/crypto/rsa_private_key_openssl.cc b/crypto/rsa_private_key_openssl.cc index 053c4a2..0df1730 100644 --- a/crypto/rsa_private_key_openssl.cc +++ b/crypto/rsa_private_key_openssl.cc @@ -19,6 +19,9 @@ namespace crypto { namespace { +typedef ScopedOpenSSL<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free>::Type + ScopedPKCS8_PRIV_KEY_INFO; + // Function pointer definition, for injecting the required key export function // into ExportKey, below. The supplied function should export EVP_PKEY into // the supplied BIO, returning 1 on success or 0 on failure. @@ -76,17 +79,16 @@ RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo( return NULL; OpenSSLErrStackTracer err_tracer(FROM_HERE); - // BIO_new_mem_buf is not const aware, but it does not modify the buffer. - char* data = reinterpret_cast<char*>(const_cast<uint8*>(&input[0])); - ScopedBIO bio(BIO_new_mem_buf(data, input.size())); - if (!bio.get()) - return NULL; // Importing is a little more involved than exporting, as we must first // PKCS#8 decode the input, and then import the EVP_PKEY from Private Key // Info structure returned. - ScopedOpenSSL<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free>::Type p8inf( - d2i_PKCS8_PRIV_KEY_INFO_bio(bio.get(), NULL)); + // + // TODO(davidben): This should check that |ptr| advanced to the end of |input| + // to ensure there is no trailing data. + const uint8_t* ptr = &input[0]; + ScopedPKCS8_PRIV_KEY_INFO p8inf( + d2i_PKCS8_PRIV_KEY_INFO(nullptr, &ptr, input.size())); if (!p8inf.get()) return NULL; diff --git a/crypto/signature_verifier_openssl.cc b/crypto/signature_verifier_openssl.cc index a855120..53637eb 100644 --- a/crypto/signature_verifier_openssl.cc +++ b/crypto/signature_verifier_openssl.cc @@ -141,19 +141,14 @@ bool SignatureVerifier::CommonInit(const EVP_MD* digest, 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)); - ScopedBIO bio(BIO_new_mem_buf(data, public_key_info_len)); - if (!bio.get()) - return false; - - ScopedEVP_PKEY public_key(d2i_PUBKEY_bio(bio.get(), NULL)); - if (!public_key.get()) + const uint8_t* ptr = public_key_info; + ScopedEVP_PKEY public_key(d2i_PUBKEY(nullptr, &ptr, public_key_info_len)); + if (!public_key.get() || ptr != public_key_info + public_key_info_len) 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()); + digest, nullptr, public_key.get()); return rv == 1; } diff --git a/crypto/signature_verifier_unittest.cc b/crypto/signature_verifier_unittest.cc index f6c42e0..b521bd7 100644 --- a/crypto/signature_verifier_unittest.cc +++ b/crypto/signature_verifier_unittest.cc @@ -258,6 +258,26 @@ TEST(SignatureVerifierTest, BasicTest) { ok = verifier.VerifyFinal(); EXPECT_FALSE(ok); } + + // Test 5: import an invalid key. + uint8_t bad_public_key_info[sizeof(public_key_info)]; + memcpy(bad_public_key_info, public_key_info, sizeof(public_key_info)); + bad_public_key_info[0] += 1; // Corrupt part of the SPKI syntax. + ok = verifier.VerifyInit(signature_algorithm, + sizeof(signature_algorithm), + signature, sizeof(signature), + bad_public_key_info, sizeof(bad_public_key_info)); + EXPECT_FALSE(ok); + + // Test 6: import a key with extra data. + uint8_t long_public_key_info[sizeof(public_key_info) + 5]; + memset(long_public_key_info, 0, sizeof(long_public_key_info)); + memcpy(long_public_key_info, public_key_info, sizeof(public_key_info)); + ok = verifier.VerifyInit(signature_algorithm, + sizeof(signature_algorithm), + signature, sizeof(signature), + long_public_key_info, sizeof(long_public_key_info)); + EXPECT_FALSE(ok); } ////////////////////////////////////////////////////////////////////// |