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

Side by Side Diff: content/renderer/webcrypto/webcrypto_impl_nss.cc

Issue 83483012: [webcrypto] Add RSA private key PKCS#8 import for NSS. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fixes for rsleevi and eroman Created 7 years 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
« no previous file with comments | « no previous file | content/renderer/webcrypto/webcrypto_impl_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | content/renderer/webcrypto/webcrypto_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698