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 GenerateKey(const blink::WebCryptoAlgorithm& algorithm,
107 blink::WebCryptoKeyUsageMask usages,
108 GenerateKeyResult* result) {
109 const AlgorithmImplementation* impl = NULL;
110 Status status = GetAlgorithmImplementation(algorithm.id(), &impl);
111 if (status.IsError())
114 return impl->GenerateKey(algorithm, extractable, usages, result);
117 // Note that this function may be called from the target Blink thread.
118 Status ImportKey(blink::WebCryptoKeyFormat format,
119 const CryptoData& key_data,
120 const blink::WebCryptoAlgorithm& algorithm,
122 blink::WebCryptoKeyUsageMask usages,
123 blink::WebCryptoKey* key) {
124 const AlgorithmImplementation* impl = NULL;
125 Status status = GetAlgorithmImplementation(algorithm.id(), &impl);
126 if (status.IsError())
129 status = impl->VerifyKeyUsagesBeforeImportKey(format, usages);
130 if (status.IsError())
134 case blink::WebCryptoKeyFormatRaw:
135 return impl->ImportKeyRaw(key_data, algorithm, extractable, usages, key);
136 case blink::WebCryptoKeyFormatSpki:
137 return impl->ImportKeySpki(key_data, algorithm, extractable, usages, key);
138 case blink::WebCryptoKeyFormatPkcs8:
139 return impl->ImportKeyPkcs8(
140 key_data, algorithm, extractable, usages, key);
141 case blink::WebCryptoKeyFormatJwk:
142 return impl->ImportKeyJwk(key_data, algorithm, extractable, usages, key);
144 return Status::ErrorUnsupported();
148 Status ExportKey(blink::WebCryptoKeyFormat format,
149 const blink::WebCryptoKey& key,
150 std::vector<uint8_t>* buffer) {
151 if (!key.extractable())
152 return Status::ErrorKeyNotExtractable();
153 return ExportKeyDontCheckExtractability(format, key, buffer);
156 Status Sign(const blink::WebCryptoAlgorithm& algorithm,
157 const blink::WebCryptoKey& key,
158 const CryptoData& data,
159 std::vector<uint8_t>* buffer) {
160 if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageSign))
161 return Status::ErrorUnexpected();
162 if (algorithm.id() != key.algorithm().id())
163 return Status::ErrorUnexpected();
165 const AlgorithmImplementation* impl = NULL;
166 Status status = GetAlgorithmImplementation(algorithm.id(), &impl);
167 if (status.IsError())
170 return impl->Sign(algorithm, key, data, buffer);
173 Status Verify(const blink::WebCryptoAlgorithm& algorithm,
174 const blink::WebCryptoKey& key,
175 const CryptoData& signature,
176 const CryptoData& data,
177 bool* signature_match) {
178 if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageVerify))
179 return Status::ErrorUnexpected();
180 if (algorithm.id() != key.algorithm().id())
181 return Status::ErrorUnexpected();
183 const AlgorithmImplementation* impl = NULL;
184 Status status = GetAlgorithmImplementation(algorithm.id(), &impl);
185 if (status.IsError())
188 return impl->Verify(algorithm, key, signature, data, signature_match);
191 Status WrapKey(blink::WebCryptoKeyFormat format,
192 const blink::WebCryptoKey& key_to_wrap,
193 const blink::WebCryptoKey& wrapping_key,
194 const blink::WebCryptoAlgorithm& wrapping_algorithm,
195 std::vector<uint8_t>* buffer) {
196 if (!KeyUsageAllows(wrapping_key, blink::WebCryptoKeyUsageWrapKey))
197 return Status::ErrorUnexpected();
199 std::vector<uint8_t> exported_data;
200 Status status = ExportKey(format, key_to_wrap, &exported_data);
201 if (status.IsError())
203 return EncryptDontCheckUsage(
204 wrapping_algorithm, wrapping_key, CryptoData(exported_data), buffer);
207 Status UnwrapKey(blink::WebCryptoKeyFormat format,
208 const CryptoData& wrapped_key_data,
209 const blink::WebCryptoKey& wrapping_key,
210 const blink::WebCryptoAlgorithm& wrapping_algorithm,
211 const blink::WebCryptoAlgorithm& algorithm,
213 blink::WebCryptoKeyUsageMask usages,
214 blink::WebCryptoKey* key) {
215 if (!KeyUsageAllows(wrapping_key, blink::WebCryptoKeyUsageUnwrapKey))
216 return Status::ErrorUnexpected();
217 if (wrapping_algorithm.id() != wrapping_key.algorithm().id())
218 return Status::ErrorUnexpected();
220 // Fail fast if the import is doomed to fail.
221 const AlgorithmImplementation* import_impl = NULL;
222 Status status = GetAlgorithmImplementation(algorithm.id(), &import_impl);
223 if (status.IsError())
226 status = import_impl->VerifyKeyUsagesBeforeImportKey(format, usages);
227 if (status.IsError())
230 std::vector<uint8_t> buffer;
231 status = DecryptDontCheckKeyUsage(
232 wrapping_algorithm, wrapping_key, wrapped_key_data, &buffer);
233 if (status.IsError())
236 // NOTE that returning the details of ImportKey() failures may leak
237 // information about the plaintext of the encrypted key (for instance the JWK
238 // key_ops). As long as the ImportKey error messages don't describe actual
239 // key bytes however this should be OK. For more discussion see
240 // http://crubg.com/372040
242 format, CryptoData(buffer), algorithm, extractable, usages, key);
245 scoped_ptr<blink::WebCryptoDigestor> CreateDigestor(
246 blink::WebCryptoAlgorithmId algorithm) {
248 return CreatePlatformDigestor(algorithm);
251 } // namespace webcrypto
253 } // namespace content