Index: content/renderer/webcrypto_impl_nss.cc |
diff --git a/content/renderer/webcrypto_impl_nss.cc b/content/renderer/webcrypto_impl_nss.cc |
index 61aa3a69dcb9ef8816003722a1d042ec0247b373..f9116a0d604cbe9d82e1c253530191eb301773b9 100644 |
--- a/content/renderer/webcrypto_impl_nss.cc |
+++ b/content/renderer/webcrypto_impl_nss.cc |
@@ -4,15 +4,40 @@ |
#include "content/renderer/webcrypto_impl.h" |
-#include <sechash.h> |
+#include <nss/sechash.h> |
+#include <nss/pk11pub.h> |
#include "base/logging.h" |
#include "crypto/nss_util.h" |
+#include "crypto/scoped_nss_types.h" |
#include "third_party/WebKit/public/platform/WebArrayBuffer.h" |
#include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" |
+#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" |
namespace content { |
+class WebCryptoSymKeyHandle : public WebKit::WebCryptoKeyHandle { |
+ public: |
+ void set_mechanism(CK_MECHANISM_TYPE mechanism) { |
+ mechanism_ = mechanism; |
eroman
2013/09/05 01:57:51
What is the initial value? I would rather this be
Bryan Eyler
2013/09/06 01:27:51
Yeah, initial value appears to be not clear. Move
|
+ } |
+ void set_slot(PK11SlotInfo* slot) { |
eroman
2013/09/05 01:57:51
I don't see any current need to specify a slot oth
Bryan Eyler
2013/09/06 01:27:51
Sure, makes sense.
|
+ slot_.reset(slot); |
+ } |
+ void set_key(PK11SymKey* key) { |
eroman
2013/09/05 01:57:51
This effectively passes ownership of the key. I th
Bryan Eyler
2013/09/06 01:27:51
It gets complicated as the slot is needed for crea
|
+ key_.reset(key); |
+ } |
+ |
+ const CK_MECHANISM_TYPE mechanism() const { return mechanism_; } |
+ PK11SlotInfo* slot() { return slot_.get(); } |
+ const PK11SymKey* key() const { return key_.get(); } |
eroman
2013/09/06 23:03:16
Don't make the pointer const. Then there is no nee
Bryan Eyler
2013/09/09 22:32:10
Done.
|
+ |
+ private: |
+ CK_MECHANISM_TYPE mechanism_; |
+ crypto::ScopedPK11Slot slot_; |
+ crypto::ScopedPK11SymKey key_; |
+}; |
+ |
bool WebCryptoImpl::digestInternal( |
const WebKit::WebCryptoAlgorithm& algorithm, |
const unsigned char* data, |
@@ -67,4 +92,162 @@ bool WebCryptoImpl::digestInternal( |
return result_length == hash_result_length; |
} |
+bool WebCryptoImpl::importKeyInternal( |
+ WebKit::WebCryptoKeyFormat format, |
+ const unsigned char* key_data, |
+ size_t key_data_size, |
+ const WebKit::WebCryptoAlgorithm& algorithm, |
+ bool extractable, |
+ WebKit::WebCryptoKeyUsageMask usage_mask, |
+ WebKit::WebCryptoKeyHandle** handle) { |
+ // TODO(bryaneyler): Need to split handling for symmetric and asymmetric keys. |
+ // Currently only supporting symmetric. |
+ scoped_ptr<WebCryptoSymKeyHandle> sym_key(new WebCryptoSymKeyHandle); |
+ |
+ switch(algorithm.id()) { |
+ case WebKit::WebCryptoAlgorithmIdHmac: { |
+ WebKit::WebCryptoHmacKeyParams* params = algorithm.hmacKeyParams(); |
eroman
2013/09/05 01:57:51
Ah! I should have defined these as "const" pointer
Bryan Eyler
2013/09/06 01:27:51
Done.
|
+ if (!params) { |
+ return false; |
+ } |
+ |
+ switch (params->hash().id()) { |
eroman
2013/09/05 01:57:51
You will have to coordinate with Elly's changelist
Bryan Eyler
2013/09/06 01:27:51
Yeah, I realized there would be a bit of overlap/m
|
+ case WebKit::WebCryptoAlgorithmIdSha1: |
+ sym_key->set_mechanism(CKM_SHA_1_HMAC); |
+ break; |
+ case WebKit::WebCryptoAlgorithmIdSha256: |
+ sym_key->set_mechanism(CKM_SHA256_HMAC); |
+ break; |
+ default: |
+ return false; |
+ } |
+ break; |
+ } |
+ default: |
+ return false; |
+ } |
+ |
+ sym_key->set_slot(PK11_GetInternalSlot()); |
+ if (!sym_key->slot()) { |
+ NOTREACHED(); |
+ return false; |
+ } |
+ |
+ CK_FLAGS flags = |
+ ((usage_mask & WebKit::WebCryptoKeyUsageEncrypt) ? CKF_ENCRYPT : 0) | |
eroman
2013/09/05 01:57:51
sleevi: My understanding is the NSS usage flags ar
Bryan Eyler
2013/09/06 01:27:51
I tried not setting the appropriate flags and it f
Ryan Sleevi
2013/09/06 19:39:02
Not for softoken (effectively), but definitely for
|
+ ((usage_mask & WebKit::WebCryptoKeyUsageDecrypt) ? CKF_DECRYPT : 0) | |
+ ((usage_mask & WebKit::WebCryptoKeyUsageSign) ? CKF_SIGN : 0) | |
+ ((usage_mask & WebKit::WebCryptoKeyUsageVerify) ? CKF_VERIFY : 0) | |
+ ((usage_mask & WebKit::WebCryptoKeyUsageDeriveKey) ? CKF_DERIVE : 0) | |
+ ((usage_mask & WebKit::WebCryptoKeyUsageWrapKey) ? CKF_WRAP : 0) | |
+ ((usage_mask & WebKit::WebCryptoKeyUsageUnwrapKey) ? CKF_UNWRAP : 0); |
+ |
+ unsigned char* raw_key_data = NULL; |
+ size_t raw_key_data_size = 0; |
+ |
+ switch (format) { |
+ case WebKit::WebCryptoKeyFormatRaw: |
+ raw_key_data_size = key_data_size; |
+ raw_key_data = new unsigned char[raw_key_data_size]; |
+ memcpy(raw_key_data, key_data, raw_key_data_size); |
eroman
2013/09/05 01:57:51
This is unnecessary. You can just pass a SECItem w
Bryan Eyler
2013/09/06 01:27:51
Yes, true. Done.
Ryan Sleevi
2013/09/06 19:39:02
Right
|
+ break; |
+ // TODO(bryaneyler): Handle additional formats. |
+ default: |
+ return false; |
+ } |
+ |
+ SECItem key_item = { |
+ siBuffer, |
+ raw_key_data, |
+ raw_key_data_size |
+ }; |
+ |
+ sym_key->set_key( |
+ PK11_ImportSymKeyWithFlags(sym_key->slot(), |
+ sym_key->mechanism(), |
+ PK11_OriginUnwrap, |
+ CKA_FLAGS_ONLY, |
+ &key_item, |
+ flags, |
+ false, |
+ NULL)); |
+ if (!sym_key->key()) { |
+ NOTREACHED(); |
+ delete[] raw_key_data; |
eroman
2013/09/05 01:57:51
See my comment above. We don't want to duplicate t
Bryan Eyler
2013/09/06 01:27:51
Done.
|
+ return false; |
+ } |
+ |
+ *handle = sym_key.release(); |
+ |
+ delete[] raw_key_data; |
eroman
2013/09/05 01:57:51
See above. We try hard in Chromium not to do manua
Bryan Eyler
2013/09/06 01:27:51
Done.
|
+ return true; |
+} |
+ |
+bool WebCryptoImpl::signInternal( |
+ const WebKit::WebCryptoAlgorithm& algorithm, |
+ const WebKit::WebCryptoKeyHandle* key, |
+ const unsigned char* data, |
+ size_t data_size, |
+ WebKit::WebArrayBuffer* buffer) { |
+ WebKit::WebArrayBuffer result; |
+ |
+ switch (algorithm.id()) { |
+ case WebKit::WebCryptoAlgorithmIdHmac: { |
+ WebKit::WebCryptoHmacParams* params = algorithm.hmacParams(); |
eroman
2013/09/05 01:57:51
const-ify please. I will change the API to disallo
Bryan Eyler
2013/09/06 01:27:51
Done.
|
+ if (!params) { |
+ return false; |
+ } |
+ |
+ const WebCryptoSymKeyHandle* sym_key = |
+ reinterpret_cast<const WebCryptoSymKeyHandle*>(key); |
+ |
+ size_t digest_length = 0; |
+ switch (params->hash().id()) { |
+ case WebKit::WebCryptoAlgorithmIdSha1: |
+ digest_length = 20; |
eroman
2013/09/05 01:57:51
Rather than hardcode this, can you use a function
Bryan Eyler
2013/09/06 01:27:51
Done. In order to do the DCHECK, I also needed to
Ryan Sleevi
2013/09/06 19:39:02
+1 to your recommended way.
|
+ DCHECK_EQ(sym_key->mechanism(), |
+ static_cast<CK_MECHANISM_TYPE>(CKM_SHA_1_HMAC)); |
+ break; |
+ case WebKit::WebCryptoAlgorithmIdSha256: |
+ digest_length = 32; |
+ DCHECK_EQ(sym_key->mechanism(), |
+ static_cast<CK_MECHANISM_TYPE>(CKM_SHA256_HMAC)); |
+ break; |
+ default: |
+ return false; |
+ } |
+ |
+ result = WebKit::WebArrayBuffer::create(digest_length, 1); |
+ |
+ SECItem param_item = { siBuffer, NULL, 0 }; |
+ SECItem data_item = { |
+ siBuffer, |
+ const_cast<unsigned char*>(data), |
+ data_size |
+ }; |
+ SECItem signature_item = { |
+ siBuffer, |
+ reinterpret_cast<unsigned char*>(result.data()), |
+ digest_length |
+ }; |
+ |
+ if (PK11_SignWithSymKey(const_cast<PK11SymKey*>(sym_key->key()), |
eroman
2013/09/05 01:57:51
Please make key() return a non-const PK11SymKey ra
Bryan Eyler
2013/09/06 01:27:51
I need to const_cast at some point because the key
eroman
2013/09/06 23:03:16
Yep, make sym_key non-const, and then change the m
Bryan Eyler
2013/09/09 22:32:10
Done.
|
+ sym_key->mechanism(), |
+ ¶m_item, |
+ &signature_item, |
+ &data_item) != SECSuccess) { |
+ NOTREACHED(); |
+ return false; |
+ } |
+ |
+ break; |
+ } |
+ default: |
+ return false; |
+ } |
+ |
+ *buffer = result; |
+ return true; |
+} |
+ |
} // namespace content |