| 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 |