| OLD | NEW |
| 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/renderer/webcrypto/platform_crypto.h" | 5 #include "content/renderer/webcrypto/platform_crypto.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 |
| 11 #include <vector> | 11 #include <vector> |
| 12 | 12 |
| 13 #include "base/lazy_instance.h" | 13 #include "base/lazy_instance.h" |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "content/renderer/webcrypto/crypto_data.h" | 15 #include "content/renderer/webcrypto/crypto_data.h" |
| 16 #include "content/renderer/webcrypto/webcrypto_util.h" | 16 #include "content/renderer/webcrypto/webcrypto_util.h" |
| 17 #include "crypto/nss_util.h" | 17 #include "crypto/nss_util.h" |
| 18 #include "crypto/scoped_nss_types.h" | 18 #include "crypto/scoped_nss_types.h" |
| 19 #include "third_party/WebKit/public/platform/WebArrayBuffer.h" | 19 #include "third_party/WebKit/public/platform/WebArrayBuffer.h" |
| 20 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" | 20 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" |
| 21 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" | 21 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" |
| 22 #ifdef WEBCRYPTO_HAS_KEY_ALGORITHM | |
| 23 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" | 22 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" |
| 24 #endif | |
| 25 | 23 |
| 26 #if defined(USE_NSS) | 24 #if defined(USE_NSS) |
| 27 #include <dlfcn.h> | 25 #include <dlfcn.h> |
| 28 #endif | 26 #endif |
| 29 | 27 |
| 30 // At the time of this writing: | 28 // At the time of this writing: |
| 31 // * Windows and Mac builds ship with their own copy of NSS (3.15+) | 29 // * Windows and Mac builds ship with their own copy of NSS (3.15+) |
| 32 // * Linux builds use the system's libnss, which is 3.14 on Debian (but 3.15+ | 30 // * Linux builds use the system's libnss, which is 3.14 on Debian (but 3.15+ |
| 33 // on other distros). | 31 // on other distros). |
| 34 // | 32 // |
| (...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 363 } | 361 } |
| 364 | 362 |
| 365 CK_MECHANISM_TYPE WebCryptoAlgorithmToGenMechanism( | 363 CK_MECHANISM_TYPE WebCryptoAlgorithmToGenMechanism( |
| 366 const blink::WebCryptoAlgorithm& algorithm) { | 364 const blink::WebCryptoAlgorithm& algorithm) { |
| 367 switch (algorithm.id()) { | 365 switch (algorithm.id()) { |
| 368 case blink::WebCryptoAlgorithmIdAesCbc: | 366 case blink::WebCryptoAlgorithmIdAesCbc: |
| 369 case blink::WebCryptoAlgorithmIdAesGcm: | 367 case blink::WebCryptoAlgorithmIdAesGcm: |
| 370 case blink::WebCryptoAlgorithmIdAesKw: | 368 case blink::WebCryptoAlgorithmIdAesKw: |
| 371 return CKM_AES_KEY_GEN; | 369 return CKM_AES_KEY_GEN; |
| 372 case blink::WebCryptoAlgorithmIdHmac: | 370 case blink::WebCryptoAlgorithmIdHmac: |
| 373 #ifdef WEBCRYPTO_HAS_KEY_ALGORITHM | |
| 374 return WebCryptoHashToHMACMechanism(algorithm.hmacKeyGenParams()->hash()); | 371 return WebCryptoHashToHMACMechanism(algorithm.hmacKeyGenParams()->hash()); |
| 375 #else | |
| 376 return WebCryptoHashToHMACMechanism(algorithm.hmacKeyParams()->hash()); | |
| 377 #endif | |
| 378 default: | 372 default: |
| 379 return CKM_INVALID_MECHANISM; | 373 return CKM_INVALID_MECHANISM; |
| 380 } | 374 } |
| 381 } | 375 } |
| 382 | 376 |
| 383 // Converts a (big-endian) WebCrypto BigInteger, with or without leading zeros, | 377 // Converts a (big-endian) WebCrypto BigInteger, with or without leading zeros, |
| 384 // to unsigned long. | 378 // to unsigned long. |
| 385 bool BigIntegerToLong(const uint8* data, | 379 bool BigIntegerToLong(const uint8* data, |
| 386 unsigned int data_size, | 380 unsigned int data_size, |
| 387 unsigned long* result) { | 381 unsigned long* result) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 401 } | 395 } |
| 402 return true; | 396 return true; |
| 403 } | 397 } |
| 404 | 398 |
| 405 bool IsAlgorithmRsa(const blink::WebCryptoAlgorithm& algorithm) { | 399 bool IsAlgorithmRsa(const blink::WebCryptoAlgorithm& algorithm) { |
| 406 return algorithm.id() == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 || | 400 return algorithm.id() == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 || |
| 407 algorithm.id() == blink::WebCryptoAlgorithmIdRsaOaep || | 401 algorithm.id() == blink::WebCryptoAlgorithmIdRsaOaep || |
| 408 algorithm.id() == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5; | 402 algorithm.id() == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5; |
| 409 } | 403 } |
| 410 | 404 |
| 411 #ifdef WEBCRYPTO_HAS_KEY_ALGORITHM | |
| 412 bool CreatePublicKeyAlgorithm(const blink::WebCryptoAlgorithm& algorithm, | 405 bool CreatePublicKeyAlgorithm(const blink::WebCryptoAlgorithm& algorithm, |
| 413 SECKEYPublicKey* key, | 406 SECKEYPublicKey* key, |
| 414 blink::WebCryptoKeyAlgorithm* key_algorithm) { | 407 blink::WebCryptoKeyAlgorithm* key_algorithm) { |
| 415 // TODO(eroman): What about other key types rsaPss, rsaOaep. | 408 // TODO(eroman): What about other key types rsaPss, rsaOaep. |
| 416 if (!key || key->keyType != rsaKey) | 409 if (!key || key->keyType != rsaKey) |
| 417 return false; | 410 return false; |
| 418 | 411 |
| 419 unsigned int modulus_length_bits = SECKEY_PublicKeyStrength(key) * 8; | 412 unsigned int modulus_length_bits = SECKEY_PublicKeyStrength(key) * 8; |
| 420 CryptoData public_exponent(key->u.rsa.publicExponent.data, | 413 CryptoData public_exponent(key->u.rsa.publicExponent.data, |
| 421 key->u.rsa.publicExponent.len); | 414 key->u.rsa.publicExponent.len); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 444 return false; | 437 return false; |
| 445 } | 438 } |
| 446 } | 439 } |
| 447 | 440 |
| 448 bool CreatePrivateKeyAlgorithm(const blink::WebCryptoAlgorithm& algorithm, | 441 bool CreatePrivateKeyAlgorithm(const blink::WebCryptoAlgorithm& algorithm, |
| 449 SECKEYPrivateKey* key, | 442 SECKEYPrivateKey* key, |
| 450 blink::WebCryptoKeyAlgorithm* key_algorithm) { | 443 blink::WebCryptoKeyAlgorithm* key_algorithm) { |
| 451 return CreatePublicKeyAlgorithm( | 444 return CreatePublicKeyAlgorithm( |
| 452 algorithm, SECKEY_ConvertToPublicKey(key), key_algorithm); | 445 algorithm, SECKEY_ConvertToPublicKey(key), key_algorithm); |
| 453 } | 446 } |
| 454 #endif | |
| 455 | 447 |
| 456 } // namespace | 448 } // namespace |
| 457 | 449 |
| 458 Status ImportKeyRaw(const blink::WebCryptoAlgorithm& algorithm, | 450 Status ImportKeyRaw(const blink::WebCryptoAlgorithm& algorithm, |
| 459 const CryptoData& key_data, | 451 const CryptoData& key_data, |
| 460 bool extractable, | 452 bool extractable, |
| 461 blink::WebCryptoKeyUsageMask usage_mask, | 453 blink::WebCryptoKeyUsageMask usage_mask, |
| 462 blink::WebCryptoKey* key) { | 454 blink::WebCryptoKey* key) { |
| 463 | 455 |
| 464 DCHECK(!algorithm.isNull()); | 456 DCHECK(!algorithm.isNull()); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 513 mechanism, | 505 mechanism, |
| 514 PK11_OriginUnwrap, | 506 PK11_OriginUnwrap, |
| 515 CKA_FLAGS_ONLY, | 507 CKA_FLAGS_ONLY, |
| 516 &key_item, | 508 &key_item, |
| 517 flags, | 509 flags, |
| 518 false, | 510 false, |
| 519 NULL)); | 511 NULL)); |
| 520 if (!pk11_sym_key.get()) | 512 if (!pk11_sym_key.get()) |
| 521 return Status::Error(); | 513 return Status::Error(); |
| 522 | 514 |
| 523 #ifdef WEBCRYPTO_HAS_KEY_ALGORITHM | |
| 524 blink::WebCryptoKeyAlgorithm key_algorithm; | 515 blink::WebCryptoKeyAlgorithm key_algorithm; |
| 525 if (!CreateSecretKeyAlgorithm( | 516 if (!CreateSecretKeyAlgorithm( |
| 526 algorithm, key_data.byte_length(), &key_algorithm)) | 517 algorithm, key_data.byte_length(), &key_algorithm)) |
| 527 return Status::ErrorUnexpected(); | 518 return Status::ErrorUnexpected(); |
| 528 #else | |
| 529 const blink::WebCryptoAlgorithm& key_algorithm = algorithm; | |
| 530 #endif | |
| 531 | 519 |
| 532 *key = blink::WebCryptoKey::create(new SymKey(pk11_sym_key.Pass()), | 520 *key = blink::WebCryptoKey::create(new SymKey(pk11_sym_key.Pass()), |
| 533 blink::WebCryptoKeyTypeSecret, | 521 blink::WebCryptoKeyTypeSecret, |
| 534 extractable, | 522 extractable, |
| 535 key_algorithm, | 523 key_algorithm, |
| 536 usage_mask); | 524 usage_mask); |
| 537 return Status::Success(); | 525 return Status::Success(); |
| 538 } | 526 } |
| 539 | 527 |
| 540 Status ExportKeyRaw(SymKey* key, blink::WebArrayBuffer* buffer) { | 528 Status ExportKeyRaw(SymKey* key, blink::WebArrayBuffer* buffer) { |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 613 SECKEY_ExtractPublicKey(spki.get())); | 601 SECKEY_ExtractPublicKey(spki.get())); |
| 614 if (!sec_public_key) | 602 if (!sec_public_key) |
| 615 return Status::Error(); | 603 return Status::Error(); |
| 616 | 604 |
| 617 const KeyType sec_key_type = SECKEY_GetPublicKeyType(sec_public_key.get()); | 605 const KeyType sec_key_type = SECKEY_GetPublicKeyType(sec_public_key.get()); |
| 618 blink::WebCryptoAlgorithm algorithm = | 606 blink::WebCryptoAlgorithm algorithm = |
| 619 ResolveNssKeyTypeWithInputAlgorithm(sec_key_type, algorithm_or_null); | 607 ResolveNssKeyTypeWithInputAlgorithm(sec_key_type, algorithm_or_null); |
| 620 if (algorithm.isNull()) | 608 if (algorithm.isNull()) |
| 621 return Status::Error(); | 609 return Status::Error(); |
| 622 | 610 |
| 623 #ifdef WEBCRYPTO_HAS_KEY_ALGORITHM | |
| 624 blink::WebCryptoKeyAlgorithm key_algorithm; | 611 blink::WebCryptoKeyAlgorithm key_algorithm; |
| 625 if (!CreatePublicKeyAlgorithm( | 612 if (!CreatePublicKeyAlgorithm( |
| 626 algorithm, sec_public_key.get(), &key_algorithm)) | 613 algorithm, sec_public_key.get(), &key_algorithm)) |
| 627 return Status::ErrorUnexpected(); | 614 return Status::ErrorUnexpected(); |
| 628 #else | |
| 629 const blink::WebCryptoAlgorithm& key_algorithm = algorithm; | |
| 630 #endif | |
| 631 | 615 |
| 632 *key = blink::WebCryptoKey::create(new PublicKey(sec_public_key.Pass()), | 616 *key = blink::WebCryptoKey::create(new PublicKey(sec_public_key.Pass()), |
| 633 blink::WebCryptoKeyTypePublic, | 617 blink::WebCryptoKeyTypePublic, |
| 634 extractable, | 618 extractable, |
| 635 key_algorithm, | 619 key_algorithm, |
| 636 usage_mask); | 620 usage_mask); |
| 637 | 621 |
| 638 return Status::Success(); | 622 return Status::Success(); |
| 639 } | 623 } |
| 640 | 624 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 683 } | 667 } |
| 684 DCHECK(seckey_private_key); | 668 DCHECK(seckey_private_key); |
| 685 crypto::ScopedSECKEYPrivateKey private_key(seckey_private_key); | 669 crypto::ScopedSECKEYPrivateKey private_key(seckey_private_key); |
| 686 | 670 |
| 687 const KeyType sec_key_type = SECKEY_GetPrivateKeyType(private_key.get()); | 671 const KeyType sec_key_type = SECKEY_GetPrivateKeyType(private_key.get()); |
| 688 blink::WebCryptoAlgorithm algorithm = | 672 blink::WebCryptoAlgorithm algorithm = |
| 689 ResolveNssKeyTypeWithInputAlgorithm(sec_key_type, algorithm_or_null); | 673 ResolveNssKeyTypeWithInputAlgorithm(sec_key_type, algorithm_or_null); |
| 690 if (algorithm.isNull()) | 674 if (algorithm.isNull()) |
| 691 return Status::Error(); | 675 return Status::Error(); |
| 692 | 676 |
| 693 #ifdef WEBCRYPTO_HAS_KEY_ALGORITHM | |
| 694 blink::WebCryptoKeyAlgorithm key_algorithm; | 677 blink::WebCryptoKeyAlgorithm key_algorithm; |
| 695 if (!CreatePrivateKeyAlgorithm(algorithm, private_key.get(), &key_algorithm)) | 678 if (!CreatePrivateKeyAlgorithm(algorithm, private_key.get(), &key_algorithm)) |
| 696 return Status::ErrorUnexpected(); | 679 return Status::ErrorUnexpected(); |
| 697 #else | |
| 698 const blink::WebCryptoAlgorithm& key_algorithm = algorithm; | |
| 699 #endif | |
| 700 | 680 |
| 701 *key = blink::WebCryptoKey::create(new PrivateKey(private_key.Pass()), | 681 *key = blink::WebCryptoKey::create(new PrivateKey(private_key.Pass()), |
| 702 blink::WebCryptoKeyTypePrivate, | 682 blink::WebCryptoKeyTypePrivate, |
| 703 extractable, | 683 extractable, |
| 704 key_algorithm, | 684 key_algorithm, |
| 705 usage_mask); | 685 usage_mask); |
| 706 | 686 |
| 707 return Status::Success(); | 687 return Status::Success(); |
| 708 } | 688 } |
| 709 | 689 |
| (...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 963 CKM_RSA_PKCS_KEY_PAIR_GEN, | 943 CKM_RSA_PKCS_KEY_PAIR_GEN, |
| 964 &rsa_gen_params, | 944 &rsa_gen_params, |
| 965 &sec_public_key, | 945 &sec_public_key, |
| 966 attribute_flags, | 946 attribute_flags, |
| 967 operation_flags, | 947 operation_flags, |
| 968 operation_flags_mask, | 948 operation_flags_mask, |
| 969 NULL)); | 949 NULL)); |
| 970 if (!private_key) | 950 if (!private_key) |
| 971 return Status::Error(); | 951 return Status::Error(); |
| 972 | 952 |
| 973 #ifdef WEBCRYPTO_HAS_KEY_ALGORITHM | |
| 974 blink::WebCryptoKeyAlgorithm key_algorithm; | 953 blink::WebCryptoKeyAlgorithm key_algorithm; |
| 975 if (!CreatePublicKeyAlgorithm(algorithm, sec_public_key, &key_algorithm)) | 954 if (!CreatePublicKeyAlgorithm(algorithm, sec_public_key, &key_algorithm)) |
| 976 return Status::ErrorUnexpected(); | 955 return Status::ErrorUnexpected(); |
| 977 #else | |
| 978 const blink::WebCryptoAlgorithm& key_algorithm = algorithm; | |
| 979 #endif | |
| 980 | 956 |
| 981 *public_key = blink::WebCryptoKey::create( | 957 *public_key = blink::WebCryptoKey::create( |
| 982 new PublicKey(crypto::ScopedSECKEYPublicKey(sec_public_key)), | 958 new PublicKey(crypto::ScopedSECKEYPublicKey(sec_public_key)), |
| 983 blink::WebCryptoKeyTypePublic, | 959 blink::WebCryptoKeyTypePublic, |
| 984 true, | 960 true, |
| 985 key_algorithm, | 961 key_algorithm, |
| 986 usage_mask); | 962 usage_mask); |
| 987 *private_key = | 963 *private_key = |
| 988 blink::WebCryptoKey::create(new PrivateKey(scoped_sec_private_key.Pass()), | 964 blink::WebCryptoKey::create(new PrivateKey(scoped_sec_private_key.Pass()), |
| 989 blink::WebCryptoKeyTypePrivate, | 965 blink::WebCryptoKeyTypePrivate, |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1042 crypto::ScopedPK11Slot slot(PK11_GetInternalKeySlot()); | 1018 crypto::ScopedPK11Slot slot(PK11_GetInternalKeySlot()); |
| 1043 if (!slot) | 1019 if (!slot) |
| 1044 return Status::Error(); | 1020 return Status::Error(); |
| 1045 | 1021 |
| 1046 crypto::ScopedPK11SymKey pk11_key( | 1022 crypto::ScopedPK11SymKey pk11_key( |
| 1047 PK11_KeyGen(slot.get(), mech, NULL, keylen_bytes, NULL)); | 1023 PK11_KeyGen(slot.get(), mech, NULL, keylen_bytes, NULL)); |
| 1048 | 1024 |
| 1049 if (!pk11_key) | 1025 if (!pk11_key) |
| 1050 return Status::Error(); | 1026 return Status::Error(); |
| 1051 | 1027 |
| 1052 #ifdef WEBCRYPTO_HAS_KEY_ALGORITHM | |
| 1053 blink::WebCryptoKeyAlgorithm key_algorithm; | 1028 blink::WebCryptoKeyAlgorithm key_algorithm; |
| 1054 if (!CreateSecretKeyAlgorithm(algorithm, keylen_bytes, &key_algorithm)) | 1029 if (!CreateSecretKeyAlgorithm(algorithm, keylen_bytes, &key_algorithm)) |
| 1055 return Status::ErrorUnexpected(); | 1030 return Status::ErrorUnexpected(); |
| 1056 #else | |
| 1057 const blink::WebCryptoAlgorithm& key_algorithm = algorithm; | |
| 1058 #endif | |
| 1059 | 1031 |
| 1060 *key = blink::WebCryptoKey::create(new SymKey(pk11_key.Pass()), | 1032 *key = blink::WebCryptoKey::create(new SymKey(pk11_key.Pass()), |
| 1061 key_type, | 1033 key_type, |
| 1062 extractable, | 1034 extractable, |
| 1063 key_algorithm, | 1035 key_algorithm, |
| 1064 usage_mask); | 1036 usage_mask); |
| 1065 return Status::Success(); | 1037 return Status::Success(); |
| 1066 } | 1038 } |
| 1067 | 1039 |
| 1068 Status ImportRsaPublicKey(const blink::WebCryptoAlgorithm& algorithm, | 1040 Status ImportRsaPublicKey(const blink::WebCryptoAlgorithm& algorithm, |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1109 SEC_ASN1EncodeItem(NULL, NULL, &pubkey_in, rsa_public_key_template)); | 1081 SEC_ASN1EncodeItem(NULL, NULL, &pubkey_in, rsa_public_key_template)); |
| 1110 if (!pubkey_der) | 1082 if (!pubkey_der) |
| 1111 return Status::Error(); | 1083 return Status::Error(); |
| 1112 | 1084 |
| 1113 // Import the DER-encoded public key to create an RSA SECKEYPublicKey. | 1085 // Import the DER-encoded public key to create an RSA SECKEYPublicKey. |
| 1114 crypto::ScopedSECKEYPublicKey pubkey( | 1086 crypto::ScopedSECKEYPublicKey pubkey( |
| 1115 SECKEY_ImportDERPublicKey(pubkey_der.get(), CKK_RSA)); | 1087 SECKEY_ImportDERPublicKey(pubkey_der.get(), CKK_RSA)); |
| 1116 if (!pubkey) | 1088 if (!pubkey) |
| 1117 return Status::Error(); | 1089 return Status::Error(); |
| 1118 | 1090 |
| 1119 #ifdef WEBCRYPTO_HAS_KEY_ALGORITHM | |
| 1120 blink::WebCryptoKeyAlgorithm key_algorithm; | 1091 blink::WebCryptoKeyAlgorithm key_algorithm; |
| 1121 if (!CreatePublicKeyAlgorithm(algorithm, pubkey.get(), &key_algorithm)) | 1092 if (!CreatePublicKeyAlgorithm(algorithm, pubkey.get(), &key_algorithm)) |
| 1122 return Status::ErrorUnexpected(); | 1093 return Status::ErrorUnexpected(); |
| 1123 #else | |
| 1124 const blink::WebCryptoAlgorithm& key_algorithm = algorithm; | |
| 1125 #endif | |
| 1126 | 1094 |
| 1127 *key = blink::WebCryptoKey::create(new PublicKey(pubkey.Pass()), | 1095 *key = blink::WebCryptoKey::create(new PublicKey(pubkey.Pass()), |
| 1128 blink::WebCryptoKeyTypePublic, | 1096 blink::WebCryptoKeyTypePublic, |
| 1129 extractable, | 1097 extractable, |
| 1130 key_algorithm, | 1098 key_algorithm, |
| 1131 usage_mask); | 1099 usage_mask); |
| 1132 return Status::Success(); | 1100 return Status::Success(); |
| 1133 } | 1101 } |
| 1134 | 1102 |
| 1135 } // namespace platform | 1103 } // namespace platform |
| 1136 | 1104 |
| 1137 } // namespace webcrypto | 1105 } // namespace webcrypto |
| 1138 | 1106 |
| 1139 } // namespace content | 1107 } // namespace content |
| OLD | NEW |