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..d71c34108607476d1160b8c3125705ae416c5a4f 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()); |
+ blink::WebCryptoAlgorithm inner_hash = |
+ blink::WebCryptoAlgorithm::createNull(); |
eroman
2013/11/20 23:57:44
[optional] Rather than assigning inside each case,
padolph
2013/11/21 01:20:13
Done.
|
+ switch (algorithm.id()) { |
+ case blink::WebCryptoAlgorithmIdHmac: |
eroman
2013/11/20 23:57:44
Doesn't look like the callers care, however note t
padolph
2013/11/21 01:20:13
Done.
|
+ if (algorithm.hmacParams()) |
+ inner_hash = algorithm.hmacParams()->hash(); |
+ break; |
+ case blink::WebCryptoAlgorithmIdRsaOaep: |
+ if (algorithm.rsaOaepParams()) |
+ inner_hash = algorithm.rsaOaepParams()->hash(); |
+ break; |
+ case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: |
+ if (algorithm.rsaSsaParams()) |
+ inner_hash = algorithm.rsaSsaParams()->hash(); |
+ break; |
+ default: |
+ break; |
+ } |
+ return inner_hash; |
+} |
+ |
} // 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)) |
+ 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, |
eroman
2013/11/20 23:57:44
indentation: Add 4 more spaces.
padolph
2013/11/21 01:20:13
fixed
|
+ &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; |
} |