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 RFCs 4055/5756 this can be used for both encryption and |
| 343 // signatures. However, this is not specific enough to build a compatible |
| 344 // Web Crypto algorithm, since in Web Crypto, RSA encryption and signature |
| 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 SECKEYPrivateKey* seckey_private_key = NULL; |
| 451 if (PK11_ImportDERPrivateKeyInfoAndReturnKey( |
| 452 PK11_GetInternalSlot(), |
| 453 &pki_der, |
| 454 NULL, // nickname |
| 455 NULL, // publicValue |
| 456 false, // isPerm |
| 457 false, // isPrivate |
| 458 KU_ALL, // usage |
| 459 &seckey_private_key, |
| 460 NULL) != SECSuccess) { |
| 461 return false; |
| 462 } |
| 463 DCHECK(seckey_private_key); |
| 464 crypto::ScopedSECKEYPrivateKey private_key(seckey_private_key); |
| 465 |
| 466 const KeyType sec_key_type = SECKEY_GetPrivateKeyType(private_key.get()); |
| 467 blink::WebCryptoAlgorithm algorithm = |
| 468 ResolveNssKeyTypeWithInputAlgorithm(sec_key_type, algorithm_or_null); |
| 469 if (algorithm.isNull()) |
| 470 return false; |
| 471 |
| 472 *key = blink::WebCryptoKey::create( |
| 473 new PrivateKeyHandle(private_key.Pass()), |
| 474 blink::WebCryptoKeyTypePrivate, |
| 475 extractable, |
| 476 algorithm, |
| 477 usage_mask); |
| 478 |
| 479 return true; |
| 480 } |
| 481 |
432 } // namespace | 482 } // namespace |
433 | 483 |
434 void WebCryptoImpl::Init() { | 484 void WebCryptoImpl::Init() { |
435 crypto::EnsureNSSInit(); | 485 crypto::EnsureNSSInit(); |
436 } | 486 } |
437 | 487 |
438 bool WebCryptoImpl::EncryptInternal( | 488 bool WebCryptoImpl::EncryptInternal( |
439 const blink::WebCryptoAlgorithm& algorithm, | 489 const blink::WebCryptoAlgorithm& algorithm, |
440 const blink::WebCryptoKey& key, | 490 const blink::WebCryptoKey& key, |
441 const unsigned char* data, | 491 const unsigned char* data, |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
673 usage_mask, | 723 usage_mask, |
674 key); | 724 key); |
675 case blink::WebCryptoKeyFormatSpki: | 725 case blink::WebCryptoKeyFormatSpki: |
676 return ImportKeyInternalSpki(key_data, | 726 return ImportKeyInternalSpki(key_data, |
677 key_data_size, | 727 key_data_size, |
678 algorithm_or_null, | 728 algorithm_or_null, |
679 extractable, | 729 extractable, |
680 usage_mask, | 730 usage_mask, |
681 key); | 731 key); |
682 case blink::WebCryptoKeyFormatPkcs8: | 732 case blink::WebCryptoKeyFormatPkcs8: |
683 // TODO(padolph): Handle PKCS#8 private key import | 733 return ImportKeyInternalPkcs8(key_data, |
684 return false; | 734 key_data_size, |
| 735 algorithm_or_null, |
| 736 extractable, |
| 737 usage_mask, |
| 738 key); |
685 default: | 739 default: |
| 740 // NOTE: blink::WebCryptoKeyFormatJwk is handled one level above. |
686 return false; | 741 return false; |
687 } | 742 } |
688 } | 743 } |
689 | 744 |
690 bool WebCryptoImpl::ExportKeyInternal( | 745 bool WebCryptoImpl::ExportKeyInternal( |
691 blink::WebCryptoKeyFormat format, | 746 blink::WebCryptoKeyFormat format, |
692 const blink::WebCryptoKey& key, | 747 const blink::WebCryptoKey& key, |
693 blink::WebArrayBuffer* buffer) { | 748 blink::WebArrayBuffer* buffer) { |
694 switch (format) { | 749 switch (format) { |
695 case blink::WebCryptoKeyFormatRaw: | 750 case blink::WebCryptoKeyFormatRaw: |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
796 break; | 851 break; |
797 } | 852 } |
798 default: | 853 default: |
799 return false; | 854 return false; |
800 } | 855 } |
801 | 856 |
802 return true; | 857 return true; |
803 } | 858 } |
804 | 859 |
805 } // namespace content | 860 } // namespace content |
OLD | NEW |