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

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: added missing openssl stub 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"
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after
226 return Status::Error(); 226 return Status::Error();
227 // Fallthrough intentional! 227 // Fallthrough intentional!
228 case blink::WebCryptoAlgorithmIdHmac: 228 case blink::WebCryptoAlgorithmIdHmac:
229 return platform::ImportKeyRaw( 229 return platform::ImportKeyRaw(
230 algorithm_or_null, key_data, extractable, usage_mask, key); 230 algorithm_or_null, key_data, extractable, usage_mask, key);
231 default: 231 default:
232 return Status::ErrorUnsupported(); 232 return Status::ErrorUnsupported();
233 } 233 }
234 } 234 }
235 235
236 // Validates the size of data input to AES-KW. AES-KW requires the input data
237 // size to be at least 24 bytes and a multiple of 8 bytes.
238 Status CheckAesKwInputSize(const CryptoData& aeskw_input_data) {
239 if (aeskw_input_data.byte_length() < 24)
240 return Status::ErrorDataTooSmall();
241 if (aeskw_input_data.byte_length() % 8)
242 return Status::ErrorInvalidAesKwDataLength();
243 return Status::Success();
244 }
245
246 Status UnwrapKeyRaw(const CryptoData& wrapped_key_data,
247 const blink::WebCryptoKey& wrapping_key,
248 const blink::WebCryptoAlgorithm& wrapping_algorithm,
249 const blink::WebCryptoAlgorithm& algorithm_or_null,
250 bool extractable,
251 blink::WebCryptoKeyUsageMask usage_mask,
252 blink::WebCryptoKey* key) {
253 // Must provide an algorithm when unwrapping a raw key
254 if (algorithm_or_null.isNull())
255 return Status::ErrorMissingAlgorithmUnwrapRawKey();
256
257 // TODO(padolph): Handle other wrapping algorithms
258 switch (wrapping_algorithm.id()) {
259 case blink::WebCryptoAlgorithmIdAesKw: {
260 platform::SymKey* platform_wrapping_key;
261 Status status = ToPlatformSymKey(wrapping_key, &platform_wrapping_key);
262 if (status.IsError())
263 return status;
264 status = CheckAesKwInputSize(wrapped_key_data);
265 if (status.IsError())
266 return status;
267 return platform::UnwrapSymKeyAesKw(wrapped_key_data,
268 platform_wrapping_key,
269 algorithm_or_null,
270 extractable,
271 usage_mask,
272 key);
273 }
274 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: {
275 platform::PrivateKey* platform_wrapping_key;
276 Status status =
277 ToPlatformPrivateKey(wrapping_key, &platform_wrapping_key);
278 if (status.IsError())
279 return status;
280 if (!wrapped_key_data.byte_length())
281 return Status::ErrorDataTooSmall();
282 return platform::UnwrapSymKeyRsaEs(wrapped_key_data,
283 platform_wrapping_key,
284 algorithm_or_null,
285 extractable,
286 usage_mask,
287 key);
288 }
289 default:
290 return Status::ErrorUnsupported();
291 }
292 }
293
294 Status DecryptAesKw(const blink::WebCryptoAlgorithm& algorithm,
295 const blink::WebCryptoKey& key,
296 const CryptoData& data,
297 blink::WebArrayBuffer* buffer) {
298 platform::SymKey* sym_key;
299 Status status = ToPlatformSymKey(key, &sym_key);
300 if (status.IsError())
301 return status;
302 status = CheckAesKwInputSize(data);
303 if (status.IsError())
304 return status;
305 return platform::DecryptAesKw(sym_key, data, buffer);
306 }
307
308 Status DecryptDontCheckKeyUsage(const blink::WebCryptoAlgorithm& algorithm,
309 const blink::WebCryptoKey& key,
310 const CryptoData& data,
311 blink::WebArrayBuffer* buffer) {
312 if (algorithm.id() != key.algorithm().id())
313 return Status::ErrorUnexpected();
314 switch (algorithm.id()) {
315 case blink::WebCryptoAlgorithmIdAesCbc:
316 return EncryptDecryptAesCbc(DECRYPT, algorithm, key, data, buffer);
317 case blink::WebCryptoAlgorithmIdAesGcm:
318 return EncryptDecryptAesGcm(DECRYPT, algorithm, key, data, buffer);
319 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5:
320 return DecryptRsaEsPkcs1v1_5(algorithm, key, data, buffer);
321 case blink::WebCryptoAlgorithmIdAesKw:
322 return DecryptAesKw(algorithm, key, data, buffer);
323 default:
324 return Status::ErrorUnsupported();
325 }
326 }
327
328 Status UnwrapKeyDecryptAndImport(
329 blink::WebCryptoKeyFormat format,
330 const CryptoData& wrapped_key_data,
331 const blink::WebCryptoKey& wrapping_key,
332 const blink::WebCryptoAlgorithm& wrapping_algorithm,
333 const blink::WebCryptoAlgorithm& algorithm_or_null,
334 bool extractable,
335 blink::WebCryptoKeyUsageMask usage_mask,
336 blink::WebCryptoKey* key) {
337 if (!KeyUsageAllows(wrapping_key, blink::WebCryptoKeyUsageUnwrapKey))
338 return Status::ErrorUnexpected();
339 blink::WebArrayBuffer buffer;
340 Status status = DecryptDontCheckKeyUsage(
341 wrapping_algorithm, wrapping_key, wrapped_key_data, &buffer);
342 if (status.IsError())
343 return status;
344 status = ImportKey(format,
345 CryptoData(buffer),
346 algorithm_or_null,
347 extractable,
348 usage_mask,
349 key);
350 // NOTE! Returning the details of any ImportKey() failure here would leak
351 // information about the plaintext internals of the encrypted key. Instead,
352 // collapse any error into the generic Status::Error().
353 return status.IsError() ? Status::Error() : Status::Success();
354 }
355
236 } // namespace 356 } // namespace
237 357
238 void Init() { platform::Init(); } 358 void Init() { platform::Init(); }
239 359
240 Status Encrypt(const blink::WebCryptoAlgorithm& algorithm, 360 Status Encrypt(const blink::WebCryptoAlgorithm& algorithm,
241 const blink::WebCryptoKey& key, 361 const blink::WebCryptoKey& key,
242 const CryptoData& data, 362 const CryptoData& data,
243 blink::WebArrayBuffer* buffer) { 363 blink::WebArrayBuffer* buffer) {
244 if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageEncrypt)) 364 if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageEncrypt))
245 return Status::ErrorUnexpected(); 365 return Status::ErrorUnexpected();
(...skipping 11 matching lines...) Expand all
257 return Status::ErrorUnsupported(); 377 return Status::ErrorUnsupported();
258 } 378 }
259 } 379 }
260 380
261 Status Decrypt(const blink::WebCryptoAlgorithm& algorithm, 381 Status Decrypt(const blink::WebCryptoAlgorithm& algorithm,
262 const blink::WebCryptoKey& key, 382 const blink::WebCryptoKey& key,
263 const CryptoData& data, 383 const CryptoData& data,
264 blink::WebArrayBuffer* buffer) { 384 blink::WebArrayBuffer* buffer) {
265 if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageDecrypt)) 385 if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageDecrypt))
266 return Status::ErrorUnexpected(); 386 return Status::ErrorUnexpected();
267 if (algorithm.id() != key.algorithm().id()) 387 return DecryptDontCheckKeyUsage(algorithm, key, data, buffer);
268 return Status::ErrorUnexpected();
269
270 switch (algorithm.id()) {
271 case blink::WebCryptoAlgorithmIdAesCbc:
272 return EncryptDecryptAesCbc(DECRYPT, algorithm, key, data, buffer);
273 case blink::WebCryptoAlgorithmIdAesGcm:
274 return EncryptDecryptAesGcm(DECRYPT, algorithm, key, data, buffer);
275 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5:
276 return DecryptRsaEsPkcs1v1_5(algorithm, key, data, buffer);
277 default:
278 return Status::ErrorUnsupported();
279 }
280 } 388 }
281 389
282 Status Digest(const blink::WebCryptoAlgorithm& algorithm, 390 Status Digest(const blink::WebCryptoAlgorithm& algorithm,
283 const CryptoData& data, 391 const CryptoData& data,
284 blink::WebArrayBuffer* buffer) { 392 blink::WebArrayBuffer* buffer) {
285 switch (algorithm.id()) { 393 switch (algorithm.id()) {
286 case blink::WebCryptoAlgorithmIdSha1: 394 case blink::WebCryptoAlgorithmIdSha1:
287 case blink::WebCryptoAlgorithmIdSha256: 395 case blink::WebCryptoAlgorithmIdSha256:
288 case blink::WebCryptoAlgorithmIdSha384: 396 case blink::WebCryptoAlgorithmIdSha384:
289 case blink::WebCryptoAlgorithmIdSha512: 397 case blink::WebCryptoAlgorithmIdSha512:
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
417 return status; 525 return status;
418 return platform::ExportKeyRaw(sym_key, buffer); 526 return platform::ExportKeyRaw(sym_key, buffer);
419 } 527 }
420 case blink::WebCryptoKeyFormatSpki: { 528 case blink::WebCryptoKeyFormatSpki: {
421 platform::PublicKey* public_key; 529 platform::PublicKey* public_key;
422 Status status = ToPlatformPublicKey(key, &public_key); 530 Status status = ToPlatformPublicKey(key, &public_key);
423 if (status.IsError()) 531 if (status.IsError())
424 return status; 532 return status;
425 return platform::ExportKeySpki(public_key, buffer); 533 return platform::ExportKeySpki(public_key, buffer);
426 } 534 }
535 case blink::WebCryptoKeyFormatJwk:
536 return ExportKeyJwk(key, buffer);
427 case blink::WebCryptoKeyFormatPkcs8: 537 case blink::WebCryptoKeyFormatPkcs8:
428 case blink::WebCryptoKeyFormatJwk:
429 // TODO(eroman): 538 // TODO(eroman):
430 return Status::ErrorUnsupported(); 539 return Status::ErrorUnsupported();
431 default: 540 default:
432 return Status::ErrorUnsupported(); 541 return Status::ErrorUnsupported();
433 } 542 }
434 } 543 }
435 544
436 Status Sign(const blink::WebCryptoAlgorithm& algorithm, 545 Status Sign(const blink::WebCryptoAlgorithm& algorithm,
437 const blink::WebCryptoKey& key, 546 const blink::WebCryptoKey& key,
438 const CryptoData& data, 547 const CryptoData& data,
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
532 const blink::WebCryptoAlgorithm& wrapping_algorithm, 641 const blink::WebCryptoAlgorithm& wrapping_algorithm,
533 const blink::WebCryptoAlgorithm& algorithm_or_null, 642 const blink::WebCryptoAlgorithm& algorithm_or_null,
534 bool extractable, 643 bool extractable,
535 blink::WebCryptoKeyUsageMask usage_mask, 644 blink::WebCryptoKeyUsageMask usage_mask,
536 blink::WebCryptoKey* key) { 645 blink::WebCryptoKey* key) {
537 if (!KeyUsageAllows(wrapping_key, blink::WebCryptoKeyUsageUnwrapKey)) 646 if (!KeyUsageAllows(wrapping_key, blink::WebCryptoKeyUsageUnwrapKey))
538 return Status::ErrorUnexpected(); 647 return Status::ErrorUnexpected();
539 if (wrapping_algorithm.id() != wrapping_key.algorithm().id()) 648 if (wrapping_algorithm.id() != wrapping_key.algorithm().id())
540 return Status::ErrorUnexpected(); 649 return Status::ErrorUnexpected();
541 650
542 // TODO(padolph): Handle formats other than raw 651 switch (format) {
543 if (format != blink::WebCryptoKeyFormatRaw) 652 case blink::WebCryptoKeyFormatRaw:
544 return Status::ErrorUnsupported(); 653 return UnwrapKeyRaw(wrapped_key_data,
545 654 wrapping_key,
546 // Must provide an algorithm when unwrapping a raw key 655 wrapping_algorithm,
547 if (format == blink::WebCryptoKeyFormatRaw && algorithm_or_null.isNull()) 656 algorithm_or_null,
548 return Status::ErrorMissingAlgorithmUnwrapRawKey(); 657 extractable,
549 658 usage_mask,
550 // TODO(padolph): Handle other wrapping algorithms 659 key);
551 switch (wrapping_algorithm.id()) { 660 case blink::WebCryptoKeyFormatJwk:
552 case blink::WebCryptoAlgorithmIdAesKw: { 661 return UnwrapKeyDecryptAndImport(format,
553 platform::SymKey* platform_wrapping_key; 662 wrapped_key_data,
554 Status status = ToPlatformSymKey(wrapping_key, &platform_wrapping_key); 663 wrapping_key,
555 if (status.IsError()) 664 wrapping_algorithm,
556 return status; 665 algorithm_or_null,
557 // AES-KW requires the wrapped key data size must be at least 24 bytes and 666 extractable,
558 // also a multiple of 8 bytes. 667 usage_mask,
559 if (wrapped_key_data.byte_length() < 24) 668 key);
560 return Status::ErrorDataTooSmall(); 669 case blink::WebCryptoKeyFormatSpki:
561 if (wrapped_key_data.byte_length() % 8) 670 case blink::WebCryptoKeyFormatPkcs8:
562 return Status::ErrorInvalidAesKwDataLength(); 671 return Status::ErrorUnsupported(); // TODO(padolph)
563 return platform::UnwrapSymKeyAesKw(wrapped_key_data,
564 platform_wrapping_key,
565 algorithm_or_null,
566 extractable,
567 usage_mask,
568 key);
569 }
570 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: {
571 platform::PrivateKey* platform_wrapping_key;
572 Status status =
573 ToPlatformPrivateKey(wrapping_key, &platform_wrapping_key);
574 if (status.IsError())
575 return status;
576 if (!wrapped_key_data.byte_length())
577 return Status::ErrorDataTooSmall();
578 return platform::UnwrapSymKeyRsaEs(wrapped_key_data,
579 platform_wrapping_key,
580 algorithm_or_null,
581 extractable,
582 usage_mask,
583 key);
584 }
585 default: 672 default:
673 NOTREACHED();
586 return Status::ErrorUnsupported(); 674 return Status::ErrorUnsupported();
587 } 675 }
588 } 676 }
589 677
590 } // namespace webcrypto 678 } // namespace webcrypto
591 679
592 } // namespace content 680 } // namespace content
OLDNEW
« no previous file with comments | « content/child/webcrypto/platform_crypto_openssl.cc ('k') | content/child/webcrypto/shared_crypto_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698