blob: 5d12133969849976d72a0305d703a3ce4ec75573 [file] [log] [blame]
[email protected]38409aec2014-07-19 00:54:511// 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.
4
eroman7bcd6a72015-09-16 02:41:215#include "components/webcrypto/algorithms/aes.h"
[email protected]38409aec2014-07-19 00:54:516
avi5dd91f82015-12-25 22:30:467#include <stddef.h>
8
eromand72073d2015-09-19 01:37:029#include "components/webcrypto/algorithms/secret_key_util.h"
eroman0bb976e2016-08-03 06:36:3810#include "components/webcrypto/algorithms/util.h"
eromanab1308a2015-10-01 19:38:0411#include "components/webcrypto/blink_key_handle.h"
erg56f12322015-04-17 00:51:4812#include "components/webcrypto/crypto_data.h"
13#include "components/webcrypto/jwk.h"
erg56f12322015-04-17 00:51:4814#include "components/webcrypto/status.h"
Blink Reformata30d4232018-04-07 15:31:0615#include "third_party/blink/public/platform/web_crypto_algorithm_params.h"
16#include "third_party/blink/public/platform/web_crypto_key_algorithm.h"
[email protected]38409aec2014-07-19 00:54:5117
[email protected]38409aec2014-07-19 00:54:5118namespace webcrypto {
19
eromandceea882015-09-16 00:31:5220namespace {
21
22// Creates an AES algorithm name for the given key size (in bytes). For
23// instance "A128CBC" is the result of suffix="CBC", keylen_bytes=16.
24std::string MakeJwkAesAlgorithmName(const std::string& suffix,
25 size_t keylen_bytes) {
26 if (keylen_bytes == 16)
27 return std::string("A128") + suffix;
28 if (keylen_bytes == 24)
29 return std::string("A192") + suffix;
30 if (keylen_bytes == 32)
31 return std::string("A256") + suffix;
32 return std::string();
33}
34
eromanab1308a2015-10-01 19:38:0435// Synthesizes an import algorithm given a key algorithm, so that
36// deserialization can re-use the ImportKey*() methods.
37blink::WebCryptoAlgorithm SynthesizeImportAlgorithmForClone(
38 const blink::WebCryptoKeyAlgorithm& algorithm) {
Blink Reformat1c4d759e2017-04-09 16:34:5439 return blink::WebCryptoAlgorithm::AdoptParamsAndCreate(algorithm.Id(),
eromanab1308a2015-10-01 19:38:0440 nullptr);
41}
42
eromandceea882015-09-16 00:31:5243} // namespace
44
[email protected]38409aec2014-07-19 00:54:5145AesAlgorithm::AesAlgorithm(blink::WebCryptoKeyUsageMask all_key_usages,
46 const std::string& jwk_suffix)
47 : all_key_usages_(all_key_usages), jwk_suffix_(jwk_suffix) {
48}
49
50AesAlgorithm::AesAlgorithm(const std::string& jwk_suffix)
Blink Reformat1c4d759e2017-04-09 16:34:5451 : all_key_usages_(blink::kWebCryptoKeyUsageEncrypt |
52 blink::kWebCryptoKeyUsageDecrypt |
53 blink::kWebCryptoKeyUsageWrapKey |
54 blink::kWebCryptoKeyUsageUnwrapKey),
55 jwk_suffix_(jwk_suffix) {}
[email protected]38409aec2014-07-19 00:54:5156
eroman9b747eaf2014-10-18 22:03:2857Status AesAlgorithm::GenerateKey(const blink::WebCryptoAlgorithm& algorithm,
58 bool extractable,
eroman0e1d34e2014-10-21 19:13:3159 blink::WebCryptoKeyUsageMask usages,
eroman9b747eaf2014-10-18 22:03:2860 GenerateKeyResult* result) const {
eroman0bb976e2016-08-03 06:36:3861 Status status = CheckKeyCreationUsages(all_key_usages_, usages);
eroman9b747eaf2014-10-18 22:03:2862 if (status.IsError())
63 return status;
[email protected]38409aec2014-07-19 00:54:5164
Miyoung Shin7561ca0b2019-03-03 14:14:1565 uint16_t keylen_bits = algorithm.AesKeyGenParams()->LengthBits();
eromand72073d2015-09-19 01:37:0266
eromanf5d6b2a2015-09-23 01:05:4367 // 192-bit AES is intentionally unsupported (http://crbug.com/533699).
eromand72073d2015-09-19 01:37:0268 if (keylen_bits == 192)
69 return Status::ErrorAes192BitUnsupported();
70
71 if (keylen_bits != 128 && keylen_bits != 256)
72 return Status::ErrorGenerateAesKeyLength();
[email protected]38409aec2014-07-19 00:54:5173
eromanba702e22015-01-01 02:48:1374 return GenerateWebCryptoSecretKey(
Blink Reformat1c4d759e2017-04-09 16:34:5475 blink::WebCryptoKeyAlgorithm::CreateAes(algorithm.Id(), keylen_bits),
eroman401e4afc2014-12-10 17:41:0476 extractable, usages, keylen_bits, result);
[email protected]38409aec2014-07-19 00:54:5177}
78
eroman0bb976e2016-08-03 06:36:3879Status AesAlgorithm::ImportKey(blink::WebCryptoKeyFormat format,
80 const CryptoData& key_data,
81 const blink::WebCryptoAlgorithm& algorithm,
82 bool extractable,
83 blink::WebCryptoKeyUsageMask usages,
84 blink::WebCryptoKey* key) const {
[email protected]38409aec2014-07-19 00:54:5185 switch (format) {
Blink Reformat1c4d759e2017-04-09 16:34:5486 case blink::kWebCryptoKeyFormatRaw:
eroman0bb976e2016-08-03 06:36:3887 return ImportKeyRaw(key_data, algorithm, extractable, usages, key);
Blink Reformat1c4d759e2017-04-09 16:34:5488 case blink::kWebCryptoKeyFormatJwk:
eroman0bb976e2016-08-03 06:36:3889 return ImportKeyJwk(key_data, algorithm, extractable, usages, key);
[email protected]38409aec2014-07-19 00:54:5190 default:
91 return Status::ErrorUnsupportedImportKeyFormat();
92 }
93}
94
eroman0bb976e2016-08-03 06:36:3895Status AesAlgorithm::ExportKey(blink::WebCryptoKeyFormat format,
96 const blink::WebCryptoKey& key,
97 std::vector<uint8_t>* buffer) const {
98 switch (format) {
Blink Reformat1c4d759e2017-04-09 16:34:5499 case blink::kWebCryptoKeyFormatRaw:
eroman0bb976e2016-08-03 06:36:38100 return ExportKeyRaw(key, buffer);
Blink Reformat1c4d759e2017-04-09 16:34:54101 case blink::kWebCryptoKeyFormatJwk:
eroman0bb976e2016-08-03 06:36:38102 return ExportKeyJwk(key, buffer);
103 default:
104 return Status::ErrorUnsupportedExportKeyFormat();
105 }
106}
107
[email protected]38409aec2014-07-19 00:54:51108Status AesAlgorithm::ImportKeyRaw(const CryptoData& key_data,
109 const blink::WebCryptoAlgorithm& algorithm,
110 bool extractable,
eroman0e1d34e2014-10-21 19:13:31111 blink::WebCryptoKeyUsageMask usages,
[email protected]38409aec2014-07-19 00:54:51112 blink::WebCryptoKey* key) const {
eroman0bb976e2016-08-03 06:36:38113 Status status = CheckKeyCreationUsages(all_key_usages_, usages);
114 if (status.IsError())
115 return status;
116
[email protected]38409aec2014-07-19 00:54:51117 const unsigned int keylen_bytes = key_data.byte_length();
eromand72073d2015-09-19 01:37:02118
eromanf5d6b2a2015-09-23 01:05:43119 // 192-bit AES is intentionally unsupported (http://crbug.com/533699).
eromand72073d2015-09-19 01:37:02120 if (keylen_bytes == 24)
121 return Status::ErrorAes192BitUnsupported();
122
123 if (keylen_bytes != 16 && keylen_bytes != 32)
124 return Status::ErrorImportAesKeyLength();
[email protected]38409aec2014-07-19 00:54:51125
126 // No possibility of overflow.
127 unsigned int keylen_bits = keylen_bytes * 8;
128
eromanba702e22015-01-01 02:48:13129 return CreateWebCryptoSecretKey(
130 key_data,
Blink Reformat1c4d759e2017-04-09 16:34:54131 blink::WebCryptoKeyAlgorithm::CreateAes(algorithm.Id(), keylen_bits),
eromanba702e22015-01-01 02:48:13132 extractable, usages, key);
[email protected]38409aec2014-07-19 00:54:51133}
134
135Status AesAlgorithm::ImportKeyJwk(const CryptoData& key_data,
136 const blink::WebCryptoAlgorithm& algorithm,
137 bool extractable,
eroman0e1d34e2014-10-21 19:13:31138 blink::WebCryptoKeyUsageMask usages,
[email protected]38409aec2014-07-19 00:54:51139 blink::WebCryptoKey* key) const {
eroman0bb976e2016-08-03 06:36:38140 Status status = CheckKeyCreationUsages(all_key_usages_, usages);
141 if (status.IsError())
142 return status;
143
[email protected]53b6c9d22014-07-19 05:08:38144 std::vector<uint8_t> raw_data;
eromandceea882015-09-16 00:31:52145 JwkReader jwk;
eroman0bb976e2016-08-03 06:36:38146 status = ReadSecretKeyNoExpectedAlgJwk(key_data, extractable, usages,
147 &raw_data, &jwk);
[email protected]38409aec2014-07-19 00:54:51148 if (status.IsError())
149 return status;
150
eromandceea882015-09-16 00:31:52151 bool has_jwk_alg;
152 std::string jwk_alg;
153 status = jwk.GetAlg(&jwk_alg, &has_jwk_alg);
154 if (status.IsError())
155 return status;
156
157 if (has_jwk_alg) {
158 std::string expected_algorithm_name =
159 MakeJwkAesAlgorithmName(jwk_suffix_, raw_data.size());
160
161 if (jwk_alg != expected_algorithm_name) {
162 // Give a different error message if the key length was wrong.
163 if (jwk_alg == MakeJwkAesAlgorithmName(jwk_suffix_, 16) ||
164 jwk_alg == MakeJwkAesAlgorithmName(jwk_suffix_, 24) ||
165 jwk_alg == MakeJwkAesAlgorithmName(jwk_suffix_, 32)) {
166 return Status::ErrorJwkIncorrectKeyLength();
167 }
168 return Status::ErrorJwkAlgorithmInconsistent();
169 }
170 }
171
eroman38bb4bd2014-11-24 23:47:06172 return ImportKeyRaw(CryptoData(raw_data), algorithm, extractable, usages,
173 key);
[email protected]38409aec2014-07-19 00:54:51174}
175
176Status AesAlgorithm::ExportKeyRaw(const blink::WebCryptoKey& key,
[email protected]53b6c9d22014-07-19 05:08:38177 std::vector<uint8_t>* buffer) const {
eromand62cb472015-09-18 18:24:23178 *buffer = GetSymmetricKeyData(key);
[email protected]38409aec2014-07-19 00:54:51179 return Status::Success();
180}
181
182Status AesAlgorithm::ExportKeyJwk(const blink::WebCryptoKey& key,
[email protected]53b6c9d22014-07-19 05:08:38183 std::vector<uint8_t>* buffer) const {
eromand62cb472015-09-18 18:24:23184 const std::vector<uint8_t>& raw_data = GetSymmetricKeyData(key);
[email protected]38409aec2014-07-19 00:54:51185
186 WriteSecretKeyJwk(CryptoData(raw_data),
187 MakeJwkAesAlgorithmName(jwk_suffix_, raw_data.size()),
Blink Reformat1c4d759e2017-04-09 16:34:54188 key.Extractable(), key.Usages(), buffer);
[email protected]38409aec2014-07-19 00:54:51189
190 return Status::Success();
191}
192
eromana895fed2014-11-08 03:10:25193Status AesAlgorithm::DeserializeKeyForClone(
194 const blink::WebCryptoKeyAlgorithm& algorithm,
195 blink::WebCryptoKeyType type,
196 bool extractable,
197 blink::WebCryptoKeyUsageMask usages,
198 const CryptoData& key_data,
199 blink::WebCryptoKey* key) const {
Blink Reformat1c4d759e2017-04-09 16:34:54200 if (algorithm.ParamsType() != blink::kWebCryptoKeyAlgorithmParamsTypeAes ||
201 type != blink::kWebCryptoKeyTypeSecret)
jbroman2e33aac2016-12-01 02:10:35202 return Status::ErrorUnexpected();
203
eromanab1308a2015-10-01 19:38:04204 return ImportKeyRaw(key_data, SynthesizeImportAlgorithmForClone(algorithm),
205 extractable, usages, key);
eromana895fed2014-11-08 03:10:25206}
207
eromanf93fd5b2014-12-11 00:21:06208Status AesAlgorithm::GetKeyLength(
209 const blink::WebCryptoAlgorithm& key_length_algorithm,
210 bool* has_length_bits,
211 unsigned int* length_bits) const {
eromand72073d2015-09-19 01:37:02212 *has_length_bits = true;
Blink Reformat1c4d759e2017-04-09 16:34:54213 *length_bits = key_length_algorithm.AesDerivedKeyParams()->LengthBits();
eromand72073d2015-09-19 01:37:02214
215 if (*length_bits == 128 || *length_bits == 256)
216 return Status::Success();
217
eromanf5d6b2a2015-09-23 01:05:43218 // 192-bit AES is intentionally unsupported (http://crbug.com/533699).
eromand72073d2015-09-19 01:37:02219 if (*length_bits == 192)
220 return Status::ErrorAes192BitUnsupported();
221
222 return Status::ErrorGetAesKeyLength();
eromanf93fd5b2014-12-11 00:21:06223}
224
[email protected]38409aec2014-07-19 00:54:51225} // namespace webcrypto