| 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 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 50 struct CK_GCM_PARAMS { | 50 struct CK_GCM_PARAMS { |
| 51 CK_BYTE_PTR pIv; | 51 CK_BYTE_PTR pIv; |
| 52 CK_ULONG ulIvLen; | 52 CK_ULONG ulIvLen; |
| 53 CK_BYTE_PTR pAAD; | 53 CK_BYTE_PTR pAAD; |
| 54 CK_ULONG ulAADLen; | 54 CK_ULONG ulAADLen; |
| 55 CK_ULONG ulTagBits; | 55 CK_ULONG ulTagBits; |
| 56 }; | 56 }; |
| 57 #endif // !defined(CKM_AES_GCM) | 57 #endif // !defined(CKM_AES_GCM) |
| 58 | 58 |
| 59 // Signature for PK11_Encrypt and PK11_Decrypt. | 59 // Signature for PK11_Encrypt and PK11_Decrypt. |
| 60 typedef SECStatus | 60 typedef SECStatus (*PK11_EncryptDecryptFunction)(PK11SymKey*, |
| 61 (*PK11_EncryptDecryptFunction)( | 61 CK_MECHANISM_TYPE, |
| 62 PK11SymKey*, CK_MECHANISM_TYPE, SECItem*, | 62 SECItem*, |
| 63 unsigned char*, unsigned int*, unsigned int, | 63 unsigned char*, |
| 64 const unsigned char*, unsigned int); | 64 unsigned int*, |
| 65 unsigned int, |
| 66 const unsigned char*, |
| 67 unsigned int); |
| 65 | 68 |
| 66 // Singleton to abstract away dynamically loading libnss3.so | 69 // Singleton to abstract away dynamically loading libnss3.so |
| 67 class AesGcmSupport { | 70 class AesGcmSupport { |
| 68 public: | 71 public: |
| 69 bool IsSupported() const { | 72 bool IsSupported() const { return pk11_encrypt_func_ && pk11_decrypt_func_; } |
| 70 return pk11_encrypt_func_ && pk11_decrypt_func_; | |
| 71 } | |
| 72 | 73 |
| 73 // Returns NULL if unsupported. | 74 // Returns NULL if unsupported. |
| 74 PK11_EncryptDecryptFunction pk11_encrypt_func() const { | 75 PK11_EncryptDecryptFunction pk11_encrypt_func() const { |
| 75 return pk11_encrypt_func_; | 76 return pk11_encrypt_func_; |
| 76 } | 77 } |
| 77 | 78 |
| 78 // Returns NULL if unsupported. | 79 // Returns NULL if unsupported. |
| 79 PK11_EncryptDecryptFunction pk11_decrypt_func() const { | 80 PK11_EncryptDecryptFunction pk11_decrypt_func() const { |
| 80 return pk11_decrypt_func_; | 81 return pk11_decrypt_func_; |
| 81 } | 82 } |
| 82 | 83 |
| 83 private: | 84 private: |
| 84 friend struct base::DefaultLazyInstanceTraits<AesGcmSupport>; | 85 friend struct base::DefaultLazyInstanceTraits<AesGcmSupport>; |
| 85 | 86 |
| 86 AesGcmSupport() { | 87 AesGcmSupport() { |
| 87 #if !defined(USE_NSS) | 88 #if !defined(USE_NSS) |
| 88 // Using a bundled version of NSS that is guaranteed to have this symbol. | 89 // Using a bundled version of NSS that is guaranteed to have this symbol. |
| 89 pk11_encrypt_func_ = PK11_Encrypt; | 90 pk11_encrypt_func_ = PK11_Encrypt; |
| 90 pk11_decrypt_func_ = PK11_Decrypt; | 91 pk11_decrypt_func_ = PK11_Decrypt; |
| 91 #else | 92 #else |
| 92 // Using system NSS libraries and PCKS #11 modules, which may not have the | 93 // Using system NSS libraries and PCKS #11 modules, which may not have the |
| 93 // necessary function (PK11_Encrypt) or mechanism support (CKM_AES_GCM). | 94 // necessary function (PK11_Encrypt) or mechanism support (CKM_AES_GCM). |
| 94 | 95 |
| 95 // If PK11_Encrypt() was successfully resolved, then NSS will support | 96 // If PK11_Encrypt() was successfully resolved, then NSS will support |
| 96 // AES-GCM directly. This was introduced in NSS 3.15. | 97 // AES-GCM directly. This was introduced in NSS 3.15. |
| 97 pk11_encrypt_func_ = | 98 pk11_encrypt_func_ = reinterpret_cast<PK11_EncryptDecryptFunction>( |
| 98 reinterpret_cast<PK11_EncryptDecryptFunction>( | 99 dlsym(RTLD_DEFAULT, "PK11_Encrypt")); |
| 99 dlsym(RTLD_DEFAULT, "PK11_Encrypt")); | 100 pk11_decrypt_func_ = reinterpret_cast<PK11_EncryptDecryptFunction>( |
| 100 pk11_decrypt_func_ = | 101 dlsym(RTLD_DEFAULT, "PK11_Decrypt")); |
| 101 reinterpret_cast<PK11_EncryptDecryptFunction>( | |
| 102 dlsym(RTLD_DEFAULT, "PK11_Decrypt")); | |
| 103 #endif | 102 #endif |
| 104 } | 103 } |
| 105 | 104 |
| 106 PK11_EncryptDecryptFunction pk11_encrypt_func_; | 105 PK11_EncryptDecryptFunction pk11_encrypt_func_; |
| 107 PK11_EncryptDecryptFunction pk11_decrypt_func_; | 106 PK11_EncryptDecryptFunction pk11_decrypt_func_; |
| 108 }; | 107 }; |
| 109 | 108 |
| 110 base::LazyInstance<AesGcmSupport>::Leaky g_aes_gcm_support = | 109 base::LazyInstance<AesGcmSupport>::Leaky g_aes_gcm_support = |
| 111 LAZY_INSTANCE_INITIALIZER; | 110 LAZY_INSTANCE_INITIALIZER; |
| 112 | 111 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 165 }; | 164 }; |
| 166 | 165 |
| 167 namespace { | 166 namespace { |
| 168 | 167 |
| 169 // Creates a SECItem for the data in |buffer|. This does NOT make a copy, so | 168 // Creates a SECItem for the data in |buffer|. This does NOT make a copy, so |
| 170 // |buffer| should outlive the SECItem. | 169 // |buffer| should outlive the SECItem. |
| 171 SECItem MakeSECItemForBuffer(const CryptoData& buffer) { | 170 SECItem MakeSECItemForBuffer(const CryptoData& buffer) { |
| 172 SECItem item = { | 171 SECItem item = { |
| 173 siBuffer, | 172 siBuffer, |
| 174 // NSS requires non-const data even though it is just for input. | 173 // NSS requires non-const data even though it is just for input. |
| 175 const_cast<unsigned char*>(buffer.bytes()), | 174 const_cast<unsigned char*>(buffer.bytes()), buffer.byte_length()}; |
| 176 buffer.byte_length() | |
| 177 }; | |
| 178 return item; | 175 return item; |
| 179 } | 176 } |
| 180 | 177 |
| 181 HASH_HashType WebCryptoAlgorithmToNSSHashType( | 178 HASH_HashType WebCryptoAlgorithmToNSSHashType( |
| 182 blink::WebCryptoAlgorithmId algorithm) { | 179 blink::WebCryptoAlgorithmId algorithm) { |
| 183 switch (algorithm) { | 180 switch (algorithm) { |
| 184 case blink::WebCryptoAlgorithmIdSha1: | 181 case blink::WebCryptoAlgorithmIdSha1: |
| 185 return HASH_AlgSHA1; | 182 return HASH_AlgSHA1; |
| 186 case blink::WebCryptoAlgorithmIdSha224: | 183 case blink::WebCryptoAlgorithmIdSha224: |
| 187 return HASH_AlgSHA224; | 184 return HASH_AlgSHA224; |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 279 return Status::Error(); | 276 return Status::Error(); |
| 280 } | 277 } |
| 281 | 278 |
| 282 ShrinkBuffer(buffer, final_output_chunk_len + output_len); | 279 ShrinkBuffer(buffer, final_output_chunk_len + output_len); |
| 283 return Status::Success(); | 280 return Status::Success(); |
| 284 } | 281 } |
| 285 | 282 |
| 286 // Helper to either encrypt or decrypt for AES-GCM. The result of encryption is | 283 // Helper to either encrypt or decrypt for AES-GCM. The result of encryption is |
| 287 // the concatenation of the ciphertext and the authentication tag. Similarly, | 284 // the concatenation of the ciphertext and the authentication tag. Similarly, |
| 288 // this is the expectation for the input to decryption. | 285 // this is the expectation for the input to decryption. |
| 289 Status AesGcmEncryptDecrypt( | 286 Status AesGcmEncryptDecrypt(EncryptOrDecrypt mode, |
| 290 EncryptOrDecrypt mode, | 287 SymKey* key, |
| 291 SymKey* key, | 288 const CryptoData& data, |
| 292 const CryptoData& data, | 289 const CryptoData& iv, |
| 293 const CryptoData& iv, | 290 const CryptoData& additional_data, |
| 294 const CryptoData& additional_data, | 291 unsigned int tag_length_bits, |
| 295 unsigned int tag_length_bits, | 292 blink::WebArrayBuffer* buffer) { |
| 296 blink::WebArrayBuffer* buffer) { | |
| 297 if (!g_aes_gcm_support.Get().IsSupported()) | 293 if (!g_aes_gcm_support.Get().IsSupported()) |
| 298 return Status::ErrorUnsupported(); | 294 return Status::ErrorUnsupported(); |
| 299 | 295 |
| 300 // TODO(eroman): Is this necessary? | 296 // TODO(eroman): Is this necessary? |
| 301 if ((tag_length_bits % 8) != 0) | 297 if ((tag_length_bits % 8) != 0) |
| 302 return Status::ErrorInvalidAesGcmTagLength(); | 298 return Status::ErrorInvalidAesGcmTagLength(); |
| 303 unsigned int tag_length_bytes = tag_length_bits / 8; | 299 unsigned int tag_length_bytes = tag_length_bits / 8; |
| 304 | 300 |
| 305 CK_GCM_PARAMS gcm_params = {0}; | 301 CK_GCM_PARAMS gcm_params = {0}; |
| 306 gcm_params.pIv = const_cast<unsigned char*>(iv.bytes()); | 302 gcm_params.pIv = const_cast<unsigned char*>(iv.bytes()); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 336 // From the analysis of that bug it looks like it might be safe to pass a | 332 // From the analysis of that bug it looks like it might be safe to pass a |
| 337 // correctly sized buffer but lie about its size. Since resizing the | 333 // correctly sized buffer but lie about its size. Since resizing the |
| 338 // WebCryptoArrayBuffer is expensive that hack may be worth looking into. | 334 // WebCryptoArrayBuffer is expensive that hack may be worth looking into. |
| 339 buffer_size = data.byte_length(); | 335 buffer_size = data.byte_length(); |
| 340 } | 336 } |
| 341 | 337 |
| 342 *buffer = blink::WebArrayBuffer::create(buffer_size, 1); | 338 *buffer = blink::WebArrayBuffer::create(buffer_size, 1); |
| 343 unsigned char* buffer_data = reinterpret_cast<unsigned char*>(buffer->data()); | 339 unsigned char* buffer_data = reinterpret_cast<unsigned char*>(buffer->data()); |
| 344 | 340 |
| 345 PK11_EncryptDecryptFunction func = | 341 PK11_EncryptDecryptFunction func = |
| 346 (mode == ENCRYPT) ? g_aes_gcm_support.Get().pk11_encrypt_func() : | 342 (mode == ENCRYPT) ? g_aes_gcm_support.Get().pk11_encrypt_func() |
| 347 g_aes_gcm_support.Get().pk11_decrypt_func(); | 343 : g_aes_gcm_support.Get().pk11_decrypt_func(); |
| 348 | 344 |
| 349 unsigned int output_len = 0; | 345 unsigned int output_len = 0; |
| 350 SECStatus result = func(key->key(), CKM_AES_GCM, ¶m, | 346 SECStatus result = func(key->key(), |
| 351 buffer_data, &output_len, buffer->byteLength(), | 347 CKM_AES_GCM, |
| 352 data.bytes(), data.byte_length()); | 348 ¶m, |
| 349 buffer_data, |
| 350 &output_len, |
| 351 buffer->byteLength(), |
| 352 data.bytes(), |
| 353 data.byte_length()); |
| 353 | 354 |
| 354 if (result != SECSuccess) | 355 if (result != SECSuccess) |
| 355 return Status::Error(); | 356 return Status::Error(); |
| 356 | 357 |
| 357 // Unfortunately the buffer needs to be shrunk for decryption (see the NSS bug | 358 // Unfortunately the buffer needs to be shrunk for decryption (see the NSS bug |
| 358 // above). | 359 // above). |
| 359 ShrinkBuffer(buffer, output_len); | 360 ShrinkBuffer(buffer, output_len); |
| 360 | 361 |
| 361 return Status::Success(); | 362 return Status::Success(); |
| 362 } | 363 } |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 398 } | 399 } |
| 399 | 400 |
| 400 bool IsAlgorithmRsa(const blink::WebCryptoAlgorithm& algorithm) { | 401 bool IsAlgorithmRsa(const blink::WebCryptoAlgorithm& algorithm) { |
| 401 return algorithm.id() == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 || | 402 return algorithm.id() == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 || |
| 402 algorithm.id() == blink::WebCryptoAlgorithmIdRsaOaep || | 403 algorithm.id() == blink::WebCryptoAlgorithmIdRsaOaep || |
| 403 algorithm.id() == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5; | 404 algorithm.id() == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5; |
| 404 } | 405 } |
| 405 | 406 |
| 406 } // namespace | 407 } // namespace |
| 407 | 408 |
| 408 Status ImportKeyRaw( | 409 Status ImportKeyRaw(const blink::WebCryptoAlgorithm& algorithm, |
| 409 const blink::WebCryptoAlgorithm& algorithm, | 410 const CryptoData& key_data, |
| 410 const CryptoData& key_data, | 411 bool extractable, |
| 411 bool extractable, | 412 blink::WebCryptoKeyUsageMask usage_mask, |
| 412 blink::WebCryptoKeyUsageMask usage_mask, | 413 blink::WebCryptoKey* key) { |
| 413 blink::WebCryptoKey* key) { | |
| 414 | 414 |
| 415 DCHECK(!algorithm.isNull()); | 415 DCHECK(!algorithm.isNull()); |
| 416 | 416 |
| 417 // TODO(bryaneyler): Need to split handling for symmetric and asymmetric keys. | 417 // TODO(bryaneyler): Need to split handling for symmetric and asymmetric keys. |
| 418 // Currently only supporting symmetric. | 418 // Currently only supporting symmetric. |
| 419 CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM; | 419 CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM; |
| 420 // Flags are verified at the Blink layer; here the flags are set to all | 420 // Flags are verified at the Blink layer; here the flags are set to all |
| 421 // possible operations for this key type. | 421 // possible operations for this key type. |
| 422 CK_FLAGS flags = 0; | 422 CK_FLAGS flags = 0; |
| 423 | 423 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 475 return Status::Error(); | 475 return Status::Error(); |
| 476 | 476 |
| 477 *key = blink::WebCryptoKey::create(new SymKey(pk11_sym_key.Pass()), | 477 *key = blink::WebCryptoKey::create(new SymKey(pk11_sym_key.Pass()), |
| 478 blink::WebCryptoKeyTypeSecret, | 478 blink::WebCryptoKeyTypeSecret, |
| 479 extractable, | 479 extractable, |
| 480 algorithm, | 480 algorithm, |
| 481 usage_mask); | 481 usage_mask); |
| 482 return Status::Success(); | 482 return Status::Success(); |
| 483 } | 483 } |
| 484 | 484 |
| 485 Status ExportKeyRaw( | 485 Status ExportKeyRaw(SymKey* key, blink::WebArrayBuffer* buffer) { |
| 486 SymKey* key, | |
| 487 blink::WebArrayBuffer* buffer) { | |
| 488 if (PK11_ExtractKeyValue(key->key()) != SECSuccess) | 486 if (PK11_ExtractKeyValue(key->key()) != SECSuccess) |
| 489 return Status::Error(); | 487 return Status::Error(); |
| 490 | 488 |
| 491 const SECItem* key_data = PK11_GetKeyData(key->key()); | 489 const SECItem* key_data = PK11_GetKeyData(key->key()); |
| 492 if (!key_data) | 490 if (!key_data) |
| 493 return Status::Error(); | 491 return Status::Error(); |
| 494 | 492 |
| 495 *buffer = CreateArrayBuffer(key_data->data, key_data->len); | 493 *buffer = CreateArrayBuffer(key_data->data, key_data->len); |
| 496 | 494 |
| 497 return Status::Success(); | 495 return Status::Success(); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 529 // TODO(padolph): Handle other key types. | 527 // TODO(padolph): Handle other key types. |
| 530 break; | 528 break; |
| 531 default: | 529 default: |
| 532 break; | 530 break; |
| 533 } | 531 } |
| 534 return blink::WebCryptoAlgorithm::createNull(); | 532 return blink::WebCryptoAlgorithm::createNull(); |
| 535 } | 533 } |
| 536 | 534 |
| 537 } // namespace | 535 } // namespace |
| 538 | 536 |
| 539 Status ImportKeySpki( | 537 Status ImportKeySpki(const blink::WebCryptoAlgorithm& algorithm_or_null, |
| 540 const blink::WebCryptoAlgorithm& algorithm_or_null, | 538 const CryptoData& key_data, |
| 541 const CryptoData& key_data, | 539 bool extractable, |
| 542 bool extractable, | 540 blink::WebCryptoKeyUsageMask usage_mask, |
| 543 blink::WebCryptoKeyUsageMask usage_mask, | 541 blink::WebCryptoKey* key) { |
| 544 blink::WebCryptoKey* key) { | |
| 545 | 542 |
| 546 DCHECK(key); | 543 DCHECK(key); |
| 547 | 544 |
| 548 if (!key_data.byte_length()) | 545 if (!key_data.byte_length()) |
| 549 return Status::ErrorImportEmptyKeyData(); | 546 return Status::ErrorImportEmptyKeyData(); |
| 550 DCHECK(key_data.bytes()); | 547 DCHECK(key_data.bytes()); |
| 551 | 548 |
| 552 // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 Subject | 549 // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 Subject |
| 553 // Public Key Info. Decode this to a CERTSubjectPublicKeyInfo. | 550 // Public Key Info. Decode this to a CERTSubjectPublicKeyInfo. |
| 554 SECItem spki_item = MakeSECItemForBuffer(key_data); | 551 SECItem spki_item = MakeSECItemForBuffer(key_data); |
| 555 const ScopedCERTSubjectPublicKeyInfo spki( | 552 const ScopedCERTSubjectPublicKeyInfo spki( |
| 556 SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_item)); | 553 SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_item)); |
| 557 if (!spki) | 554 if (!spki) |
| 558 return Status::Error(); | 555 return Status::Error(); |
| 559 | 556 |
| 560 crypto::ScopedSECKEYPublicKey sec_public_key( | 557 crypto::ScopedSECKEYPublicKey sec_public_key( |
| 561 SECKEY_ExtractPublicKey(spki.get())); | 558 SECKEY_ExtractPublicKey(spki.get())); |
| 562 if (!sec_public_key) | 559 if (!sec_public_key) |
| 563 return Status::Error(); | 560 return Status::Error(); |
| 564 | 561 |
| 565 const KeyType sec_key_type = SECKEY_GetPublicKeyType(sec_public_key.get()); | 562 const KeyType sec_key_type = SECKEY_GetPublicKeyType(sec_public_key.get()); |
| 566 blink::WebCryptoAlgorithm algorithm = | 563 blink::WebCryptoAlgorithm algorithm = |
| 567 ResolveNssKeyTypeWithInputAlgorithm(sec_key_type, algorithm_or_null); | 564 ResolveNssKeyTypeWithInputAlgorithm(sec_key_type, algorithm_or_null); |
| 568 if (algorithm.isNull()) | 565 if (algorithm.isNull()) |
| 569 return Status::Error(); | 566 return Status::Error(); |
| 570 | 567 |
| 571 *key = blink::WebCryptoKey::create( | 568 *key = blink::WebCryptoKey::create(new PublicKey(sec_public_key.Pass()), |
| 572 new PublicKey(sec_public_key.Pass()), | 569 blink::WebCryptoKeyTypePublic, |
| 573 blink::WebCryptoKeyTypePublic, | 570 extractable, |
| 574 extractable, | 571 algorithm, |
| 575 algorithm, | 572 usage_mask); |
| 576 usage_mask); | |
| 577 | 573 |
| 578 return Status::Success(); | 574 return Status::Success(); |
| 579 } | 575 } |
| 580 | 576 |
| 581 Status ExportKeySpki( | 577 Status ExportKeySpki(PublicKey* key, blink::WebArrayBuffer* buffer) { |
| 582 PublicKey* key, | |
| 583 blink::WebArrayBuffer* buffer) { | |
| 584 const crypto::ScopedSECItem spki_der( | 578 const crypto::ScopedSECItem spki_der( |
| 585 SECKEY_EncodeDERSubjectPublicKeyInfo(key->key())); | 579 SECKEY_EncodeDERSubjectPublicKeyInfo(key->key())); |
| 586 if (!spki_der) | 580 if (!spki_der) |
| 587 return Status::Error(); | 581 return Status::Error(); |
| 588 | 582 |
| 589 DCHECK(spki_der->data); | 583 DCHECK(spki_der->data); |
| 590 DCHECK(spki_der->len); | 584 DCHECK(spki_der->len); |
| 591 | 585 |
| 592 *buffer = CreateArrayBuffer(spki_der->data, spki_der->len); | 586 *buffer = CreateArrayBuffer(spki_der->data, spki_der->len); |
| 593 | 587 |
| 594 return Status::Success(); | 588 return Status::Success(); |
| 595 } | 589 } |
| 596 | 590 |
| 597 Status ImportKeyPkcs8( | 591 Status ImportKeyPkcs8(const blink::WebCryptoAlgorithm& algorithm_or_null, |
| 598 const blink::WebCryptoAlgorithm& algorithm_or_null, | 592 const CryptoData& key_data, |
| 599 const CryptoData& key_data, | 593 bool extractable, |
| 600 bool extractable, | 594 blink::WebCryptoKeyUsageMask usage_mask, |
| 601 blink::WebCryptoKeyUsageMask usage_mask, | 595 blink::WebCryptoKey* key) { |
| 602 blink::WebCryptoKey* key) { | |
| 603 | 596 |
| 604 DCHECK(key); | 597 DCHECK(key); |
| 605 | 598 |
| 606 if (!key_data.byte_length()) | 599 if (!key_data.byte_length()) |
| 607 return Status::ErrorImportEmptyKeyData(); | 600 return Status::ErrorImportEmptyKeyData(); |
| 608 DCHECK(key_data.bytes()); | 601 DCHECK(key_data.bytes()); |
| 609 | 602 |
| 610 // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 PKCS#8 | 603 // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 PKCS#8 |
| 611 // private key info object. | 604 // private key info object. |
| 612 SECItem pki_der = MakeSECItemForBuffer(key_data); | 605 SECItem pki_der = MakeSECItemForBuffer(key_data); |
| 613 | 606 |
| 614 SECKEYPrivateKey* seckey_private_key = NULL; | 607 SECKEYPrivateKey* seckey_private_key = NULL; |
| 615 crypto::ScopedPK11Slot slot(PK11_GetInternalSlot()); | 608 crypto::ScopedPK11Slot slot(PK11_GetInternalSlot()); |
| 616 if (PK11_ImportDERPrivateKeyInfoAndReturnKey( | 609 if (PK11_ImportDERPrivateKeyInfoAndReturnKey(slot.get(), |
| 617 slot.get(), | 610 &pki_der, |
| 618 &pki_der, | 611 NULL, // nickname |
| 619 NULL, // nickname | 612 NULL, // publicValue |
| 620 NULL, // publicValue | 613 false, // isPerm |
| 621 false, // isPerm | 614 false, // isPrivate |
| 622 false, // isPrivate | 615 KU_ALL, // usage |
| 623 KU_ALL, // usage | 616 &seckey_private_key, |
| 624 &seckey_private_key, | 617 NULL) != SECSuccess) { |
| 625 NULL) != SECSuccess) { | |
| 626 return Status::Error(); | 618 return Status::Error(); |
| 627 } | 619 } |
| 628 DCHECK(seckey_private_key); | 620 DCHECK(seckey_private_key); |
| 629 crypto::ScopedSECKEYPrivateKey private_key(seckey_private_key); | 621 crypto::ScopedSECKEYPrivateKey private_key(seckey_private_key); |
| 630 | 622 |
| 631 const KeyType sec_key_type = SECKEY_GetPrivateKeyType(private_key.get()); | 623 const KeyType sec_key_type = SECKEY_GetPrivateKeyType(private_key.get()); |
| 632 blink::WebCryptoAlgorithm algorithm = | 624 blink::WebCryptoAlgorithm algorithm = |
| 633 ResolveNssKeyTypeWithInputAlgorithm(sec_key_type, algorithm_or_null); | 625 ResolveNssKeyTypeWithInputAlgorithm(sec_key_type, algorithm_or_null); |
| 634 if (algorithm.isNull()) | 626 if (algorithm.isNull()) |
| 635 return Status::Error(); | 627 return Status::Error(); |
| 636 | 628 |
| 637 *key = blink::WebCryptoKey::create( | 629 *key = blink::WebCryptoKey::create(new PrivateKey(private_key.Pass()), |
| 638 new PrivateKey(private_key.Pass()), | 630 blink::WebCryptoKeyTypePrivate, |
| 639 blink::WebCryptoKeyTypePrivate, | 631 extractable, |
| 640 extractable, | 632 algorithm, |
| 641 algorithm, | 633 usage_mask); |
| 642 usage_mask); | |
| 643 | 634 |
| 644 return Status::Success(); | 635 return Status::Success(); |
| 645 } | 636 } |
| 646 | 637 |
| 647 // ----------------------------------- | 638 // ----------------------------------- |
| 648 // Hmac | 639 // Hmac |
| 649 // ----------------------------------- | 640 // ----------------------------------- |
| 650 | 641 |
| 651 Status SignHmac( | 642 Status SignHmac(SymKey* key, |
| 652 SymKey* key, | 643 const blink::WebCryptoAlgorithm& hash, |
| 653 const blink::WebCryptoAlgorithm& hash, | 644 const CryptoData& data, |
| 654 const CryptoData& data, | 645 blink::WebArrayBuffer* buffer) { |
| 655 blink::WebArrayBuffer* buffer) { | |
| 656 DCHECK_EQ(PK11_GetMechanism(key->key()), WebCryptoHashToHMACMechanism(hash)); | 646 DCHECK_EQ(PK11_GetMechanism(key->key()), WebCryptoHashToHMACMechanism(hash)); |
| 657 | 647 |
| 658 SECItem param_item = { siBuffer, NULL, 0 }; | 648 SECItem param_item = {siBuffer, NULL, 0}; |
| 659 SECItem data_item = MakeSECItemForBuffer(data); | 649 SECItem data_item = MakeSECItemForBuffer(data); |
| 660 // First call is to figure out the length. | 650 // First call is to figure out the length. |
| 661 SECItem signature_item = { siBuffer, NULL, 0 }; | 651 SECItem signature_item = {siBuffer, NULL, 0}; |
| 662 | 652 |
| 663 if (PK11_SignWithSymKey(key->key(), | 653 if (PK11_SignWithSymKey(key->key(), |
| 664 PK11_GetMechanism(key->key()), | 654 PK11_GetMechanism(key->key()), |
| 665 ¶m_item, | 655 ¶m_item, |
| 666 &signature_item, | 656 &signature_item, |
| 667 &data_item) != SECSuccess) { | 657 &data_item) != SECSuccess) { |
| 668 return Status::Error(); | 658 return Status::Error(); |
| 669 } | 659 } |
| 670 | 660 |
| 671 DCHECK_NE(0u, signature_item.len); | 661 DCHECK_NE(0u, signature_item.len); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 682 } | 672 } |
| 683 | 673 |
| 684 DCHECK_EQ(buffer->byteLength(), signature_item.len); | 674 DCHECK_EQ(buffer->byteLength(), signature_item.len); |
| 685 return Status::Success(); | 675 return Status::Success(); |
| 686 } | 676 } |
| 687 | 677 |
| 688 // ----------------------------------- | 678 // ----------------------------------- |
| 689 // RsaEsPkcs1v1_5 | 679 // RsaEsPkcs1v1_5 |
| 690 // ----------------------------------- | 680 // ----------------------------------- |
| 691 | 681 |
| 692 Status EncryptRsaEsPkcs1v1_5( | 682 Status EncryptRsaEsPkcs1v1_5(PublicKey* key, |
| 693 PublicKey* key, | 683 const CryptoData& data, |
| 694 const CryptoData& data, | 684 blink::WebArrayBuffer* buffer) { |
| 695 blink::WebArrayBuffer* buffer) { | |
| 696 const unsigned int encrypted_length_bytes = | 685 const unsigned int encrypted_length_bytes = |
| 697 SECKEY_PublicKeyStrength(key->key()); | 686 SECKEY_PublicKeyStrength(key->key()); |
| 698 | 687 |
| 699 // RSAES can operate on messages up to a length of k - 11, where k is the | 688 // RSAES can operate on messages up to a length of k - 11, where k is the |
| 700 // octet length of the RSA modulus. | 689 // octet length of the RSA modulus. |
| 701 if (encrypted_length_bytes < 11 || | 690 if (encrypted_length_bytes < 11 || |
| 702 encrypted_length_bytes - 11 < data.byte_length()) | 691 encrypted_length_bytes - 11 < data.byte_length()) |
| 703 return Status::ErrorDataTooLarge(); | 692 return Status::ErrorDataTooLarge(); |
| 704 | 693 |
| 705 *buffer = blink::WebArrayBuffer::create(encrypted_length_bytes, 1); | 694 *buffer = blink::WebArrayBuffer::create(encrypted_length_bytes, 1); |
| 706 unsigned char* const buffer_data = | 695 unsigned char* const buffer_data = |
| 707 reinterpret_cast<unsigned char*>(buffer->data()); | 696 reinterpret_cast<unsigned char*>(buffer->data()); |
| 708 | 697 |
| 709 if (PK11_PubEncryptPKCS1(key->key(), | 698 if (PK11_PubEncryptPKCS1(key->key(), |
| 710 buffer_data, | 699 buffer_data, |
| 711 const_cast<unsigned char*>(data.bytes()), | 700 const_cast<unsigned char*>(data.bytes()), |
| 712 data.byte_length(), | 701 data.byte_length(), |
| 713 NULL) != SECSuccess) { | 702 NULL) != SECSuccess) { |
| 714 return Status::Error(); | 703 return Status::Error(); |
| 715 } | 704 } |
| 716 return Status::Success(); | 705 return Status::Success(); |
| 717 } | 706 } |
| 718 | 707 |
| 719 Status DecryptRsaEsPkcs1v1_5( | 708 Status DecryptRsaEsPkcs1v1_5(PrivateKey* key, |
| 720 PrivateKey* key, | 709 const CryptoData& data, |
| 721 const CryptoData& data, | 710 blink::WebArrayBuffer* buffer) { |
| 722 blink::WebArrayBuffer* buffer) { | |
| 723 const int modulus_length_bytes = PK11_GetPrivateModulusLen(key->key()); | 711 const int modulus_length_bytes = PK11_GetPrivateModulusLen(key->key()); |
| 724 if (modulus_length_bytes <= 0) | 712 if (modulus_length_bytes <= 0) |
| 725 return Status::ErrorUnexpected(); | 713 return Status::ErrorUnexpected(); |
| 726 const unsigned int max_output_length_bytes = modulus_length_bytes; | 714 const unsigned int max_output_length_bytes = modulus_length_bytes; |
| 727 | 715 |
| 728 *buffer = blink::WebArrayBuffer::create(max_output_length_bytes, 1); | 716 *buffer = blink::WebArrayBuffer::create(max_output_length_bytes, 1); |
| 729 unsigned char* const buffer_data = | 717 unsigned char* const buffer_data = |
| 730 reinterpret_cast<unsigned char*>(buffer->data()); | 718 reinterpret_cast<unsigned char*>(buffer->data()); |
| 731 | 719 |
| 732 unsigned int output_length_bytes = 0; | 720 unsigned int output_length_bytes = 0; |
| 733 if (PK11_PrivDecryptPKCS1(key->key(), | 721 if (PK11_PrivDecryptPKCS1(key->key(), |
| 734 buffer_data, | 722 buffer_data, |
| 735 &output_length_bytes, | 723 &output_length_bytes, |
| 736 max_output_length_bytes, | 724 max_output_length_bytes, |
| 737 const_cast<unsigned char*>(data.bytes()), | 725 const_cast<unsigned char*>(data.bytes()), |
| 738 data.byte_length()) != SECSuccess) { | 726 data.byte_length()) != SECSuccess) { |
| 739 return Status::Error(); | 727 return Status::Error(); |
| 740 } | 728 } |
| 741 DCHECK_LE(output_length_bytes, max_output_length_bytes); | 729 DCHECK_LE(output_length_bytes, max_output_length_bytes); |
| 742 ShrinkBuffer(buffer, output_length_bytes); | 730 ShrinkBuffer(buffer, output_length_bytes); |
| 743 return Status::Success(); | 731 return Status::Success(); |
| 744 } | 732 } |
| 745 | 733 |
| 746 // ----------------------------------- | 734 // ----------------------------------- |
| 747 // RsaSsaPkcs1v1_5 | 735 // RsaSsaPkcs1v1_5 |
| 748 // ----------------------------------- | 736 // ----------------------------------- |
| 749 | 737 |
| 750 Status SignRsaSsaPkcs1v1_5( | 738 Status SignRsaSsaPkcs1v1_5(PrivateKey* key, |
| 751 PrivateKey* key, | 739 const blink::WebCryptoAlgorithm& hash, |
| 752 const blink::WebCryptoAlgorithm& hash, | 740 const CryptoData& data, |
| 753 const CryptoData& data, | 741 blink::WebArrayBuffer* buffer) { |
| 754 blink::WebArrayBuffer* buffer) { | |
| 755 // Pick the NSS signing algorithm by combining RSA-SSA (RSA PKCS1) and the | 742 // Pick the NSS signing algorithm by combining RSA-SSA (RSA PKCS1) and the |
| 756 // inner hash of the input Web Crypto algorithm. | 743 // inner hash of the input Web Crypto algorithm. |
| 757 SECOidTag sign_alg_tag; | 744 SECOidTag sign_alg_tag; |
| 758 switch (hash.id()) { | 745 switch (hash.id()) { |
| 759 case blink::WebCryptoAlgorithmIdSha1: | 746 case blink::WebCryptoAlgorithmIdSha1: |
| 760 sign_alg_tag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; | 747 sign_alg_tag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; |
| 761 break; | 748 break; |
| 762 case blink::WebCryptoAlgorithmIdSha224: | 749 case blink::WebCryptoAlgorithmIdSha224: |
| 763 sign_alg_tag = SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION; | 750 sign_alg_tag = SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION; |
| 764 break; | 751 break; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 781 data.byte_length(), | 768 data.byte_length(), |
| 782 key->key(), | 769 key->key(), |
| 783 sign_alg_tag) != SECSuccess) { | 770 sign_alg_tag) != SECSuccess) { |
| 784 return Status::Error(); | 771 return Status::Error(); |
| 785 } | 772 } |
| 786 | 773 |
| 787 *buffer = CreateArrayBuffer(signature_item->data, signature_item->len); | 774 *buffer = CreateArrayBuffer(signature_item->data, signature_item->len); |
| 788 return Status::Success(); | 775 return Status::Success(); |
| 789 } | 776 } |
| 790 | 777 |
| 791 Status VerifyRsaSsaPkcs1v1_5( | 778 Status VerifyRsaSsaPkcs1v1_5(PublicKey* key, |
| 792 PublicKey* key, | 779 const blink::WebCryptoAlgorithm& hash, |
| 793 const blink::WebCryptoAlgorithm& hash, | 780 const CryptoData& signature, |
| 794 const CryptoData& signature, | 781 const CryptoData& data, |
| 795 const CryptoData& data, | 782 bool* signature_match) { |
| 796 bool* signature_match) { | |
| 797 const SECItem signature_item = MakeSECItemForBuffer(signature); | 783 const SECItem signature_item = MakeSECItemForBuffer(signature); |
| 798 | 784 |
| 799 SECOidTag hash_alg_tag; | 785 SECOidTag hash_alg_tag; |
| 800 switch (hash.id()) { | 786 switch (hash.id()) { |
| 801 case blink::WebCryptoAlgorithmIdSha1: | 787 case blink::WebCryptoAlgorithmIdSha1: |
| 802 hash_alg_tag = SEC_OID_SHA1; | 788 hash_alg_tag = SEC_OID_SHA1; |
| 803 break; | 789 break; |
| 804 case blink::WebCryptoAlgorithmIdSha224: | 790 case blink::WebCryptoAlgorithmIdSha224: |
| 805 hash_alg_tag = SEC_OID_SHA224; | 791 hash_alg_tag = SEC_OID_SHA224; |
| 806 break; | 792 break; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 847 blink::WebArrayBuffer* buffer) { | 833 blink::WebArrayBuffer* buffer) { |
| 848 // TODO(eroman): Inline. | 834 // TODO(eroman): Inline. |
| 849 return AesGcmEncryptDecrypt( | 835 return AesGcmEncryptDecrypt( |
| 850 mode, key, data, iv, additional_data, tag_length_bits, buffer); | 836 mode, key, data, iv, additional_data, tag_length_bits, buffer); |
| 851 } | 837 } |
| 852 | 838 |
| 853 // ----------------------------------- | 839 // ----------------------------------- |
| 854 // Key generation | 840 // Key generation |
| 855 // ----------------------------------- | 841 // ----------------------------------- |
| 856 | 842 |
| 857 Status GenerateRsaKeyPair( | 843 Status GenerateRsaKeyPair(const blink::WebCryptoAlgorithm& algorithm, |
| 858 const blink::WebCryptoAlgorithm& algorithm, | 844 bool extractable, |
| 859 bool extractable, | 845 blink::WebCryptoKeyUsageMask usage_mask, |
| 860 blink::WebCryptoKeyUsageMask usage_mask, | 846 blink::WebCryptoKey* public_key, |
| 861 blink::WebCryptoKey* public_key, | 847 blink::WebCryptoKey* private_key) { |
| 862 blink::WebCryptoKey* private_key) { | |
| 863 const blink::WebCryptoRsaKeyGenParams* const params = | 848 const blink::WebCryptoRsaKeyGenParams* const params = |
| 864 algorithm.rsaKeyGenParams(); | 849 algorithm.rsaKeyGenParams(); |
| 865 DCHECK(params); | 850 DCHECK(params); |
| 866 | 851 |
| 867 crypto::ScopedPK11Slot slot(PK11_GetInternalKeySlot()); | 852 crypto::ScopedPK11Slot slot(PK11_GetInternalKeySlot()); |
| 868 if (!slot) | 853 if (!slot) |
| 869 return Status::Error(); | 854 return Status::Error(); |
| 870 | 855 |
| 871 unsigned long public_exponent; | 856 unsigned long public_exponent; |
| 872 if (!params->modulusLengthBits()) | 857 if (!params->modulusLengthBits()) |
| 873 return Status::ErrorGenerateRsaZeroModulus(); | 858 return Status::ErrorGenerateRsaZeroModulus(); |
| 874 | 859 |
| 875 if (!BigIntegerToLong(params->publicExponent().data(), | 860 if (!BigIntegerToLong(params->publicExponent().data(), |
| 876 params->publicExponent().size(), | 861 params->publicExponent().size(), |
| 877 &public_exponent) || !public_exponent) { | 862 &public_exponent) || |
| 863 !public_exponent) { |
| 878 return Status::ErrorGenerateKeyPublicExponent(); | 864 return Status::ErrorGenerateKeyPublicExponent(); |
| 879 } | 865 } |
| 880 | 866 |
| 881 PK11RSAGenParams rsa_gen_params; | 867 PK11RSAGenParams rsa_gen_params; |
| 882 rsa_gen_params.keySizeInBits = params->modulusLengthBits(); | 868 rsa_gen_params.keySizeInBits = params->modulusLengthBits(); |
| 883 rsa_gen_params.pe = public_exponent; | 869 rsa_gen_params.pe = public_exponent; |
| 884 | 870 |
| 885 // Flags are verified at the Blink layer; here the flags are set to all | 871 // Flags are verified at the Blink layer; here the flags are set to all |
| 886 // possible operations for the given key type. | 872 // possible operations for the given key type. |
| 887 CK_FLAGS operation_flags; | 873 CK_FLAGS operation_flags; |
| 888 switch (algorithm.id()) { | 874 switch (algorithm.id()) { |
| 889 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: | 875 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: |
| 890 case blink::WebCryptoAlgorithmIdRsaOaep: | 876 case blink::WebCryptoAlgorithmIdRsaOaep: |
| 891 operation_flags = CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP; | 877 operation_flags = CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP; |
| 892 break; | 878 break; |
| 893 case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: | 879 case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: |
| 894 operation_flags = CKF_SIGN | CKF_VERIFY; | 880 operation_flags = CKF_SIGN | CKF_VERIFY; |
| 895 break; | 881 break; |
| 896 default: | 882 default: |
| 897 NOTREACHED(); | 883 NOTREACHED(); |
| 898 return Status::ErrorUnexpected(); | 884 return Status::ErrorUnexpected(); |
| 899 } | 885 } |
| 900 const CK_FLAGS operation_flags_mask = CKF_ENCRYPT | CKF_DECRYPT | | 886 const CK_FLAGS operation_flags_mask = |
| 901 CKF_SIGN | CKF_VERIFY | CKF_WRAP | | 887 CKF_ENCRYPT | CKF_DECRYPT | CKF_SIGN | CKF_VERIFY | CKF_WRAP | CKF_UNWRAP; |
| 902 CKF_UNWRAP; | |
| 903 const PK11AttrFlags attribute_flags = 0; // Default all PK11_ATTR_ flags. | 888 const PK11AttrFlags attribute_flags = 0; // Default all PK11_ATTR_ flags. |
| 904 | 889 |
| 905 // Note: NSS does not generate an sec_public_key if the call below fails, | 890 // Note: NSS does not generate an sec_public_key if the call below fails, |
| 906 // so there is no danger of a leaked sec_public_key. | 891 // so there is no danger of a leaked sec_public_key. |
| 907 SECKEYPublicKey* sec_public_key; | 892 SECKEYPublicKey* sec_public_key; |
| 908 crypto::ScopedSECKEYPrivateKey scoped_sec_private_key( | 893 crypto::ScopedSECKEYPrivateKey scoped_sec_private_key( |
| 909 PK11_GenerateKeyPairWithOpFlags(slot.get(), | 894 PK11_GenerateKeyPairWithOpFlags(slot.get(), |
| 910 CKM_RSA_PKCS_KEY_PAIR_GEN, | 895 CKM_RSA_PKCS_KEY_PAIR_GEN, |
| 911 &rsa_gen_params, | 896 &rsa_gen_params, |
| 912 &sec_public_key, | 897 &sec_public_key, |
| 913 attribute_flags, | 898 attribute_flags, |
| 914 operation_flags, | 899 operation_flags, |
| 915 operation_flags_mask, | 900 operation_flags_mask, |
| 916 NULL)); | 901 NULL)); |
| 917 if (!private_key) | 902 if (!private_key) |
| 918 return Status::Error(); | 903 return Status::Error(); |
| 919 | 904 |
| 920 *public_key = blink::WebCryptoKey::create( | 905 *public_key = blink::WebCryptoKey::create( |
| 921 new PublicKey(crypto::ScopedSECKEYPublicKey(sec_public_key)), | 906 new PublicKey(crypto::ScopedSECKEYPublicKey(sec_public_key)), |
| 922 blink::WebCryptoKeyTypePublic, | 907 blink::WebCryptoKeyTypePublic, |
| 923 true, | 908 true, |
| 924 algorithm, | 909 algorithm, |
| 925 usage_mask); | 910 usage_mask); |
| 926 *private_key = blink::WebCryptoKey::create( | 911 *private_key = |
| 927 new PrivateKey(scoped_sec_private_key.Pass()), | 912 blink::WebCryptoKey::create(new PrivateKey(scoped_sec_private_key.Pass()), |
| 928 blink::WebCryptoKeyTypePrivate, | 913 blink::WebCryptoKeyTypePrivate, |
| 929 extractable, | 914 extractable, |
| 930 algorithm, | 915 algorithm, |
| 931 usage_mask); | 916 usage_mask); |
| 932 | 917 |
| 933 return Status::Success(); | 918 return Status::Success(); |
| 934 } | 919 } |
| 935 | 920 |
| 936 void Init() { | 921 void Init() { crypto::EnsureNSSInit(); } |
| 937 crypto::EnsureNSSInit(); | |
| 938 } | |
| 939 | 922 |
| 940 Status DigestSha( | 923 Status DigestSha(blink::WebCryptoAlgorithmId algorithm, |
| 941 blink::WebCryptoAlgorithmId algorithm, | 924 const CryptoData& data, |
| 942 const CryptoData& data, | 925 blink::WebArrayBuffer* buffer) { |
| 943 blink::WebArrayBuffer* buffer) { | |
| 944 HASH_HashType hash_type = WebCryptoAlgorithmToNSSHashType(algorithm); | 926 HASH_HashType hash_type = WebCryptoAlgorithmToNSSHashType(algorithm); |
| 945 if (hash_type == HASH_AlgNULL) | 927 if (hash_type == HASH_AlgNULL) |
| 946 return Status::ErrorUnsupported(); | 928 return Status::ErrorUnsupported(); |
| 947 | 929 |
| 948 HASHContext* context = HASH_Create(hash_type); | 930 HASHContext* context = HASH_Create(hash_type); |
| 949 if (!context) | 931 if (!context) |
| 950 return Status::Error(); | 932 return Status::Error(); |
| 951 | 933 |
| 952 HASH_Begin(context); | 934 HASH_Begin(context); |
| 953 | 935 |
| 954 HASH_Update(context, data.bytes(), data.byte_length()); | 936 HASH_Update(context, data.bytes(), data.byte_length()); |
| 955 | 937 |
| 956 unsigned int hash_result_length = HASH_ResultLenContext(context); | 938 unsigned int hash_result_length = HASH_ResultLenContext(context); |
| 957 DCHECK_LE(hash_result_length, static_cast<size_t>(HASH_LENGTH_MAX)); | 939 DCHECK_LE(hash_result_length, static_cast<size_t>(HASH_LENGTH_MAX)); |
| 958 | 940 |
| 959 *buffer = blink::WebArrayBuffer::create(hash_result_length, 1); | 941 *buffer = blink::WebArrayBuffer::create(hash_result_length, 1); |
| 960 | 942 |
| 961 unsigned char* digest = reinterpret_cast<unsigned char*>(buffer->data()); | 943 unsigned char* digest = reinterpret_cast<unsigned char*>(buffer->data()); |
| 962 | 944 |
| 963 unsigned int result_length = 0; | 945 unsigned int result_length = 0; |
| 964 HASH_End(context, digest, &result_length, hash_result_length); | 946 HASH_End(context, digest, &result_length, hash_result_length); |
| 965 | 947 |
| 966 HASH_Destroy(context); | 948 HASH_Destroy(context); |
| 967 | 949 |
| 968 if (result_length != hash_result_length) | 950 if (result_length != hash_result_length) |
| 969 return Status::ErrorUnexpected(); | 951 return Status::ErrorUnexpected(); |
| 970 return Status::Success(); | 952 return Status::Success(); |
| 971 } | 953 } |
| 972 | 954 |
| 973 Status GenerateSecretKey( | 955 Status GenerateSecretKey(const blink::WebCryptoAlgorithm& algorithm, |
| 974 const blink::WebCryptoAlgorithm& algorithm, | 956 bool extractable, |
| 975 bool extractable, | 957 blink::WebCryptoKeyUsageMask usage_mask, |
| 976 blink::WebCryptoKeyUsageMask usage_mask, | 958 unsigned keylen_bytes, |
| 977 unsigned keylen_bytes, | 959 blink::WebCryptoKey* key) { |
| 978 blink::WebCryptoKey* key) { | |
| 979 CK_MECHANISM_TYPE mech = WebCryptoAlgorithmToGenMechanism(algorithm); | 960 CK_MECHANISM_TYPE mech = WebCryptoAlgorithmToGenMechanism(algorithm); |
| 980 blink::WebCryptoKeyType key_type = blink::WebCryptoKeyTypeSecret; | 961 blink::WebCryptoKeyType key_type = blink::WebCryptoKeyTypeSecret; |
| 981 | 962 |
| 982 if (mech == CKM_INVALID_MECHANISM) | 963 if (mech == CKM_INVALID_MECHANISM) |
| 983 return Status::ErrorUnsupported(); | 964 return Status::ErrorUnsupported(); |
| 984 | 965 |
| 985 crypto::ScopedPK11Slot slot(PK11_GetInternalKeySlot()); | 966 crypto::ScopedPK11Slot slot(PK11_GetInternalKeySlot()); |
| 986 if (!slot) | 967 if (!slot) |
| 987 return Status::Error(); | 968 return Status::Error(); |
| 988 | 969 |
| 989 crypto::ScopedPK11SymKey pk11_key( | 970 crypto::ScopedPK11SymKey pk11_key( |
| 990 PK11_KeyGen(slot.get(), mech, NULL, keylen_bytes, NULL)); | 971 PK11_KeyGen(slot.get(), mech, NULL, keylen_bytes, NULL)); |
| 991 | 972 |
| 992 if (!pk11_key) | 973 if (!pk11_key) |
| 993 return Status::Error(); | 974 return Status::Error(); |
| 994 | 975 |
| 995 *key = blink::WebCryptoKey::create(new SymKey(pk11_key.Pass()), | 976 *key = blink::WebCryptoKey::create(new SymKey(pk11_key.Pass()), |
| 996 key_type, | 977 key_type, |
| 997 extractable, | 978 extractable, |
| 998 algorithm, | 979 algorithm, |
| 999 usage_mask); | 980 usage_mask); |
| 1000 return Status::Success(); | 981 return Status::Success(); |
| 1001 } | 982 } |
| 1002 | 983 |
| 1003 Status ImportRsaPublicKey( | 984 Status ImportRsaPublicKey(const blink::WebCryptoAlgorithm& algorithm, |
| 1004 const blink::WebCryptoAlgorithm& algorithm, | 985 bool extractable, |
| 1005 bool extractable, | 986 blink::WebCryptoKeyUsageMask usage_mask, |
| 1006 blink::WebCryptoKeyUsageMask usage_mask, | 987 const CryptoData& modulus_data, |
| 1007 const CryptoData& modulus_data, | 988 const CryptoData& exponent_data, |
| 1008 const CryptoData& exponent_data, | 989 blink::WebCryptoKey* key) { |
| 1009 blink::WebCryptoKey* key) { | |
| 1010 | 990 |
| 1011 if (!modulus_data.byte_length()) | 991 if (!modulus_data.byte_length()) |
| 1012 return Status::ErrorImportRsaEmptyModulus(); | 992 return Status::ErrorImportRsaEmptyModulus(); |
| 1013 | 993 |
| 1014 if (!exponent_data.byte_length()) | 994 if (!exponent_data.byte_length()) |
| 1015 return Status::ErrorImportRsaEmptyExponent(); | 995 return Status::ErrorImportRsaEmptyExponent(); |
| 1016 | 996 |
| 1017 DCHECK(modulus_data.bytes()); | 997 DCHECK(modulus_data.bytes()); |
| 1018 DCHECK(exponent_data.bytes()); | 998 DCHECK(exponent_data.bytes()); |
| 1019 | 999 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1058 algorithm, | 1038 algorithm, |
| 1059 usage_mask); | 1039 usage_mask); |
| 1060 return Status::Success(); | 1040 return Status::Success(); |
| 1061 } | 1041 } |
| 1062 | 1042 |
| 1063 } // namespace platform | 1043 } // namespace platform |
| 1064 | 1044 |
| 1065 } // namespace webcrypto | 1045 } // namespace webcrypto |
| 1066 | 1046 |
| 1067 } // namespace content | 1047 } // namespace content |
| OLD | NEW |