| 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/child/webcrypto/platform_crypto.h" | 5 #include "content/child/webcrypto/platform_crypto.h" |
| 6 | 6 |
| 7 #include <cryptohi.h> | 7 #include <cryptohi.h> |
| 8 #include <pk11pub.h> | 8 #include <pk11pub.h> |
| 9 #include <secerr.h> | 9 #include <secerr.h> |
| 10 #include <sechash.h> | 10 #include <sechash.h> |
| (...skipping 535 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 546 size_t reverse_i = data_size - i - 1; | 546 size_t reverse_i = data_size - i - 1; |
| 547 | 547 |
| 548 if (reverse_i >= sizeof(unsigned long) && data[i]) | 548 if (reverse_i >= sizeof(unsigned long) && data[i]) |
| 549 return false; // Too large for a long. | 549 return false; // Too large for a long. |
| 550 | 550 |
| 551 *result |= data[i] << 8 * reverse_i; | 551 *result |= data[i] << 8 * reverse_i; |
| 552 } | 552 } |
| 553 return true; | 553 return true; |
| 554 } | 554 } |
| 555 | 555 |
| 556 bool IsAlgorithmRsa(const blink::WebCryptoAlgorithm& algorithm) { | |
| 557 return algorithm.id() == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 || | |
| 558 algorithm.id() == blink::WebCryptoAlgorithmIdRsaOaep || | |
| 559 algorithm.id() == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5; | |
| 560 } | |
| 561 | |
| 562 bool CreatePublicKeyAlgorithm(const blink::WebCryptoAlgorithm& algorithm, | 556 bool CreatePublicKeyAlgorithm(const blink::WebCryptoAlgorithm& algorithm, |
| 563 SECKEYPublicKey* key, | 557 SECKEYPublicKey* key, |
| 564 blink::WebCryptoKeyAlgorithm* key_algorithm) { | 558 blink::WebCryptoKeyAlgorithm* key_algorithm) { |
| 565 // TODO(eroman): What about other key types rsaPss, rsaOaep. | 559 // TODO(eroman): What about other key types rsaPss, rsaOaep. |
| 566 if (!key || key->keyType != rsaKey) | 560 if (!key || key->keyType != rsaKey) |
| 567 return false; | 561 return false; |
| 568 | 562 |
| 569 unsigned int modulus_length_bits = SECKEY_PublicKeyStrength(key) * 8; | 563 unsigned int modulus_length_bits = SECKEY_PublicKeyStrength(key) * 8; |
| 570 CryptoData public_exponent(key->u.rsa.publicExponent.data, | 564 CryptoData public_exponent(key->u.rsa.publicExponent.data, |
| 571 key->u.rsa.publicExponent.len); | 565 key->u.rsa.publicExponent.len); |
| 572 | 566 |
| 573 switch (algorithm.paramsType()) { | 567 switch (algorithm.paramsType()) { |
| 574 case blink::WebCryptoAlgorithmParamsTypeRsaHashedImportParams: | 568 case blink::WebCryptoAlgorithmParamsTypeRsaHashedImportParams: |
| 575 case blink::WebCryptoAlgorithmParamsTypeRsaHashedKeyGenParams: | 569 case blink::WebCryptoAlgorithmParamsTypeRsaHashedKeyGenParams: |
| 576 *key_algorithm = blink::WebCryptoKeyAlgorithm::createRsaHashed( | 570 *key_algorithm = blink::WebCryptoKeyAlgorithm::createRsaHashed( |
| 577 algorithm.id(), | 571 algorithm.id(), |
| 578 modulus_length_bits, | 572 modulus_length_bits, |
| 579 public_exponent.bytes(), | 573 public_exponent.bytes(), |
| 580 public_exponent.byte_length(), | 574 public_exponent.byte_length(), |
| 581 GetInnerHashAlgorithm(algorithm).id()); | 575 GetInnerHashAlgorithm(algorithm).id()); |
| 582 return true; | 576 return true; |
| 583 case blink::WebCryptoAlgorithmParamsTypeRsaKeyGenParams: | |
| 584 case blink::WebCryptoAlgorithmParamsTypeNone: | |
| 585 *key_algorithm = blink::WebCryptoKeyAlgorithm::createRsa( | |
| 586 algorithm.id(), | |
| 587 modulus_length_bits, | |
| 588 public_exponent.bytes(), | |
| 589 public_exponent.byte_length()); | |
| 590 return true; | |
| 591 default: | 577 default: |
| 592 return false; | 578 return false; |
| 593 } | 579 } |
| 594 } | 580 } |
| 595 | 581 |
| 596 bool CreatePrivateKeyAlgorithm(const blink::WebCryptoAlgorithm& algorithm, | 582 bool CreatePrivateKeyAlgorithm(const blink::WebCryptoAlgorithm& algorithm, |
| 597 SECKEYPrivateKey* key, | 583 SECKEYPrivateKey* key, |
| 598 blink::WebCryptoKeyAlgorithm* key_algorithm) { | 584 blink::WebCryptoKeyAlgorithm* key_algorithm) { |
| 599 crypto::ScopedSECKEYPublicKey public_key(SECKEY_ConvertToPublicKey(key)); | 585 crypto::ScopedSECKEYPublicKey public_key(SECKEY_ConvertToPublicKey(key)); |
| 600 return CreatePublicKeyAlgorithm(algorithm, public_key.get(), key_algorithm); | 586 return CreatePublicKeyAlgorithm(algorithm, public_key.get(), key_algorithm); |
| (...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 980 crypto::NSSDestroyer<CERTSubjectPublicKeyInfo, | 966 crypto::NSSDestroyer<CERTSubjectPublicKeyInfo, |
| 981 SECKEY_DestroySubjectPublicKeyInfo> > | 967 SECKEY_DestroySubjectPublicKeyInfo> > |
| 982 ScopedCERTSubjectPublicKeyInfo; | 968 ScopedCERTSubjectPublicKeyInfo; |
| 983 | 969 |
| 984 // Validates an NSS KeyType against a WebCrypto import algorithm. | 970 // Validates an NSS KeyType against a WebCrypto import algorithm. |
| 985 bool ValidateNssKeyTypeAgainstInputAlgorithm( | 971 bool ValidateNssKeyTypeAgainstInputAlgorithm( |
| 986 KeyType key_type, | 972 KeyType key_type, |
| 987 const blink::WebCryptoAlgorithm& algorithm) { | 973 const blink::WebCryptoAlgorithm& algorithm) { |
| 988 switch (key_type) { | 974 switch (key_type) { |
| 989 case rsaKey: | 975 case rsaKey: |
| 990 return IsAlgorithmRsa(algorithm); | 976 return IsAlgorithmRsa(algorithm.id()); |
| 991 case dsaKey: | 977 case dsaKey: |
| 992 case ecKey: | 978 case ecKey: |
| 993 case rsaPssKey: | 979 case rsaPssKey: |
| 994 case rsaOaepKey: | 980 case rsaOaepKey: |
| 995 // TODO(padolph): Handle other key types. | 981 // TODO(padolph): Handle other key types. |
| 996 break; | 982 break; |
| 997 default: | 983 default: |
| 998 break; | 984 break; |
| 999 } | 985 } |
| 1000 return false; | 986 return false; |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1107 AssignVectorFromSecItem(key_props.exponent2, exponent2); | 1093 AssignVectorFromSecItem(key_props.exponent2, exponent2); |
| 1108 AssignVectorFromSecItem(key_props.coefficient, coefficient); | 1094 AssignVectorFromSecItem(key_props.coefficient, coefficient); |
| 1109 | 1095 |
| 1110 return Status::Success(); | 1096 return Status::Success(); |
| 1111 } | 1097 } |
| 1112 | 1098 |
| 1113 Status ExportKeyPkcs8(PrivateKey* key, | 1099 Status ExportKeyPkcs8(PrivateKey* key, |
| 1114 const blink::WebCryptoKeyAlgorithm& key_algorithm, | 1100 const blink::WebCryptoKeyAlgorithm& key_algorithm, |
| 1115 std::vector<uint8>* buffer) { | 1101 std::vector<uint8>* buffer) { |
| 1116 // TODO(eroman): Support other RSA key types as they are added to Blink. | 1102 // TODO(eroman): Support other RSA key types as they are added to Blink. |
| 1117 if (key_algorithm.id() != blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 && | 1103 if (key_algorithm.id() != blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 && |
| 1118 key_algorithm.id() != blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 && | |
| 1119 key_algorithm.id() != blink::WebCryptoAlgorithmIdRsaOaep) | 1104 key_algorithm.id() != blink::WebCryptoAlgorithmIdRsaOaep) |
| 1120 return Status::ErrorUnsupported(); | 1105 return Status::ErrorUnsupported(); |
| 1121 | 1106 |
| 1122 // TODO(rsleevi): Implement OAEP support according to the spec. | 1107 // TODO(rsleevi): Implement OAEP support according to the spec. |
| 1123 | 1108 |
| 1124 #if defined(USE_NSS) | 1109 #if defined(USE_NSS) |
| 1125 // PK11_ExportDERPrivateKeyInfo isn't available. Use our fallback code. | 1110 // PK11_ExportDERPrivateKeyInfo isn't available. Use our fallback code. |
| 1126 const SECOidTag algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION; | 1111 const SECOidTag algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION; |
| 1127 const int kPrivateKeyInfoVersion = 0; | 1112 const int kPrivateKeyInfoVersion = 0; |
| 1128 | 1113 |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1260 &signature_item, | 1245 &signature_item, |
| 1261 &data_item) != SECSuccess) { | 1246 &data_item) != SECSuccess) { |
| 1262 return Status::OperationError(); | 1247 return Status::OperationError(); |
| 1263 } | 1248 } |
| 1264 | 1249 |
| 1265 DCHECK_EQ(buffer->size(), signature_item.len); | 1250 DCHECK_EQ(buffer->size(), signature_item.len); |
| 1266 return Status::Success(); | 1251 return Status::Success(); |
| 1267 } | 1252 } |
| 1268 | 1253 |
| 1269 // ----------------------------------- | 1254 // ----------------------------------- |
| 1270 // RsaEsPkcs1v1_5 | |
| 1271 // ----------------------------------- | |
| 1272 | |
| 1273 Status EncryptRsaEsPkcs1v1_5(PublicKey* key, | |
| 1274 const CryptoData& data, | |
| 1275 std::vector<uint8>* buffer) { | |
| 1276 const unsigned int encrypted_length_bytes = | |
| 1277 SECKEY_PublicKeyStrength(key->key()); | |
| 1278 | |
| 1279 // RSAES can operate on messages up to a length of k - 11, where k is the | |
| 1280 // octet length of the RSA modulus. | |
| 1281 if (encrypted_length_bytes < 11 || | |
| 1282 encrypted_length_bytes - 11 < data.byte_length()) | |
| 1283 return Status::ErrorDataTooLarge(); | |
| 1284 | |
| 1285 buffer->resize(encrypted_length_bytes); | |
| 1286 unsigned char* const buffer_data = Uint8VectorStart(buffer); | |
| 1287 | |
| 1288 if (PK11_PubEncryptPKCS1(key->key(), | |
| 1289 buffer_data, | |
| 1290 const_cast<unsigned char*>(data.bytes()), | |
| 1291 data.byte_length(), | |
| 1292 NULL) != SECSuccess) { | |
| 1293 return Status::OperationError(); | |
| 1294 } | |
| 1295 return Status::Success(); | |
| 1296 } | |
| 1297 | |
| 1298 Status DecryptRsaEsPkcs1v1_5(PrivateKey* key, | |
| 1299 const CryptoData& data, | |
| 1300 std::vector<uint8>* buffer) { | |
| 1301 const int modulus_length_bytes = PK11_GetPrivateModulusLen(key->key()); | |
| 1302 if (modulus_length_bytes <= 0) | |
| 1303 return Status::ErrorUnexpected(); | |
| 1304 const unsigned int max_output_length_bytes = modulus_length_bytes; | |
| 1305 | |
| 1306 buffer->resize(max_output_length_bytes); | |
| 1307 unsigned char* const buffer_data = Uint8VectorStart(buffer); | |
| 1308 | |
| 1309 unsigned int output_length_bytes = 0; | |
| 1310 if (PK11_PrivDecryptPKCS1(key->key(), | |
| 1311 buffer_data, | |
| 1312 &output_length_bytes, | |
| 1313 max_output_length_bytes, | |
| 1314 const_cast<unsigned char*>(data.bytes()), | |
| 1315 data.byte_length()) != SECSuccess) { | |
| 1316 return Status::OperationError(); | |
| 1317 } | |
| 1318 DCHECK_LE(output_length_bytes, max_output_length_bytes); | |
| 1319 buffer->resize(output_length_bytes); | |
| 1320 return Status::Success(); | |
| 1321 } | |
| 1322 | |
| 1323 // ----------------------------------- | |
| 1324 // RsaOaep | 1255 // RsaOaep |
| 1325 // ----------------------------------- | 1256 // ----------------------------------- |
| 1326 | 1257 |
| 1327 Status EncryptRsaOaep(PublicKey* key, | 1258 Status EncryptRsaOaep(PublicKey* key, |
| 1328 const blink::WebCryptoAlgorithm& hash, | 1259 const blink::WebCryptoAlgorithm& hash, |
| 1329 const CryptoData& label, | 1260 const CryptoData& label, |
| 1330 const CryptoData& data, | 1261 const CryptoData& data, |
| 1331 std::vector<uint8>* buffer) { | 1262 std::vector<uint8>* buffer) { |
| 1332 if (!g_nss_runtime_support.Get().IsRsaOaepSupported()) | 1263 if (!g_nss_runtime_support.Get().IsRsaOaepSupported()) |
| 1333 return Status::ErrorUnsupported(); | 1264 return Status::ErrorUnsupported(); |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1505 | 1436 |
| 1506 // ----------------------------------- | 1437 // ----------------------------------- |
| 1507 // Key generation | 1438 // Key generation |
| 1508 // ----------------------------------- | 1439 // ----------------------------------- |
| 1509 | 1440 |
| 1510 Status GenerateRsaKeyPair(const blink::WebCryptoAlgorithm& algorithm, | 1441 Status GenerateRsaKeyPair(const blink::WebCryptoAlgorithm& algorithm, |
| 1511 bool extractable, | 1442 bool extractable, |
| 1512 blink::WebCryptoKeyUsageMask usage_mask, | 1443 blink::WebCryptoKeyUsageMask usage_mask, |
| 1513 unsigned int modulus_length_bits, | 1444 unsigned int modulus_length_bits, |
| 1514 const CryptoData& public_exponent, | 1445 const CryptoData& public_exponent, |
| 1515 const blink::WebCryptoAlgorithm& hash_or_null, | |
| 1516 blink::WebCryptoKey* public_key, | 1446 blink::WebCryptoKey* public_key, |
| 1517 blink::WebCryptoKey* private_key) { | 1447 blink::WebCryptoKey* private_key) { |
| 1518 if (algorithm.id() == blink::WebCryptoAlgorithmIdRsaOaep && | 1448 if (algorithm.id() == blink::WebCryptoAlgorithmIdRsaOaep && |
| 1519 !g_nss_runtime_support.Get().IsRsaOaepSupported()) { | 1449 !g_nss_runtime_support.Get().IsRsaOaepSupported()) { |
| 1520 return Status::ErrorUnsupported(); | 1450 return Status::ErrorUnsupported(); |
| 1521 } | 1451 } |
| 1522 | 1452 |
| 1523 crypto::ScopedPK11Slot slot(PK11_GetInternalKeySlot()); | 1453 crypto::ScopedPK11Slot slot(PK11_GetInternalKeySlot()); |
| 1524 if (!slot) | 1454 if (!slot) |
| 1525 return Status::OperationError(); | 1455 return Status::OperationError(); |
| 1526 | 1456 |
| 1527 unsigned long public_exponent_long; | 1457 unsigned long public_exponent_long; |
| 1528 if (!BigIntegerToLong(public_exponent.bytes(), | 1458 if (!BigIntegerToLong(public_exponent.bytes(), |
| 1529 public_exponent.byte_length(), | 1459 public_exponent.byte_length(), |
| 1530 &public_exponent_long) || | 1460 &public_exponent_long) || |
| 1531 !public_exponent_long) { | 1461 !public_exponent_long) { |
| 1532 return Status::ErrorGenerateKeyPublicExponent(); | 1462 return Status::ErrorGenerateKeyPublicExponent(); |
| 1533 } | 1463 } |
| 1534 | 1464 |
| 1535 PK11RSAGenParams rsa_gen_params; | 1465 PK11RSAGenParams rsa_gen_params; |
| 1536 rsa_gen_params.keySizeInBits = modulus_length_bits; | 1466 rsa_gen_params.keySizeInBits = modulus_length_bits; |
| 1537 rsa_gen_params.pe = public_exponent_long; | 1467 rsa_gen_params.pe = public_exponent_long; |
| 1538 | 1468 |
| 1539 // Flags are verified at the Blink layer; here the flags are set to all | 1469 // Flags are verified at the Blink layer; here the flags are set to all |
| 1540 // possible operations for the given key type. | 1470 // possible operations for the given key type. |
| 1541 CK_FLAGS operation_flags; | 1471 CK_FLAGS operation_flags; |
| 1542 switch (algorithm.id()) { | 1472 switch (algorithm.id()) { |
| 1543 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: | |
| 1544 case blink::WebCryptoAlgorithmIdRsaOaep: | 1473 case blink::WebCryptoAlgorithmIdRsaOaep: |
| 1545 operation_flags = CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP; | 1474 operation_flags = CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP; |
| 1546 break; | 1475 break; |
| 1547 case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: | 1476 case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: |
| 1548 operation_flags = CKF_SIGN | CKF_VERIFY; | 1477 operation_flags = CKF_SIGN | CKF_VERIFY; |
| 1549 break; | 1478 break; |
| 1550 default: | 1479 default: |
| 1551 NOTREACHED(); | 1480 NOTREACHED(); |
| 1552 return Status::ErrorUnexpected(); | 1481 return Status::ErrorUnexpected(); |
| 1553 } | 1482 } |
| (...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1928 if (PK11_ExtractKeyValue(decrypted.get()) != SECSuccess) | 1857 if (PK11_ExtractKeyValue(decrypted.get()) != SECSuccess) |
| 1929 return Status::OperationError(); | 1858 return Status::OperationError(); |
| 1930 const SECItem* const key_data = PK11_GetKeyData(decrypted.get()); | 1859 const SECItem* const key_data = PK11_GetKeyData(decrypted.get()); |
| 1931 if (!key_data) | 1860 if (!key_data) |
| 1932 return Status::OperationError(); | 1861 return Status::OperationError(); |
| 1933 buffer->assign(key_data->data, key_data->data + key_data->len); | 1862 buffer->assign(key_data->data, key_data->data + key_data->len); |
| 1934 | 1863 |
| 1935 return Status::Success(); | 1864 return Status::Success(); |
| 1936 } | 1865 } |
| 1937 | 1866 |
| 1938 Status WrapSymKeyRsaEs(SymKey* key, | |
| 1939 PublicKey* wrapping_key, | |
| 1940 std::vector<uint8>* buffer) { | |
| 1941 // Check the raw length of the key to be wrapped against the max size allowed | |
| 1942 // by the RSA wrapping key. With PKCS#1 v1.5 padding used in this function, | |
| 1943 // the maximum data length that can be encrypted is the wrapping_key's modulus | |
| 1944 // byte length minus eleven bytes. | |
| 1945 const unsigned int input_length_bytes = PK11_GetKeyLength(key->key()); | |
| 1946 const unsigned int modulus_length_bytes = | |
| 1947 SECKEY_PublicKeyStrength(wrapping_key->key()); | |
| 1948 if (modulus_length_bytes < 11 || | |
| 1949 modulus_length_bytes - 11 < input_length_bytes) | |
| 1950 return Status::ErrorDataTooLarge(); | |
| 1951 | |
| 1952 buffer->resize(modulus_length_bytes); | |
| 1953 SECItem wrapped_key_item = MakeSECItemForBuffer(CryptoData(*buffer)); | |
| 1954 | |
| 1955 if (SECSuccess != | |
| 1956 PK11_PubWrapSymKey( | |
| 1957 CKM_RSA_PKCS, wrapping_key->key(), key->key(), &wrapped_key_item)) { | |
| 1958 return Status::OperationError(); | |
| 1959 } | |
| 1960 if (wrapped_key_item.len != modulus_length_bytes) | |
| 1961 return Status::ErrorUnexpected(); | |
| 1962 | |
| 1963 return Status::Success(); | |
| 1964 } | |
| 1965 | |
| 1966 Status UnwrapSymKeyRsaEs(const CryptoData& wrapped_key_data, | |
| 1967 PrivateKey* wrapping_key, | |
| 1968 const blink::WebCryptoAlgorithm& algorithm, | |
| 1969 bool extractable, | |
| 1970 blink::WebCryptoKeyUsageMask usage_mask, | |
| 1971 blink::WebCryptoKey* key) { | |
| 1972 // Verify wrapped_key_data size does not exceed the modulus of the RSA key. | |
| 1973 const int modulus_length_bytes = | |
| 1974 PK11_GetPrivateModulusLen(wrapping_key->key()); | |
| 1975 if (modulus_length_bytes <= 0) | |
| 1976 return Status::ErrorUnexpected(); | |
| 1977 if (wrapped_key_data.byte_length() > | |
| 1978 static_cast<unsigned int>(modulus_length_bytes)) | |
| 1979 return Status::ErrorDataTooLarge(); | |
| 1980 | |
| 1981 // Determine the proper NSS key properties from the input algorithm. | |
| 1982 CK_MECHANISM_TYPE mechanism; | |
| 1983 CK_FLAGS flags; | |
| 1984 Status status = | |
| 1985 WebCryptoAlgorithmToNssMechFlags(algorithm, &mechanism, &flags); | |
| 1986 if (status.IsError()) | |
| 1987 return status; | |
| 1988 | |
| 1989 SECItem wrapped_key_item = MakeSECItemForBuffer(wrapped_key_data); | |
| 1990 | |
| 1991 crypto::ScopedPK11SymKey unwrapped_key( | |
| 1992 PK11_PubUnwrapSymKeyWithFlagsPerm(wrapping_key->key(), | |
| 1993 &wrapped_key_item, | |
| 1994 mechanism, | |
| 1995 CKA_DECRYPT, | |
| 1996 0, | |
| 1997 flags, | |
| 1998 false)); | |
| 1999 if (!unwrapped_key) | |
| 2000 return Status::OperationError(); | |
| 2001 | |
| 2002 const unsigned int key_length = PK11_GetKeyLength(unwrapped_key.get()); | |
| 2003 | |
| 2004 blink::WebCryptoKeyAlgorithm key_algorithm; | |
| 2005 if (!CreateSecretKeyAlgorithm(algorithm, key_length, &key_algorithm)) | |
| 2006 return Status::ErrorUnexpected(); | |
| 2007 | |
| 2008 scoped_ptr<SymKey> key_handle; | |
| 2009 status = SymKey::Create(unwrapped_key.Pass(), &key_handle); | |
| 2010 if (status.IsError()) | |
| 2011 return status; | |
| 2012 | |
| 2013 *key = blink::WebCryptoKey::create(key_handle.release(), | |
| 2014 blink::WebCryptoKeyTypeSecret, | |
| 2015 extractable, | |
| 2016 key_algorithm, | |
| 2017 usage_mask); | |
| 2018 return Status::Success(); | |
| 2019 } | |
| 2020 | |
| 2021 } // namespace platform | 1867 } // namespace platform |
| 2022 | 1868 |
| 2023 } // namespace webcrypto | 1869 } // namespace webcrypto |
| 2024 | 1870 |
| 2025 } // namespace content | 1871 } // namespace content |
| OLD | NEW |