Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(370)

Side by Side Diff: content/child/webcrypto/shared_crypto.cc

Issue 195983010: [webcrypto] Add JWK symmetric key AES-KW unwrap for NSS. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: minor comment change Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 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/child/webcrypto/shared_crypto.h" 5 #include "content/child/webcrypto/shared_crypto.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "content/child/webcrypto/crypto_data.h" 8 #include "content/child/webcrypto/crypto_data.h"
9 #include "content/child/webcrypto/platform_crypto.h" 9 #include "content/child/webcrypto/platform_crypto.h"
10 #include "content/child/webcrypto/webcrypto_util.h" 10 #include "content/child/webcrypto/webcrypto_util.h"
11 #include "crypto/secure_util.h" 11 #include "crypto/secure_util.h"
12 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" 12 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h"
13 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" 13 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
14 #include "third_party/WebKit/public/platform/WebCryptoKey.h" 14 #include "third_party/WebKit/public/platform/WebCryptoKey.h"
15 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" 15 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
16 16
17 namespace content { 17 namespace content {
18 18
19 namespace webcrypto { 19 namespace webcrypto {
20 20
21 namespace { 21 namespace {
22 22
23 // TODO(eroman): Move this helper to WebCryptoKey. 23 // TODO(eroman): Move this helper to WebCryptoKey.
24 bool KeyUsageAllows(const blink::WebCryptoKey& key, 24 bool KeyUsageAllows(const blink::WebCryptoKey& key, unsigned int usage) {
eroman 2014/03/14 22:14:53 This is not what I expect as a caller to KeyUsageA
padolph 2014/03/17 03:24:36 Done.
25 const blink::WebCryptoKeyUsage usage) {
26 return ((key.usages() & usage) != 0); 25 return ((key.usages() & usage) != 0);
27 } 26 }
28 27
29 bool IsValidAesKeyLengthBits(unsigned int length_bits) { 28 bool IsValidAesKeyLengthBits(unsigned int length_bits) {
30 return length_bits == 128 || length_bits == 192 || length_bits == 256; 29 return length_bits == 128 || length_bits == 192 || length_bits == 256;
31 } 30 }
32 31
33 bool IsValidAesKeyLengthBytes(unsigned int length_bytes) { 32 bool IsValidAesKeyLengthBytes(unsigned int length_bytes) {
34 return length_bytes == 16 || length_bytes == 24 || length_bytes == 32; 33 return length_bytes == 16 || length_bytes == 24 || length_bytes == 32;
35 } 34 }
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
226 return Status::Error(); 225 return Status::Error();
227 // Fallthrough intentional! 226 // Fallthrough intentional!
228 case blink::WebCryptoAlgorithmIdHmac: 227 case blink::WebCryptoAlgorithmIdHmac:
229 return platform::ImportKeyRaw( 228 return platform::ImportKeyRaw(
230 algorithm_or_null, key_data, extractable, usage_mask, key); 229 algorithm_or_null, key_data, extractable, usage_mask, key);
231 default: 230 default:
232 return Status::ErrorUnsupported(); 231 return Status::ErrorUnsupported();
233 } 232 }
234 } 233 }
235 234
235 // Validates the size of data input to AES-KW. AES-KW requires the input data
236 // size to be at least 24 bytes and a multiple of 8 bytes.
237 Status CheckAesKwInputSize(const CryptoData& aeskw_input_data) {
238 if (aeskw_input_data.byte_length() < 24)
239 return Status::ErrorDataTooSmall();
240 if (aeskw_input_data.byte_length() % 8)
241 return Status::ErrorInvalidAesKwDataLength();
242 return Status::Success();
243 }
244
245 Status UnwrapKeyRaw(const CryptoData& wrapped_key_data,
246 const blink::WebCryptoKey& wrapping_key,
247 const blink::WebCryptoAlgorithm& wrapping_algorithm,
248 const blink::WebCryptoAlgorithm& algorithm_or_null,
249 bool extractable,
250 blink::WebCryptoKeyUsageMask usage_mask,
251 blink::WebCryptoKey* key) {
252 // Must provide an algorithm when unwrapping a raw key
253 if (algorithm_or_null.isNull())
254 return Status::ErrorMissingAlgorithmUnwrapRawKey();
255
256 // TODO(padolph): Handle other wrapping algorithms
257 switch (wrapping_algorithm.id()) {
258 case blink::WebCryptoAlgorithmIdAesKw: {
259 platform::SymKey* platform_wrapping_key;
260 Status status = ToPlatformSymKey(wrapping_key, &platform_wrapping_key);
261 if (status.IsError())
262 return status;
263 status = CheckAesKwInputSize(wrapped_key_data);
264 if (status.IsError())
265 return status;
266 return platform::UnwrapSymKeyAesKw(wrapped_key_data,
267 platform_wrapping_key,
268 algorithm_or_null,
269 extractable,
270 usage_mask,
271 key);
272 }
273 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: {
274 platform::PrivateKey* platform_wrapping_key;
275 Status status =
276 ToPlatformPrivateKey(wrapping_key, &platform_wrapping_key);
277 if (status.IsError())
278 return status;
279 if (!wrapped_key_data.byte_length())
280 return Status::ErrorDataTooSmall();
281 return platform::UnwrapSymKeyRsaEs(wrapped_key_data,
282 platform_wrapping_key,
283 algorithm_or_null,
284 extractable,
285 usage_mask,
286 key);
287 }
288 default:
289 return Status::ErrorUnsupported();
290 }
291 }
292
293 Status UnwrapKeyDecryptAndImport(
294 blink::WebCryptoKeyFormat format,
295 const CryptoData& wrapped_key_data,
296 const blink::WebCryptoKey& wrapping_key,
297 const blink::WebCryptoAlgorithm& wrapping_algorithm,
298 const blink::WebCryptoAlgorithm& algorithm_or_null,
299 bool extractable,
300 blink::WebCryptoKeyUsageMask usage_mask,
301 blink::WebCryptoKey* key) {
302 blink::WebArrayBuffer buffer;
303 Status status =
304 Decrypt(wrapping_algorithm, wrapping_key, wrapped_key_data, &buffer);
305 if (status.IsError())
306 return status;
307 return ImportKey(format,
eroman 2014/03/14 22:14:53 I don't think we should return the error from Impo
padolph 2014/03/17 03:24:36 Thanks. I had seen your earlier comment in the cod
308 CryptoData(buffer),
309 algorithm_or_null,
310 extractable,
311 usage_mask,
312 key);
313 }
314
315 Status DecryptAesKw(const blink::WebCryptoAlgorithm& algorithm,
316 const blink::WebCryptoKey& key,
317 const CryptoData& data,
318 blink::WebArrayBuffer* buffer) {
319 platform::SymKey* sym_key;
320 Status status = ToPlatformSymKey(key, &sym_key);
321 if (status.IsError())
322 return status;
323 status = CheckAesKwInputSize(data);
324 if (status.IsError())
325 return status;
326 return platform::DecryptAesKw(sym_key, data, buffer);
327 }
328
236 } // namespace 329 } // namespace
237 330
238 void Init() { platform::Init(); } 331 void Init() { platform::Init(); }
239 332
240 Status Encrypt(const blink::WebCryptoAlgorithm& algorithm, 333 Status Encrypt(const blink::WebCryptoAlgorithm& algorithm,
241 const blink::WebCryptoKey& key, 334 const blink::WebCryptoKey& key,
242 const CryptoData& data, 335 const CryptoData& data,
243 blink::WebArrayBuffer* buffer) { 336 blink::WebArrayBuffer* buffer) {
244 if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageEncrypt)) 337 if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageEncrypt))
245 return Status::ErrorUnexpected(); 338 return Status::ErrorUnexpected();
246 if (algorithm.id() != key.algorithm().id()) 339 if (algorithm.id() != key.algorithm().id())
247 return Status::ErrorUnexpected(); 340 return Status::ErrorUnexpected();
248 341
249 switch (algorithm.id()) { 342 switch (algorithm.id()) {
250 case blink::WebCryptoAlgorithmIdAesCbc: 343 case blink::WebCryptoAlgorithmIdAesCbc:
251 return EncryptDecryptAesCbc(ENCRYPT, algorithm, key, data, buffer); 344 return EncryptDecryptAesCbc(ENCRYPT, algorithm, key, data, buffer);
252 case blink::WebCryptoAlgorithmIdAesGcm: 345 case blink::WebCryptoAlgorithmIdAesGcm:
253 return EncryptDecryptAesGcm(ENCRYPT, algorithm, key, data, buffer); 346 return EncryptDecryptAesGcm(ENCRYPT, algorithm, key, data, buffer);
254 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: 347 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5:
255 return EncryptRsaEsPkcs1v1_5(algorithm, key, data, buffer); 348 return EncryptRsaEsPkcs1v1_5(algorithm, key, data, buffer);
256 default: 349 default:
257 return Status::ErrorUnsupported(); 350 return Status::ErrorUnsupported();
258 } 351 }
259 } 352 }
260 353
261 Status Decrypt(const blink::WebCryptoAlgorithm& algorithm, 354 Status Decrypt(const blink::WebCryptoAlgorithm& algorithm,
262 const blink::WebCryptoKey& key, 355 const blink::WebCryptoKey& key,
263 const CryptoData& data, 356 const CryptoData& data,
264 blink::WebArrayBuffer* buffer) { 357 blink::WebArrayBuffer* buffer) {
265 if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageDecrypt))
266 return Status::ErrorUnexpected();
267 if (algorithm.id() != key.algorithm().id()) 358 if (algorithm.id() != key.algorithm().id())
268 return Status::ErrorUnexpected(); 359 return Status::ErrorUnexpected();
269 360
270 switch (algorithm.id()) { 361 switch (algorithm.id()) {
271 case blink::WebCryptoAlgorithmIdAesCbc: 362 case blink::WebCryptoAlgorithmIdAesCbc:
363 case blink::WebCryptoAlgorithmIdAesGcm:
364 if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageDecrypt))
365 return Status::ErrorUnexpected();
366 break;
367 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5:
368 if (!KeyUsageAllows(key,
369 blink::WebCryptoKeyUsageDecrypt |
370 blink::WebCryptoKeyUsageUnwrapKey))
371 return Status::ErrorUnexpected();
372 break;
373 case blink::WebCryptoAlgorithmIdAesKw:
374 if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageUnwrapKey))
375 return Status::ErrorUnexpected();
376 break;
377 default:
378 return Status::ErrorUnsupported();
379 }
380
381 switch (algorithm.id()) {
382 case blink::WebCryptoAlgorithmIdAesCbc:
272 return EncryptDecryptAesCbc(DECRYPT, algorithm, key, data, buffer); 383 return EncryptDecryptAesCbc(DECRYPT, algorithm, key, data, buffer);
273 case blink::WebCryptoAlgorithmIdAesGcm: 384 case blink::WebCryptoAlgorithmIdAesGcm:
274 return EncryptDecryptAesGcm(DECRYPT, algorithm, key, data, buffer); 385 return EncryptDecryptAesGcm(DECRYPT, algorithm, key, data, buffer);
275 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: 386 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5:
276 return DecryptRsaEsPkcs1v1_5(algorithm, key, data, buffer); 387 return DecryptRsaEsPkcs1v1_5(algorithm, key, data, buffer);
388 case blink::WebCryptoAlgorithmIdAesKw:
389 return DecryptAesKw(algorithm, key, data, buffer);
277 default: 390 default:
278 return Status::ErrorUnsupported(); 391 return Status::ErrorUnsupported();
279 } 392 }
280 } 393 }
281 394
282 Status Digest(const blink::WebCryptoAlgorithm& algorithm, 395 Status Digest(const blink::WebCryptoAlgorithm& algorithm,
283 const CryptoData& data, 396 const CryptoData& data,
284 blink::WebArrayBuffer* buffer) { 397 blink::WebArrayBuffer* buffer) {
285 switch (algorithm.id()) { 398 switch (algorithm.id()) {
286 case blink::WebCryptoAlgorithmIdSha1: 399 case blink::WebCryptoAlgorithmIdSha1:
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
423 return status; 536 return status;
424 return platform::ExportKeyRaw(sym_key, buffer); 537 return platform::ExportKeyRaw(sym_key, buffer);
425 } 538 }
426 case blink::WebCryptoKeyFormatSpki: { 539 case blink::WebCryptoKeyFormatSpki: {
427 platform::PublicKey* public_key; 540 platform::PublicKey* public_key;
428 Status status = ToPlatformPublicKey(key, &public_key); 541 Status status = ToPlatformPublicKey(key, &public_key);
429 if (status.IsError()) 542 if (status.IsError())
430 return status; 543 return status;
431 return platform::ExportKeySpki(public_key, buffer); 544 return platform::ExportKeySpki(public_key, buffer);
432 } 545 }
546 case blink::WebCryptoKeyFormatJwk:
547 return ExportKeyJwk(key, buffer);
433 case blink::WebCryptoKeyFormatPkcs8: 548 case blink::WebCryptoKeyFormatPkcs8:
434 case blink::WebCryptoKeyFormatJwk:
435 // TODO(eroman): 549 // TODO(eroman):
436 return Status::ErrorUnsupported(); 550 return Status::ErrorUnsupported();
437 default: 551 default:
438 return Status::ErrorUnsupported(); 552 return Status::ErrorUnsupported();
439 } 553 }
440 } 554 }
441 555
442 Status Sign(const blink::WebCryptoAlgorithm& algorithm, 556 Status Sign(const blink::WebCryptoAlgorithm& algorithm,
443 const blink::WebCryptoKey& key, 557 const blink::WebCryptoKey& key,
444 const CryptoData& data, 558 const CryptoData& data,
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
538 const blink::WebCryptoAlgorithm& wrapping_algorithm, 652 const blink::WebCryptoAlgorithm& wrapping_algorithm,
539 const blink::WebCryptoAlgorithm& algorithm_or_null, 653 const blink::WebCryptoAlgorithm& algorithm_or_null,
540 bool extractable, 654 bool extractable,
541 blink::WebCryptoKeyUsageMask usage_mask, 655 blink::WebCryptoKeyUsageMask usage_mask,
542 blink::WebCryptoKey* key) { 656 blink::WebCryptoKey* key) {
543 if (!KeyUsageAllows(wrapping_key, blink::WebCryptoKeyUsageUnwrapKey)) 657 if (!KeyUsageAllows(wrapping_key, blink::WebCryptoKeyUsageUnwrapKey))
544 return Status::ErrorUnexpected(); 658 return Status::ErrorUnexpected();
545 if (wrapping_algorithm.id() != wrapping_key.algorithm().id()) 659 if (wrapping_algorithm.id() != wrapping_key.algorithm().id())
546 return Status::ErrorUnexpected(); 660 return Status::ErrorUnexpected();
547 661
548 // TODO(padolph): Handle formats other than raw 662 switch (format) {
549 if (format != blink::WebCryptoKeyFormatRaw) 663 case blink::WebCryptoKeyFormatRaw:
550 return Status::ErrorUnsupported(); 664 return UnwrapKeyRaw(wrapped_key_data,
551 665 wrapping_key,
552 // Must provide an algorithm when unwrapping a raw key 666 wrapping_algorithm,
553 if (format == blink::WebCryptoKeyFormatRaw && algorithm_or_null.isNull()) 667 algorithm_or_null,
554 return Status::ErrorMissingAlgorithmUnwrapRawKey(); 668 extractable,
555 669 usage_mask,
556 // TODO(padolph): Handle other wrapping algorithms 670 key);
557 switch (wrapping_algorithm.id()) { 671 case blink::WebCryptoKeyFormatJwk:
558 case blink::WebCryptoAlgorithmIdAesKw: { 672 return UnwrapKeyDecryptAndImport(format,
559 platform::SymKey* platform_wrapping_key; 673 wrapped_key_data,
560 Status status = ToPlatformSymKey(wrapping_key, &platform_wrapping_key); 674 wrapping_key,
561 if (status.IsError()) 675 wrapping_algorithm,
562 return status; 676 algorithm_or_null,
563 // AES-KW requires the wrapped key data size must be at least 24 bytes and 677 extractable,
564 // also a multiple of 8 bytes. 678 usage_mask,
565 if (wrapped_key_data.byte_length() < 24) 679 key);
566 return Status::ErrorDataTooSmall(); 680 case blink::WebCryptoKeyFormatSpki:
567 if (wrapped_key_data.byte_length() % 8) 681 case blink::WebCryptoKeyFormatPkcs8:
568 return Status::ErrorInvalidAesKwDataLength(); 682 return Status::ErrorUnsupported(); // TODO(padolph)
569 return platform::UnwrapSymKeyAesKw(wrapped_key_data,
570 platform_wrapping_key,
571 algorithm_or_null,
572 extractable,
573 usage_mask,
574 key);
575 }
576 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: {
577 platform::PrivateKey* platform_wrapping_key;
578 Status status =
579 ToPlatformPrivateKey(wrapping_key, &platform_wrapping_key);
580 if (status.IsError())
581 return status;
582 if (!wrapped_key_data.byte_length())
583 return Status::ErrorDataTooSmall();
584 return platform::UnwrapSymKeyRsaEs(wrapped_key_data,
585 platform_wrapping_key,
586 algorithm_or_null,
587 extractable,
588 usage_mask,
589 key);
590 }
591 default: 683 default:
684 NOTREACHED();
592 return Status::ErrorUnsupported(); 685 return Status::ErrorUnsupported();
593 } 686 }
594 } 687 }
595 688
596 } // namespace webcrypto 689 } // namespace webcrypto
597 690
598 } // namespace content 691 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698