Chromium Code Reviews| Index: content/renderer/webcrypto/webcrypto_impl_nss.cc |
| diff --git a/content/renderer/webcrypto/webcrypto_impl_nss.cc b/content/renderer/webcrypto/webcrypto_impl_nss.cc |
| index 1590a09961558af8bc8d14fd7f28b86ea432e7aa..fa4e5c70384e23afb4056e3d3fbad8ae612535fa 100644 |
| --- a/content/renderer/webcrypto/webcrypto_impl_nss.cc |
| +++ b/content/renderer/webcrypto/webcrypto_impl_nss.cc |
| @@ -238,6 +238,31 @@ bool BigIntegerToLong(const uint8* data, |
| return true; |
| } |
| +// TODO(padolph): Move to webcrypto_util |
| +blink::WebCryptoAlgorithm GetInnerHashAlgorithm( |
| + const blink::WebCryptoAlgorithm& algorithm) { |
| + DCHECK(!algorithm.isNull()); |
| + switch (algorithm.id()) { |
| + case blink::WebCryptoAlgorithmIdHmac: |
| + if (algorithm.hmacParams()) |
| + return algorithm.hmacParams()->hash(); |
| + else if (algorithm.hmacKeyParams()) |
| + return algorithm.hmacKeyParams()->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(); |
| +} |
| + |
| } // namespace |
| void WebCryptoImpl::Init() { |
| @@ -557,6 +582,12 @@ bool WebCryptoImpl::SignInternal( |
| const unsigned char* data, |
| unsigned data_size, |
| 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; |
| switch (algorithm.id()) { |
| @@ -570,7 +601,6 @@ bool WebCryptoImpl::SignInternal( |
| DCHECK_EQ(PK11_GetMechanism(sym_key->key()), |
| WebCryptoAlgorithmToHMACMechanism(params->hash())); |
| - DCHECK_NE(0, key.usages() & blink::WebCryptoKeyUsageSign); |
| SECItem param_item = { siBuffer, NULL, 0 }; |
| SECItem data_item = { |
| @@ -608,6 +638,46 @@ bool WebCryptoImpl::SignInternal( |
| break; |
| } |
| + case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: { |
| + // Only private key signing is supported. |
| + if (key.type() != blink::WebCryptoKeyTypePrivate) |
| + return false; |
| + |
| + const blink::WebCryptoAlgorithm hash_algorithm = |
| + GetInnerHashAlgorithm(algorithm); |
| + if (hash_algorithm.isNull()) // TODO(padolph): DCHECK instead? |
| + return false; |
| + blink::WebArrayBuffer digest; |
| + if (!DigestInternal(hash_algorithm, data, data_size, &digest)) |
|
Ryan Sleevi
2013/11/21 01:45:57
I'm not sure this is the right approach.
Why not
padolph
2013/11/28 02:29:09
Done. Rewrote to use SEC_SignData (a sequence of S
|
| + return false; |
| + const SECItem digest_item = { |
| + siBuffer, |
| + reinterpret_cast<unsigned char*>(digest.data()), |
| + digest.byteLength() |
| + }; |
| + |
| + PrivateKeyHandle* const private_key = |
| + reinterpret_cast<PrivateKeyHandle*>(key.handle()); |
| + DCHECK(private_key); |
| + DCHECK(private_key->key()); |
| + const int signature_length = PK11_SignatureLen(private_key->key()); |
| + if (signature_length <= 0) |
| + return false; |
| + result = blink::WebArrayBuffer::create(signature_length, 1); |
| + SECItem signature_item = { |
| + siBuffer, |
| + reinterpret_cast<unsigned char*>(result.data()), |
| + signature_length |
| + }; |
| + if (PK11_Sign(private_key->key(), |
| + &signature_item, |
| + &digest_item) != SECSuccess ) { |
| + return false; |
| + } |
| + DCHECK_EQ(result.byteLength(), signature_item.len); |
| + |
| + break; |
| + } |
| default: |
| return false; |
| } |
| @@ -641,6 +711,40 @@ bool WebCryptoImpl::VerifySignatureInternal( |
| break; |
| } |
| + case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: { |
| + // Only public key signature verification is supported. |
| + if (key.type() != blink::WebCryptoKeyTypePublic) |
| + return false; |
| + |
| + const blink::WebCryptoAlgorithm hash_algorithm = |
| + GetInnerHashAlgorithm(algorithm); |
| + if (hash_algorithm.isNull()) // TODO(padolph): DCHECK instead? |
| + return false; |
| + blink::WebArrayBuffer digest; |
| + if (!DigestInternal(hash_algorithm, data, data_size, &digest)) |
| + return false; |
| + const SECItem digest_item = { |
| + siBuffer, |
| + reinterpret_cast<unsigned char*>(digest.data()), |
| + digest.byteLength() |
| + }; |
| + |
| + 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 |
| + }; |
| + *signature_match = PK11_Verify(public_key->key(), |
| + &signature_item, |
| + &digest_item, |
| + NULL) == SECSuccess; |
| + |
| + break; |
| + } |
| default: |
| return false; |
| } |