summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authordavidben <davidben@chromium.org>2014-11-10 16:13:13 -0800
committerCommit bot <commit-bot@chromium.org>2014-11-11 00:13:48 +0000
commit40af916dfb14ca12890e3a7cf8b50d8e62c69695 (patch)
tree5b870f1349f77e8ebac518c57e04b114eab35d81 /crypto
parent991bb31434938a71af3cbb3e080cfea6a0240009 (diff)
downloadchromium_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.cc3
-rw-r--r--crypto/rsa_private_key_openssl.cc16
-rw-r--r--crypto/signature_verifier_openssl.cc13
-rw-r--r--crypto/signature_verifier_unittest.cc20
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);
}
//////////////////////////////////////////////////////////////////////