| Index: content/renderer/webcrypto/platform_crypto_nss.cc
|
| diff --git a/content/renderer/webcrypto/webcrypto_impl_nss.cc b/content/renderer/webcrypto/platform_crypto_nss.cc
|
| similarity index 59%
|
| rename from content/renderer/webcrypto/webcrypto_impl_nss.cc
|
| rename to content/renderer/webcrypto/platform_crypto_nss.cc
|
| index e70aab82e2a10ed7a681911494a97be3cca29480..344a83ef8a867daae78ff40e1aa7aa4057e02cde 100644
|
| --- a/content/renderer/webcrypto/webcrypto_impl_nss.cc
|
| +++ b/content/renderer/webcrypto/platform_crypto_nss.cc
|
| @@ -2,7 +2,7 @@
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| -#include "content/renderer/webcrypto/webcrypto_impl.h"
|
| +#include "content/renderer/webcrypto/platform_crypto.h"
|
|
|
| #include <cryptohi.h>
|
| #include <pk11pub.h>
|
| @@ -12,10 +12,10 @@
|
|
|
| #include "base/lazy_instance.h"
|
| #include "base/logging.h"
|
| +#include "content/renderer/webcrypto/crypto_data.h"
|
| #include "content/renderer/webcrypto/webcrypto_util.h"
|
| #include "crypto/nss_util.h"
|
| #include "crypto/scoped_nss_types.h"
|
| -#include "crypto/secure_util.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"
|
| @@ -111,52 +111,89 @@ base::LazyInstance<AesGcmSupport>::Leaky g_aes_gcm_support =
|
| LAZY_INSTANCE_INITIALIZER;
|
|
|
| namespace content {
|
| +namespace webcrypto {
|
|
|
| -using webcrypto::Status;
|
| -
|
| -namespace {
|
| +class PlatformKey : public blink::WebCryptoKeyHandle {
|
| + public:
|
| + virtual PlatformSymKey* AsSymKey() { return NULL; }
|
| + virtual PlatformPublicKey* AsPublicKey() { return NULL; }
|
| + virtual PlatformPrivateKey* AsPrivateKey() { return NULL; }
|
| +};
|
|
|
| -class SymKeyHandle : public blink::WebCryptoKeyHandle {
|
| +class PlatformSymKey : public PlatformKey {
|
| public:
|
| - explicit SymKeyHandle(crypto::ScopedPK11SymKey key) : key_(key.Pass()) {}
|
| + explicit PlatformSymKey(crypto::ScopedPK11SymKey key) : key_(key.Pass()) {}
|
|
|
| PK11SymKey* key() { return key_.get(); }
|
|
|
| + virtual PlatformSymKey* AsSymKey() OVERRIDE { return this; }
|
| +
|
| private:
|
| crypto::ScopedPK11SymKey key_;
|
|
|
| - DISALLOW_COPY_AND_ASSIGN(SymKeyHandle);
|
| + DISALLOW_COPY_AND_ASSIGN(PlatformSymKey);
|
| };
|
|
|
| -class PublicKeyHandle : public blink::WebCryptoKeyHandle {
|
| +class PlatformPublicKey : public PlatformKey {
|
| public:
|
| - explicit PublicKeyHandle(crypto::ScopedSECKEYPublicKey key)
|
| + explicit PlatformPublicKey(crypto::ScopedSECKEYPublicKey key)
|
| : key_(key.Pass()) {}
|
|
|
| SECKEYPublicKey* key() { return key_.get(); }
|
|
|
| + virtual PlatformPublicKey* AsPublicKey() OVERRIDE { return this; }
|
| +
|
| private:
|
| crypto::ScopedSECKEYPublicKey key_;
|
|
|
| - DISALLOW_COPY_AND_ASSIGN(PublicKeyHandle);
|
| + DISALLOW_COPY_AND_ASSIGN(PlatformPublicKey);
|
| };
|
|
|
| -class PrivateKeyHandle : public blink::WebCryptoKeyHandle {
|
| +class PlatformPrivateKey : public PlatformKey {
|
| public:
|
| - explicit PrivateKeyHandle(crypto::ScopedSECKEYPrivateKey key)
|
| + explicit PlatformPrivateKey(crypto::ScopedSECKEYPrivateKey key)
|
| : key_(key.Pass()) {}
|
|
|
| SECKEYPrivateKey* key() { return key_.get(); }
|
|
|
| + virtual PlatformPrivateKey* AsPrivateKey() OVERRIDE { return this; }
|
| +
|
| private:
|
| crypto::ScopedSECKEYPrivateKey key_;
|
|
|
| - DISALLOW_COPY_AND_ASSIGN(PrivateKeyHandle);
|
| + DISALLOW_COPY_AND_ASSIGN(PlatformPrivateKey);
|
| };
|
|
|
| +PlatformSymKey* PlatformCrypto::ToSymKey(const blink::WebCryptoKey& key) {
|
| + return static_cast<PlatformKey*>(key.handle())->AsSymKey();
|
| +}
|
| +
|
| +PlatformPublicKey* PlatformCrypto::ToPublicKey(const blink::WebCryptoKey& key) {
|
| + return static_cast<PlatformKey*>(key.handle())->AsPublicKey();
|
| +}
|
| +
|
| +PlatformPrivateKey* PlatformCrypto::ToPrivateKey(
|
| + const blink::WebCryptoKey& key) {
|
| + return static_cast<PlatformKey*>(key.handle())->AsPrivateKey();
|
| +}
|
| +
|
| +namespace {
|
| +
|
| +// Creates a SECItem for the data in |buffer|. This does NOT make a copy, so
|
| +// |buffer| should outlive the SECItem.
|
| +SECItem MakeSECItemForBuffer(const CryptoData& buffer) {
|
| + SECItem item = {
|
| + siBuffer,
|
| + // NSS requires non-const data even though it is just for input.
|
| + const_cast<unsigned char*>(buffer.bytes()),
|
| + buffer.byte_length()
|
| + };
|
| + return item;
|
| +}
|
| +
|
| HASH_HashType WebCryptoAlgorithmToNSSHashType(
|
| - const blink::WebCryptoAlgorithm& algorithm) {
|
| - switch (algorithm.id()) {
|
| + blink::WebCryptoAlgorithmId algorithm) {
|
| + switch (algorithm) {
|
| case blink::WebCryptoAlgorithmIdSha1:
|
| return HASH_AlgSHA1;
|
| case blink::WebCryptoAlgorithmIdSha224:
|
| @@ -194,40 +231,27 @@ CK_MECHANISM_TYPE WebCryptoHashToHMACMechanism(
|
|
|
| Status AesCbcEncryptDecrypt(
|
| CK_ATTRIBUTE_TYPE operation,
|
| - const blink::WebCryptoAlgorithm& algorithm,
|
| - const blink::WebCryptoKey& key,
|
| - const unsigned char* data,
|
| - unsigned int data_size,
|
| + PlatformSymKey* key,
|
| + const CryptoData& iv,
|
| + const CryptoData& data,
|
| blink::WebArrayBuffer* buffer) {
|
| - DCHECK_EQ(blink::WebCryptoAlgorithmIdAesCbc, algorithm.id());
|
| - DCHECK_EQ(algorithm.id(), key.algorithm().id());
|
| - DCHECK_EQ(blink::WebCryptoKeyTypeSecret, key.type());
|
| DCHECK(operation == CKA_ENCRYPT || operation == CKA_DECRYPT);
|
|
|
| - SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle());
|
| -
|
| - const blink::WebCryptoAesCbcParams* params = algorithm.aesCbcParams();
|
| - if (params->iv().size() != AES_BLOCK_SIZE)
|
| - return Status::ErrorIncorrectSizeAesCbcIv();
|
| -
|
| - SECItem iv_item;
|
| - iv_item.type = siBuffer;
|
| - iv_item.data = const_cast<unsigned char*>(params->iv().data());
|
| - iv_item.len = params->iv().size();
|
| + SECItem iv_item = MakeSECItemForBuffer(iv);
|
|
|
| crypto::ScopedSECItem param(PK11_ParamFromIV(CKM_AES_CBC_PAD, &iv_item));
|
| if (!param)
|
| return Status::Error();
|
|
|
| crypto::ScopedPK11Context context(PK11_CreateContextBySymKey(
|
| - CKM_AES_CBC_PAD, operation, sym_key->key(), param.get()));
|
| + CKM_AES_CBC_PAD, operation, key->key(), param.get()));
|
|
|
| if (!context.get())
|
| return Status::Error();
|
|
|
| // Oddly PK11_CipherOp takes input and output lengths as "int" rather than
|
| // "unsigned int". Do some checks now to avoid integer overflowing.
|
| - if (data_size >= INT_MAX - AES_BLOCK_SIZE) {
|
| + if (data.byte_length() >= INT_MAX - AES_BLOCK_SIZE) {
|
| // TODO(eroman): Handle this by chunking the input fed into NSS. Right now
|
| // it doesn't make much difference since the one-shot API would end up
|
| // blowing out the memory and crashing anyway.
|
| @@ -238,14 +262,14 @@ Status AesCbcEncryptDecrypt(
|
| // input, or input which is not a multiple of the block size. See also
|
| // https://bugzilla.mozilla.com/show_bug.cgi?id=921687.
|
| if (operation == CKA_DECRYPT &&
|
| - (data_size == 0 || (data_size % AES_BLOCK_SIZE != 0))) {
|
| + (data.byte_length() == 0 || (data.byte_length() % AES_BLOCK_SIZE != 0))) {
|
| return Status::Error();
|
| }
|
|
|
| // TODO(eroman): Refine the output buffer size. It can be computed exactly for
|
| // encryption, and can be smaller for decryption.
|
| - unsigned int output_max_len = data_size + AES_BLOCK_SIZE;
|
| - CHECK_GT(output_max_len, data_size);
|
| + unsigned int output_max_len = data.byte_length() + AES_BLOCK_SIZE;
|
| + CHECK_GT(output_max_len, data.byte_length());
|
|
|
| *buffer = blink::WebArrayBuffer::create(output_max_len, 1);
|
|
|
| @@ -256,8 +280,8 @@ Status AesCbcEncryptDecrypt(
|
| buffer_data,
|
| &output_len,
|
| buffer->byteLength(),
|
| - data,
|
| - data_size)) {
|
| + data.bytes(),
|
| + data.byte_length())) {
|
| return Status::Error();
|
| }
|
|
|
| @@ -269,7 +293,7 @@ Status AesCbcEncryptDecrypt(
|
| return Status::Error();
|
| }
|
|
|
| - webcrypto::ShrinkBuffer(buffer, final_output_chunk_len + output_len);
|
| + ShrinkBuffer(buffer, final_output_chunk_len + output_len);
|
| return Status::Success();
|
| }
|
|
|
| @@ -278,24 +302,13 @@ Status AesCbcEncryptDecrypt(
|
| // this is the expectation for the input to decryption.
|
| Status AesGcmEncryptDecrypt(
|
| bool encrypt,
|
| - const blink::WebCryptoAlgorithm& algorithm,
|
| - const blink::WebCryptoKey& key,
|
| - const unsigned char* data,
|
| - unsigned int data_size,
|
| + PlatformSymKey* key,
|
| + const blink::WebCryptoAesGcmParams* params,
|
| + const CryptoData& data,
|
| blink::WebArrayBuffer* buffer) {
|
| - DCHECK_EQ(blink::WebCryptoAlgorithmIdAesGcm, algorithm.id());
|
| - DCHECK_EQ(algorithm.id(), key.algorithm().id());
|
| - DCHECK_EQ(blink::WebCryptoKeyTypeSecret, key.type());
|
| -
|
| if (!g_aes_gcm_support.Get().IsSupported())
|
| return Status::ErrorUnsupported();
|
|
|
| - SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle());
|
| -
|
| - const blink::WebCryptoAesGcmParams* params = algorithm.aesGcmParams();
|
| - if (!params)
|
| - return Status::ErrorUnexpected();
|
| -
|
| // TODO(eroman): The spec doesn't define the default value. Assume 128 for now
|
| // since that is the maximum tag length:
|
| // http://www.w3.org/2012/webcrypto/track/issues/46
|
| @@ -309,9 +322,8 @@ Status AesGcmEncryptDecrypt(
|
| unsigned int tag_length_bytes = tag_length_bits / 8;
|
|
|
| CK_GCM_PARAMS gcm_params = {0};
|
| - gcm_params.pIv =
|
| - const_cast<unsigned char*>(algorithm.aesGcmParams()->iv().data());
|
| - gcm_params.ulIvLen = algorithm.aesGcmParams()->iv().size();
|
| + gcm_params.pIv = const_cast<unsigned char*>(params->iv().data());
|
| + gcm_params.ulIvLen = params->iv().size();
|
|
|
| gcm_params.pAAD =
|
| const_cast<unsigned char*>(params->optionalAdditionalData().data());
|
| @@ -329,12 +341,12 @@ Status AesGcmEncryptDecrypt(
|
| // Calculate the output buffer size.
|
| if (encrypt) {
|
| // TODO(eroman): This is ugly, abstract away the safe integer arithmetic.
|
| - if (data_size > (UINT_MAX - tag_length_bytes))
|
| + if (data.byte_length() > (UINT_MAX - tag_length_bytes))
|
| return Status::ErrorDataTooLarge();
|
| - buffer_size = data_size + tag_length_bytes;
|
| + buffer_size = data.byte_length() + tag_length_bytes;
|
| } else {
|
| // TODO(eroman): In theory the buffer allocated for the plain text should be
|
| - // sized as |data_size - tag_length_bytes|.
|
| + // sized as |data.byte_length() - tag_length_bytes|.
|
| //
|
| // However NSS has a bug whereby it will fail if the output buffer size is
|
| // not at least as large as the ciphertext:
|
| @@ -344,7 +356,7 @@ Status AesGcmEncryptDecrypt(
|
| // From the analysis of that bug it looks like it might be safe to pass a
|
| // correctly sized buffer but lie about its size. Since resizing the
|
| // WebCryptoArrayBuffer is expensive that hack may be worth looking into.
|
| - buffer_size = data_size;
|
| + buffer_size = data.byte_length();
|
| }
|
|
|
| *buffer = blink::WebArrayBuffer::create(buffer_size, 1);
|
| @@ -355,16 +367,16 @@ Status AesGcmEncryptDecrypt(
|
| g_aes_gcm_support.Get().pk11_decrypt_func();
|
|
|
| unsigned int output_len = 0;
|
| - SECStatus result = func(sym_key->key(), CKM_AES_GCM, ¶m,
|
| + SECStatus result = func(key->key(), CKM_AES_GCM, ¶m,
|
| buffer_data, &output_len, buffer->byteLength(),
|
| - data, data_size);
|
| + data.bytes(), data.byte_length());
|
|
|
| if (result != SECSuccess)
|
| return Status::Error();
|
|
|
| // Unfortunately the buffer needs to be shrunk for decryption (see the NSS bug
|
| // above).
|
| - webcrypto::ShrinkBuffer(buffer, output_len);
|
| + ShrinkBuffer(buffer, output_len);
|
|
|
| return Status::Success();
|
| }
|
| @@ -411,9 +423,10 @@ bool IsAlgorithmRsa(const blink::WebCryptoAlgorithm& algorithm) {
|
| algorithm.id() == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5;
|
| }
|
|
|
| -Status ImportKeyInternalRaw(
|
| - const unsigned char* key_data,
|
| - unsigned int key_data_size,
|
| +} // namespace
|
| +
|
| +Status PlatformCrypto::PlatformImportKeyRaw(
|
| + const CryptoData& key_data,
|
| const blink::WebCryptoAlgorithm& algorithm,
|
| bool extractable,
|
| blink::WebCryptoKeyUsageMask usage_mask,
|
| @@ -421,19 +434,6 @@ Status ImportKeyInternalRaw(
|
|
|
| DCHECK(!algorithm.isNull());
|
|
|
| - blink::WebCryptoKeyType type;
|
| - switch (algorithm.id()) {
|
| - case blink::WebCryptoAlgorithmIdHmac:
|
| - case blink::WebCryptoAlgorithmIdAesCbc:
|
| - case blink::WebCryptoAlgorithmIdAesKw:
|
| - case blink::WebCryptoAlgorithmIdAesGcm:
|
| - type = blink::WebCryptoKeyTypeSecret;
|
| - break;
|
| - // TODO(bryaneyler): Support more key types.
|
| - default:
|
| - return Status::ErrorUnsupported();
|
| - }
|
| -
|
| // TODO(bryaneyler): Need to split handling for symmetric and asymmetric keys.
|
| // Currently only supporting symmetric.
|
| CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM;
|
| @@ -479,11 +479,7 @@ Status ImportKeyInternalRaw(
|
| DCHECK_NE(CKM_INVALID_MECHANISM, mechanism);
|
| DCHECK_NE(0ul, flags);
|
|
|
| - SECItem key_item = {
|
| - siBuffer,
|
| - const_cast<unsigned char*>(key_data),
|
| - key_data_size
|
| - };
|
| + SECItem key_item = MakeSECItemForBuffer(key_data);
|
|
|
| crypto::ScopedPK11Slot slot(PK11_GetInternalSlot());
|
| crypto::ScopedPK11SymKey pk11_sym_key(
|
| @@ -498,37 +494,31 @@ Status ImportKeyInternalRaw(
|
| if (!pk11_sym_key.get())
|
| return Status::Error();
|
|
|
| - *key = blink::WebCryptoKey::create(new SymKeyHandle(pk11_sym_key.Pass()),
|
| - type, extractable, algorithm, usage_mask);
|
| + *key = blink::WebCryptoKey::create(new PlatformSymKey(pk11_sym_key.Pass()),
|
| + blink::WebCryptoKeyTypeSecret,
|
| + extractable,
|
| + algorithm,
|
| + usage_mask);
|
| return Status::Success();
|
| }
|
|
|
| -Status ExportKeyInternalRaw(
|
| - const blink::WebCryptoKey& key,
|
| +Status PlatformCrypto::PlatformExportKeyRaw(
|
| + PlatformSymKey* key,
|
| blink::WebArrayBuffer* buffer) {
|
| -
|
| - DCHECK(key.handle());
|
| - DCHECK(buffer);
|
| -
|
| - if (!key.extractable())
|
| - return Status::ErrorKeyNotExtractable();
|
| - if (key.type() != blink::WebCryptoKeyTypeSecret)
|
| - return Status::ErrorUnexpectedKeyType();
|
| -
|
| - SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle());
|
| -
|
| - if (PK11_ExtractKeyValue(sym_key->key()) != SECSuccess)
|
| + if (PK11_ExtractKeyValue(key->key()) != SECSuccess)
|
| return Status::Error();
|
|
|
| - const SECItem* key_data = PK11_GetKeyData(sym_key->key());
|
| + const SECItem* key_data = PK11_GetKeyData(key->key());
|
| if (!key_data)
|
| return Status::Error();
|
|
|
| - *buffer = webcrypto::CreateArrayBuffer(key_data->data, key_data->len);
|
| + *buffer = CreateArrayBuffer(key_data->data, key_data->len);
|
|
|
| return Status::Success();
|
| }
|
|
|
| +namespace {
|
| +
|
| typedef scoped_ptr<CERTSubjectPublicKeyInfo,
|
| crypto::NSSDestroyer<CERTSubjectPublicKeyInfo,
|
| SECKEY_DestroySubjectPublicKeyInfo> >
|
| @@ -564,9 +554,10 @@ blink::WebCryptoAlgorithm ResolveNssKeyTypeWithInputAlgorithm(
|
| return blink::WebCryptoAlgorithm::createNull();
|
| }
|
|
|
| -Status ImportKeyInternalSpki(
|
| - const unsigned char* key_data,
|
| - unsigned int key_data_size,
|
| +} // namespace
|
| +
|
| +Status PlatformCrypto::PlatformImportKeySpki(
|
| + const CryptoData& key_data,
|
| const blink::WebCryptoAlgorithm& algorithm_or_null,
|
| bool extractable,
|
| blink::WebCryptoKeyUsageMask usage_mask,
|
| @@ -574,13 +565,13 @@ Status ImportKeyInternalSpki(
|
|
|
| DCHECK(key);
|
|
|
| - if (!key_data_size)
|
| + if (!key_data.byte_length())
|
| return Status::ErrorImportEmptyKeyData();
|
| - DCHECK(key_data);
|
| + DCHECK(key_data.bytes());
|
|
|
| // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 Subject
|
| // Public Key Info. Decode this to a CERTSubjectPublicKeyInfo.
|
| - SECItem spki_item = {siBuffer, const_cast<uint8*>(key_data), key_data_size};
|
| + SECItem spki_item = MakeSECItemForBuffer(key_data);
|
| const ScopedCERTSubjectPublicKeyInfo spki(
|
| SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_item));
|
| if (!spki)
|
| @@ -598,7 +589,7 @@ Status ImportKeyInternalSpki(
|
| return Status::Error();
|
|
|
| *key = blink::WebCryptoKey::create(
|
| - new PublicKeyHandle(sec_public_key.Pass()),
|
| + new PlatformPublicKey(sec_public_key.Pass()),
|
| blink::WebCryptoKeyTypePublic,
|
| extractable,
|
| algorithm,
|
| @@ -607,37 +598,24 @@ Status ImportKeyInternalSpki(
|
| return Status::Success();
|
| }
|
|
|
| -Status ExportKeyInternalSpki(
|
| - const blink::WebCryptoKey& key,
|
| +Status PlatformCrypto::PlatformExportKeySpki(
|
| + PlatformPublicKey* key,
|
| blink::WebArrayBuffer* buffer) {
|
| -
|
| - DCHECK(key.handle());
|
| - DCHECK(buffer);
|
| -
|
| - if (!key.extractable())
|
| - return Status::ErrorKeyNotExtractable();
|
| - if (key.type() != blink::WebCryptoKeyTypePublic)
|
| - return Status::ErrorUnexpectedKeyType();
|
| -
|
| - PublicKeyHandle* const pub_key =
|
| - reinterpret_cast<PublicKeyHandle*>(key.handle());
|
| -
|
| const crypto::ScopedSECItem spki_der(
|
| - SECKEY_EncodeDERSubjectPublicKeyInfo(pub_key->key()));
|
| + SECKEY_EncodeDERSubjectPublicKeyInfo(key->key()));
|
| if (!spki_der)
|
| return Status::Error();
|
|
|
| DCHECK(spki_der->data);
|
| DCHECK(spki_der->len);
|
|
|
| - *buffer = webcrypto::CreateArrayBuffer(spki_der->data, spki_der->len);
|
| + *buffer = CreateArrayBuffer(spki_der->data, spki_der->len);
|
|
|
| return Status::Success();
|
| }
|
|
|
| -Status ImportKeyInternalPkcs8(
|
| - const unsigned char* key_data,
|
| - unsigned int key_data_size,
|
| +Status PlatformCrypto::PlatformImportKeyPkcs8(
|
| + const CryptoData& key_data,
|
| const blink::WebCryptoAlgorithm& algorithm_or_null,
|
| bool extractable,
|
| blink::WebCryptoKeyUsageMask usage_mask,
|
| @@ -645,13 +623,13 @@ Status ImportKeyInternalPkcs8(
|
|
|
| DCHECK(key);
|
|
|
| - if (!key_data_size)
|
| + if (!key_data.byte_length())
|
| return Status::ErrorImportEmptyKeyData();
|
| - DCHECK(key_data);
|
| + DCHECK(key_data.bytes());
|
|
|
| // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 PKCS#8
|
| // private key info object.
|
| - SECItem pki_der = {siBuffer, const_cast<uint8*>(key_data), key_data_size};
|
| + SECItem pki_der = MakeSECItemForBuffer(key_data);
|
|
|
| SECKEYPrivateKey* seckey_private_key = NULL;
|
| crypto::ScopedPK11Slot slot(PK11_GetInternalSlot());
|
| @@ -677,7 +655,7 @@ Status ImportKeyInternalPkcs8(
|
| return Status::Error();
|
|
|
| *key = blink::WebCryptoKey::create(
|
| - new PrivateKeyHandle(private_key.Pass()),
|
| + new PlatformPrivateKey(private_key.Pass()),
|
| blink::WebCryptoKeyTypePrivate,
|
| extractable,
|
| algorithm,
|
| @@ -690,34 +668,20 @@ Status ImportKeyInternalPkcs8(
|
| // Hmac
|
| // -----------------------------------
|
|
|
| -Status SignHmac(
|
| - const blink::WebCryptoAlgorithm& algorithm,
|
| - const blink::WebCryptoKey& key,
|
| - const unsigned char* data,
|
| - unsigned int data_size,
|
| +Status PlatformCrypto::PlatformSignHmac(
|
| + PlatformSymKey* key,
|
| + const blink::WebCryptoAlgorithm& hash,
|
| + const CryptoData& data,
|
| blink::WebArrayBuffer* buffer) {
|
| - DCHECK_EQ(blink::WebCryptoAlgorithmIdHmac, algorithm.id());
|
| -
|
| - const blink::WebCryptoHmacParams* params = algorithm.hmacParams();
|
| - if (!params)
|
| - return Status::ErrorUnexpected();
|
| -
|
| - SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle());
|
| -
|
| - DCHECK_EQ(PK11_GetMechanism(sym_key->key()),
|
| - WebCryptoHashToHMACMechanism(params->hash()));
|
| + DCHECK_EQ(PK11_GetMechanism(key->key()), WebCryptoHashToHMACMechanism(hash));
|
|
|
| SECItem param_item = { siBuffer, NULL, 0 };
|
| - SECItem data_item = {
|
| - siBuffer,
|
| - const_cast<unsigned char*>(data),
|
| - data_size
|
| - };
|
| + SECItem data_item = MakeSECItemForBuffer(data);
|
| // First call is to figure out the length.
|
| SECItem signature_item = { siBuffer, NULL, 0 };
|
|
|
| - if (PK11_SignWithSymKey(sym_key->key(),
|
| - PK11_GetMechanism(sym_key->key()),
|
| + if (PK11_SignWithSymKey(key->key(),
|
| + PK11_GetMechanism(key->key()),
|
| ¶m_item,
|
| &signature_item,
|
| &data_item) != SECSuccess) {
|
| @@ -729,8 +693,8 @@ Status SignHmac(
|
| *buffer = blink::WebArrayBuffer::create(signature_item.len, 1);
|
| signature_item.data = reinterpret_cast<unsigned char*>(buffer->data());
|
|
|
| - if (PK11_SignWithSymKey(sym_key->key(),
|
| - PK11_GetMechanism(sym_key->key()),
|
| + if (PK11_SignWithSymKey(key->key(),
|
| + PK11_GetMechanism(key->key()),
|
| ¶m_item,
|
| &signature_item,
|
| &data_item) != SECSuccess) {
|
| @@ -741,98 +705,42 @@ Status SignHmac(
|
| return Status::Success();
|
| }
|
|
|
| -Status VerifyHmac(
|
| - const blink::WebCryptoAlgorithm& algorithm,
|
| - const blink::WebCryptoKey& key,
|
| - const unsigned char* signature,
|
| - unsigned int signature_size,
|
| - const unsigned char* data,
|
| - unsigned int data_size,
|
| - bool* signature_match) {
|
| - DCHECK_EQ(blink::WebCryptoAlgorithmIdHmac, algorithm.id());
|
| -
|
| - blink::WebArrayBuffer result;
|
| - Status status = SignHmac(algorithm, key, data, data_size, &result);
|
| - if (status.IsError())
|
| - return status;
|
| -
|
| - // Handling of truncated signatures is underspecified in the WebCrypto
|
| - // spec, so here we fail verification if a truncated signature is being
|
| - // verified.
|
| - // See https://www.w3.org/Bugs/Public/show_bug.cgi?id=23097
|
| - *signature_match =
|
| - result.byteLength() == signature_size &&
|
| - crypto::SecureMemEqual(result.data(), signature, signature_size);
|
| -
|
| - return Status::Success();
|
| -}
|
| -
|
| // -----------------------------------
|
| // RsaEsPkcs1v1_5
|
| // -----------------------------------
|
|
|
| -Status EncryptRsaEsPkcs1v1_5(
|
| - const blink::WebCryptoAlgorithm& algorithm,
|
| - const blink::WebCryptoKey& key,
|
| - const unsigned char* data,
|
| - unsigned int data_size,
|
| +Status PlatformCrypto::PlatformEncryptRsaEsPkcs1v1_5(
|
| + PlatformPublicKey* key,
|
| + const CryptoData& data,
|
| blink::WebArrayBuffer* buffer) {
|
| - DCHECK_EQ(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, algorithm.id());
|
| -
|
| - // RSAES encryption does not support empty input
|
| - if (!data_size)
|
| - return Status::Error();
|
| - DCHECK(data);
|
| -
|
| - if (key.type() != blink::WebCryptoKeyTypePublic)
|
| - return Status::ErrorUnexpectedKeyType();
|
| -
|
| - PublicKeyHandle* const public_key =
|
| - reinterpret_cast<PublicKeyHandle*>(key.handle());
|
| -
|
| const unsigned int encrypted_length_bytes =
|
| - SECKEY_PublicKeyStrength(public_key->key());
|
| + SECKEY_PublicKeyStrength(key->key());
|
|
|
| // RSAES can operate on messages up to a length of k - 11, where k is the
|
| // octet length of the RSA modulus.
|
| - if (encrypted_length_bytes < 11 || encrypted_length_bytes - 11 < data_size)
|
| + if (encrypted_length_bytes < 11 ||
|
| + encrypted_length_bytes - 11 < data.byte_length())
|
| return Status::ErrorDataTooLarge();
|
|
|
| *buffer = blink::WebArrayBuffer::create(encrypted_length_bytes, 1);
|
| unsigned char* const buffer_data =
|
| reinterpret_cast<unsigned char*>(buffer->data());
|
|
|
| - if (PK11_PubEncryptPKCS1(public_key->key(),
|
| + if (PK11_PubEncryptPKCS1(key->key(),
|
| buffer_data,
|
| - const_cast<unsigned char*>(data),
|
| - data_size,
|
| + const_cast<unsigned char*>(data.bytes()),
|
| + data.byte_length(),
|
| NULL) != SECSuccess) {
|
| return Status::Error();
|
| }
|
| return Status::Success();
|
| }
|
|
|
| -Status DecryptRsaEsPkcs1v1_5(
|
| - const blink::WebCryptoAlgorithm& algorithm,
|
| - const blink::WebCryptoKey& key,
|
| - const unsigned char* data,
|
| - unsigned int data_size,
|
| +Status PlatformCrypto::PlatformDecryptRsaEsPkcs1v1_5(
|
| + PlatformPrivateKey* key,
|
| + const CryptoData& data,
|
| blink::WebArrayBuffer* buffer) {
|
| - DCHECK_EQ(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, algorithm.id());
|
| -
|
| - // RSAES decryption does not support empty input
|
| - if (!data_size)
|
| - return Status::Error();
|
| - DCHECK(data);
|
| -
|
| - if (key.type() != blink::WebCryptoKeyTypePrivate)
|
| - return Status::ErrorUnexpectedKeyType();
|
| -
|
| - PrivateKeyHandle* const private_key =
|
| - reinterpret_cast<PrivateKeyHandle*>(key.handle());
|
| -
|
| - const int modulus_length_bytes =
|
| - PK11_GetPrivateModulusLen(private_key->key());
|
| + const int modulus_length_bytes = PK11_GetPrivateModulusLen(key->key());
|
| if (modulus_length_bytes <= 0)
|
| return Status::ErrorUnexpected();
|
| const unsigned int max_output_length_bytes = modulus_length_bytes;
|
| @@ -842,16 +750,16 @@ Status DecryptRsaEsPkcs1v1_5(
|
| reinterpret_cast<unsigned char*>(buffer->data());
|
|
|
| unsigned int output_length_bytes = 0;
|
| - if (PK11_PrivDecryptPKCS1(private_key->key(),
|
| + if (PK11_PrivDecryptPKCS1(key->key(),
|
| buffer_data,
|
| &output_length_bytes,
|
| max_output_length_bytes,
|
| - const_cast<unsigned char*>(data),
|
| - data_size) != SECSuccess) {
|
| + const_cast<unsigned char*>(data.bytes()),
|
| + data.byte_length()) != SECSuccess) {
|
| return Status::Error();
|
| }
|
| DCHECK_LE(output_length_bytes, max_output_length_bytes);
|
| - webcrypto::ShrinkBuffer(buffer, output_length_bytes);
|
| + ShrinkBuffer(buffer, output_length_bytes);
|
| return Status::Success();
|
| }
|
|
|
| @@ -859,29 +767,15 @@ Status DecryptRsaEsPkcs1v1_5(
|
| // RsaSsaPkcs1v1_5
|
| // -----------------------------------
|
|
|
| -Status SignRsaSsaPkcs1v1_5(
|
| - const blink::WebCryptoAlgorithm& algorithm,
|
| - const blink::WebCryptoKey& key,
|
| - const unsigned char* data,
|
| - unsigned int data_size,
|
| +Status PlatformCrypto::PlatformSignRsaSsaPkcs1v1_5(
|
| + PlatformPrivateKey* key,
|
| + const blink::WebCryptoAlgorithm& hash,
|
| + const CryptoData& data,
|
| blink::WebArrayBuffer* buffer) {
|
| - DCHECK_EQ(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, algorithm.id());
|
| -
|
| - if (key.type() != blink::WebCryptoKeyTypePrivate)
|
| - return Status::ErrorUnexpectedKeyType();
|
| -
|
| - if (webcrypto::GetInnerHashAlgorithm(algorithm).isNull())
|
| - return Status::ErrorUnexpected();
|
| -
|
| - 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()) {
|
| + switch (hash.id()) {
|
| case blink::WebCryptoAlgorithmIdSha1:
|
| sign_alg_tag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
|
| break;
|
| @@ -903,44 +797,27 @@ Status SignRsaSsaPkcs1v1_5(
|
|
|
| crypto::ScopedSECItem signature_item(SECITEM_AllocItem(NULL, NULL, 0));
|
| if (SEC_SignData(signature_item.get(),
|
| - data,
|
| - data_size,
|
| - private_key->key(),
|
| + data.bytes(),
|
| + data.byte_length(),
|
| + key->key(),
|
| sign_alg_tag) != SECSuccess) {
|
| return Status::Error();
|
| }
|
|
|
| - *buffer = webcrypto::CreateArrayBuffer(signature_item->data,
|
| - signature_item->len);
|
| + *buffer = CreateArrayBuffer(signature_item->data, signature_item->len);
|
| return Status::Success();
|
| }
|
|
|
| -Status VerifyRsaSsaPkcs1v1_5(
|
| - const blink::WebCryptoAlgorithm& algorithm,
|
| - const blink::WebCryptoKey& key,
|
| - const unsigned char* signature,
|
| - unsigned int signature_size,
|
| - const unsigned char* data,
|
| - unsigned int data_size,
|
| +Status PlatformCrypto::PlatformVerifyRsaSsaPkcs1v1_5(
|
| + PlatformPublicKey* key,
|
| + const blink::WebCryptoAlgorithm& hash,
|
| + const CryptoData& signature,
|
| + const CryptoData& data,
|
| bool* signature_match) {
|
| - DCHECK_EQ(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, algorithm.id());
|
| -
|
| - if (key.type() != blink::WebCryptoKeyTypePublic)
|
| - return Status::ErrorUnexpectedKeyType();
|
| -
|
| - 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
|
| - };
|
| + const SECItem signature_item = MakeSECItemForBuffer(signature);
|
|
|
| SECOidTag hash_alg_tag;
|
| - switch (webcrypto::GetInnerHashAlgorithm(algorithm).id()) {
|
| + switch (hash.id()) {
|
| case blink::WebCryptoAlgorithmIdSha1:
|
| hash_alg_tag = SEC_OID_SHA1;
|
| break;
|
| @@ -961,9 +838,9 @@ Status VerifyRsaSsaPkcs1v1_5(
|
| }
|
|
|
| *signature_match =
|
| - SECSuccess == VFY_VerifyDataDirect(data,
|
| - data_size,
|
| - public_key->key(),
|
| + SECSuccess == VFY_VerifyDataDirect(data.bytes(),
|
| + data.byte_length(),
|
| + key->key(),
|
| &signature_item,
|
| SEC_OID_PKCS1_RSA_ENCRYPTION,
|
| hash_alg_tag,
|
| @@ -972,11 +849,41 @@ Status VerifyRsaSsaPkcs1v1_5(
|
| return Status::Success();
|
| }
|
|
|
| +Status PlatformCrypto::PlatformEncryptAesCbc(PlatformSymKey* key,
|
| + const CryptoData& iv,
|
| + const CryptoData& data,
|
| + blink::WebArrayBuffer* buffer) {
|
| + return AesCbcEncryptDecrypt(CKA_ENCRYPT, key, iv, data, buffer);
|
| +}
|
| +
|
| +Status PlatformCrypto::PlatformDecryptAesCbc(PlatformSymKey* key,
|
| + const CryptoData& iv,
|
| + const CryptoData& data,
|
| + blink::WebArrayBuffer* buffer) {
|
| + return AesCbcEncryptDecrypt(CKA_DECRYPT, key, iv, data, buffer);
|
| +}
|
| +
|
| +Status PlatformCrypto::PlatformEncryptAesGcm(
|
| + PlatformSymKey* key,
|
| + const blink::WebCryptoAesGcmParams* params,
|
| + const CryptoData& data,
|
| + blink::WebArrayBuffer* buffer) {
|
| + return AesGcmEncryptDecrypt(true, key, params, data, buffer);
|
| +}
|
| +
|
| +Status PlatformCrypto::PlatformDecryptAesGcm(
|
| + PlatformSymKey* key,
|
| + const blink::WebCryptoAesGcmParams* params,
|
| + const CryptoData& data,
|
| + blink::WebArrayBuffer* buffer) {
|
| + return AesGcmEncryptDecrypt(false, key, params, data, buffer);
|
| +}
|
| +
|
| // -----------------------------------
|
| // Key generation
|
| // -----------------------------------
|
|
|
| -Status GenerateRsaKeyPair(
|
| +Status PlatformCrypto::PlatformGenerateRsaKeyPair(
|
| const blink::WebCryptoAlgorithm& algorithm,
|
| bool extractable,
|
| blink::WebCryptoKeyUsageMask usage_mask,
|
| @@ -1040,13 +947,13 @@ Status GenerateRsaKeyPair(
|
| return Status::Error();
|
|
|
| *public_key = blink::WebCryptoKey::create(
|
| - new PublicKeyHandle(crypto::ScopedSECKEYPublicKey(sec_public_key)),
|
| + new PlatformPublicKey(crypto::ScopedSECKEYPublicKey(sec_public_key)),
|
| blink::WebCryptoKeyTypePublic,
|
| true,
|
| algorithm,
|
| usage_mask);
|
| *private_key = blink::WebCryptoKey::create(
|
| - new PrivateKeyHandle(scoped_sec_private_key.Pass()),
|
| + new PlatformPrivateKey(scoped_sec_private_key.Pass()),
|
| blink::WebCryptoKeyTypePrivate,
|
| extractable,
|
| algorithm,
|
| @@ -1055,106 +962,13 @@ Status GenerateRsaKeyPair(
|
| return Status::Success();
|
| }
|
|
|
| -// Get the secret key length in bytes from generation parameters. This resolves
|
| -// any defaults.
|
| -Status GetGenerateSecretKeyLength(const blink::WebCryptoAlgorithm& algorithm,
|
| - unsigned int* keylen_bytes) {
|
| - *keylen_bytes = 0;
|
| -
|
| - switch (algorithm.id()) {
|
| - case blink::WebCryptoAlgorithmIdAesCbc:
|
| - case blink::WebCryptoAlgorithmIdAesGcm:
|
| - case blink::WebCryptoAlgorithmIdAesKw: {
|
| - const blink::WebCryptoAesKeyGenParams* params =
|
| - algorithm.aesKeyGenParams();
|
| - DCHECK(params);
|
| - // Ensure the key length is a multiple of 8 bits. Let NSS verify further
|
| - // algorithm-specific length restrictions.
|
| - if (params->lengthBits() % 8)
|
| - return Status::ErrorGenerateKeyLength();
|
| - *keylen_bytes = params->lengthBits() / 8;
|
| - break;
|
| - }
|
| - case blink::WebCryptoAlgorithmIdHmac: {
|
| - const blink::WebCryptoHmacKeyParams* params = algorithm.hmacKeyParams();
|
| - DCHECK(params);
|
| - if (params->hasLengthBytes())
|
| - *keylen_bytes = params->optionalLengthBytes();
|
| - else
|
| - *keylen_bytes = webcrypto::ShaBlockSizeBytes(params->hash().id());
|
| - break;
|
| - }
|
| -
|
| - default:
|
| - return Status::ErrorUnsupported();
|
| - }
|
| -
|
| - if (*keylen_bytes == 0)
|
| - return Status::ErrorGenerateKeyLength();
|
| -
|
| - return Status::Success();
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -void WebCryptoImpl::Init() {
|
| +PlatformCrypto::PlatformCrypto() {
|
| crypto::EnsureNSSInit();
|
| }
|
|
|
| -Status WebCryptoImpl::EncryptInternal(
|
| - const blink::WebCryptoAlgorithm& algorithm,
|
| - const blink::WebCryptoKey& key,
|
| - const unsigned char* data,
|
| - unsigned int data_size,
|
| - blink::WebArrayBuffer* buffer) {
|
| -
|
| - DCHECK_EQ(algorithm.id(), key.algorithm().id());
|
| - DCHECK(key.handle());
|
| - DCHECK(buffer);
|
| -
|
| - switch (algorithm.id()) {
|
| - case blink::WebCryptoAlgorithmIdAesCbc:
|
| - return AesCbcEncryptDecrypt(
|
| - CKA_ENCRYPT, algorithm, key, data, data_size, buffer);
|
| - case blink::WebCryptoAlgorithmIdAesGcm:
|
| - return AesGcmEncryptDecrypt(
|
| - true, algorithm, key, data, data_size, buffer);
|
| - case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5:
|
| - return EncryptRsaEsPkcs1v1_5(algorithm, key, data, data_size, buffer);
|
| - default:
|
| - return Status::ErrorUnsupported();
|
| - }
|
| -}
|
| -
|
| -Status WebCryptoImpl::DecryptInternal(
|
| - const blink::WebCryptoAlgorithm& algorithm,
|
| - const blink::WebCryptoKey& key,
|
| - const unsigned char* data,
|
| - unsigned int data_size,
|
| - blink::WebArrayBuffer* buffer) {
|
| -
|
| - DCHECK_EQ(algorithm.id(), key.algorithm().id());
|
| - DCHECK(key.handle());
|
| - DCHECK(buffer);
|
| -
|
| - switch (algorithm.id()) {
|
| - case blink::WebCryptoAlgorithmIdAesCbc:
|
| - return AesCbcEncryptDecrypt(
|
| - CKA_DECRYPT, algorithm, key, data, data_size, buffer);
|
| - case blink::WebCryptoAlgorithmIdAesGcm:
|
| - return AesGcmEncryptDecrypt(
|
| - false, algorithm, key, data, data_size, buffer);
|
| - case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5:
|
| - return DecryptRsaEsPkcs1v1_5(algorithm, key, data, data_size, buffer);
|
| - default:
|
| - return Status::ErrorUnsupported();
|
| - }
|
| -}
|
| -
|
| -Status WebCryptoImpl::DigestInternal(
|
| - const blink::WebCryptoAlgorithm& algorithm,
|
| - const unsigned char* data,
|
| - unsigned int data_size,
|
| +Status PlatformCrypto::PlatformDigestSha(
|
| + blink::WebCryptoAlgorithmId algorithm,
|
| + const CryptoData& data,
|
| blink::WebArrayBuffer* buffer) {
|
| HASH_HashType hash_type = WebCryptoAlgorithmToNSSHashType(algorithm);
|
| if (hash_type == HASH_AlgNULL)
|
| @@ -1166,7 +980,7 @@ Status WebCryptoImpl::DigestInternal(
|
|
|
| HASH_Begin(context);
|
|
|
| - HASH_Update(context, data, data_size);
|
| + HASH_Update(context, data.bytes(), data.byte_length());
|
|
|
| unsigned int hash_result_length = HASH_ResultLenContext(context);
|
| DCHECK_LE(hash_result_length, static_cast<size_t>(HASH_LENGTH_MAX));
|
| @@ -1185,23 +999,18 @@ Status WebCryptoImpl::DigestInternal(
|
| return Status::Success();
|
| }
|
|
|
| -Status WebCryptoImpl::GenerateSecretKeyInternal(
|
| +Status PlatformCrypto::PlatformGenerateSecretKey(
|
| const blink::WebCryptoAlgorithm& algorithm,
|
| bool extractable,
|
| blink::WebCryptoKeyUsageMask usage_mask,
|
| + unsigned keylen_bytes,
|
| blink::WebCryptoKey* key) {
|
| -
|
| CK_MECHANISM_TYPE mech = WebCryptoAlgorithmToGenMechanism(algorithm);
|
| blink::WebCryptoKeyType key_type = blink::WebCryptoKeyTypeSecret;
|
|
|
| if (mech == CKM_INVALID_MECHANISM)
|
| return Status::ErrorUnsupported();
|
|
|
| - unsigned int keylen_bytes = 0;
|
| - Status status = GetGenerateSecretKeyLength(algorithm, &keylen_bytes);
|
| - if (status.IsError())
|
| - return status;
|
| -
|
| crypto::ScopedPK11Slot slot(PK11_GetInternalKeySlot());
|
| if (!slot)
|
| return Status::Error();
|
| @@ -1212,159 +1021,30 @@ Status WebCryptoImpl::GenerateSecretKeyInternal(
|
| if (!pk11_key)
|
| return Status::Error();
|
|
|
| - *key = blink::WebCryptoKey::create(
|
| - new SymKeyHandle(pk11_key.Pass()),
|
| - key_type, extractable, algorithm, usage_mask);
|
| + *key = blink::WebCryptoKey::create(new PlatformSymKey(pk11_key.Pass()),
|
| + key_type,
|
| + extractable,
|
| + algorithm,
|
| + usage_mask);
|
| return Status::Success();
|
| }
|
|
|
| -Status WebCryptoImpl::GenerateKeyPairInternal(
|
| - const blink::WebCryptoAlgorithm& algorithm,
|
| - bool extractable,
|
| - blink::WebCryptoKeyUsageMask usage_mask,
|
| - blink::WebCryptoKey* public_key,
|
| - blink::WebCryptoKey* private_key) {
|
| -
|
| - // TODO(padolph): Handle other asymmetric algorithm key generation.
|
| - switch (algorithm.id()) {
|
| - case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5:
|
| - case blink::WebCryptoAlgorithmIdRsaOaep:
|
| - case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5:
|
| - return GenerateRsaKeyPair(algorithm, extractable, usage_mask,
|
| - public_key, private_key);
|
| - default:
|
| - return Status::ErrorUnsupported();
|
| - }
|
| -}
|
| -
|
| -Status WebCryptoImpl::ImportKeyInternal(
|
| - blink::WebCryptoKeyFormat format,
|
| - const unsigned char* key_data,
|
| - unsigned int key_data_size,
|
| - const blink::WebCryptoAlgorithm& algorithm_or_null,
|
| - bool extractable,
|
| - blink::WebCryptoKeyUsageMask usage_mask,
|
| - blink::WebCryptoKey* key) {
|
| -
|
| - switch (format) {
|
| - case blink::WebCryptoKeyFormatRaw:
|
| - // A 'raw'-formatted key import requires an input algorithm.
|
| - if (algorithm_or_null.isNull())
|
| - return Status::ErrorMissingAlgorithmImportRawKey();
|
| - return ImportKeyInternalRaw(key_data,
|
| - key_data_size,
|
| - algorithm_or_null,
|
| - extractable,
|
| - usage_mask,
|
| - key);
|
| - case blink::WebCryptoKeyFormatSpki:
|
| - return ImportKeyInternalSpki(key_data,
|
| - key_data_size,
|
| - algorithm_or_null,
|
| - extractable,
|
| - usage_mask,
|
| - key);
|
| - case blink::WebCryptoKeyFormatPkcs8:
|
| - return ImportKeyInternalPkcs8(key_data,
|
| - key_data_size,
|
| - algorithm_or_null,
|
| - extractable,
|
| - usage_mask,
|
| - key);
|
| - default:
|
| - // NOTE: blink::WebCryptoKeyFormatJwk is handled one level above.
|
| - return Status::ErrorUnsupported();
|
| - }
|
| -}
|
| -
|
| -Status WebCryptoImpl::ExportKeyInternal(
|
| - blink::WebCryptoKeyFormat format,
|
| - const blink::WebCryptoKey& key,
|
| - blink::WebArrayBuffer* buffer) {
|
| - switch (format) {
|
| - case blink::WebCryptoKeyFormatRaw:
|
| - return ExportKeyInternalRaw(key, buffer);
|
| - case blink::WebCryptoKeyFormatSpki:
|
| - return ExportKeyInternalSpki(key, buffer);
|
| - case blink::WebCryptoKeyFormatPkcs8:
|
| - // TODO(padolph): Implement pkcs8 export
|
| - return Status::ErrorUnsupported();
|
| - default:
|
| - return Status::ErrorUnsupported();
|
| - }
|
| -}
|
| -
|
| -Status WebCryptoImpl::SignInternal(
|
| - const blink::WebCryptoAlgorithm& algorithm,
|
| - const blink::WebCryptoKey& key,
|
| - const unsigned char* data,
|
| - unsigned int data_size,
|
| - blink::WebArrayBuffer* buffer) {
|
| -
|
| - // Note: It is not an error to sign empty data.
|
| -
|
| - DCHECK(buffer);
|
| - DCHECK_NE(0, key.usages() & blink::WebCryptoKeyUsageSign);
|
| -
|
| - switch (algorithm.id()) {
|
| - case blink::WebCryptoAlgorithmIdHmac:
|
| - return SignHmac(algorithm, key, data, data_size, buffer);
|
| - case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5:
|
| - return SignRsaSsaPkcs1v1_5(algorithm, key, data, data_size, buffer);
|
| - default:
|
| - return Status::ErrorUnsupported();
|
| - }
|
| -}
|
| -
|
| -Status WebCryptoImpl::VerifySignatureInternal(
|
| - const blink::WebCryptoAlgorithm& algorithm,
|
| - const blink::WebCryptoKey& key,
|
| - const unsigned char* signature,
|
| - unsigned int signature_size,
|
| - const unsigned char* data,
|
| - unsigned int data_size,
|
| - bool* signature_match) {
|
| -
|
| - if (!signature_size) {
|
| - // None of the algorithms generate valid zero-length signatures so this
|
| - // will necessarily fail verification. Early return to protect
|
| - // implementations from dealing with a NULL signature pointer.
|
| - *signature_match = false;
|
| - return Status::Success();
|
| - }
|
| -
|
| - DCHECK(signature);
|
| -
|
| - switch (algorithm.id()) {
|
| - case blink::WebCryptoAlgorithmIdHmac:
|
| - return VerifyHmac(algorithm, key, signature, signature_size,
|
| - data, data_size, signature_match);
|
| - case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5:
|
| - return VerifyRsaSsaPkcs1v1_5(algorithm, key, signature, signature_size,
|
| - data, data_size, signature_match);
|
| - default:
|
| - return Status::ErrorUnsupported();
|
| - }
|
| -}
|
| -
|
| -Status WebCryptoImpl::ImportRsaPublicKeyInternal(
|
| - const unsigned char* modulus_data,
|
| - unsigned int modulus_size,
|
| - const unsigned char* exponent_data,
|
| - unsigned int exponent_size,
|
| +Status PlatformCrypto::PlatformImportRsaPublicKey(
|
| + const CryptoData& modulus_data,
|
| + const CryptoData& exponent_data,
|
| const blink::WebCryptoAlgorithm& algorithm,
|
| bool extractable,
|
| blink::WebCryptoKeyUsageMask usage_mask,
|
| blink::WebCryptoKey* key) {
|
|
|
| - if (!modulus_size)
|
| + if (!modulus_data.byte_length())
|
| return Status::ErrorImportRsaEmptyModulus();
|
|
|
| - if (!exponent_size)
|
| + if (!exponent_data.byte_length())
|
| return Status::ErrorImportRsaEmptyExponent();
|
|
|
| - DCHECK(modulus_data);
|
| - DCHECK(exponent_data);
|
| + DCHECK(modulus_data.bytes());
|
| + DCHECK(exponent_data.bytes());
|
|
|
| // NSS does not provide a way to create an RSA public key directly from the
|
| // modulus and exponent values, but it can import an DER-encoded ASN.1 blob
|
| @@ -1379,10 +1059,10 @@ Status WebCryptoImpl::ImportRsaPublicKeyInternal(
|
| SECItem exponent;
|
| };
|
| const RsaPublicKeyData pubkey_in = {
|
| - {siUnsignedInteger, const_cast<unsigned char*>(modulus_data),
|
| - modulus_size},
|
| - {siUnsignedInteger, const_cast<unsigned char*>(exponent_data),
|
| - exponent_size}};
|
| + {siUnsignedInteger, const_cast<unsigned char*>(modulus_data.bytes()),
|
| + modulus_data.byte_length()},
|
| + {siUnsignedInteger, const_cast<unsigned char*>(exponent_data.bytes()),
|
| + exponent_data.byte_length()}};
|
| const SEC_ASN1Template rsa_public_key_template[] = {
|
| {SEC_ASN1_SEQUENCE, 0, NULL, sizeof(RsaPublicKeyData)},
|
| {SEC_ASN1_INTEGER, offsetof(RsaPublicKeyData, modulus), },
|
| @@ -1390,8 +1070,8 @@ Status WebCryptoImpl::ImportRsaPublicKeyInternal(
|
| {0, }};
|
|
|
| // DER-encode the public key.
|
| - crypto::ScopedSECItem pubkey_der(SEC_ASN1EncodeItem(
|
| - NULL, NULL, &pubkey_in, rsa_public_key_template));
|
| + crypto::ScopedSECItem pubkey_der(
|
| + SEC_ASN1EncodeItem(NULL, NULL, &pubkey_in, rsa_public_key_template));
|
| if (!pubkey_der)
|
| return Status::Error();
|
|
|
| @@ -1401,7 +1081,7 @@ Status WebCryptoImpl::ImportRsaPublicKeyInternal(
|
| if (!pubkey)
|
| return Status::Error();
|
|
|
| - *key = blink::WebCryptoKey::create(new PublicKeyHandle(pubkey.Pass()),
|
| + *key = blink::WebCryptoKey::create(new PlatformPublicKey(pubkey.Pass()),
|
| blink::WebCryptoKeyTypePublic,
|
| extractable,
|
| algorithm,
|
| @@ -1409,4 +1089,5 @@ Status WebCryptoImpl::ImportRsaPublicKeyInternal(
|
| return Status::Success();
|
| }
|
|
|
| +} // namespace webcrypto
|
| } // namespace content
|
|
|