OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/renderer/webcrypto/webcrypto_impl.h" | |
6 | |
7 #include <algorithm> | 5 #include <algorithm> |
8 #include <functional> | 6 #include <functional> |
9 #include <map> | 7 #include <map> |
10 #include "base/json/json_reader.h" | 8 #include "base/json/json_reader.h" |
11 #include "base/lazy_instance.h" | 9 #include "base/lazy_instance.h" |
12 #include "base/logging.h" | 10 #include "base/logging.h" |
13 #include "base/memory/scoped_ptr.h" | 11 #include "base/memory/scoped_ptr.h" |
14 #include "base/strings/string_piece.h" | 12 #include "base/strings/string_piece.h" |
15 #include "base/values.h" | 13 #include "base/values.h" |
| 14 #include "content/renderer/webcrypto/crypto_data.h" |
| 15 #include "content/renderer/webcrypto/platform_crypto.h" |
| 16 #include "content/renderer/webcrypto/platform_crypto.h" |
16 #include "content/renderer/webcrypto/webcrypto_util.h" | 17 #include "content/renderer/webcrypto/webcrypto_util.h" |
17 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" | |
18 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" | |
19 #include "third_party/WebKit/public/platform/WebCryptoKey.h" | |
20 #include "third_party/WebKit/public/platform/WebString.h" | |
21 | 18 |
22 namespace content { | 19 namespace content { |
23 | 20 |
24 using webcrypto::Status; | 21 namespace webcrypto { |
25 | 22 |
26 namespace { | 23 namespace { |
27 | 24 |
28 void CompleteWithError(const Status& status, blink::WebCryptoResult* result) { | |
29 DCHECK(status.IsError()); | |
30 if (status.HasErrorDetails()) | |
31 result->completeWithError(blink::WebString::fromUTF8(status.ToString())); | |
32 else | |
33 result->completeWithError(); | |
34 } | |
35 | |
36 bool IsAlgorithmAsymmetric(const blink::WebCryptoAlgorithm& algorithm) { | |
37 // TODO(padolph): include all other asymmetric algorithms once they are | |
38 // defined, e.g. EC and DH. | |
39 return (algorithm.id() == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 || | |
40 algorithm.id() == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 || | |
41 algorithm.id() == blink::WebCryptoAlgorithmIdRsaOaep); | |
42 } | |
43 | 25 |
44 typedef blink::WebCryptoAlgorithm (*AlgorithmCreationFunc)(); | 26 typedef blink::WebCryptoAlgorithm (*AlgorithmCreationFunc)(); |
45 | 27 |
46 class JwkAlgorithmInfo { | 28 class JwkAlgorithmInfo { |
47 public: | 29 public: |
48 JwkAlgorithmInfo() | 30 JwkAlgorithmInfo() |
49 : creation_func_(NULL), | 31 : creation_func_(NULL), |
50 required_key_length_bytes_(NO_KEY_SIZE_REQUIREMENT) { | 32 required_key_length_bytes_(NO_KEY_SIZE_REQUIREMENT) { |
51 | 33 |
52 } | 34 } |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 typedef std::map<std::string, JwkAlgorithmInfo> JwkAlgorithmInfoMap; | 69 typedef std::map<std::string, JwkAlgorithmInfo> JwkAlgorithmInfoMap; |
88 | 70 |
89 class JwkAlgorithmRegistry { | 71 class JwkAlgorithmRegistry { |
90 public: | 72 public: |
91 JwkAlgorithmRegistry() { | 73 JwkAlgorithmRegistry() { |
92 // TODO(eroman): | 74 // TODO(eroman): |
93 // http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-20 | 75 // http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-20 |
94 // says HMAC with SHA-2 should have a key size at least as large as the | 76 // says HMAC with SHA-2 should have a key size at least as large as the |
95 // hash output. | 77 // hash output. |
96 alg_to_info_["HS256"] = JwkAlgorithmInfo( | 78 alg_to_info_["HS256"] = JwkAlgorithmInfo( |
97 &BindAlgorithmId<webcrypto::CreateHmacAlgorithmByHashId, | 79 &BindAlgorithmId<CreateHmacAlgorithmByHashId, |
98 blink::WebCryptoAlgorithmIdSha256>); | 80 blink::WebCryptoAlgorithmIdSha256>); |
99 alg_to_info_["HS384"] = JwkAlgorithmInfo( | 81 alg_to_info_["HS384"] = JwkAlgorithmInfo( |
100 &BindAlgorithmId<webcrypto::CreateHmacAlgorithmByHashId, | 82 &BindAlgorithmId<CreateHmacAlgorithmByHashId, |
101 blink::WebCryptoAlgorithmIdSha384>); | 83 blink::WebCryptoAlgorithmIdSha384>); |
102 alg_to_info_["HS512"] = JwkAlgorithmInfo( | 84 alg_to_info_["HS512"] = JwkAlgorithmInfo( |
103 &BindAlgorithmId<webcrypto::CreateHmacAlgorithmByHashId, | 85 &BindAlgorithmId<CreateHmacAlgorithmByHashId, |
104 blink::WebCryptoAlgorithmIdSha512>); | 86 blink::WebCryptoAlgorithmIdSha512>); |
105 alg_to_info_["RS256"] = JwkAlgorithmInfo( | 87 alg_to_info_["RS256"] = JwkAlgorithmInfo( |
106 &BindAlgorithmId<webcrypto::CreateRsaSsaAlgorithm, | 88 &BindAlgorithmId<CreateRsaSsaAlgorithm, |
107 blink::WebCryptoAlgorithmIdSha256>); | 89 blink::WebCryptoAlgorithmIdSha256>); |
108 alg_to_info_["RS384"] = JwkAlgorithmInfo( | 90 alg_to_info_["RS384"] = JwkAlgorithmInfo( |
109 &BindAlgorithmId<webcrypto::CreateRsaSsaAlgorithm, | 91 &BindAlgorithmId<CreateRsaSsaAlgorithm, |
110 blink::WebCryptoAlgorithmIdSha384>); | 92 blink::WebCryptoAlgorithmIdSha384>); |
111 alg_to_info_["RS512"] = JwkAlgorithmInfo( | 93 alg_to_info_["RS512"] = JwkAlgorithmInfo( |
112 &BindAlgorithmId<webcrypto::CreateRsaSsaAlgorithm, | 94 &BindAlgorithmId<CreateRsaSsaAlgorithm, |
113 blink::WebCryptoAlgorithmIdSha512>); | 95 blink::WebCryptoAlgorithmIdSha512>); |
114 alg_to_info_["RSA1_5"] = JwkAlgorithmInfo( | 96 alg_to_info_["RSA1_5"] = JwkAlgorithmInfo( |
115 &BindAlgorithmId<webcrypto::CreateAlgorithm, | 97 &BindAlgorithmId<CreateAlgorithm, |
116 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5>); | 98 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5>); |
117 alg_to_info_["RSA-OAEP"] = JwkAlgorithmInfo( | 99 alg_to_info_["RSA-OAEP"] = JwkAlgorithmInfo( |
118 &BindAlgorithmId<webcrypto::CreateRsaOaepAlgorithm, | 100 &BindAlgorithmId<CreateRsaOaepAlgorithm, |
119 blink::WebCryptoAlgorithmIdSha1>); | 101 blink::WebCryptoAlgorithmIdSha1>); |
120 // TODO(padolph): The Web Crypto spec does not enumerate AES-KW 128 yet | 102 // TODO(padolph): The Web Crypto spec does not enumerate AES-KW 128 yet |
121 alg_to_info_["A128KW"] = | 103 alg_to_info_["A128KW"] = |
122 JwkAlgorithmInfo(&blink::WebCryptoAlgorithm::createNull, 128); | 104 JwkAlgorithmInfo(&blink::WebCryptoAlgorithm::createNull, 128); |
123 // TODO(padolph): The Web Crypto spec does not enumerate AES-KW 256 yet | 105 // TODO(padolph): The Web Crypto spec does not enumerate AES-KW 256 yet |
124 alg_to_info_["A256KW"] = | 106 alg_to_info_["A256KW"] = |
125 JwkAlgorithmInfo(&blink::WebCryptoAlgorithm::createNull, 256); | 107 JwkAlgorithmInfo(&blink::WebCryptoAlgorithm::createNull, 256); |
126 alg_to_info_["A128GCM"] = JwkAlgorithmInfo( | 108 alg_to_info_["A128GCM"] = JwkAlgorithmInfo( |
127 &BindAlgorithmId<webcrypto::CreateAlgorithm, | 109 &BindAlgorithmId<CreateAlgorithm, |
128 blink::WebCryptoAlgorithmIdAesGcm>, 128); | 110 blink::WebCryptoAlgorithmIdAesGcm>, 128); |
129 alg_to_info_["A256GCM"] = JwkAlgorithmInfo( | 111 alg_to_info_["A256GCM"] = JwkAlgorithmInfo( |
130 &BindAlgorithmId<webcrypto::CreateAlgorithm, | 112 &BindAlgorithmId<CreateAlgorithm, |
131 blink::WebCryptoAlgorithmIdAesGcm>, 256); | 113 blink::WebCryptoAlgorithmIdAesGcm>, 256); |
132 alg_to_info_["A128CBC"] = JwkAlgorithmInfo( | 114 alg_to_info_["A128CBC"] = JwkAlgorithmInfo( |
133 &BindAlgorithmId<webcrypto::CreateAlgorithm, | 115 &BindAlgorithmId<CreateAlgorithm, |
134 blink::WebCryptoAlgorithmIdAesCbc>, 128); | 116 blink::WebCryptoAlgorithmIdAesCbc>, 128); |
135 alg_to_info_["A192CBC"] = JwkAlgorithmInfo( | 117 alg_to_info_["A192CBC"] = JwkAlgorithmInfo( |
136 &BindAlgorithmId<webcrypto::CreateAlgorithm, | 118 &BindAlgorithmId<CreateAlgorithm, |
137 blink::WebCryptoAlgorithmIdAesCbc>, 192); | 119 blink::WebCryptoAlgorithmIdAesCbc>, 192); |
138 alg_to_info_["A256CBC"] = JwkAlgorithmInfo( | 120 alg_to_info_["A256CBC"] = JwkAlgorithmInfo( |
139 &BindAlgorithmId<webcrypto::CreateAlgorithm, | 121 &BindAlgorithmId<CreateAlgorithm, |
140 blink::WebCryptoAlgorithmIdAesCbc>, 256); | 122 blink::WebCryptoAlgorithmIdAesCbc>, 256); |
141 } | 123 } |
142 | 124 |
143 // Returns NULL if the algorithm name was not registered. | 125 // Returns NULL if the algorithm name was not registered. |
144 const JwkAlgorithmInfo* GetAlgorithmInfo(const std::string& jwk_alg) const { | 126 const JwkAlgorithmInfo* GetAlgorithmInfo(const std::string& jwk_alg) const { |
145 const JwkAlgorithmInfoMap::const_iterator pos = alg_to_info_.find(jwk_alg); | 127 const JwkAlgorithmInfoMap::const_iterator pos = alg_to_info_.find(jwk_alg); |
146 if (pos == alg_to_info_.end()) | 128 if (pos == alg_to_info_.end()) |
147 return NULL; | 129 return NULL; |
148 return &pos->second; | 130 return &pos->second; |
149 } | 131 } |
(...skipping 18 matching lines...) Expand all Loading... |
168 const blink::WebCryptoAlgorithm& alg2) { | 150 const blink::WebCryptoAlgorithm& alg2) { |
169 DCHECK(!alg1.isNull()); | 151 DCHECK(!alg1.isNull()); |
170 DCHECK(!alg2.isNull()); | 152 DCHECK(!alg2.isNull()); |
171 if (alg1.id() != alg2.id()) | 153 if (alg1.id() != alg2.id()) |
172 return false; | 154 return false; |
173 switch (alg1.id()) { | 155 switch (alg1.id()) { |
174 case blink::WebCryptoAlgorithmIdHmac: | 156 case blink::WebCryptoAlgorithmIdHmac: |
175 case blink::WebCryptoAlgorithmIdRsaOaep: | 157 case blink::WebCryptoAlgorithmIdRsaOaep: |
176 case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: | 158 case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: |
177 if (WebCryptoAlgorithmsConsistent( | 159 if (WebCryptoAlgorithmsConsistent( |
178 webcrypto::GetInnerHashAlgorithm(alg1), | 160 GetInnerHashAlgorithm(alg1), |
179 webcrypto::GetInnerHashAlgorithm(alg2))) { | 161 GetInnerHashAlgorithm(alg2))) { |
180 return true; | 162 return true; |
181 } | 163 } |
182 break; | 164 break; |
183 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: | 165 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: |
184 case blink::WebCryptoAlgorithmIdSha1: | 166 case blink::WebCryptoAlgorithmIdSha1: |
185 case blink::WebCryptoAlgorithmIdSha224: | 167 case blink::WebCryptoAlgorithmIdSha224: |
186 case blink::WebCryptoAlgorithmIdSha256: | 168 case blink::WebCryptoAlgorithmIdSha256: |
187 case blink::WebCryptoAlgorithmIdSha384: | 169 case blink::WebCryptoAlgorithmIdSha384: |
188 case blink::WebCryptoAlgorithmIdSha512: | 170 case blink::WebCryptoAlgorithmIdSha512: |
189 case blink::WebCryptoAlgorithmIdAesCbc: | 171 case blink::WebCryptoAlgorithmIdAesCbc: |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
235 // the base64-decoded bytes to |*result|. If the property does not exist or is | 217 // the base64-decoded bytes to |*result|. If the property does not exist or is |
236 // not a string, or could not be base64-decoded, returns an error. | 218 // not a string, or could not be base64-decoded, returns an error. |
237 Status GetJwkBytes(base::DictionaryValue* dict, | 219 Status GetJwkBytes(base::DictionaryValue* dict, |
238 const std::string& path, | 220 const std::string& path, |
239 std::string* result) { | 221 std::string* result) { |
240 std::string base64_string; | 222 std::string base64_string; |
241 Status status = GetJwkString(dict, path, &base64_string); | 223 Status status = GetJwkString(dict, path, &base64_string); |
242 if (status.IsError()) | 224 if (status.IsError()) |
243 return status; | 225 return status; |
244 | 226 |
245 if (!webcrypto::Base64DecodeUrlSafe(base64_string, result)) | 227 if (!Base64DecodeUrlSafe(base64_string, result)) |
246 return Status::ErrorJwkBase64Decode(path); | 228 return Status::ErrorJwkBase64Decode(path); |
247 | 229 |
248 return Status::Success(); | 230 return Status::Success(); |
249 } | 231 } |
250 | 232 |
251 // Extracts the optional boolean property with key |path| from |dict| and saves | 233 // Extracts the optional boolean property with key |path| from |dict| and saves |
252 // the result to |*result| if it was found. If the property exists and is not a | 234 // the result to |*result| if it was found. If the property exists and is not a |
253 // boolean, returns an error. Otherwise returns success, and sets | 235 // boolean, returns an error. Otherwise returns success, and sets |
254 // |*property_exists| if it was found. | 236 // |*property_exists| if it was found. |
255 Status GetOptionalJwkBool(base::DictionaryValue* dict, | 237 Status GetOptionalJwkBool(base::DictionaryValue* dict, |
256 const std::string& path, | 238 const std::string& path, |
257 bool* result, | 239 bool* result, |
258 bool* property_exists) { | 240 bool* property_exists) { |
259 *property_exists = false; | 241 *property_exists = false; |
260 base::Value* value = NULL; | 242 base::Value* value = NULL; |
261 if (!dict->Get(path, &value)) | 243 if (!dict->Get(path, &value)) |
262 return Status::Success(); | 244 return Status::Success(); |
263 | 245 |
264 if (!value->GetAsBoolean(result)) | 246 if (!value->GetAsBoolean(result)) |
265 return Status::ErrorJwkPropertyWrongType(path, "boolean"); | 247 return Status::ErrorJwkPropertyWrongType(path, "boolean"); |
266 | 248 |
267 *property_exists = true; | 249 *property_exists = true; |
268 return Status::Success(); | 250 return Status::Success(); |
269 } | 251 } |
270 | 252 |
271 } // namespace | 253 } // namespace |
272 | 254 |
273 WebCryptoImpl::WebCryptoImpl() { | 255 Status PlatformCrypto::ImportKeyJwk( |
274 Init(); | 256 const CryptoData& key_data, |
275 } | |
276 | |
277 void WebCryptoImpl::encrypt( | |
278 const blink::WebCryptoAlgorithm& algorithm, | |
279 const blink::WebCryptoKey& key, | |
280 const unsigned char* data, | |
281 unsigned int data_size, | |
282 blink::WebCryptoResult result) { | |
283 DCHECK(!algorithm.isNull()); | |
284 blink::WebArrayBuffer buffer; | |
285 Status status = EncryptInternal(algorithm, key, data, data_size, &buffer); | |
286 if (status.IsError()) | |
287 CompleteWithError(status, &result); | |
288 else | |
289 result.completeWithBuffer(buffer); | |
290 } | |
291 | |
292 void WebCryptoImpl::decrypt( | |
293 const blink::WebCryptoAlgorithm& algorithm, | |
294 const blink::WebCryptoKey& key, | |
295 const unsigned char* data, | |
296 unsigned int data_size, | |
297 blink::WebCryptoResult result) { | |
298 DCHECK(!algorithm.isNull()); | |
299 blink::WebArrayBuffer buffer; | |
300 Status status = DecryptInternal(algorithm, key, data, data_size, &buffer); | |
301 if (status.IsError()) | |
302 CompleteWithError(status, &result); | |
303 else | |
304 result.completeWithBuffer(buffer); | |
305 } | |
306 | |
307 void WebCryptoImpl::digest( | |
308 const blink::WebCryptoAlgorithm& algorithm, | |
309 const unsigned char* data, | |
310 unsigned int data_size, | |
311 blink::WebCryptoResult result) { | |
312 DCHECK(!algorithm.isNull()); | |
313 blink::WebArrayBuffer buffer; | |
314 Status status = DigestInternal(algorithm, data, data_size, &buffer); | |
315 if (status.IsError()) | |
316 CompleteWithError(status, &result); | |
317 else | |
318 result.completeWithBuffer(buffer); | |
319 } | |
320 | |
321 void WebCryptoImpl::generateKey( | |
322 const blink::WebCryptoAlgorithm& algorithm, | |
323 bool extractable, | |
324 blink::WebCryptoKeyUsageMask usage_mask, | |
325 blink::WebCryptoResult result) { | |
326 DCHECK(!algorithm.isNull()); | |
327 if (IsAlgorithmAsymmetric(algorithm)) { | |
328 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull(); | |
329 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull(); | |
330 Status status = GenerateKeyPairInternal( | |
331 algorithm, extractable, usage_mask, &public_key, &private_key); | |
332 if (status.IsError()) { | |
333 CompleteWithError(status, &result); | |
334 } else { | |
335 DCHECK(public_key.handle()); | |
336 DCHECK(private_key.handle()); | |
337 DCHECK_EQ(algorithm.id(), public_key.algorithm().id()); | |
338 DCHECK_EQ(algorithm.id(), private_key.algorithm().id()); | |
339 DCHECK_EQ(true, public_key.extractable()); | |
340 DCHECK_EQ(extractable, private_key.extractable()); | |
341 DCHECK_EQ(usage_mask, public_key.usages()); | |
342 DCHECK_EQ(usage_mask, private_key.usages()); | |
343 result.completeWithKeyPair(public_key, private_key); | |
344 } | |
345 } else { | |
346 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); | |
347 Status status = GenerateSecretKeyInternal( | |
348 algorithm, extractable, usage_mask, &key); | |
349 if (status.IsError()) { | |
350 CompleteWithError(status, &result); | |
351 } else { | |
352 DCHECK(key.handle()); | |
353 DCHECK_EQ(algorithm.id(), key.algorithm().id()); | |
354 DCHECK_EQ(extractable, key.extractable()); | |
355 DCHECK_EQ(usage_mask, key.usages()); | |
356 result.completeWithKey(key); | |
357 } | |
358 } | |
359 } | |
360 | |
361 void WebCryptoImpl::importKey( | |
362 blink::WebCryptoKeyFormat format, | |
363 const unsigned char* key_data, | |
364 unsigned int key_data_size, | |
365 const blink::WebCryptoAlgorithm& algorithm_or_null, | 257 const blink::WebCryptoAlgorithm& algorithm_or_null, |
366 bool extractable, | 258 bool extractable, |
367 blink::WebCryptoKeyUsageMask usage_mask, | 259 blink::WebCryptoKeyUsageMask usage_mask, |
368 blink::WebCryptoResult result) { | |
369 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); | |
370 Status status = Status::Error(); | |
371 if (format == blink::WebCryptoKeyFormatJwk) { | |
372 status = ImportKeyJwk(key_data, | |
373 key_data_size, | |
374 algorithm_or_null, | |
375 extractable, | |
376 usage_mask, | |
377 &key); | |
378 } else { | |
379 status = ImportKeyInternal(format, | |
380 key_data, | |
381 key_data_size, | |
382 algorithm_or_null, | |
383 extractable, | |
384 usage_mask, | |
385 &key); | |
386 } | |
387 if (status.IsError()) { | |
388 CompleteWithError(status, &result); | |
389 } else { | |
390 DCHECK(key.handle()); | |
391 DCHECK(!key.algorithm().isNull()); | |
392 DCHECK_EQ(extractable, key.extractable()); | |
393 result.completeWithKey(key); | |
394 } | |
395 } | |
396 | |
397 void WebCryptoImpl::exportKey( | |
398 blink::WebCryptoKeyFormat format, | |
399 const blink::WebCryptoKey& key, | |
400 blink::WebCryptoResult result) { | |
401 blink::WebArrayBuffer buffer; | |
402 Status status = ExportKeyInternal(format, key, &buffer); | |
403 if (status.IsError()) | |
404 CompleteWithError(status, &result); | |
405 else | |
406 result.completeWithBuffer(buffer); | |
407 } | |
408 | |
409 void WebCryptoImpl::sign( | |
410 const blink::WebCryptoAlgorithm& algorithm, | |
411 const blink::WebCryptoKey& key, | |
412 const unsigned char* data, | |
413 unsigned int data_size, | |
414 blink::WebCryptoResult result) { | |
415 DCHECK(!algorithm.isNull()); | |
416 blink::WebArrayBuffer buffer; | |
417 Status status = SignInternal(algorithm, key, data, data_size, &buffer); | |
418 if (status.IsError()) | |
419 CompleteWithError(status, &result); | |
420 else | |
421 result.completeWithBuffer(buffer); | |
422 } | |
423 | |
424 void WebCryptoImpl::verifySignature( | |
425 const blink::WebCryptoAlgorithm& algorithm, | |
426 const blink::WebCryptoKey& key, | |
427 const unsigned char* signature, | |
428 unsigned int signature_size, | |
429 const unsigned char* data, | |
430 unsigned int data_size, | |
431 blink::WebCryptoResult result) { | |
432 DCHECK(!algorithm.isNull()); | |
433 bool signature_match = false; | |
434 Status status = VerifySignatureInternal(algorithm, | |
435 key, | |
436 signature, | |
437 signature_size, | |
438 data, | |
439 data_size, | |
440 &signature_match); | |
441 if (status.IsError()) | |
442 CompleteWithError(status, &result); | |
443 else | |
444 result.completeWithBoolean(signature_match); | |
445 } | |
446 | |
447 Status WebCryptoImpl::ImportKeyJwk( | |
448 const unsigned char* key_data, | |
449 unsigned int key_data_size, | |
450 const blink::WebCryptoAlgorithm& algorithm_or_null, | |
451 bool extractable, | |
452 blink::WebCryptoKeyUsageMask usage_mask, | |
453 blink::WebCryptoKey* key) { | 260 blink::WebCryptoKey* key) { |
454 | 261 |
455 // The goal of this method is to extract key material and meta data from the | 262 // The goal of this method is to extract key material and meta data from the |
456 // incoming JWK, combine them with the input parameters, and ultimately import | 263 // incoming JWK, combine them with the input parameters, and ultimately import |
457 // a Web Crypto Key. | 264 // a Web Crypto Key. |
458 // | 265 // |
459 // JSON Web Key Format (JWK) | 266 // JSON Web Key Format (JWK) |
460 // http://tools.ietf.org/html/draft-ietf-jose-json-web-key-16 | 267 // http://tools.ietf.org/html/draft-ietf-jose-json-web-key-16 |
461 // TODO(padolph): Not all possible values are handled by this code right now | 268 // TODO(padolph): Not all possible values are handled by this code right now |
462 // | 269 // |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
580 // Web Crypto Key non-extractable. Conversely, if the JWK extractable is | 387 // Web Crypto Key non-extractable. Conversely, if the JWK extractable is |
581 // false but the input parameter is true, it is an inconsistency. If both | 388 // false but the input parameter is true, it is an inconsistency. If both |
582 // are true or both are false, use that value. | 389 // are true or both are false, use that value. |
583 // | 390 // |
584 // usage_mask | 391 // usage_mask |
585 // The input usage_mask must be a strict subset of the interpreted JWK use | 392 // The input usage_mask must be a strict subset of the interpreted JWK use |
586 // value, else it is judged inconsistent. In all cases the input usage_mask | 393 // value, else it is judged inconsistent. In all cases the input usage_mask |
587 // is used as the final usage_mask. | 394 // is used as the final usage_mask. |
588 // | 395 // |
589 | 396 |
590 if (!key_data_size) | 397 if (!key_data.byte_length()) |
591 return Status::ErrorImportEmptyKeyData(); | 398 return Status::ErrorImportEmptyKeyData(); |
592 DCHECK(key); | 399 DCHECK(key); |
593 | 400 |
594 // Parse the incoming JWK JSON. | 401 // Parse the incoming JWK JSON. |
595 base::StringPiece json_string(reinterpret_cast<const char*>(key_data), | 402 base::StringPiece json_string(reinterpret_cast<const char*>(key_data.bytes()), |
596 key_data_size); | 403 key_data.byte_length()); |
597 scoped_ptr<base::Value> value(base::JSONReader::Read(json_string)); | 404 scoped_ptr<base::Value> value(base::JSONReader::Read(json_string)); |
598 // Note, bare pointer dict_value is ok since it points into scoped value. | 405 // Note, bare pointer dict_value is ok since it points into scoped value. |
599 base::DictionaryValue* dict_value = NULL; | 406 base::DictionaryValue* dict_value = NULL; |
600 if (!value.get() || !value->GetAsDictionary(&dict_value) || !dict_value) | 407 if (!value.get() || !value->GetAsDictionary(&dict_value) || !dict_value) |
601 return Status::ErrorJwkNotDictionary(); | 408 return Status::ErrorJwkNotDictionary(); |
602 | 409 |
603 // JWK "kty". Exit early if this required JWK parameter is missing. | 410 // JWK "kty". Exit early if this required JWK parameter is missing. |
604 std::string jwk_kty_value; | 411 std::string jwk_kty_value; |
605 Status status = GetJwkString(dict_value, "kty", &jwk_kty_value); | 412 Status status = GetJwkString(dict_value, "kty", &jwk_kty_value); |
606 if (status.IsError()) | 413 if (status.IsError()) |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
708 // string. For example "A128CBC" implies the JWK carries 128 bits | 515 // string. For example "A128CBC" implies the JWK carries 128 bits |
709 // of key material. For such keys validate that enough bytes were provided. | 516 // of key material. For such keys validate that enough bytes were provided. |
710 // If this validation is not done, then it would be possible to select a | 517 // If this validation is not done, then it would be possible to select a |
711 // different algorithm by passing a different lengthed key, since that is | 518 // different algorithm by passing a different lengthed key, since that is |
712 // how WebCrypto interprets things. | 519 // how WebCrypto interprets things. |
713 if (algorithm_info && | 520 if (algorithm_info && |
714 algorithm_info->IsInvalidKeyByteLength(jwk_k_value.size())) { | 521 algorithm_info->IsInvalidKeyByteLength(jwk_k_value.size())) { |
715 return Status::ErrorJwkIncorrectKeyLength(); | 522 return Status::ErrorJwkIncorrectKeyLength(); |
716 } | 523 } |
717 | 524 |
718 return ImportKeyInternal(blink::WebCryptoKeyFormatRaw, | 525 return ImportKey(blink::WebCryptoKeyFormatRaw, |
719 reinterpret_cast<const uint8*>(jwk_k_value.data()), | 526 jwk_k_value, |
720 jwk_k_value.size(), | 527 algorithm, |
721 algorithm, | 528 extractable, |
722 extractable, | 529 usage_mask, |
723 usage_mask, | 530 key); |
724 key); | |
725 } else if (jwk_kty_value == "RSA") { | 531 } else if (jwk_kty_value == "RSA") { |
726 | 532 |
727 // An RSA public key must have an "n" (modulus) and an "e" (exponent) entry | 533 // An RSA public key must have an "n" (modulus) and an "e" (exponent) entry |
728 // in the JWK, while an RSA private key must have those, plus at least a "d" | 534 // in the JWK, while an RSA private key must have those, plus at least a "d" |
729 // (private exponent) entry. | 535 // (private exponent) entry. |
730 // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18, | 536 // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18, |
731 // section 6.3. | 537 // section 6.3. |
732 | 538 |
733 // RSA private key import is not currently supported, so fail here if a "d" | 539 // RSA private key import is not currently supported, so fail here if a "d" |
734 // entry is found. | 540 // entry is found. |
735 // TODO(padolph): Support RSA private key import. | 541 // TODO(padolph): Support RSA private key import. |
736 if (dict_value->HasKey("d")) | 542 if (dict_value->HasKey("d")) |
737 return Status::ErrorJwkRsaPrivateKeyUnsupported(); | 543 return Status::ErrorJwkRsaPrivateKeyUnsupported(); |
738 | 544 |
739 std::string jwk_n_value; | 545 std::string jwk_n_value; |
740 status = GetJwkBytes(dict_value, "n", &jwk_n_value); | 546 status = GetJwkBytes(dict_value, "n", &jwk_n_value); |
741 if (status.IsError()) | 547 if (status.IsError()) |
742 return status; | 548 return status; |
743 std::string jwk_e_value; | 549 std::string jwk_e_value; |
744 status = GetJwkBytes(dict_value, "e", &jwk_e_value); | 550 status = GetJwkBytes(dict_value, "e", &jwk_e_value); |
745 if (status.IsError()) | 551 if (status.IsError()) |
746 return status; | 552 return status; |
747 | 553 |
748 return ImportRsaPublicKeyInternal( | 554 return PlatformImportRsaPublicKey(jwk_n_value, |
749 reinterpret_cast<const uint8*>(jwk_n_value.data()), | 555 jwk_e_value, |
750 jwk_n_value.size(), | 556 algorithm, |
751 reinterpret_cast<const uint8*>(jwk_e_value.data()), | 557 extractable, |
752 jwk_e_value.size(), | 558 usage_mask, |
753 algorithm, | 559 key); |
754 extractable, | |
755 usage_mask, | |
756 key); | |
757 | 560 |
758 } else { | 561 } else { |
759 return Status::ErrorJwkUnrecognizedKty(); | 562 return Status::ErrorJwkUnrecognizedKty(); |
760 } | 563 } |
761 | 564 |
762 return Status::Success(); | 565 return Status::Success(); |
763 } | 566 } |
764 | 567 |
| 568 } // namespace webcrypto |
| 569 |
765 } // namespace content | 570 } // namespace content |
OLD | NEW |