Cleanup: Pass std::string as const reference from pdf/
[chromium-blink-merge.git] / components / webcrypto / webcrypto_util.cc
blob26d428fca8bfedca4efd1347a72f5cf34e434cc2
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/webcrypto/webcrypto_util.h"
7 #include "base/logging.h"
8 #include "components/webcrypto/status.h"
9 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h"
10 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
11 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
13 namespace webcrypto {
15 namespace {
17 // Converts a (big-endian) WebCrypto BigInteger, with or without leading zeros,
18 // to unsigned int.
19 bool BigIntegerToUint(const uint8_t* data,
20 size_t data_size,
21 unsigned int* result) {
22 if (data_size == 0)
23 return false;
25 *result = 0;
26 for (size_t i = 0; i < data_size; ++i) {
27 size_t reverse_i = data_size - i - 1;
29 if (reverse_i >= sizeof(*result) && data[i])
30 return false; // Too large for a uint.
32 *result |= data[i] << 8 * reverse_i;
34 return true;
38 } // namespace
40 blink::WebCryptoAlgorithm CreateAlgorithm(blink::WebCryptoAlgorithmId id) {
41 return blink::WebCryptoAlgorithm::adoptParamsAndCreate(id, NULL);
44 blink::WebCryptoAlgorithm CreateRsaHashedImportAlgorithm(
45 blink::WebCryptoAlgorithmId id,
46 blink::WebCryptoAlgorithmId hash_id) {
47 DCHECK(blink::WebCryptoAlgorithm::isHash(hash_id));
48 return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
49 id, new blink::WebCryptoRsaHashedImportParams(CreateAlgorithm(hash_id)));
52 blink::WebCryptoAlgorithm CreateEcImportAlgorithm(
53 blink::WebCryptoAlgorithmId id,
54 blink::WebCryptoNamedCurve named_curve) {
55 return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
56 id, new blink::WebCryptoEcKeyImportParams(named_curve));
59 bool ContainsKeyUsages(blink::WebCryptoKeyUsageMask a,
60 blink::WebCryptoKeyUsageMask b) {
61 return (a & b) == b;
65 Status CheckKeyCreationUsages(blink::WebCryptoKeyUsageMask all_possible_usages,
66 blink::WebCryptoKeyUsageMask actual_usages,
67 bool allow_empty_usages) {
68 if (!allow_empty_usages && actual_usages == 0)
69 return Status::ErrorCreateKeyEmptyUsages();
71 if (!ContainsKeyUsages(all_possible_usages, actual_usages))
72 return Status::ErrorCreateKeyBadUsages();
73 return Status::Success();
76 Status GetRsaKeyGenParameters(
77 const blink::WebCryptoRsaHashedKeyGenParams* params,
78 unsigned int* public_exponent,
79 unsigned int* modulus_length_bits) {
80 *modulus_length_bits = params->modulusLengthBits();
82 // Limit the RSA key sizes to:
83 // * Multiple of 8 bits
84 // * 256 bits to 16K bits
85 // This corresponds to the values that NSS would allow, which was relevant
86 // back when Chromium's WebCrypto supported both OpenSSL and NSS.
87 if (*modulus_length_bits < 256 || *modulus_length_bits > 16384 ||
88 (*modulus_length_bits % 8) != 0) {
89 return Status::ErrorGenerateRsaUnsupportedModulus();
92 if (!BigIntegerToUint(params->publicExponent().data(),
93 params->publicExponent().size(), public_exponent)) {
94 return Status::ErrorGenerateKeyPublicExponent();
97 // OpenSSL hangs when given bad public exponents. Use a whitelist to avoid
98 // feeding OpenSSL data that could hang.
99 if (*public_exponent != 3 && *public_exponent != 65537)
100 return Status::ErrorGenerateKeyPublicExponent();
102 return Status::Success();
105 Status VerifyUsagesBeforeImportAsymmetricKey(
106 blink::WebCryptoKeyFormat format,
107 blink::WebCryptoKeyUsageMask all_public_key_usages,
108 blink::WebCryptoKeyUsageMask all_private_key_usages,
109 blink::WebCryptoKeyUsageMask usages) {
110 switch (format) {
111 case blink::WebCryptoKeyFormatSpki:
112 return CheckKeyCreationUsages(all_public_key_usages, usages, true);
113 case blink::WebCryptoKeyFormatPkcs8:
114 return CheckKeyCreationUsages(all_private_key_usages, usages, false);
115 case blink::WebCryptoKeyFormatJwk: {
116 // The JWK could represent either a public key or private key. The usages
117 // must make sense for one of the two. The usages will be checked again by
118 // ImportKeyJwk() once the key type has been determined.
119 if (CheckKeyCreationUsages(all_public_key_usages, usages, true)
120 .IsError() &&
121 CheckKeyCreationUsages(all_private_key_usages, usages, false)
122 .IsError()) {
123 return Status::ErrorCreateKeyBadUsages();
125 return Status::Success();
127 default:
128 return Status::ErrorUnsupportedImportKeyFormat();
132 void TruncateToBitLength(size_t length_bits, std::vector<uint8_t>* bytes) {
133 size_t length_bytes = NumBitsToBytes(length_bits);
135 if (bytes->size() != length_bytes) {
136 CHECK_LT(length_bytes, bytes->size());
137 bytes->resize(length_bytes);
140 size_t remainder_bits = length_bits % 8;
142 // Zero any "unused bits" in the final byte
143 if (remainder_bits)
144 (*bytes)[bytes->size() - 1] &= ~((0xFF) >> remainder_bits);
148 Status GetUsagesForGenerateAsymmetricKey(
149 blink::WebCryptoKeyUsageMask combined_usages,
150 blink::WebCryptoKeyUsageMask all_public_usages,
151 blink::WebCryptoKeyUsageMask all_private_usages,
152 blink::WebCryptoKeyUsageMask* public_usages,
153 blink::WebCryptoKeyUsageMask* private_usages) {
154 Status status = CheckKeyCreationUsages(all_public_usages | all_private_usages,
155 combined_usages, true);
156 if (status.IsError())
157 return status;
159 *public_usages = combined_usages & all_public_usages;
160 *private_usages = combined_usages & all_private_usages;
162 if (*private_usages == 0)
163 return Status::ErrorCreateKeyEmptyUsages();
165 return Status::Success();
168 } // namespace webcrypto