diff options
author | eroman <eroman@chromium.org> | 2015-10-01 12:38:04 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-10-01 19:40:33 +0000 |
commit | ab1308a6162d76b060d0e02d9ffadacd526627ed (patch) | |
tree | 1380b79e0687c43cf217093d05947bb072f4e9e3 | |
parent | c6ce7678b2d6d02dd1f47f330a5aed368fcb9c6a (diff) | |
download | chromium_src-ab1308a6162d76b060d0e02d9ffadacd526627ed.zip chromium_src-ab1308a6162d76b060d0e02d9ffadacd526627ed.tar.gz chromium_src-ab1308a6162d76b060d0e02d9ffadacd526627ed.tar.bz2 |
Finish re-organizing the components/webcrypto files
webcrypto_util.h and util_openssl have been deleted.
The final file naming and organization for the various "utility" code is:
* blink_key_handle.h -- Code for creating and extracting values from blink::WebCryptoKeyHandle.
* secret_key_util.h -- Common code used by symmetric key algorithms.
* asymmetric_key_util.h -- Common code used by asymmetric key algorithms.
* test_helpers.h -- Common code used by unit tests.
* util.h -- Common code that didn't quite fit into the other _util files. There isn't enough stuff in here yet to justify finer grained file structure.
Review URL: https://codereview.chromium.org/1360253003
Cr-Commit-Position: refs/heads/master@{#351865}
45 files changed, 543 insertions, 492 deletions
diff --git a/components/webcrypto/BUILD.gn b/components/webcrypto/BUILD.gn index 3472831..aebf172 100644 --- a/components/webcrypto/BUILD.gn +++ b/components/webcrypto/BUILD.gn @@ -20,6 +20,8 @@ source_set("webcrypto") { "algorithms/aes_ctr.cc", "algorithms/aes_gcm.cc", "algorithms/aes_kw.cc", + "algorithms/asymmetric_key_util.cc", + "algorithms/asymmetric_key_util.h", "algorithms/ec.cc", "algorithms/ec.h", "algorithms/ecdh.cc", @@ -37,22 +39,20 @@ source_set("webcrypto") { "algorithms/secret_key_util.cc", "algorithms/secret_key_util.h", "algorithms/sha.cc", - "algorithms/util_openssl.cc", - "algorithms/util_openssl.h", + "algorithms/util.cc", + "algorithms/util.h", + "blink_key_handle.cc", + "blink_key_handle.h", "crypto_data.cc", "crypto_data.h", "generate_key_result.cc", "generate_key_result.h", "jwk.cc", "jwk.h", - "key.cc", - "key.h", "status.cc", "status.h", "webcrypto_impl.cc", "webcrypto_impl.h", - "webcrypto_util.cc", - "webcrypto_util.h", ] deps = [ diff --git a/components/webcrypto/algorithm_dispatch.cc b/components/webcrypto/algorithm_dispatch.cc index feacd23..63f529b 100644 --- a/components/webcrypto/algorithm_dispatch.cc +++ b/components/webcrypto/algorithm_dispatch.cc @@ -11,7 +11,6 @@ #include "components/webcrypto/crypto_data.h" #include "components/webcrypto/generate_key_result.h" #include "components/webcrypto/status.h" -#include "components/webcrypto/webcrypto_util.h" #include "crypto/openssl_util.h" #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" diff --git a/components/webcrypto/algorithm_implementation.cc b/components/webcrypto/algorithm_implementation.cc index 5f54791..8db7482 100644 --- a/components/webcrypto/algorithm_implementation.cc +++ b/components/webcrypto/algorithm_implementation.cc @@ -4,7 +4,7 @@ #include "components/webcrypto/algorithm_implementation.h" -#include "components/webcrypto/key.h" +#include "components/webcrypto/blink_key_handle.h" #include "components/webcrypto/status.h" namespace webcrypto { diff --git a/components/webcrypto/algorithms/aes.cc b/components/webcrypto/algorithms/aes.cc index f42d508..09dbfd4 100644 --- a/components/webcrypto/algorithms/aes.cc +++ b/components/webcrypto/algorithms/aes.cc @@ -6,11 +6,10 @@ #include "base/logging.h" #include "components/webcrypto/algorithms/secret_key_util.h" +#include "components/webcrypto/blink_key_handle.h" #include "components/webcrypto/crypto_data.h" #include "components/webcrypto/jwk.h" -#include "components/webcrypto/key.h" #include "components/webcrypto/status.h" -#include "components/webcrypto/webcrypto_util.h" #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" @@ -31,6 +30,14 @@ std::string MakeJwkAesAlgorithmName(const std::string& suffix, return std::string(); } +// Synthesizes an import algorithm given a key algorithm, so that +// deserialization can re-use the ImportKey*() methods. +blink::WebCryptoAlgorithm SynthesizeImportAlgorithmForClone( + const blink::WebCryptoKeyAlgorithm& algorithm) { + return blink::WebCryptoAlgorithm::adoptParamsAndCreate(algorithm.id(), + nullptr); +} + } // namespace AesAlgorithm::AesAlgorithm(blink::WebCryptoKeyUsageMask all_key_usages, @@ -50,7 +57,7 @@ Status AesAlgorithm::GenerateKey(const blink::WebCryptoAlgorithm& algorithm, bool extractable, blink::WebCryptoKeyUsageMask usages, GenerateKeyResult* result) const { - Status status = CheckKeyCreationUsages(all_key_usages_, usages, false); + Status status = CheckSecretKeyCreationUsages(all_key_usages_, usages); if (status.IsError()) return status; @@ -74,7 +81,7 @@ Status AesAlgorithm::VerifyKeyUsagesBeforeImportKey( switch (format) { case blink::WebCryptoKeyFormatRaw: case blink::WebCryptoKeyFormatJwk: - return CheckKeyCreationUsages(all_key_usages_, usages, false); + return CheckSecretKeyCreationUsages(all_key_usages_, usages); default: return Status::ErrorUnsupportedImportKeyFormat(); } @@ -164,8 +171,8 @@ Status AesAlgorithm::DeserializeKeyForClone( blink::WebCryptoKeyUsageMask usages, const CryptoData& key_data, blink::WebCryptoKey* key) const { - return ImportKeyRaw(key_data, CreateAlgorithm(algorithm.id()), extractable, - usages, key); + return ImportKeyRaw(key_data, SynthesizeImportAlgorithmForClone(algorithm), + extractable, usages, key); } Status AesAlgorithm::GetKeyLength( diff --git a/components/webcrypto/algorithms/aes_cbc.cc b/components/webcrypto/algorithms/aes_cbc.cc index 849f181..0d9c88e 100644 --- a/components/webcrypto/algorithms/aes_cbc.cc +++ b/components/webcrypto/algorithms/aes_cbc.cc @@ -9,11 +9,10 @@ #include "base/numerics/safe_math.h" #include "base/stl_util.h" #include "components/webcrypto/algorithms/aes.h" -#include "components/webcrypto/algorithms/util_openssl.h" +#include "components/webcrypto/algorithms/util.h" +#include "components/webcrypto/blink_key_handle.h" #include "components/webcrypto/crypto_data.h" -#include "components/webcrypto/key.h" #include "components/webcrypto/status.h" -#include "components/webcrypto/webcrypto_util.h" #include "crypto/openssl_util.h" #include "crypto/scoped_openssl_types.h" #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" diff --git a/components/webcrypto/algorithms/aes_cbc_unittest.cc b/components/webcrypto/algorithms/aes_cbc_unittest.cc index 2aec041..44f07ea 100644 --- a/components/webcrypto/algorithms/aes_cbc_unittest.cc +++ b/components/webcrypto/algorithms/aes_cbc_unittest.cc @@ -3,11 +3,11 @@ // found in the LICENSE file. #include "base/stl_util.h" +#include "base/values.h" #include "components/webcrypto/algorithm_dispatch.h" #include "components/webcrypto/algorithms/test_helpers.h" #include "components/webcrypto/crypto_data.h" #include "components/webcrypto/status.h" -#include "components/webcrypto/webcrypto_util.h" #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" diff --git a/components/webcrypto/algorithms/aes_ctr.cc b/components/webcrypto/algorithms/aes_ctr.cc index 9c9892c..f4c16b6 100644 --- a/components/webcrypto/algorithms/aes_ctr.cc +++ b/components/webcrypto/algorithms/aes_ctr.cc @@ -10,11 +10,10 @@ #include "base/numerics/safe_math.h" #include "base/stl_util.h" #include "components/webcrypto/algorithms/aes.h" -#include "components/webcrypto/algorithms/util_openssl.h" +#include "components/webcrypto/algorithms/util.h" +#include "components/webcrypto/blink_key_handle.h" #include "components/webcrypto/crypto_data.h" -#include "components/webcrypto/key.h" #include "components/webcrypto/status.h" -#include "components/webcrypto/webcrypto_util.h" #include "crypto/openssl_util.h" #include "crypto/scoped_openssl_types.h" #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" diff --git a/components/webcrypto/algorithms/aes_ctr_unittest.cc b/components/webcrypto/algorithms/aes_ctr_unittest.cc index c9c26f8..9bdbf38 100644 --- a/components/webcrypto/algorithms/aes_ctr_unittest.cc +++ b/components/webcrypto/algorithms/aes_ctr_unittest.cc @@ -3,11 +3,11 @@ // found in the LICENSE file. #include "base/stl_util.h" +#include "base/values.h" #include "components/webcrypto/algorithm_dispatch.h" #include "components/webcrypto/algorithms/test_helpers.h" #include "components/webcrypto/crypto_data.h" #include "components/webcrypto/status.h" -#include "components/webcrypto/webcrypto_util.h" #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" diff --git a/components/webcrypto/algorithms/aes_gcm.cc b/components/webcrypto/algorithms/aes_gcm.cc index 57fa77f..3685bd9 100644 --- a/components/webcrypto/algorithms/aes_gcm.cc +++ b/components/webcrypto/algorithms/aes_gcm.cc @@ -8,11 +8,10 @@ #include "base/logging.h" #include "base/stl_util.h" #include "components/webcrypto/algorithms/aes.h" -#include "components/webcrypto/algorithms/util_openssl.h" +#include "components/webcrypto/algorithms/util.h" +#include "components/webcrypto/blink_key_handle.h" #include "components/webcrypto/crypto_data.h" -#include "components/webcrypto/key.h" #include "components/webcrypto/status.h" -#include "components/webcrypto/webcrypto_util.h" #include "crypto/openssl_util.h" #include "crypto/scoped_openssl_types.h" #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" diff --git a/components/webcrypto/algorithms/aes_gcm_unittest.cc b/components/webcrypto/algorithms/aes_gcm_unittest.cc index 60e8582..94ba9be 100644 --- a/components/webcrypto/algorithms/aes_gcm_unittest.cc +++ b/components/webcrypto/algorithms/aes_gcm_unittest.cc @@ -3,11 +3,11 @@ // found in the LICENSE file. #include "base/stl_util.h" +#include "base/values.h" #include "components/webcrypto/algorithm_dispatch.h" #include "components/webcrypto/algorithms/test_helpers.h" #include "components/webcrypto/crypto_data.h" #include "components/webcrypto/status.h" -#include "components/webcrypto/webcrypto_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" diff --git a/components/webcrypto/algorithms/aes_kw.cc b/components/webcrypto/algorithms/aes_kw.cc index 89ef6d3..295d911 100644 --- a/components/webcrypto/algorithms/aes_kw.cc +++ b/components/webcrypto/algorithms/aes_kw.cc @@ -9,9 +9,9 @@ #include "base/numerics/safe_math.h" #include "base/stl_util.h" #include "components/webcrypto/algorithms/aes.h" -#include "components/webcrypto/algorithms/util_openssl.h" +#include "components/webcrypto/algorithms/util.h" +#include "components/webcrypto/blink_key_handle.h" #include "components/webcrypto/crypto_data.h" -#include "components/webcrypto/key.h" #include "components/webcrypto/status.h" #include "crypto/openssl_util.h" #include "crypto/scoped_openssl_types.h" diff --git a/components/webcrypto/algorithms/aes_kw_unittest.cc b/components/webcrypto/algorithms/aes_kw_unittest.cc index a2e0837..3002544 100644 --- a/components/webcrypto/algorithms/aes_kw_unittest.cc +++ b/components/webcrypto/algorithms/aes_kw_unittest.cc @@ -3,11 +3,11 @@ // found in the LICENSE file. #include "base/stl_util.h" +#include "base/values.h" #include "components/webcrypto/algorithm_dispatch.h" #include "components/webcrypto/algorithms/test_helpers.h" #include "components/webcrypto/crypto_data.h" #include "components/webcrypto/status.h" -#include "components/webcrypto/webcrypto_util.h" #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" diff --git a/components/webcrypto/algorithms/util_openssl.cc b/components/webcrypto/algorithms/asymmetric_key_util.cc index 34b26a4..9abd47c 100644 --- a/components/webcrypto/algorithms/util_openssl.cc +++ b/components/webcrypto/algorithms/asymmetric_key_util.cc @@ -1,20 +1,16 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. +// Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/webcrypto/algorithms/util_openssl.h" +#include "components/webcrypto/algorithms/asymmetric_key_util.h" -#include <openssl/evp.h> #include <openssl/pkcs12.h> -#include <openssl/rand.h> -#include "base/stl_util.h" -#include "components/webcrypto/algorithm_implementations.h" +#include "components/webcrypto/algorithms/util.h" +#include "components/webcrypto/blink_key_handle.h" #include "components/webcrypto/crypto_data.h" #include "components/webcrypto/generate_key_result.h" -#include "components/webcrypto/key.h" #include "components/webcrypto/status.h" -#include "components/webcrypto/webcrypto_util.h" #include "crypto/openssl_util.h" namespace webcrypto { @@ -61,72 +57,6 @@ Status ExportPKeyPkcs8(EVP_PKEY* key, std::vector<uint8_t>* buffer) { } // namespace -const EVP_MD* GetDigest(blink::WebCryptoAlgorithmId id) { - switch (id) { - case blink::WebCryptoAlgorithmIdSha1: - return EVP_sha1(); - case blink::WebCryptoAlgorithmIdSha256: - return EVP_sha256(); - case blink::WebCryptoAlgorithmIdSha384: - return EVP_sha384(); - case blink::WebCryptoAlgorithmIdSha512: - return EVP_sha512(); - default: - return NULL; - } -} - -Status AeadEncryptDecrypt(EncryptOrDecrypt mode, - const std::vector<uint8_t>& raw_key, - const CryptoData& data, - unsigned int tag_length_bytes, - const CryptoData& iv, - const CryptoData& additional_data, - const EVP_AEAD* aead_alg, - std::vector<uint8_t>* buffer) { - crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); - EVP_AEAD_CTX ctx; - - if (!aead_alg) - return Status::ErrorUnexpected(); - - if (!EVP_AEAD_CTX_init(&ctx, aead_alg, vector_as_array(&raw_key), - raw_key.size(), tag_length_bytes, NULL)) { - return Status::OperationError(); - } - - crypto::ScopedOpenSSL<EVP_AEAD_CTX, EVP_AEAD_CTX_cleanup> ctx_cleanup(&ctx); - - size_t len; - int ok; - - if (mode == DECRYPT) { - if (data.byte_length() < tag_length_bytes) - return Status::ErrorDataTooSmall(); - - buffer->resize(data.byte_length() - tag_length_bytes); - - ok = EVP_AEAD_CTX_open(&ctx, vector_as_array(buffer), &len, buffer->size(), - iv.bytes(), iv.byte_length(), data.bytes(), - data.byte_length(), additional_data.bytes(), - additional_data.byte_length()); - } else { - // No need to check for unsigned integer overflow here (seal fails if - // the output buffer is too small). - buffer->resize(data.byte_length() + EVP_AEAD_max_overhead(aead_alg)); - - ok = EVP_AEAD_CTX_seal(&ctx, vector_as_array(buffer), &len, buffer->size(), - iv.bytes(), iv.byte_length(), data.bytes(), - data.byte_length(), additional_data.bytes(), - additional_data.byte_length()); - } - - if (!ok) - return Status::OperationError(); - buffer->resize(len); - return Status::Success(); -} - Status CreateWebCryptoPublicKey(crypto::ScopedEVP_PKEY public_key, const blink::WebCryptoKeyAlgorithm& algorithm, bool extractable, @@ -163,6 +93,20 @@ Status CreateWebCryptoPrivateKey(crypto::ScopedEVP_PKEY private_key, return Status::Success(); } +Status CheckPrivateKeyCreationUsages( + blink::WebCryptoKeyUsageMask all_possible_usages, + blink::WebCryptoKeyUsageMask actual_usages) { + return CheckKeyCreationUsages(all_possible_usages, actual_usages, + EmptyUsagePolicy::REJECT_EMPTY); +} + +Status CheckPublicKeyCreationUsages( + blink::WebCryptoKeyUsageMask all_possible_usages, + blink::WebCryptoKeyUsageMask actual_usages) { + return CheckKeyCreationUsages(all_possible_usages, actual_usages, + EmptyUsagePolicy::ALLOW_EMPTY); +} + Status ImportUnverifiedPkeyFromSpki(const CryptoData& key_data, int expected_pkey_id, crypto::ScopedEVP_PKEY* pkey) { @@ -200,14 +144,51 @@ Status ImportUnverifiedPkeyFromPkcs8(const CryptoData& key_data, return Status::Success(); } -BIGNUM* CreateBIGNUM(const std::string& n) { - return BN_bin2bn(reinterpret_cast<const uint8_t*>(n.data()), n.size(), NULL); +Status VerifyUsagesBeforeImportAsymmetricKey( + blink::WebCryptoKeyFormat format, + blink::WebCryptoKeyUsageMask all_public_key_usages, + blink::WebCryptoKeyUsageMask all_private_key_usages, + blink::WebCryptoKeyUsageMask usages) { + switch (format) { + case blink::WebCryptoKeyFormatSpki: + return CheckPublicKeyCreationUsages(all_public_key_usages, usages); + case blink::WebCryptoKeyFormatPkcs8: + return CheckPrivateKeyCreationUsages(all_private_key_usages, usages); + case blink::WebCryptoKeyFormatJwk: { + // The JWK could represent either a public key or private key. The usages + // must make sense for one of the two. The usages will be checked again by + // ImportKeyJwk() once the key type has been determined. + if (CheckPublicKeyCreationUsages(all_public_key_usages, usages) + .IsError() && + CheckPrivateKeyCreationUsages(all_private_key_usages, usages) + .IsError()) { + return Status::ErrorCreateKeyBadUsages(); + } + return Status::Success(); + } + default: + return Status::ErrorUnsupportedImportKeyFormat(); + } } -std::vector<uint8_t> BIGNUMToVector(const BIGNUM* n) { - std::vector<uint8_t> v(BN_num_bytes(n)); - BN_bn2bin(n, vector_as_array(&v)); - return v; +Status GetUsagesForGenerateAsymmetricKey( + blink::WebCryptoKeyUsageMask combined_usages, + blink::WebCryptoKeyUsageMask all_public_usages, + blink::WebCryptoKeyUsageMask all_private_usages, + blink::WebCryptoKeyUsageMask* public_usages, + blink::WebCryptoKeyUsageMask* private_usages) { + // Ensure that the combined usages is a subset of the total possible usages. + Status status = + CheckKeyCreationUsages(all_public_usages | all_private_usages, + combined_usages, EmptyUsagePolicy::ALLOW_EMPTY); + if (status.IsError()) + return status; + + *public_usages = combined_usages & all_public_usages; + *private_usages = combined_usages & all_private_usages; + + // Ensure that the private key has non-empty usages. + return CheckPrivateKeyCreationUsages(all_private_usages, *private_usages); } } // namespace webcrypto diff --git a/components/webcrypto/algorithms/util_openssl.h b/components/webcrypto/algorithms/asymmetric_key_util.h index f3e4dda..51ed79a 100644 --- a/components/webcrypto/algorithms/util_openssl.h +++ b/components/webcrypto/algorithms/asymmetric_key_util.h @@ -1,44 +1,21 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. +// Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_WEBCRYPTO_ALGORITHMS_UTIL_OPENSSL_H_ -#define COMPONENTS_WEBCRYPTO_ALGORITHMS_UTIL_OPENSSL_H_ - -#include <string> -#include <vector> - -#include <openssl/base.h> +#ifndef COMPONENTS_WEBCRYPTO_ALGORITHMS_ASYMMETRIC_KEY_UTIL_ +#define COMPONENTS_WEBCRYPTO_ALGORITHMS_ASYMMETRIC_KEY_UTIL_ #include "crypto/scoped_openssl_types.h" #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" #include "third_party/WebKit/public/platform/WebCryptoKey.h" +// This file contains functions shared by multiple asymmetric key algorithms. + namespace webcrypto { class CryptoData; -class GenerateKeyResult; class Status; -// The values of these constants correspond with the "enc" parameter of -// EVP_CipherInit_ex(), do not change. -enum EncryptOrDecrypt { DECRYPT = 0, ENCRYPT = 1 }; - -const EVP_MD* GetDigest(blink::WebCryptoAlgorithmId id); - -// Does either encryption or decryption for an AEAD algorithm. -// * |mode| controls whether encryption or decryption is done -// * |aead_alg| the algorithm (for instance AES-GCM) -// * |buffer| where the ciphertext or plaintext is written to. -Status AeadEncryptDecrypt(EncryptOrDecrypt mode, - const std::vector<uint8_t>& raw_key, - const CryptoData& data, - unsigned int tag_length_bytes, - const CryptoData& iv, - const CryptoData& additional_data, - const EVP_AEAD* aead_alg, - std::vector<uint8_t>* buffer); - // Creates a WebCrypto public key given an EVP_PKEY. This step includes // exporting the key to SPKI format, for use by serialization later. Status CreateWebCryptoPublicKey(crypto::ScopedEVP_PKEY public_key, @@ -55,6 +32,19 @@ Status CreateWebCryptoPrivateKey(crypto::ScopedEVP_PKEY private_key, blink::WebCryptoKeyUsageMask usages, blink::WebCryptoKey* key); +// Checks that a private key can be created using |actual_usages|, where +// |all_possible_usages| is the full set of allowed private key usages. Note +// that private keys are not allowed to have empty usages. +Status CheckPrivateKeyCreationUsages( + blink::WebCryptoKeyUsageMask all_possible_usages, + blink::WebCryptoKeyUsageMask actual_usages); + +// Checks that a public key can be created using |actual_usages|, where +// |all_possible_usages| is the full set of allowed public key usages +Status CheckPublicKeyCreationUsages( + blink::WebCryptoKeyUsageMask all_possible_usages, + blink::WebCryptoKeyUsageMask actual_usages); + // Imports SPKI bytes to an EVP_PKEY for a public key. The resulting asymmetric // key may be invalid, and should be verified using something like // RSA_check_key(). The only validation performed by this function is to ensure @@ -71,12 +61,23 @@ Status ImportUnverifiedPkeyFromPkcs8(const CryptoData& key_data, int expected_pkey_id, crypto::ScopedEVP_PKEY* pkey); -// Allocates a new BIGNUM given a std::string big-endian representation. -BIGNUM* CreateBIGNUM(const std::string& n); - -// Converts a BIGNUM to a big endian byte array. -std::vector<uint8_t> BIGNUMToVector(const BIGNUM* n); +// Verifies that |usages| is valid when importing a key of the given format. +Status VerifyUsagesBeforeImportAsymmetricKey( + blink::WebCryptoKeyFormat format, + blink::WebCryptoKeyUsageMask all_public_key_usages, + blink::WebCryptoKeyUsageMask all_private_key_usages, + blink::WebCryptoKeyUsageMask usages); + +// Splits the combined usages given to GenerateKey() into the respective usages +// for the public key and private key. Returns an error if the usages are +// invalid. +Status GetUsagesForGenerateAsymmetricKey( + blink::WebCryptoKeyUsageMask combined_usages, + blink::WebCryptoKeyUsageMask all_public_usages, + blink::WebCryptoKeyUsageMask all_private_usages, + blink::WebCryptoKeyUsageMask* public_usages, + blink::WebCryptoKeyUsageMask* private_usages); } // namespace webcrypto -#endif // COMPONENTS_WEBCRYPTO_ALGORITHMS_UTIL_OPENSSL_H_ +#endif // COMPONENTS_WEBCRYPTO_ALGORITHMS_ASYMMETRIC_KEY_UTIL_ diff --git a/components/webcrypto/algorithms/ec.cc b/components/webcrypto/algorithms/ec.cc index 49abbad..20baa57 100644 --- a/components/webcrypto/algorithms/ec.cc +++ b/components/webcrypto/algorithms/ec.cc @@ -11,13 +11,13 @@ #include "base/logging.h" #include "base/stl_util.h" -#include "components/webcrypto/algorithms/util_openssl.h" +#include "components/webcrypto/algorithms/asymmetric_key_util.h" +#include "components/webcrypto/algorithms/util.h" +#include "components/webcrypto/blink_key_handle.h" #include "components/webcrypto/crypto_data.h" #include "components/webcrypto/generate_key_result.h" #include "components/webcrypto/jwk.h" -#include "components/webcrypto/key.h" #include "components/webcrypto/status.h" -#include "components/webcrypto/webcrypto_util.h" #include "crypto/openssl_util.h" #include "crypto/scoped_openssl_types.h" #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" @@ -209,6 +209,15 @@ Status GetPublicKey(EC_KEY* ec, return Status::Success(); } +// Synthesizes an import algorithm given a key algorithm, so that +// deserialization can re-use the ImportKey*() methods. +blink::WebCryptoAlgorithm SynthesizeImportAlgorithmForClone( + const blink::WebCryptoKeyAlgorithm& algorithm) { + return blink::WebCryptoAlgorithm::adoptParamsAndCreate( + algorithm.id(), new blink::WebCryptoEcKeyImportParams( + algorithm.ecParams()->namedCurve())); +} + } // namespace Status EcAlgorithm::GenerateKey(const blink::WebCryptoAlgorithm& algorithm, @@ -379,9 +388,12 @@ Status EcAlgorithm::ImportKeyJwk(const CryptoData& key_data, bool is_private_key = jwk.HasMember("d"); // Now that the key type is known, verify the usages. - status = CheckKeyCreationUsages( - is_private_key ? all_private_key_usages_ : all_public_key_usages_, usages, - !is_private_key); + if (is_private_key) { + status = CheckPrivateKeyCreationUsages(all_private_key_usages_, usages); + } else { + status = CheckPublicKeyCreationUsages(all_public_key_usages_, usages); + } + if (status.IsError()) return status; @@ -525,11 +537,12 @@ Status EcAlgorithm::DeserializeKeyForClone( blink::WebCryptoKeyUsageMask usages, const CryptoData& key_data, blink::WebCryptoKey* key) const { - blink::WebCryptoAlgorithm import_algorithm = CreateEcImportAlgorithm( - algorithm.id(), algorithm.ecParams()->namedCurve()); + blink::WebCryptoAlgorithm import_algorithm = + SynthesizeImportAlgorithmForClone(algorithm); Status status; + // The serialized data will be either SPKI or PKCS8 formatted. switch (type) { case blink::WebCryptoKeyTypePublic: status = diff --git a/components/webcrypto/algorithms/ecdh.cc b/components/webcrypto/algorithms/ecdh.cc index fb63ec2..9da36e9 100644 --- a/components/webcrypto/algorithms/ecdh.cc +++ b/components/webcrypto/algorithms/ecdh.cc @@ -10,12 +10,11 @@ #include "base/stl_util.h" #include "components/webcrypto/algorithm_implementation.h" #include "components/webcrypto/algorithms/ec.h" -#include "components/webcrypto/algorithms/util_openssl.h" +#include "components/webcrypto/algorithms/util.h" +#include "components/webcrypto/blink_key_handle.h" #include "components/webcrypto/crypto_data.h" #include "components/webcrypto/generate_key_result.h" -#include "components/webcrypto/key.h" #include "components/webcrypto/status.h" -#include "components/webcrypto/webcrypto_util.h" #include "crypto/openssl_util.h" #include "crypto/scoped_openssl_types.h" #include "crypto/secure_util.h" diff --git a/components/webcrypto/algorithms/ecdh_unittest.cc b/components/webcrypto/algorithms/ecdh_unittest.cc index 9c5b057..961c6d5 100644 --- a/components/webcrypto/algorithms/ecdh_unittest.cc +++ b/components/webcrypto/algorithms/ecdh_unittest.cc @@ -4,11 +4,11 @@ #include "base/stl_util.h" #include "components/webcrypto/algorithm_dispatch.h" +#include "components/webcrypto/algorithms/ec.h" #include "components/webcrypto/algorithms/test_helpers.h" #include "components/webcrypto/crypto_data.h" #include "components/webcrypto/jwk.h" #include "components/webcrypto/status.h" -#include "components/webcrypto/webcrypto_util.h" #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" diff --git a/components/webcrypto/algorithms/ecdsa.cc b/components/webcrypto/algorithms/ecdsa.cc index 18857c7..367e0f0 100644 --- a/components/webcrypto/algorithms/ecdsa.cc +++ b/components/webcrypto/algorithms/ecdsa.cc @@ -10,12 +10,11 @@ #include "base/stl_util.h" #include "components/webcrypto/algorithm_implementation.h" #include "components/webcrypto/algorithms/ec.h" -#include "components/webcrypto/algorithms/util_openssl.h" +#include "components/webcrypto/algorithms/util.h" +#include "components/webcrypto/blink_key_handle.h" #include "components/webcrypto/crypto_data.h" #include "components/webcrypto/generate_key_result.h" -#include "components/webcrypto/key.h" #include "components/webcrypto/status.h" -#include "components/webcrypto/webcrypto_util.h" #include "crypto/openssl_util.h" #include "crypto/scoped_openssl_types.h" #include "crypto/secure_util.h" @@ -34,7 +33,7 @@ Status GetPKeyAndDigest(const blink::WebCryptoAlgorithm& algorithm, EVP_PKEY** pkey, const EVP_MD** digest) { *pkey = GetEVP_PKEY(key); - *digest = GetDigest(algorithm.ecdsaParams()->hash().id()); + *digest = GetDigest(algorithm.ecdsaParams()->hash()); if (!*digest) return Status::ErrorUnsupported(); return Status::Success(); diff --git a/components/webcrypto/algorithms/ecdsa_unittest.cc b/components/webcrypto/algorithms/ecdsa_unittest.cc index b753f48..4b2e651 100644 --- a/components/webcrypto/algorithms/ecdsa_unittest.cc +++ b/components/webcrypto/algorithms/ecdsa_unittest.cc @@ -8,7 +8,6 @@ #include "components/webcrypto/crypto_data.h" #include "components/webcrypto/jwk.h" #include "components/webcrypto/status.h" -#include "components/webcrypto/webcrypto_util.h" #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" diff --git a/components/webcrypto/algorithms/hkdf.cc b/components/webcrypto/algorithms/hkdf.cc index d02560d..0ccb8579 100644 --- a/components/webcrypto/algorithms/hkdf.cc +++ b/components/webcrypto/algorithms/hkdf.cc @@ -9,11 +9,10 @@ #include "base/stl_util.h" #include "components/webcrypto/algorithm_implementation.h" #include "components/webcrypto/algorithms/secret_key_util.h" -#include "components/webcrypto/algorithms/util_openssl.h" +#include "components/webcrypto/algorithms/util.h" +#include "components/webcrypto/blink_key_handle.h" #include "components/webcrypto/crypto_data.h" -#include "components/webcrypto/key.h" #include "components/webcrypto/status.h" -#include "components/webcrypto/webcrypto_util.h" #include "crypto/openssl_util.h" #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" @@ -34,7 +33,7 @@ class HkdfImplementation : public AlgorithmImplementation { blink::WebCryptoKeyUsageMask usages) const override { if (format != blink::WebCryptoKeyFormatRaw) return Status::ErrorUnsupportedImportKeyFormat(); - return CheckKeyCreationUsages(kValidUsages, usages, false); + return CheckSecretKeyCreationUsages(kValidUsages, usages); } Status ImportKeyRaw(const CryptoData& key_data, @@ -59,7 +58,7 @@ class HkdfImplementation : public AlgorithmImplementation { const blink::WebCryptoHkdfParams* params = algorithm.hkdfParams(); - const EVP_MD* digest_algorithm = GetDigest(params->hash().id()); + const EVP_MD* digest_algorithm = GetDigest(params->hash()); if (!digest_algorithm) return Status::ErrorUnsupported(); diff --git a/components/webcrypto/algorithms/hmac.cc b/components/webcrypto/algorithms/hmac.cc index 021facd..28ef3a0 100644 --- a/components/webcrypto/algorithms/hmac.cc +++ b/components/webcrypto/algorithms/hmac.cc @@ -9,12 +9,11 @@ #include "base/stl_util.h" #include "components/webcrypto/algorithm_implementation.h" #include "components/webcrypto/algorithms/secret_key_util.h" -#include "components/webcrypto/algorithms/util_openssl.h" +#include "components/webcrypto/algorithms/util.h" +#include "components/webcrypto/blink_key_handle.h" #include "components/webcrypto/crypto_data.h" #include "components/webcrypto/jwk.h" -#include "components/webcrypto/key.h" #include "components/webcrypto/status.h" -#include "components/webcrypto/webcrypto_util.h" #include "crypto/openssl_util.h" #include "crypto/secure_util.h" #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" @@ -26,7 +25,7 @@ namespace { Status GetDigestBlockSizeBits(const blink::WebCryptoAlgorithm& algorithm, unsigned int* block_size_bits) { - const EVP_MD* md = GetDigest(algorithm.id()); + const EVP_MD* md = GetDigest(algorithm); if (!md) return Status::ErrorUnsupported(); *block_size_bits = static_cast<unsigned int>(8 * EVP_MD_block_size(md)); @@ -89,7 +88,7 @@ Status SignHmac(const std::vector<uint8_t>& raw_key, std::vector<uint8_t>* buffer) { crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); - const EVP_MD* digest_algorithm = GetDigest(hash.id()); + const EVP_MD* digest_algorithm = GetDigest(hash); if (!digest_algorithm) return Status::ErrorUnsupported(); size_t hmac_expected_length = EVP_MD_size(digest_algorithm); @@ -116,7 +115,7 @@ class HmacImplementation : public AlgorithmImplementation { bool extractable, blink::WebCryptoKeyUsageMask usages, GenerateKeyResult* result) const override { - Status status = CheckKeyCreationUsages(kAllKeyUsages, usages, false); + Status status = CheckSecretKeyCreationUsages(kAllKeyUsages, usages); if (status.IsError()) return status; @@ -146,7 +145,7 @@ class HmacImplementation : public AlgorithmImplementation { switch (format) { case blink::WebCryptoKeyFormatRaw: case blink::WebCryptoKeyFormatJwk: - return CheckKeyCreationUsages(kAllKeyUsages, usages, false); + return CheckSecretKeyCreationUsages(kAllKeyUsages, usages); default: return Status::ErrorUnsupportedImportKeyFormat(); } diff --git a/components/webcrypto/algorithms/hmac_unittest.cc b/components/webcrypto/algorithms/hmac_unittest.cc index 11aa759..4c8a67a 100644 --- a/components/webcrypto/algorithms/hmac_unittest.cc +++ b/components/webcrypto/algorithms/hmac_unittest.cc @@ -4,11 +4,11 @@ #include "base/logging.h" #include "base/stl_util.h" +#include "base/values.h" #include "components/webcrypto/algorithm_dispatch.h" #include "components/webcrypto/algorithms/test_helpers.h" #include "components/webcrypto/crypto_data.h" #include "components/webcrypto/status.h" -#include "components/webcrypto/webcrypto_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" diff --git a/components/webcrypto/algorithms/pbkdf2.cc b/components/webcrypto/algorithms/pbkdf2.cc index 609e744..b5cf5ca 100644 --- a/components/webcrypto/algorithms/pbkdf2.cc +++ b/components/webcrypto/algorithms/pbkdf2.cc @@ -5,11 +5,10 @@ #include "base/stl_util.h" #include "components/webcrypto/algorithm_implementation.h" #include "components/webcrypto/algorithms/secret_key_util.h" -#include "components/webcrypto/algorithms/util_openssl.h" +#include "components/webcrypto/algorithms/util.h" +#include "components/webcrypto/blink_key_handle.h" #include "components/webcrypto/crypto_data.h" -#include "components/webcrypto/key.h" #include "components/webcrypto/status.h" -#include "components/webcrypto/webcrypto_util.h" #include "crypto/openssl_util.h" #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" @@ -30,7 +29,7 @@ class Pbkdf2Implementation : public AlgorithmImplementation { blink::WebCryptoKeyUsageMask usages) const override { switch (format) { case blink::WebCryptoKeyFormatRaw: - return CheckKeyCreationUsages(kAllKeyUsages, usages, false); + return CheckSecretKeyCreationUsages(kAllKeyUsages, usages); default: return Status::ErrorUnsupportedImportKeyFormat(); } @@ -64,8 +63,7 @@ class Pbkdf2Implementation : public AlgorithmImplementation { const blink::WebCryptoPbkdf2Params* params = algorithm.pbkdf2Params(); - const blink::WebCryptoAlgorithm& hash = params->hash(); - const EVP_MD* digest_algorithm = GetDigest(hash.id()); + const EVP_MD* digest_algorithm = GetDigest(params->hash()); if (!digest_algorithm) return Status::ErrorUnsupported(); diff --git a/components/webcrypto/algorithms/rsa.cc b/components/webcrypto/algorithms/rsa.cc index d99f909..892a5a0 100644 --- a/components/webcrypto/algorithms/rsa.cc +++ b/components/webcrypto/algorithms/rsa.cc @@ -8,13 +8,13 @@ #include "base/logging.h" #include "base/stl_util.h" -#include "components/webcrypto/algorithms/util_openssl.h" +#include "components/webcrypto/algorithms/asymmetric_key_util.h" +#include "components/webcrypto/algorithms/util.h" +#include "components/webcrypto/blink_key_handle.h" #include "components/webcrypto/crypto_data.h" #include "components/webcrypto/generate_key_result.h" #include "components/webcrypto/jwk.h" -#include "components/webcrypto/key.h" #include "components/webcrypto/status.h" -#include "components/webcrypto/webcrypto_util.h" #include "crypto/openssl_util.h" #include "crypto/scoped_openssl_types.h" #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" @@ -104,6 +104,26 @@ Status ReadRsaKeyJwk(const CryptoData& key_data, return Status::Success(); } +// Converts a (big-endian) WebCrypto BigInteger, with or without leading zeros, +// to unsigned int. +bool BigIntegerToUint(const uint8_t* data, + size_t data_size, + unsigned int* result) { + if (data_size == 0) + return false; + + *result = 0; + for (size_t i = 0; i < data_size; ++i) { + size_t reverse_i = data_size - i - 1; + + if (reverse_i >= sizeof(*result) && data[i]) + return false; // Too large for a uint. + + *result |= data[i] << 8 * reverse_i; + } + return true; +} + // Creates a blink::WebCryptoAlgorithm having the modulus length and public // exponent of |key|. Status CreateRsaHashedKeyAlgorithm( @@ -228,6 +248,22 @@ Status ImportRsaPublicKey(const blink::WebCryptoAlgorithm& algorithm, extractable, usages, key); } +// Converts a BIGNUM to a big endian byte array. +std::vector<uint8_t> BIGNUMToVector(const BIGNUM* n) { + std::vector<uint8_t> v(BN_num_bytes(n)); + BN_bn2bin(n, vector_as_array(&v)); + return v; +} + +// Synthesizes an import algorithm given a key algorithm, so that +// deserialization can re-use the ImportKey*() methods. +blink::WebCryptoAlgorithm SynthesizeImportAlgorithmForClone( + const blink::WebCryptoKeyAlgorithm& algorithm) { + return blink::WebCryptoAlgorithm::adoptParamsAndCreate( + algorithm.id(), new blink::WebCryptoRsaHashedImportParams( + algorithm.rsaHashedParams()->hash())); +} + } // namespace Status RsaHashedAlgorithm::GenerateKey( @@ -247,12 +283,29 @@ Status RsaHashedAlgorithm::GenerateKey( const blink::WebCryptoRsaHashedKeyGenParams* params = algorithm.rsaHashedKeyGenParams(); + unsigned int modulus_length_bits = params->modulusLengthBits(); + + // Limit the RSA key sizes to: + // * Multiple of 8 bits + // * 256 bits to 16K bits + // + // These correspond with limitations at the time there was an NSS WebCrypto + // implementation. However in practice the upper bound is also helpful + // because generating large RSA keys is very slow. + if (modulus_length_bits < 256 || modulus_length_bits > 16384 || + (modulus_length_bits % 8) != 0) { + return Status::ErrorGenerateRsaUnsupportedModulus(); + } + unsigned int public_exponent = 0; - unsigned int modulus_length_bits = 0; - status = - GetRsaKeyGenParameters(params, &public_exponent, &modulus_length_bits); - if (status.IsError()) - return status; + if (!BigIntegerToUint(params->publicExponent().data(), + params->publicExponent().size(), &public_exponent)) { + return Status::ErrorGenerateKeyPublicExponent(); + } + + // OpenSSL hangs when given bad public exponents. Use a whitelist. + if (public_exponent != 3 && public_exponent != 65537) + return Status::ErrorGenerateKeyPublicExponent(); crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); @@ -380,9 +433,12 @@ Status RsaHashedAlgorithm::ImportKeyJwk( return status; // Once the key type is known, verify the usages. - status = CheckKeyCreationUsages( - jwk.is_private_key ? all_private_key_usages_ : all_public_key_usages_, - usages, !jwk.is_private_key); + if (jwk.is_private_key) { + status = CheckPrivateKeyCreationUsages(all_private_key_usages_, usages); + } else { + status = CheckPublicKeyCreationUsages(all_public_key_usages_, usages); + } + if (status.IsError()) return status; @@ -465,11 +521,12 @@ Status RsaHashedAlgorithm::DeserializeKeyForClone( blink::WebCryptoKeyUsageMask usages, const CryptoData& key_data, blink::WebCryptoKey* key) const { - blink::WebCryptoAlgorithm import_algorithm = CreateRsaHashedImportAlgorithm( - algorithm.id(), algorithm.rsaHashedParams()->hash().id()); + blink::WebCryptoAlgorithm import_algorithm = + SynthesizeImportAlgorithmForClone(algorithm); Status status; + // The serialized data will be either SPKI or PKCS8 formatted. switch (type) { case blink::WebCryptoKeyTypePublic: status = diff --git a/components/webcrypto/algorithms/rsa_oaep.cc b/components/webcrypto/algorithms/rsa_oaep.cc index f68a411..5a697095 100644 --- a/components/webcrypto/algorithms/rsa_oaep.cc +++ b/components/webcrypto/algorithms/rsa_oaep.cc @@ -6,9 +6,9 @@ #include "base/stl_util.h" #include "components/webcrypto/algorithms/rsa.h" -#include "components/webcrypto/algorithms/util_openssl.h" +#include "components/webcrypto/algorithms/util.h" +#include "components/webcrypto/blink_key_handle.h" #include "components/webcrypto/crypto_data.h" -#include "components/webcrypto/key.h" #include "components/webcrypto/status.h" #include "crypto/openssl_util.h" #include "crypto/scoped_openssl_types.h" @@ -42,8 +42,7 @@ Status CommonEncryptDecrypt(InitFunc init_func, crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); EVP_PKEY* pkey = GetEVP_PKEY(key); - const EVP_MD* digest = - GetDigest(key.algorithm().rsaHashedParams()->hash().id()); + const EVP_MD* digest = GetDigest(key.algorithm().rsaHashedParams()->hash()); if (!digest) return Status::ErrorUnsupported(); diff --git a/components/webcrypto/algorithms/rsa_oaep_unittest.cc b/components/webcrypto/algorithms/rsa_oaep_unittest.cc index 6d3811a..32cd135 100644 --- a/components/webcrypto/algorithms/rsa_oaep_unittest.cc +++ b/components/webcrypto/algorithms/rsa_oaep_unittest.cc @@ -9,7 +9,6 @@ #include "components/webcrypto/crypto_data.h" #include "components/webcrypto/jwk.h" #include "components/webcrypto/status.h" -#include "components/webcrypto/webcrypto_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" diff --git a/components/webcrypto/algorithms/rsa_pss_unittest.cc b/components/webcrypto/algorithms/rsa_pss_unittest.cc index 00ef290..e8b2bfd 100644 --- a/components/webcrypto/algorithms/rsa_pss_unittest.cc +++ b/components/webcrypto/algorithms/rsa_pss_unittest.cc @@ -9,7 +9,6 @@ #include "components/webcrypto/crypto_data.h" #include "components/webcrypto/jwk.h" #include "components/webcrypto/status.h" -#include "components/webcrypto/webcrypto_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" #include "third_party/WebKit/public/platform/WebCryptoKey.h" diff --git a/components/webcrypto/algorithms/rsa_sign.cc b/components/webcrypto/algorithms/rsa_sign.cc index 97522ce..5c038b5 100644 --- a/components/webcrypto/algorithms/rsa_sign.cc +++ b/components/webcrypto/algorithms/rsa_sign.cc @@ -5,9 +5,9 @@ #include "base/numerics/safe_math.h" #include "base/stl_util.h" #include "components/webcrypto/algorithms/rsa_sign.h" -#include "components/webcrypto/algorithms/util_openssl.h" +#include "components/webcrypto/algorithms/util.h" +#include "components/webcrypto/blink_key_handle.h" #include "components/webcrypto/crypto_data.h" -#include "components/webcrypto/key.h" #include "components/webcrypto/status.h" #include "crypto/openssl_util.h" #include "crypto/scoped_openssl_types.h" @@ -24,7 +24,7 @@ Status GetPKeyAndDigest(const blink::WebCryptoKey& key, const EVP_MD** digest) { *pkey = GetEVP_PKEY(key); - *digest = GetDigest(key.algorithm().rsaHashedParams()->hash().id()); + *digest = GetDigest(key.algorithm().rsaHashedParams()->hash()); if (!*digest) return Status::ErrorUnsupported(); diff --git a/components/webcrypto/algorithms/rsa_ssa_unittest.cc b/components/webcrypto/algorithms/rsa_ssa_unittest.cc index 60caa508..31cc967 100644 --- a/components/webcrypto/algorithms/rsa_ssa_unittest.cc +++ b/components/webcrypto/algorithms/rsa_ssa_unittest.cc @@ -4,11 +4,11 @@ #include "base/logging.h" #include "base/stl_util.h" +#include "base/values.h" #include "components/webcrypto/algorithm_dispatch.h" #include "components/webcrypto/algorithms/test_helpers.h" #include "components/webcrypto/crypto_data.h" #include "components/webcrypto/status.h" -#include "components/webcrypto/webcrypto_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" #include "third_party/WebKit/public/platform/WebCryptoKey.h" diff --git a/components/webcrypto/algorithms/secret_key_util.cc b/components/webcrypto/algorithms/secret_key_util.cc index 8e20144..dcdecfa 100644 --- a/components/webcrypto/algorithms/secret_key_util.cc +++ b/components/webcrypto/algorithms/secret_key_util.cc @@ -7,12 +7,12 @@ #include <openssl/rand.h> #include "base/stl_util.h" +#include "components/webcrypto/algorithms/util.h" +#include "components/webcrypto/blink_key_handle.h" #include "components/webcrypto/crypto_data.h" #include "components/webcrypto/generate_key_result.h" #include "components/webcrypto/jwk.h" -#include "components/webcrypto/key.h" #include "components/webcrypto/status.h" -#include "components/webcrypto/webcrypto_util.h" #include "crypto/openssl_util.h" namespace webcrypto { @@ -51,6 +51,13 @@ Status CreateWebCryptoSecretKey(const CryptoData& key_data, return Status::Success(); } +Status CheckSecretKeyCreationUsages( + blink::WebCryptoKeyUsageMask all_possible_usages, + blink::WebCryptoKeyUsageMask actual_usages) { + return CheckKeyCreationUsages(all_possible_usages, actual_usages, + EmptyUsagePolicy::REJECT_EMPTY); +} + void WriteSecretKeyJwk(const CryptoData& raw_key_data, const std::string& algorithm, bool extractable, diff --git a/components/webcrypto/algorithms/secret_key_util.h b/components/webcrypto/algorithms/secret_key_util.h index 19ebdbb..cfef769 100644 --- a/components/webcrypto/algorithms/secret_key_util.h +++ b/components/webcrypto/algorithms/secret_key_util.h @@ -30,7 +30,7 @@ Status GenerateWebCryptoSecretKey(const blink::WebCryptoKeyAlgorithm& algorithm, unsigned int keylen_bits, GenerateKeyResult* result); -// Creates a WebCrypto secret key given a the raw data. The provided |key_data| +// Creates a WebCrypto secret key given the raw data. The provided |key_data| // will be copied into the new key. This function does not do any validation // checks for the provided parameters. Status CreateWebCryptoSecretKey(const CryptoData& key_data, @@ -39,6 +39,11 @@ Status CreateWebCryptoSecretKey(const CryptoData& key_data, blink::WebCryptoKeyUsageMask usages, blink::WebCryptoKey* key); +// Checks that |actual_usages| is a non-empty subset of |all_possible_usages|. +Status CheckSecretKeyCreationUsages( + blink::WebCryptoKeyUsageMask all_possible_usages, + blink::WebCryptoKeyUsageMask actual_usages); + // Writes a JWK-formatted symmetric key to |jwk_key_data|. // * raw_key_data: The actual key data // * algorithm: The JWK algorithm name (i.e. "alg") diff --git a/components/webcrypto/algorithms/sha.cc b/components/webcrypto/algorithms/sha.cc index cd1a333..2d8b544 100644 --- a/components/webcrypto/algorithms/sha.cc +++ b/components/webcrypto/algorithms/sha.cc @@ -9,10 +9,9 @@ #include "base/logging.h" #include "base/stl_util.h" #include "components/webcrypto/algorithm_implementation.h" -#include "components/webcrypto/algorithms/util_openssl.h" +#include "components/webcrypto/algorithms/util.h" #include "components/webcrypto/crypto_data.h" #include "components/webcrypto/status.h" -#include "components/webcrypto/webcrypto_util.h" #include "crypto/openssl_util.h" #include "crypto/scoped_openssl_types.h" @@ -24,9 +23,9 @@ namespace { // part of WebCrypto, that allows chunks of data to be streamed in before // computing a SHA-* digest (as opposed to ShaImplementation, which computes // digests over complete messages) -class DigestorOpenSsl : public blink::WebCryptoDigestor { +class DigestorImpl : public blink::WebCryptoDigestor { public: - explicit DigestorOpenSsl(blink::WebCryptoAlgorithmId algorithm_id) + explicit DigestorImpl(blink::WebCryptoAlgorithmId algorithm_id) : initialized_(false), digest_context_(EVP_MD_CTX_create()), algorithm_id_(algorithm_id) {} @@ -112,7 +111,7 @@ class ShaImplementation : public AlgorithmImplementation { Status Digest(const blink::WebCryptoAlgorithm& algorithm, const CryptoData& data, std::vector<uint8_t>* buffer) const override { - DigestorOpenSsl digestor(algorithm.id()); + DigestorImpl digestor(algorithm.id()); Status error = digestor.ConsumeWithStatus(data.bytes(), data.byte_length()); // http://crbug.com/366427: the spec does not define any other failures for // digest, so none of the subsequent errors are spec compliant. @@ -130,7 +129,7 @@ scoped_ptr<AlgorithmImplementation> CreateShaImplementation() { scoped_ptr<blink::WebCryptoDigestor> CreateDigestorImplementation( blink::WebCryptoAlgorithmId algorithm) { - return scoped_ptr<blink::WebCryptoDigestor>(new DigestorOpenSsl(algorithm)); + return scoped_ptr<blink::WebCryptoDigestor>(new DigestorImpl(algorithm)); } } // namespace webcrypto diff --git a/components/webcrypto/algorithms/sha_unittest.cc b/components/webcrypto/algorithms/sha_unittest.cc index bc0d04f..4e82d98 100644 --- a/components/webcrypto/algorithms/sha_unittest.cc +++ b/components/webcrypto/algorithms/sha_unittest.cc @@ -4,11 +4,11 @@ #include "base/logging.h" #include "base/stl_util.h" +#include "base/values.h" #include "components/webcrypto/algorithm_dispatch.h" #include "components/webcrypto/algorithms/test_helpers.h" #include "components/webcrypto/crypto_data.h" #include "components/webcrypto/status.h" -#include "components/webcrypto/webcrypto_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" #include "third_party/WebKit/public/platform/WebCryptoKey.h" diff --git a/components/webcrypto/algorithms/test_helpers.cc b/components/webcrypto/algorithms/test_helpers.cc index b096ac3..22db00f 100644 --- a/components/webcrypto/algorithms/test_helpers.cc +++ b/components/webcrypto/algorithms/test_helpers.cc @@ -21,7 +21,6 @@ #include "components/webcrypto/generate_key_result.h" #include "components/webcrypto/jwk.h" #include "components/webcrypto/status.h" -#include "components/webcrypto/webcrypto_util.h" #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" #include "third_party/re2/re2/re2.h" @@ -663,4 +662,23 @@ blink::WebCryptoAlgorithm CreateHmacImportAlgorithmNoLength( new blink::WebCryptoHmacImportParams(CreateAlgorithm(hash_id), false, 0)); } +blink::WebCryptoAlgorithm CreateAlgorithm(blink::WebCryptoAlgorithmId id) { + return blink::WebCryptoAlgorithm::adoptParamsAndCreate(id, nullptr); +} + +blink::WebCryptoAlgorithm CreateRsaHashedImportAlgorithm( + blink::WebCryptoAlgorithmId id, + blink::WebCryptoAlgorithmId hash_id) { + DCHECK(blink::WebCryptoAlgorithm::isHash(hash_id)); + return blink::WebCryptoAlgorithm::adoptParamsAndCreate( + id, new blink::WebCryptoRsaHashedImportParams(CreateAlgorithm(hash_id))); +} + +blink::WebCryptoAlgorithm CreateEcImportAlgorithm( + blink::WebCryptoAlgorithmId id, + blink::WebCryptoNamedCurve named_curve) { + return blink::WebCryptoAlgorithm::adoptParamsAndCreate( + id, new blink::WebCryptoEcKeyImportParams(named_curve)); +} + } // namespace webcrypto diff --git a/components/webcrypto/algorithms/test_helpers.h b/components/webcrypto/algorithms/test_helpers.h index 1887255..3cc87d2 100644 --- a/components/webcrypto/algorithms/test_helpers.h +++ b/components/webcrypto/algorithms/test_helpers.h @@ -217,6 +217,20 @@ blink::WebCryptoAlgorithm CreateHmacImportAlgorithm( blink::WebCryptoAlgorithm CreateHmacImportAlgorithmNoLength( blink::WebCryptoAlgorithmId hash_id); +// Creates a WebCryptoAlgorithm without any parameters. +blink::WebCryptoAlgorithm CreateAlgorithm(blink::WebCryptoAlgorithmId id); + +// Creates an import algorithm for RSA algorithms that take a hash. +// It is an error to call this with a hash_id that is not a SHA*. +blink::WebCryptoAlgorithm CreateRsaHashedImportAlgorithm( + blink::WebCryptoAlgorithmId id, + blink::WebCryptoAlgorithmId hash_id); + +// Creates an import algorithm for EC keys. +blink::WebCryptoAlgorithm CreateEcImportAlgorithm( + blink::WebCryptoAlgorithmId id, + blink::WebCryptoNamedCurve named_curve); + } // namespace webcrypto #endif // COMPONENTS_WEBCRYPTO_ALGORITHMS_TEST_HELPERS_H_ diff --git a/components/webcrypto/algorithms/util.cc b/components/webcrypto/algorithms/util.cc new file mode 100644 index 0000000..43e728c --- /dev/null +++ b/components/webcrypto/algorithms/util.cc @@ -0,0 +1,127 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/webcrypto/algorithms/util.h" + +#include <openssl/aead.h> +#include <openssl/bn.h> +#include <openssl/digest.h> + +#include "base/logging.h" +#include "base/stl_util.h" +#include "components/webcrypto/crypto_data.h" +#include "components/webcrypto/status.h" +#include "crypto/openssl_util.h" +#include "crypto/scoped_openssl_types.h" + +namespace webcrypto { + +const EVP_MD* GetDigest(const blink::WebCryptoAlgorithm& hash_algorithm) { + return GetDigest(hash_algorithm.id()); +} + +const EVP_MD* GetDigest(blink::WebCryptoAlgorithmId id) { + switch (id) { + case blink::WebCryptoAlgorithmIdSha1: + return EVP_sha1(); + case blink::WebCryptoAlgorithmIdSha256: + return EVP_sha256(); + case blink::WebCryptoAlgorithmIdSha384: + return EVP_sha384(); + case blink::WebCryptoAlgorithmIdSha512: + return EVP_sha512(); + default: + return NULL; + } +} + +void TruncateToBitLength(size_t length_bits, std::vector<uint8_t>* bytes) { + size_t length_bytes = NumBitsToBytes(length_bits); + + if (bytes->size() != length_bytes) { + CHECK_LT(length_bytes, bytes->size()); + bytes->resize(length_bytes); + } + + size_t remainder_bits = length_bits % 8; + + // Zero any "unused bits" in the final byte. + if (remainder_bits) + (*bytes)[bytes->size() - 1] &= ~((0xFF) >> remainder_bits); +} + +Status CheckKeyCreationUsages(blink::WebCryptoKeyUsageMask all_possible_usages, + blink::WebCryptoKeyUsageMask actual_usages, + EmptyUsagePolicy empty_usage_policy) { + if (actual_usages == 0 && + empty_usage_policy == EmptyUsagePolicy::REJECT_EMPTY) { + return Status::ErrorCreateKeyEmptyUsages(); + } + + if (!ContainsKeyUsages(all_possible_usages, actual_usages)) + return Status::ErrorCreateKeyBadUsages(); + return Status::Success(); +} + +bool ContainsKeyUsages(blink::WebCryptoKeyUsageMask a, + blink::WebCryptoKeyUsageMask b) { + return (a & b) == b; +} + +BIGNUM* CreateBIGNUM(const std::string& n) { + return BN_bin2bn(reinterpret_cast<const uint8_t*>(n.data()), n.size(), NULL); +} + +Status AeadEncryptDecrypt(EncryptOrDecrypt mode, + const std::vector<uint8_t>& raw_key, + const CryptoData& data, + unsigned int tag_length_bytes, + const CryptoData& iv, + const CryptoData& additional_data, + const EVP_AEAD* aead_alg, + std::vector<uint8_t>* buffer) { + crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); + EVP_AEAD_CTX ctx; + + if (!aead_alg) + return Status::ErrorUnexpected(); + + if (!EVP_AEAD_CTX_init(&ctx, aead_alg, vector_as_array(&raw_key), + raw_key.size(), tag_length_bytes, NULL)) { + return Status::OperationError(); + } + + crypto::ScopedOpenSSL<EVP_AEAD_CTX, EVP_AEAD_CTX_cleanup> ctx_cleanup(&ctx); + + size_t len; + int ok; + + if (mode == DECRYPT) { + if (data.byte_length() < tag_length_bytes) + return Status::ErrorDataTooSmall(); + + buffer->resize(data.byte_length() - tag_length_bytes); + + ok = EVP_AEAD_CTX_open(&ctx, vector_as_array(buffer), &len, buffer->size(), + iv.bytes(), iv.byte_length(), data.bytes(), + data.byte_length(), additional_data.bytes(), + additional_data.byte_length()); + } else { + // No need to check for unsigned integer overflow here (seal fails if + // the output buffer is too small). + buffer->resize(data.byte_length() + EVP_AEAD_max_overhead(aead_alg)); + + ok = EVP_AEAD_CTX_seal(&ctx, vector_as_array(buffer), &len, buffer->size(), + iv.bytes(), iv.byte_length(), data.bytes(), + data.byte_length(), additional_data.bytes(), + additional_data.byte_length()); + } + + if (!ok) + return Status::OperationError(); + buffer->resize(len); + return Status::Success(); +} + +} // namespace webcrypto diff --git a/components/webcrypto/algorithms/util.h b/components/webcrypto/algorithms/util.h new file mode 100644 index 0000000..8fa2926 --- /dev/null +++ b/components/webcrypto/algorithms/util.h @@ -0,0 +1,96 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_WEBCRYPTO_ALGORITHMS_UTIL_H_ +#define COMPONENTS_WEBCRYPTO_ALGORITHMS_UTIL_H_ + +#include <string> +#include <vector> + +#include <openssl/base.h> + +#include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" +#include "third_party/WebKit/public/platform/WebCryptoKey.h" + +// This file contains miscellaneous helpers that don't belong in any of the +// other *_util.h + +namespace webcrypto { + +class CryptoData; +class GenerateKeyResult; +class Status; + +// Returns the EVP_MD that corresponds with |hash_algorithm|, or nullptr on +// failure. +const EVP_MD* GetDigest(const blink::WebCryptoAlgorithm& hash_algorithm); + +// Returns the EVP_MD that corresponds with |id|, or nullptr on failure. +const EVP_MD* GetDigest(blink::WebCryptoAlgorithmId id); + +// Truncates an octet string to a particular bit length. This is accomplished by +// resizing to the closest byte length, and then zero-ing the unused +// least-significant bits of the final byte. +// +// It is an error to call this function with a bit length that is larger than +// that of |bytes|. +// +// TODO(eroman): This operation is not yet defined by the WebCrypto spec, +// however this is a reasonable interpretation: +// https://www.w3.org/Bugs/Public/show_bug.cgi?id=27402 +void TruncateToBitLength(size_t length_bits, std::vector<uint8_t>* bytes); + +// Rounds a bit count (up) to the nearest byte count. +// +// This is mathematically equivalent to (x + 7) / 8, however has no +// possibility of integer overflow. +template <typename T> +T NumBitsToBytes(T x) { + return (x / 8) + (7 + (x % 8)) / 8; +} + +enum class EmptyUsagePolicy { + // Allow keys to have empty usages. + ALLOW_EMPTY, + + // Do not allow keys to have empty usages. + REJECT_EMPTY, +}; + +// Verifies whether a key can be created using |actual_usages| when the +// algorithm supports |all_possible_usages|. +Status CheckKeyCreationUsages(blink::WebCryptoKeyUsageMask all_possible_usages, + blink::WebCryptoKeyUsageMask actual_usages, + EmptyUsagePolicy empty_usage_policy); + +// TODO(eroman): This doesn't really belong in this file. Move it into Blink +// instead. +// +// Returns true if the set bits in b make up a subset of the set bits in a. +bool ContainsKeyUsages(blink::WebCryptoKeyUsageMask a, + blink::WebCryptoKeyUsageMask b); + +// Allocates a new BIGNUM given a std::string big-endian representation. +BIGNUM* CreateBIGNUM(const std::string& n); + +// The values of these constants correspond with the "enc" parameter of +// EVP_CipherInit_ex(), do not change. +enum EncryptOrDecrypt { DECRYPT = 0, ENCRYPT = 1 }; + +// Does either encryption or decryption for an AEAD algorithm. +// * |mode| controls whether encryption or decryption is done +// * |aead_alg| the algorithm (for instance AES-GCM) +// * |buffer| where the ciphertext or plaintext is written to. +Status AeadEncryptDecrypt(EncryptOrDecrypt mode, + const std::vector<uint8_t>& raw_key, + const CryptoData& data, + unsigned int tag_length_bytes, + const CryptoData& iv, + const CryptoData& additional_data, + const EVP_AEAD* aead_alg, + std::vector<uint8_t>* buffer); + +} // namespace webcrypto + +#endif // COMPONENTS_WEBCRYPTO_ALGORITHMS_UTIL_H_ diff --git a/components/webcrypto/key.cc b/components/webcrypto/blink_key_handle.cc index 3fe3fe8..6b8c1f4 100644 --- a/components/webcrypto/key.cc +++ b/components/webcrypto/blink_key_handle.cc @@ -2,13 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/webcrypto/key.h" +#include "components/webcrypto/blink_key_handle.h" #include "base/logging.h" #include "base/macros.h" #include "components/webcrypto/crypto_data.h" #include "components/webcrypto/status.h" -#include "components/webcrypto/webcrypto_util.h" namespace webcrypto { diff --git a/components/webcrypto/key.h b/components/webcrypto/blink_key_handle.h index 60fa5d4..049657c 100644 --- a/components/webcrypto/key.h +++ b/components/webcrypto/blink_key_handle.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_WEBCRYPTO_KEY_H_ -#define COMPONENTS_WEBCRYPTO_KEY_H_ +#ifndef COMPONENTS_WEBCRYPTO_BLINK_KEY_HANDLE_H_ +#define COMPONENTS_WEBCRYPTO_BLINK_KEY_HANDLE_H_ #include <openssl/base.h> #include <stdint.h> @@ -13,6 +13,14 @@ #include "crypto/scoped_openssl_types.h" #include "third_party/WebKit/public/platform/WebCryptoKey.h" +// Blink keys (blink::WebCryptoKey) have an associated key handle +// (blink::WebCryptoKeyHandle) used to store custom data. This is where the +// underlying EVP_PKEY is stored for asymmetric keys, or an std::vector +// containing the bytes for symmetric keys. +// +// This file contains helpers for creating the key handles, and extracting +// properties from it. + namespace webcrypto { class CryptoData; @@ -50,4 +58,4 @@ blink::WebCryptoKeyHandle* CreateAsymmetricKeyHandle( } // namespace webcrypto -#endif // COMPONENTS_WEBCRYPTO_KEY_H_ +#endif // COMPONENTS_WEBCRYPTO_BLINK_KEY_HANDLE_H_ diff --git a/components/webcrypto/jwk.cc b/components/webcrypto/jwk.cc index 1a3245a..023ea82 100644 --- a/components/webcrypto/jwk.cc +++ b/components/webcrypto/jwk.cc @@ -12,9 +12,9 @@ #include "base/stl_util.h" #include "base/strings/string_piece.h" #include "base/strings/stringprintf.h" +#include "components/webcrypto/algorithms/util.h" #include "components/webcrypto/crypto_data.h" #include "components/webcrypto/status.h" -#include "components/webcrypto/webcrypto_util.h" // JSON Web Key Format (JWK) is defined by: // http://tools.ietf.org/html/draft-ietf-jose-json-web-key diff --git a/components/webcrypto/status_unittest.cc b/components/webcrypto/status_unittest.cc index 3102f77..ad79136 100644 --- a/components/webcrypto/status_unittest.cc +++ b/components/webcrypto/status_unittest.cc @@ -7,7 +7,6 @@ #include "components/webcrypto/algorithms/test_helpers.h" #include "components/webcrypto/crypto_data.h" #include "components/webcrypto/status.h" -#include "components/webcrypto/webcrypto_util.h" #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" diff --git a/components/webcrypto/webcrypto.gyp b/components/webcrypto/webcrypto.gyp index fef6ead..e4cf9af 100644 --- a/components/webcrypto/webcrypto.gyp +++ b/components/webcrypto/webcrypto.gyp @@ -30,6 +30,8 @@ 'algorithms/aes_ctr.cc', 'algorithms/aes_gcm.cc', 'algorithms/aes_kw.cc', + 'algorithms/asymmetric_key_util.cc', + 'algorithms/asymmetric_key_util.h', 'algorithms/ec.cc', 'algorithms/ec.h', 'algorithms/ecdh.cc', @@ -47,22 +49,20 @@ 'algorithms/secret_key_util.cc', 'algorithms/secret_key_util.h', 'algorithms/sha.cc', - 'algorithms/util_openssl.cc', - 'algorithms/util_openssl.h', + 'algorithms/util.cc', + 'algorithms/util.h', + 'blink_key_handle.cc', + 'blink_key_handle.h', 'crypto_data.cc', 'crypto_data.h', 'generate_key_result.cc', 'generate_key_result.h', 'jwk.cc', 'jwk.h', - 'key.cc', - 'key.h', 'status.cc', 'status.h', 'webcrypto_impl.cc', 'webcrypto_impl.h', - 'webcrypto_util.cc', - 'webcrypto_util.h', ], }, ], diff --git a/components/webcrypto/webcrypto_impl.cc b/components/webcrypto/webcrypto_impl.cc index cdc075c..71d4b2b 100644 --- a/components/webcrypto/webcrypto_impl.cc +++ b/components/webcrypto/webcrypto_impl.cc @@ -19,7 +19,6 @@ #include "components/webcrypto/crypto_data.h" #include "components/webcrypto/generate_key_result.h" #include "components/webcrypto/status.h" -#include "components/webcrypto/webcrypto_util.h" #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" #include "third_party/WebKit/public/platform/WebString.h" diff --git a/components/webcrypto/webcrypto_util.cc b/components/webcrypto/webcrypto_util.cc deleted file mode 100644 index 26d428f..0000000 --- a/components/webcrypto/webcrypto_util.cc +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/webcrypto/webcrypto_util.h" - -#include "base/logging.h" -#include "components/webcrypto/status.h" -#include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" -#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" -#include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" - -namespace webcrypto { - -namespace { - -// Converts a (big-endian) WebCrypto BigInteger, with or without leading zeros, -// to unsigned int. -bool BigIntegerToUint(const uint8_t* data, - size_t data_size, - unsigned int* result) { - if (data_size == 0) - return false; - - *result = 0; - for (size_t i = 0; i < data_size; ++i) { - size_t reverse_i = data_size - i - 1; - - if (reverse_i >= sizeof(*result) && data[i]) - return false; // Too large for a uint. - - *result |= data[i] << 8 * reverse_i; - } - return true; -} - - -} // namespace - -blink::WebCryptoAlgorithm CreateAlgorithm(blink::WebCryptoAlgorithmId id) { - return blink::WebCryptoAlgorithm::adoptParamsAndCreate(id, NULL); -} - -blink::WebCryptoAlgorithm CreateRsaHashedImportAlgorithm( - blink::WebCryptoAlgorithmId id, - blink::WebCryptoAlgorithmId hash_id) { - DCHECK(blink::WebCryptoAlgorithm::isHash(hash_id)); - return blink::WebCryptoAlgorithm::adoptParamsAndCreate( - id, new blink::WebCryptoRsaHashedImportParams(CreateAlgorithm(hash_id))); -} - -blink::WebCryptoAlgorithm CreateEcImportAlgorithm( - blink::WebCryptoAlgorithmId id, - blink::WebCryptoNamedCurve named_curve) { - return blink::WebCryptoAlgorithm::adoptParamsAndCreate( - id, new blink::WebCryptoEcKeyImportParams(named_curve)); -} - -bool ContainsKeyUsages(blink::WebCryptoKeyUsageMask a, - blink::WebCryptoKeyUsageMask b) { - return (a & b) == b; -} - - -Status CheckKeyCreationUsages(blink::WebCryptoKeyUsageMask all_possible_usages, - blink::WebCryptoKeyUsageMask actual_usages, - bool allow_empty_usages) { - if (!allow_empty_usages && actual_usages == 0) - return Status::ErrorCreateKeyEmptyUsages(); - - if (!ContainsKeyUsages(all_possible_usages, actual_usages)) - return Status::ErrorCreateKeyBadUsages(); - return Status::Success(); -} - -Status GetRsaKeyGenParameters( - const blink::WebCryptoRsaHashedKeyGenParams* params, - unsigned int* public_exponent, - unsigned int* modulus_length_bits) { - *modulus_length_bits = params->modulusLengthBits(); - - // Limit the RSA key sizes to: - // * Multiple of 8 bits - // * 256 bits to 16K bits - // This corresponds to the values that NSS would allow, which was relevant - // back when Chromium's WebCrypto supported both OpenSSL and NSS. - if (*modulus_length_bits < 256 || *modulus_length_bits > 16384 || - (*modulus_length_bits % 8) != 0) { - return Status::ErrorGenerateRsaUnsupportedModulus(); - } - - if (!BigIntegerToUint(params->publicExponent().data(), - params->publicExponent().size(), public_exponent)) { - return Status::ErrorGenerateKeyPublicExponent(); - } - - // OpenSSL hangs when given bad public exponents. Use a whitelist to avoid - // feeding OpenSSL data that could hang. - if (*public_exponent != 3 && *public_exponent != 65537) - return Status::ErrorGenerateKeyPublicExponent(); - - return Status::Success(); -} - -Status VerifyUsagesBeforeImportAsymmetricKey( - blink::WebCryptoKeyFormat format, - blink::WebCryptoKeyUsageMask all_public_key_usages, - blink::WebCryptoKeyUsageMask all_private_key_usages, - blink::WebCryptoKeyUsageMask usages) { - switch (format) { - case blink::WebCryptoKeyFormatSpki: - return CheckKeyCreationUsages(all_public_key_usages, usages, true); - case blink::WebCryptoKeyFormatPkcs8: - return CheckKeyCreationUsages(all_private_key_usages, usages, false); - case blink::WebCryptoKeyFormatJwk: { - // The JWK could represent either a public key or private key. The usages - // must make sense for one of the two. The usages will be checked again by - // ImportKeyJwk() once the key type has been determined. - if (CheckKeyCreationUsages(all_public_key_usages, usages, true) - .IsError() && - CheckKeyCreationUsages(all_private_key_usages, usages, false) - .IsError()) { - return Status::ErrorCreateKeyBadUsages(); - } - return Status::Success(); - } - default: - return Status::ErrorUnsupportedImportKeyFormat(); - } -} - -void TruncateToBitLength(size_t length_bits, std::vector<uint8_t>* bytes) { - size_t length_bytes = NumBitsToBytes(length_bits); - - if (bytes->size() != length_bytes) { - CHECK_LT(length_bytes, bytes->size()); - bytes->resize(length_bytes); - } - - size_t remainder_bits = length_bits % 8; - - // Zero any "unused bits" in the final byte - if (remainder_bits) - (*bytes)[bytes->size() - 1] &= ~((0xFF) >> remainder_bits); -} - - -Status GetUsagesForGenerateAsymmetricKey( - blink::WebCryptoKeyUsageMask combined_usages, - blink::WebCryptoKeyUsageMask all_public_usages, - blink::WebCryptoKeyUsageMask all_private_usages, - blink::WebCryptoKeyUsageMask* public_usages, - blink::WebCryptoKeyUsageMask* private_usages) { - Status status = CheckKeyCreationUsages(all_public_usages | all_private_usages, - combined_usages, true); - if (status.IsError()) - return status; - - *public_usages = combined_usages & all_public_usages; - *private_usages = combined_usages & all_private_usages; - - if (*private_usages == 0) - return Status::ErrorCreateKeyEmptyUsages(); - - return Status::Success(); -} - -} // namespace webcrypto diff --git a/components/webcrypto/webcrypto_util.h b/components/webcrypto/webcrypto_util.h deleted file mode 100644 index b9b69d0..0000000 --- a/components/webcrypto/webcrypto_util.h +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_WEBCRYPTO_WEBCRYPTO_UTIL_H_ -#define COMPONENTS_WEBCRYPTO_WEBCRYPTO_UTIL_H_ - -#include <stdint.h> -#include <string> - -#include "base/values.h" -#include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" -#include "third_party/WebKit/public/platform/WebCryptoKey.h" - -// TODO(eroman): The remaining functions in this file need to be sorted -// out. They should be moved to a more domain specific location (for -// instance test helpers, asymmetric algorithm helpers, etc.). - -namespace webcrypto { - -class Status; - -// Creates a WebCryptoAlgorithm without any parameters. -blink::WebCryptoAlgorithm CreateAlgorithm(blink::WebCryptoAlgorithmId id); - -// Creates an import algorithm for RSA algorithms that take a hash. -// It is an error to call this with a hash_id that is not a SHA*. -blink::WebCryptoAlgorithm CreateRsaHashedImportAlgorithm( - blink::WebCryptoAlgorithmId id, - blink::WebCryptoAlgorithmId hash_id); - -// Creates an import algorithm for EC keys. -blink::WebCryptoAlgorithm CreateEcImportAlgorithm( - blink::WebCryptoAlgorithmId id, - blink::WebCryptoNamedCurve named_curve); - -// Returns true if the set bits in b make up a subset of the set bits in a. -bool ContainsKeyUsages(blink::WebCryptoKeyUsageMask a, - blink::WebCryptoKeyUsageMask b); - -Status CheckKeyCreationUsages(blink::WebCryptoKeyUsageMask all_possible_usages, - blink::WebCryptoKeyUsageMask actual_usages, - bool allow_empty_usages); - -// Extracts the public exponent and modulus length from the Blink parameters. -// On success it is guaranteed that: -// * public_exponent is either 3 or 65537 -// * modulus_length_bits is a multiple of 8 -// * modulus_length is >= 256 -// * modulus_length is <= 16K -Status GetRsaKeyGenParameters( - const blink::WebCryptoRsaHashedKeyGenParams* params, - unsigned int* public_exponent, - unsigned int* modulus_length_bits); - -// Verifies that |usages| is valid when importing a key of the given format. -Status VerifyUsagesBeforeImportAsymmetricKey( - blink::WebCryptoKeyFormat format, - blink::WebCryptoKeyUsageMask all_public_key_usages, - blink::WebCryptoKeyUsageMask all_private_key_usages, - blink::WebCryptoKeyUsageMask usages); - -// Truncates an octet string to a particular bit length. This is accomplished by -// resizing to the closest byte length, and then zero-ing the unused -// least-significant bits of the final byte. -// -// It is an error to call this function with a bit length that is larger than -// that of |bytes|. -// -// TODO(eroman): This operation is not yet defined by the WebCrypto spec, -// however this is a reasonable interpretation: -// https://www.w3.org/Bugs/Public/show_bug.cgi?id=27402 -void TruncateToBitLength(size_t length_bits, std::vector<uint8_t>* bytes); - -// Rounds a bit count (up) to the nearest byte count. -// -// This is mathematically equivalent to (x + 7) / 8, however has no -// possibility of integer overflow. -template <typename T> -T NumBitsToBytes(T x) { - return (x / 8) + (7 + (x % 8)) / 8; -} - - -// Splits the combined usages given to GenerateKey() into the respective usages -// for the public key and private key. Returns an error if the usages are -// invalid. -Status GetUsagesForGenerateAsymmetricKey( - blink::WebCryptoKeyUsageMask combined_usages, - blink::WebCryptoKeyUsageMask all_public_usages, - blink::WebCryptoKeyUsageMask all_private_usages, - blink::WebCryptoKeyUsageMask* public_usages, - blink::WebCryptoKeyUsageMask* private_usages); - -} // namespace webcrypto - -#endif // COMPONENTS_WEBCRYPTO_WEBCRYPTO_UTIL_H_ |