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 "content/child/webcrypto/algorithm_dispatch.h"
7 #include "base/logging.h"
8 #include "content/child/webcrypto/algorithm_implementation.h"
9 #include "content/child/webcrypto/algorithm_registry.h"
10 #include "content/child/webcrypto/crypto_data.h"
11 #include "content/child/webcrypto/platform_crypto.h"
12 #include "content/child/webcrypto/status.h"
13 #include "content/child/webcrypto/webcrypto_util.h"
14 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
22 Status
DecryptDontCheckKeyUsage(const blink::WebCryptoAlgorithm
& algorithm
,
23 const blink::WebCryptoKey
& key
,
24 const CryptoData
& data
,
25 std::vector
<uint8_t>* buffer
) {
26 if (algorithm
.id() != key
.algorithm().id())
27 return Status::ErrorUnexpected();
29 const AlgorithmImplementation
* impl
= NULL
;
30 Status status
= GetAlgorithmImplementation(algorithm
.id(), &impl
);
34 return impl
->Decrypt(algorithm
, key
, data
, buffer
);
37 Status
EncryptDontCheckUsage(const blink::WebCryptoAlgorithm
& algorithm
,
38 const blink::WebCryptoKey
& key
,
39 const CryptoData
& data
,
40 std::vector
<uint8_t>* buffer
) {
41 if (algorithm
.id() != key
.algorithm().id())
42 return Status::ErrorUnexpected();
44 const AlgorithmImplementation
* impl
= NULL
;
45 Status status
= GetAlgorithmImplementation(algorithm
.id(), &impl
);
49 return impl
->Encrypt(algorithm
, key
, data
, buffer
);
52 Status
ExportKeyDontCheckExtractability(blink::WebCryptoKeyFormat format
,
53 const blink::WebCryptoKey
& key
,
54 std::vector
<uint8_t>* buffer
) {
55 const AlgorithmImplementation
* impl
= NULL
;
56 Status status
= GetAlgorithmImplementation(key
.algorithm().id(), &impl
);
61 case blink::WebCryptoKeyFormatRaw
:
62 return impl
->ExportKeyRaw(key
, buffer
);
63 case blink::WebCryptoKeyFormatSpki
:
64 return impl
->ExportKeySpki(key
, buffer
);
65 case blink::WebCryptoKeyFormatPkcs8
:
66 return impl
->ExportKeyPkcs8(key
, buffer
);
67 case blink::WebCryptoKeyFormatJwk
:
68 return impl
->ExportKeyJwk(key
, buffer
);
70 return Status::ErrorUnsupported();
76 Status
Encrypt(const blink::WebCryptoAlgorithm
& algorithm
,
77 const blink::WebCryptoKey
& key
,
78 const CryptoData
& data
,
79 std::vector
<uint8_t>* buffer
) {
80 if (!KeyUsageAllows(key
, blink::WebCryptoKeyUsageEncrypt
))
81 return Status::ErrorUnexpected();
82 return EncryptDontCheckUsage(algorithm
, key
, data
, buffer
);
85 Status
Decrypt(const blink::WebCryptoAlgorithm
& algorithm
,
86 const blink::WebCryptoKey
& key
,
87 const CryptoData
& data
,
88 std::vector
<uint8_t>* buffer
) {
89 if (!KeyUsageAllows(key
, blink::WebCryptoKeyUsageDecrypt
))
90 return Status::ErrorUnexpected();
91 return DecryptDontCheckKeyUsage(algorithm
, key
, data
, buffer
);
94 Status
Digest(const blink::WebCryptoAlgorithm
& algorithm
,
95 const CryptoData
& data
,
96 std::vector
<uint8_t>* buffer
) {
97 const AlgorithmImplementation
* impl
= NULL
;
98 Status status
= GetAlgorithmImplementation(algorithm
.id(), &impl
);
102 return impl
->Digest(algorithm
, data
, buffer
);
105 Status
GenerateSecretKey(const blink::WebCryptoAlgorithm
& algorithm
,
107 blink::WebCryptoKeyUsageMask usage_mask
,
108 blink::WebCryptoKey
* key
) {
109 const AlgorithmImplementation
* impl
= NULL
;
110 Status status
= GetAlgorithmImplementation(algorithm
.id(), &impl
);
111 if (status
.IsError())
114 status
= impl
->VerifyKeyUsagesBeforeGenerateKey(usage_mask
);
115 if (status
.IsError())
118 return impl
->GenerateSecretKey(algorithm
, extractable
, usage_mask
, key
);
121 Status
GenerateKeyPair(const blink::WebCryptoAlgorithm
& algorithm
,
123 blink::WebCryptoKeyUsageMask combined_usage_mask
,
124 blink::WebCryptoKey
* public_key
,
125 blink::WebCryptoKey
* private_key
) {
126 const AlgorithmImplementation
* impl
= NULL
;
127 Status status
= GetAlgorithmImplementation(algorithm
.id(), &impl
);
128 if (status
.IsError())
131 blink::WebCryptoKeyUsageMask public_usage_mask
;
132 blink::WebCryptoKeyUsageMask private_usage_mask
;
133 status
= impl
->VerifyKeyUsagesBeforeGenerateKeyPair(
134 combined_usage_mask
, &public_usage_mask
, &private_usage_mask
);
135 if (status
.IsError())
138 return impl
->GenerateKeyPair(algorithm
,
146 // Note that this function may be called from the target Blink thread.
147 Status
ImportKey(blink::WebCryptoKeyFormat format
,
148 const CryptoData
& key_data
,
149 const blink::WebCryptoAlgorithm
& algorithm
,
151 blink::WebCryptoKeyUsageMask usage_mask
,
152 blink::WebCryptoKey
* key
) {
153 const AlgorithmImplementation
* impl
= NULL
;
154 Status status
= GetAlgorithmImplementation(algorithm
.id(), &impl
);
155 if (status
.IsError())
158 status
= impl
->VerifyKeyUsagesBeforeImportKey(format
, usage_mask
);
159 if (status
.IsError())
163 case blink::WebCryptoKeyFormatRaw
:
164 return impl
->ImportKeyRaw(
165 key_data
, algorithm
, extractable
, usage_mask
, key
);
166 case blink::WebCryptoKeyFormatSpki
:
167 return impl
->ImportKeySpki(
168 key_data
, algorithm
, extractable
, usage_mask
, key
);
169 case blink::WebCryptoKeyFormatPkcs8
:
170 return impl
->ImportKeyPkcs8(
171 key_data
, algorithm
, extractable
, usage_mask
, key
);
172 case blink::WebCryptoKeyFormatJwk
:
173 return impl
->ImportKeyJwk(
174 key_data
, algorithm
, extractable
, usage_mask
, key
);
176 return Status::ErrorUnsupported();
180 Status
ExportKey(blink::WebCryptoKeyFormat format
,
181 const blink::WebCryptoKey
& key
,
182 std::vector
<uint8_t>* buffer
) {
183 if (!key
.extractable())
184 return Status::ErrorKeyNotExtractable();
185 return ExportKeyDontCheckExtractability(format
, key
, buffer
);
188 Status
Sign(const blink::WebCryptoAlgorithm
& algorithm
,
189 const blink::WebCryptoKey
& key
,
190 const CryptoData
& data
,
191 std::vector
<uint8_t>* buffer
) {
192 if (!KeyUsageAllows(key
, blink::WebCryptoKeyUsageSign
))
193 return Status::ErrorUnexpected();
194 if (algorithm
.id() != key
.algorithm().id())
195 return Status::ErrorUnexpected();
197 const AlgorithmImplementation
* impl
= NULL
;
198 Status status
= GetAlgorithmImplementation(algorithm
.id(), &impl
);
199 if (status
.IsError())
202 return impl
->Sign(algorithm
, key
, data
, buffer
);
205 Status
Verify(const blink::WebCryptoAlgorithm
& algorithm
,
206 const blink::WebCryptoKey
& key
,
207 const CryptoData
& signature
,
208 const CryptoData
& data
,
209 bool* signature_match
) {
210 if (!KeyUsageAllows(key
, blink::WebCryptoKeyUsageVerify
))
211 return Status::ErrorUnexpected();
212 if (algorithm
.id() != key
.algorithm().id())
213 return Status::ErrorUnexpected();
215 const AlgorithmImplementation
* impl
= NULL
;
216 Status status
= GetAlgorithmImplementation(algorithm
.id(), &impl
);
217 if (status
.IsError())
220 return impl
->Verify(algorithm
, key
, signature
, data
, signature_match
);
223 Status
WrapKey(blink::WebCryptoKeyFormat format
,
224 const blink::WebCryptoKey
& key_to_wrap
,
225 const blink::WebCryptoKey
& wrapping_key
,
226 const blink::WebCryptoAlgorithm
& wrapping_algorithm
,
227 std::vector
<uint8_t>* buffer
) {
228 if (!KeyUsageAllows(wrapping_key
, blink::WebCryptoKeyUsageWrapKey
))
229 return Status::ErrorUnexpected();
231 std::vector
<uint8_t> exported_data
;
232 Status status
= ExportKey(format
, key_to_wrap
, &exported_data
);
233 if (status
.IsError())
235 return EncryptDontCheckUsage(
236 wrapping_algorithm
, wrapping_key
, CryptoData(exported_data
), buffer
);
239 Status
UnwrapKey(blink::WebCryptoKeyFormat format
,
240 const CryptoData
& wrapped_key_data
,
241 const blink::WebCryptoKey
& wrapping_key
,
242 const blink::WebCryptoAlgorithm
& wrapping_algorithm
,
243 const blink::WebCryptoAlgorithm
& algorithm
,
245 blink::WebCryptoKeyUsageMask usage_mask
,
246 blink::WebCryptoKey
* key
) {
247 if (!KeyUsageAllows(wrapping_key
, blink::WebCryptoKeyUsageUnwrapKey
))
248 return Status::ErrorUnexpected();
249 if (wrapping_algorithm
.id() != wrapping_key
.algorithm().id())
250 return Status::ErrorUnexpected();
252 // Fail fast if the import is doomed to fail.
253 const AlgorithmImplementation
* import_impl
= NULL
;
254 Status status
= GetAlgorithmImplementation(algorithm
.id(), &import_impl
);
255 if (status
.IsError())
258 status
= import_impl
->VerifyKeyUsagesBeforeImportKey(format
, usage_mask
);
259 if (status
.IsError())
262 std::vector
<uint8_t> buffer
;
263 status
= DecryptDontCheckKeyUsage(
264 wrapping_algorithm
, wrapping_key
, wrapped_key_data
, &buffer
);
265 if (status
.IsError())
268 // NOTE that returning the details of ImportKey() failures may leak
269 // information about the plaintext of the encrypted key (for instance the JWK
270 // key_ops). As long as the ImportKey error messages don't describe actual
271 // key bytes however this should be OK. For more discussion see
272 // http://crubg.com/372040
274 format
, CryptoData(buffer
), algorithm
, extractable
, usage_mask
, key
);
277 scoped_ptr
<blink::WebCryptoDigestor
> CreateDigestor(
278 blink::WebCryptoAlgorithmId algorithm
) {
280 return CreatePlatformDigestor(algorithm
);
283 } // namespace webcrypto
285 } // namespace content