Commit 056b5905 authored by padolph@netflix.com's avatar padolph@netflix.com

[webcrypto] Add RSASSA-PKCS1-v1_5 sign and verify for NSS.

BUG=245025
TEST=content_unittests --gtest_filter="WebCryptoImpl*"

Review URL: https://codereview.chromium.org/68303009

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@245430 0039d316-1c4b-4281-b951-d872f2087c98
parent 8c79522a
...@@ -437,6 +437,8 @@ bool ImportKeyInternalRaw( ...@@ -437,6 +437,8 @@ bool ImportKeyInternalRaw(
return false; return false;
} }
// TODO(bryaneyler): Need to split handling for symmetric and asymmetric keys.
// Currently only supporting symmetric.
CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM; CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM;
// Flags are verified at the Blink layer; here the flags are set to all // Flags are verified at the Blink layer; here the flags are set to all
// possible operations for this key type. // possible operations for this key type.
...@@ -1058,6 +1060,12 @@ bool WebCryptoImpl::SignInternal( ...@@ -1058,6 +1060,12 @@ bool WebCryptoImpl::SignInternal(
const unsigned char* data, const unsigned char* data,
unsigned data_size, unsigned data_size,
blink::WebArrayBuffer* buffer) { blink::WebArrayBuffer* buffer) {
// Note: It is not an error to sign empty data.
DCHECK(buffer);
DCHECK_NE(0, key.usages() & blink::WebCryptoKeyUsageSign);
blink::WebArrayBuffer result; blink::WebArrayBuffer result;
switch (algorithm.id()) { switch (algorithm.id()) {
...@@ -1071,7 +1079,6 @@ bool WebCryptoImpl::SignInternal( ...@@ -1071,7 +1079,6 @@ bool WebCryptoImpl::SignInternal(
DCHECK_EQ(PK11_GetMechanism(sym_key->key()), DCHECK_EQ(PK11_GetMechanism(sym_key->key()),
WebCryptoHashToHMACMechanism(params->hash())); WebCryptoHashToHMACMechanism(params->hash()));
DCHECK_NE(0, key.usages() & blink::WebCryptoKeyUsageSign);
SECItem param_item = { siBuffer, NULL, 0 }; SECItem param_item = { siBuffer, NULL, 0 };
SECItem data_item = { SECItem data_item = {
...@@ -1109,6 +1116,53 @@ bool WebCryptoImpl::SignInternal( ...@@ -1109,6 +1116,53 @@ bool WebCryptoImpl::SignInternal(
break; break;
} }
case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: {
if (key.type() != blink::WebCryptoKeyTypePrivate ||
webcrypto::GetInnerHashAlgorithm(algorithm).isNull())
return false;
PrivateKeyHandle* const private_key =
reinterpret_cast<PrivateKeyHandle*>(key.handle());
DCHECK(private_key);
DCHECK(private_key->key());
// Pick the NSS signing algorithm by combining RSA-SSA (RSA PKCS1) and the
// inner hash of the input Web Crypto algorithm.
SECOidTag sign_alg_tag;
switch (webcrypto::GetInnerHashAlgorithm(algorithm).id()) {
case blink::WebCryptoAlgorithmIdSha1:
sign_alg_tag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
break;
case blink::WebCryptoAlgorithmIdSha224:
sign_alg_tag = SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION;
break;
case blink::WebCryptoAlgorithmIdSha256:
sign_alg_tag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
break;
case blink::WebCryptoAlgorithmIdSha384:
sign_alg_tag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;
break;
case blink::WebCryptoAlgorithmIdSha512:
sign_alg_tag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
break;
default:
return false;
}
crypto::ScopedSECItem signature_item(SECITEM_AllocItem(NULL, NULL, 0));
if (SEC_SignData(signature_item.get(),
data,
data_size,
private_key->key(),
sign_alg_tag) != SECSuccess) {
return false;
}
result = webcrypto::CreateArrayBuffer(signature_item->data,
signature_item->len);
break;
}
default: default:
return false; return false;
} }
...@@ -1125,6 +1179,11 @@ bool WebCryptoImpl::VerifySignatureInternal( ...@@ -1125,6 +1179,11 @@ bool WebCryptoImpl::VerifySignatureInternal(
const unsigned char* data, const unsigned char* data,
unsigned data_size, unsigned data_size,
bool* signature_match) { bool* signature_match) {
if (!signature_size)
return false;
DCHECK(signature);
switch (algorithm.id()) { switch (algorithm.id()) {
case blink::WebCryptoAlgorithmIdHmac: { case blink::WebCryptoAlgorithmIdHmac: {
blink::WebArrayBuffer result; blink::WebArrayBuffer result;
...@@ -1142,6 +1201,54 @@ bool WebCryptoImpl::VerifySignatureInternal( ...@@ -1142,6 +1201,54 @@ bool WebCryptoImpl::VerifySignatureInternal(
break; break;
} }
case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: {
if (key.type() != blink::WebCryptoKeyTypePublic)
return false;
PublicKeyHandle* const public_key =
reinterpret_cast<PublicKeyHandle*>(key.handle());
DCHECK(public_key);
DCHECK(public_key->key());
const SECItem signature_item = {
siBuffer,
const_cast<unsigned char*>(signature),
signature_size
};
SECOidTag hash_alg_tag;
switch (webcrypto::GetInnerHashAlgorithm(algorithm).id()) {
case blink::WebCryptoAlgorithmIdSha1:
hash_alg_tag = SEC_OID_SHA1;
break;
case blink::WebCryptoAlgorithmIdSha224:
hash_alg_tag = SEC_OID_SHA224;
break;
case blink::WebCryptoAlgorithmIdSha256:
hash_alg_tag = SEC_OID_SHA256;
break;
case blink::WebCryptoAlgorithmIdSha384:
hash_alg_tag = SEC_OID_SHA384;
break;
case blink::WebCryptoAlgorithmIdSha512:
hash_alg_tag = SEC_OID_SHA512;
break;
default:
return false;
}
*signature_match =
SECSuccess == VFY_VerifyDataDirect(data,
data_size,
public_key->key(),
&signature_item,
SEC_OID_PKCS1_RSA_ENCRYPTION,
hash_alg_tag,
NULL,
NULL);
break;
}
default: default:
return false; return false;
} }
......
...@@ -15,14 +15,6 @@ namespace webcrypto { ...@@ -15,14 +15,6 @@ namespace webcrypto {
namespace { namespace {
bool IsHashAlgorithm(blink::WebCryptoAlgorithmId alg_id) {
return alg_id == blink::WebCryptoAlgorithmIdSha1 ||
alg_id == blink::WebCryptoAlgorithmIdSha224 ||
alg_id == blink::WebCryptoAlgorithmIdSha256 ||
alg_id == blink::WebCryptoAlgorithmIdSha384 ||
alg_id == blink::WebCryptoAlgorithmIdSha512;
}
} // namespace } // namespace
const uint8* Uint8VectorStart(const std::vector<uint8>& data) { const uint8* Uint8VectorStart(const std::vector<uint8>& data) {
...@@ -64,16 +56,35 @@ bool Base64DecodeUrlSafe(const std::string& input, std::string* output) { ...@@ -64,16 +56,35 @@ bool Base64DecodeUrlSafe(const std::string& input, std::string* output) {
return base::Base64Decode(base64EncodedText, output); return base::Base64Decode(base64EncodedText, output);
} }
bool IsHashAlgorithm(blink::WebCryptoAlgorithmId alg_id) {
return alg_id == blink::WebCryptoAlgorithmIdSha1 ||
alg_id == blink::WebCryptoAlgorithmIdSha224 ||
alg_id == blink::WebCryptoAlgorithmIdSha256 ||
alg_id == blink::WebCryptoAlgorithmIdSha384 ||
alg_id == blink::WebCryptoAlgorithmIdSha512;
}
blink::WebCryptoAlgorithm GetInnerHashAlgorithm( blink::WebCryptoAlgorithm GetInnerHashAlgorithm(
const blink::WebCryptoAlgorithm& algorithm) { const blink::WebCryptoAlgorithm& algorithm) {
if (algorithm.hmacParams()) DCHECK(!algorithm.isNull());
return algorithm.hmacParams()->hash(); switch (algorithm.id()) {
if (algorithm.hmacKeyParams()) case blink::WebCryptoAlgorithmIdHmac:
return algorithm.hmacKeyParams()->hash(); if (algorithm.hmacParams())
if (algorithm.rsaSsaParams()) return algorithm.hmacParams()->hash();
return algorithm.rsaSsaParams()->hash(); else if (algorithm.hmacKeyParams())
if (algorithm.rsaOaepParams()) return algorithm.hmacKeyParams()->hash();
return algorithm.rsaOaepParams()->hash(); break;
case blink::WebCryptoAlgorithmIdRsaOaep:
if (algorithm.rsaOaepParams())
return algorithm.rsaOaepParams()->hash();
break;
case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5:
if (algorithm.rsaSsaParams())
return algorithm.rsaSsaParams()->hash();
break;
default:
break;
}
return blink::WebCryptoAlgorithm::createNull(); return blink::WebCryptoAlgorithm::createNull();
} }
......
...@@ -35,6 +35,8 @@ blink::WebArrayBuffer CreateArrayBuffer(const uint8* data, unsigned data_size); ...@@ -35,6 +35,8 @@ blink::WebArrayBuffer CreateArrayBuffer(const uint8* data, unsigned data_size);
// In Web Crypto, this type of encoding is only used inside JWK. // In Web Crypto, this type of encoding is only used inside JWK.
bool Base64DecodeUrlSafe(const std::string& input, std::string* output); bool Base64DecodeUrlSafe(const std::string& input, std::string* output);
CONTENT_EXPORT bool IsHashAlgorithm(blink::WebCryptoAlgorithmId alg_id);
// Returns the "hash" param for an algorithm if it exists, otherwise returns // Returns the "hash" param for an algorithm if it exists, otherwise returns
// a null algorithm. // a null algorithm.
blink::WebCryptoAlgorithm GetInnerHashAlgorithm( blink::WebCryptoAlgorithm GetInnerHashAlgorithm(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment