OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 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" | 5 #include "content/renderer/webcrypto/webcrypto_impl.h" |
6 | 6 |
7 #include <cryptohi.h> | 7 #include <cryptohi.h> |
8 #include <pk11pub.h> | 8 #include <pk11pub.h> |
9 #include <sechash.h> | 9 #include <sechash.h> |
10 | 10 |
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
317 NULL)); | 317 NULL)); |
318 if (!pk11_sym_key.get()) { | 318 if (!pk11_sym_key.get()) { |
319 return false; | 319 return false; |
320 } | 320 } |
321 | 321 |
322 *key = blink::WebCryptoKey::create(new SymKeyHandle(pk11_sym_key.Pass()), | 322 *key = blink::WebCryptoKey::create(new SymKeyHandle(pk11_sym_key.Pass()), |
323 type, extractable, algorithm, usage_mask); | 323 type, extractable, algorithm, usage_mask); |
324 return true; | 324 return true; |
325 } | 325 } |
326 | 326 |
327 typedef scoped_ptr_malloc< | 327 typedef scoped_ptr<CERTSubjectPublicKeyInfo, |
328 CERTSubjectPublicKeyInfo, | 328 crypto::NSSDestroyer<CERTSubjectPublicKeyInfo, |
329 crypto::NSSDestroyer<CERTSubjectPublicKeyInfo, | 329 SECKEY_DestroySubjectPublicKeyInfo> > |
330 SECKEY_DestroySubjectPublicKeyInfo> > | |
331 ScopedCERTSubjectPublicKeyInfo; | 330 ScopedCERTSubjectPublicKeyInfo; |
332 | 331 |
332 // Validates an NSS KeyType against a WebCrypto algorithm. Some NSS KeyTypes | |
333 // contain enough information to fabricate a Web Crypto algorithm, which is | |
334 // returned if the input algorithm isNull(). This function indicates failure by | |
335 // returning a Null algorithm. | |
336 blink::WebCryptoAlgorithm ResolveNssKeyTypeWithInputAlgorithm( | |
337 KeyType key_type, | |
338 const blink::WebCryptoAlgorithm& algorithm_or_null) { | |
339 switch (key_type) { | |
340 case rsaKey: | |
341 // NSS's rsaKey KeyType maps to keys with SEC_OID_PKCS1_RSA_ENCRYPTION and | |
342 // according to RFC 4055 this can be used for both encryption and | |
Ryan Sleevi
2013/11/25 06:59:44
Note the existence of http://tools.ietf.org/html/r
padolph
2013/11/25 23:02:58
Done.
| |
343 // signatures. However, this is not specific enough to build a compatible | |
344 // Web Crypto algorithm, since in Web Crypto RSA encryption and signature | |
Ryan Sleevi
2013/11/25 06:59:44
"since in Web Crypto" -> "since in Web Crypto,"
padolph
2013/11/25 23:02:58
Done.
| |
345 // algorithms are distinct. So if the input algorithm isNull() here, we | |
346 // have to fail. | |
347 if (!algorithm_or_null.isNull() && IsAlgorithmRsa(algorithm_or_null)) | |
348 return algorithm_or_null; | |
349 break; | |
350 case dsaKey: | |
351 case ecKey: | |
352 case rsaPssKey: | |
353 case rsaOaepKey: | |
354 // TODO(padolph): Handle other key types. | |
355 break; | |
356 default: | |
357 break; | |
358 } | |
359 return blink::WebCryptoAlgorithm::createNull(); | |
360 } | |
361 | |
333 bool ImportKeyInternalSpki( | 362 bool ImportKeyInternalSpki( |
334 const unsigned char* key_data, | 363 const unsigned char* key_data, |
335 unsigned key_data_size, | 364 unsigned key_data_size, |
336 const blink::WebCryptoAlgorithm& algorithm_or_null, | 365 const blink::WebCryptoAlgorithm& algorithm_or_null, |
337 bool extractable, | 366 bool extractable, |
338 blink::WebCryptoKeyUsageMask usage_mask, | 367 blink::WebCryptoKeyUsageMask usage_mask, |
339 blink::WebCryptoKey* key) { | 368 blink::WebCryptoKey* key) { |
340 | 369 |
341 DCHECK(key); | 370 DCHECK(key); |
342 | 371 |
343 if (!key_data_size) | 372 if (!key_data_size) |
344 return false; | 373 return false; |
345 | |
346 DCHECK(key_data); | 374 DCHECK(key_data); |
347 | 375 |
348 // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 Subject | 376 // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 Subject |
349 // Public Key Info. Decode this to a CERTSubjectPublicKeyInfo. | 377 // Public Key Info. Decode this to a CERTSubjectPublicKeyInfo. |
350 SECItem spki_item = { | 378 SECItem spki_item = {siBuffer, const_cast<uint8*>(key_data), key_data_size}; |
351 siBuffer, | |
352 const_cast<uint8*>(key_data), | |
353 key_data_size | |
354 }; | |
355 const ScopedCERTSubjectPublicKeyInfo spki( | 379 const ScopedCERTSubjectPublicKeyInfo spki( |
356 SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_item)); | 380 SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_item)); |
357 if (!spki) | 381 if (!spki) |
358 return false; | 382 return false; |
359 | 383 |
360 crypto::ScopedSECKEYPublicKey sec_public_key( | 384 crypto::ScopedSECKEYPublicKey sec_public_key( |
361 SECKEY_ExtractPublicKey(spki.get())); | 385 SECKEY_ExtractPublicKey(spki.get())); |
362 if (!sec_public_key) | 386 if (!sec_public_key) |
363 return false; | 387 return false; |
364 | 388 |
365 const KeyType sec_key_type = SECKEY_GetPublicKeyType(sec_public_key.get()); | 389 const KeyType sec_key_type = SECKEY_GetPublicKeyType(sec_public_key.get()); |
366 | |
367 // Validate the sec_key_type against the input algorithm. Some NSS KeyType's | |
368 // contain enough information to fabricate a Web Crypto Algorithm, which will | |
369 // be used if the input algorithm isNull(). Others like 'rsaKey' do not (see | |
370 // below). | |
371 blink::WebCryptoAlgorithm algorithm = | 390 blink::WebCryptoAlgorithm algorithm = |
372 blink::WebCryptoAlgorithm::createNull(); | 391 ResolveNssKeyTypeWithInputAlgorithm(sec_key_type, algorithm_or_null); |
373 switch (sec_key_type) { | 392 if (algorithm.isNull()) |
374 case rsaKey: | 393 return false; |
375 // NSS's rsaKey KeyType maps to keys with SEC_OID_PKCS1_RSA_ENCRYPTION and | |
376 // according to RFC 4055 this can be used for both encryption and | |
377 // signatures. However, this is not specific enough to build a compatible | |
378 // Web Crypto algorithm, since in Web Crypto RSA encryption and signature | |
379 // algorithms are distinct. So if the input algorithm isNull() here, we | |
380 // have to fail. | |
381 if (algorithm_or_null.isNull() || !IsAlgorithmRsa(algorithm_or_null)) | |
382 return false; | |
383 algorithm = algorithm_or_null; | |
384 break; | |
385 case dsaKey: | |
386 case ecKey: | |
387 case rsaPssKey: | |
388 case rsaOaepKey: | |
389 // TODO(padolph): Handle other key types. | |
390 return false; | |
391 default: | |
392 return false; | |
393 } | |
394 | 394 |
395 *key = blink::WebCryptoKey::create( | 395 *key = blink::WebCryptoKey::create( |
396 new PublicKeyHandle(sec_public_key.Pass()), | 396 new PublicKeyHandle(sec_public_key.Pass()), |
397 blink::WebCryptoKeyTypePublic, | 397 blink::WebCryptoKeyTypePublic, |
398 extractable, | 398 extractable, |
399 algorithm, | 399 algorithm, |
400 usage_mask); | 400 usage_mask); |
401 | 401 |
402 return true; | 402 return true; |
403 } | 403 } |
(...skipping 18 matching lines...) Expand all Loading... | |
422 | 422 |
423 DCHECK(spki_der->data); | 423 DCHECK(spki_der->data); |
424 DCHECK(spki_der->len); | 424 DCHECK(spki_der->len); |
425 | 425 |
426 *buffer = blink::WebArrayBuffer::create(spki_der->len, 1); | 426 *buffer = blink::WebArrayBuffer::create(spki_der->len, 1); |
427 memcpy(buffer->data(), spki_der->data, spki_der->len); | 427 memcpy(buffer->data(), spki_der->data, spki_der->len); |
428 | 428 |
429 return true; | 429 return true; |
430 } | 430 } |
431 | 431 |
432 bool ImportKeyInternalPkcs8( | |
433 const unsigned char* key_data, | |
434 unsigned key_data_size, | |
435 const blink::WebCryptoAlgorithm& algorithm_or_null, | |
436 bool extractable, | |
437 blink::WebCryptoKeyUsageMask usage_mask, | |
438 blink::WebCryptoKey* key) { | |
439 | |
440 DCHECK(key); | |
441 | |
442 if (!key_data_size) | |
443 return false; | |
444 DCHECK(key_data); | |
445 | |
446 // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 PKCS#8 | |
447 // private key info object. | |
448 SECItem pki_der = {siBuffer, const_cast<uint8*>(key_data), key_data_size}; | |
449 | |
450 crypto::ScopedPK11Slot slot(PK11_GetInternalKeySlot()); | |
Ryan Sleevi
2013/11/25 06:59:44
This should be PK11_GetInternalSlot, not PK11_GetI
padolph
2013/11/25 23:02:58
Done.
| |
451 if (!slot) | |
452 return false; | |
453 | |
454 SECKEYPrivateKey* seckey_private_key = NULL; | |
455 // TODO(padolph): Verify correct values of isPerm, isPrivate, and usage below. | |
Ryan Sleevi
2013/11/25 06:59:44
isPerm/isPrivate is correct. Usage is (probably) w
padolph
2013/11/25 23:02:58
Thanks.
For usage, there are two cases to conside
eroman
2013/11/26 03:40:28
Setting usage to 0 seems like the right approach t
padolph
2013/11/27 03:35:34
Thanks for the guidance. I'll use KU_ALL because i
| |
456 if (PK11_ImportDERPrivateKeyInfoAndReturnKey( | |
457 slot.get(), | |
Ryan Sleevi
2013/11/25 06:59:44
These should all be indented an additional 4 space
padolph
2013/11/25 23:02:58
Done.
| |
458 &pki_der, | |
459 NULL, | |
460 NULL, | |
461 false, // isPerm | |
462 false, // isPrivate | |
463 0, // usage | |
464 &seckey_private_key, | |
465 NULL) != SECSuccess) { | |
466 return false; | |
467 } | |
468 DCHECK(seckey_private_key); | |
469 crypto::ScopedSECKEYPrivateKey private_key(seckey_private_key); | |
470 | |
471 const KeyType sec_key_type = SECKEY_GetPrivateKeyType(private_key.get()); | |
472 blink::WebCryptoAlgorithm algorithm = | |
473 ResolveNssKeyTypeWithInputAlgorithm(sec_key_type, algorithm_or_null); | |
474 if (algorithm.isNull()) | |
475 return false; | |
476 | |
477 *key = blink::WebCryptoKey::create( | |
478 new PrivateKeyHandle(private_key.Pass()), | |
479 blink::WebCryptoKeyTypePrivate, | |
480 extractable, | |
481 algorithm, | |
482 usage_mask); | |
483 | |
484 return true; | |
485 } | |
486 | |
432 } // namespace | 487 } // namespace |
433 | 488 |
434 void WebCryptoImpl::Init() { | 489 void WebCryptoImpl::Init() { |
435 crypto::EnsureNSSInit(); | 490 crypto::EnsureNSSInit(); |
436 } | 491 } |
437 | 492 |
438 bool WebCryptoImpl::EncryptInternal( | 493 bool WebCryptoImpl::EncryptInternal( |
439 const blink::WebCryptoAlgorithm& algorithm, | 494 const blink::WebCryptoAlgorithm& algorithm, |
440 const blink::WebCryptoKey& key, | 495 const blink::WebCryptoKey& key, |
441 const unsigned char* data, | 496 const unsigned char* data, |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
673 usage_mask, | 728 usage_mask, |
674 key); | 729 key); |
675 case blink::WebCryptoKeyFormatSpki: | 730 case blink::WebCryptoKeyFormatSpki: |
676 return ImportKeyInternalSpki(key_data, | 731 return ImportKeyInternalSpki(key_data, |
677 key_data_size, | 732 key_data_size, |
678 algorithm_or_null, | 733 algorithm_or_null, |
679 extractable, | 734 extractable, |
680 usage_mask, | 735 usage_mask, |
681 key); | 736 key); |
682 case blink::WebCryptoKeyFormatPkcs8: | 737 case blink::WebCryptoKeyFormatPkcs8: |
683 // TODO(padolph): Handle PKCS#8 private key import | 738 return ImportKeyInternalPkcs8(key_data, |
684 return false; | 739 key_data_size, |
740 algorithm_or_null, | |
741 extractable, | |
742 usage_mask, | |
743 key); | |
685 default: | 744 default: |
745 // NOTE: blink::WebCryptoKeyFormatJwk is handled one level above. | |
686 return false; | 746 return false; |
687 } | 747 } |
688 } | 748 } |
689 | 749 |
690 bool WebCryptoImpl::ExportKeyInternal( | 750 bool WebCryptoImpl::ExportKeyInternal( |
691 blink::WebCryptoKeyFormat format, | 751 blink::WebCryptoKeyFormat format, |
692 const blink::WebCryptoKey& key, | 752 const blink::WebCryptoKey& key, |
693 blink::WebArrayBuffer* buffer) { | 753 blink::WebArrayBuffer* buffer) { |
694 switch (format) { | 754 switch (format) { |
695 case blink::WebCryptoKeyFormatRaw: | 755 case blink::WebCryptoKeyFormatRaw: |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
796 break; | 856 break; |
797 } | 857 } |
798 default: | 858 default: |
799 return false; | 859 return false; |
800 } | 860 } |
801 | 861 |
802 return true; | 862 return true; |
803 } | 863 } |
804 | 864 |
805 } // namespace content | 865 } // namespace content |
OLD | NEW |