| 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> |
| 11 | 11 |
| 12 #include <vector> | 12 #include <vector> |
| 13 | 13 |
| 14 #include "base/lazy_instance.h" | 14 #include "base/lazy_instance.h" |
| 15 #include "base/logging.h" | 15 #include "base/logging.h" |
| 16 #include "base/memory/scoped_ptr.h" | 16 #include "base/memory/scoped_ptr.h" |
| 17 #include "content/child/webcrypto/crypto_data.h" | 17 #include "content/child/webcrypto/crypto_data.h" |
| 18 #include "content/child/webcrypto/status.h" | 18 #include "content/child/webcrypto/status.h" |
| 19 #include "content/child/webcrypto/webcrypto_util.h" | 19 #include "content/child/webcrypto/webcrypto_util.h" |
| 20 #include "crypto/nss_util.h" | 20 #include "crypto/nss_util.h" |
| 21 #include "crypto/scoped_nss_types.h" | 21 #include "crypto/scoped_nss_types.h" |
| 22 #include "third_party/WebKit/public/platform/WebArrayBuffer.h" | |
| 23 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" | 22 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" |
| 24 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" | 23 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" |
| 25 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" | 24 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" |
| 26 | 25 |
| 27 #if defined(USE_NSS) | 26 #if defined(USE_NSS) |
| 28 #include <dlfcn.h> | 27 #include <dlfcn.h> |
| 29 #include <secoid.h> | 28 #include <secoid.h> |
| 30 #endif | 29 #endif |
| 31 | 30 |
| 32 // At the time of this writing: | 31 // At the time of this writing: |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 113 | 112 |
| 114 base::LazyInstance<AesGcmSupport>::Leaky g_aes_gcm_support = | 113 base::LazyInstance<AesGcmSupport>::Leaky g_aes_gcm_support = |
| 115 LAZY_INSTANCE_INITIALIZER; | 114 LAZY_INSTANCE_INITIALIZER; |
| 116 | 115 |
| 117 namespace content { | 116 namespace content { |
| 118 | 117 |
| 119 namespace webcrypto { | 118 namespace webcrypto { |
| 120 | 119 |
| 121 namespace platform { | 120 namespace platform { |
| 122 | 121 |
| 122 // Each key maintains a copy of its serialized form |
| 123 // in either 'raw', 'pkcs8', or 'spki' format. This is to allow |
| 124 // structured cloning of keys synchronously from the target Blink |
| 125 // thread without having to lock access to the key. |
| 126 // |
| 127 // TODO(eroman): Take advantage of this for implementing exportKey(): no need |
| 128 // to call into NSS if the serialized form already exists. |
| 129 // http://crubg.com/366836 |
| 123 class SymKey : public Key { | 130 class SymKey : public Key { |
| 124 public: | 131 public: |
| 125 explicit SymKey(crypto::ScopedPK11SymKey key) : key_(key.Pass()) {} | 132 static Status Create(crypto::ScopedPK11SymKey key, scoped_ptr<SymKey>* out) { |
| 133 out->reset(new SymKey(key.Pass())); |
| 134 return ExportKeyRaw(out->get(), &(*out)->serialized_key_); |
| 135 } |
| 126 | 136 |
| 127 PK11SymKey* key() { return key_.get(); } | 137 PK11SymKey* key() { return key_.get(); } |
| 128 | 138 |
| 129 virtual SymKey* AsSymKey() OVERRIDE { return this; } | 139 virtual SymKey* AsSymKey() OVERRIDE { return this; } |
| 130 virtual PublicKey* AsPublicKey() OVERRIDE { return NULL; } | 140 virtual PublicKey* AsPublicKey() OVERRIDE { return NULL; } |
| 131 virtual PrivateKey* AsPrivateKey() OVERRIDE { return NULL; } | 141 virtual PrivateKey* AsPrivateKey() OVERRIDE { return NULL; } |
| 132 | 142 |
| 143 virtual bool ThreadSafeSerializeForClone( |
| 144 blink::WebVector<uint8>* key_data) OVERRIDE { |
| 145 key_data->assign(Uint8VectorStart(serialized_key_), serialized_key_.size()); |
| 146 return true; |
| 147 } |
| 148 |
| 133 private: | 149 private: |
| 150 explicit SymKey(crypto::ScopedPK11SymKey key) : key_(key.Pass()) {} |
| 151 |
| 134 crypto::ScopedPK11SymKey key_; | 152 crypto::ScopedPK11SymKey key_; |
| 153 std::vector<uint8> serialized_key_; |
| 135 | 154 |
| 136 DISALLOW_COPY_AND_ASSIGN(SymKey); | 155 DISALLOW_COPY_AND_ASSIGN(SymKey); |
| 137 }; | 156 }; |
| 138 | 157 |
| 139 class PublicKey : public Key { | 158 class PublicKey : public Key { |
| 140 public: | 159 public: |
| 141 explicit PublicKey(crypto::ScopedSECKEYPublicKey key) : key_(key.Pass()) {} | 160 static Status Create(crypto::ScopedSECKEYPublicKey key, |
| 161 scoped_ptr<PublicKey>* out) { |
| 162 out->reset(new PublicKey(key.Pass())); |
| 163 return ExportKeySpki(out->get(), &(*out)->serialized_key_); |
| 164 } |
| 142 | 165 |
| 143 SECKEYPublicKey* key() { return key_.get(); } | 166 SECKEYPublicKey* key() { return key_.get(); } |
| 144 | 167 |
| 145 virtual SymKey* AsSymKey() OVERRIDE { return NULL; } | 168 virtual SymKey* AsSymKey() OVERRIDE { return NULL; } |
| 146 virtual PublicKey* AsPublicKey() OVERRIDE { return this; } | 169 virtual PublicKey* AsPublicKey() OVERRIDE { return this; } |
| 147 virtual PrivateKey* AsPrivateKey() OVERRIDE { return NULL; } | 170 virtual PrivateKey* AsPrivateKey() OVERRIDE { return NULL; } |
| 148 | 171 |
| 172 virtual bool ThreadSafeSerializeForClone( |
| 173 blink::WebVector<uint8>* key_data) OVERRIDE { |
| 174 key_data->assign(Uint8VectorStart(serialized_key_), serialized_key_.size()); |
| 175 return true; |
| 176 } |
| 177 |
| 149 private: | 178 private: |
| 179 explicit PublicKey(crypto::ScopedSECKEYPublicKey key) : key_(key.Pass()) {} |
| 180 |
| 150 crypto::ScopedSECKEYPublicKey key_; | 181 crypto::ScopedSECKEYPublicKey key_; |
| 182 std::vector<uint8> serialized_key_; |
| 151 | 183 |
| 152 DISALLOW_COPY_AND_ASSIGN(PublicKey); | 184 DISALLOW_COPY_AND_ASSIGN(PublicKey); |
| 153 }; | 185 }; |
| 154 | 186 |
| 155 class PrivateKey : public Key { | 187 class PrivateKey : public Key { |
| 156 public: | 188 public: |
| 157 explicit PrivateKey(crypto::ScopedSECKEYPrivateKey key) : key_(key.Pass()) {} | 189 static Status Create(crypto::ScopedSECKEYPrivateKey key, |
| 190 const blink::WebCryptoKeyAlgorithm& algorithm, |
| 191 scoped_ptr<PrivateKey>* out) { |
| 192 out->reset(new PrivateKey(key.Pass())); |
| 193 return ExportKeyPkcs8(out->get(), algorithm, &(*out)->serialized_key_); |
| 194 } |
| 158 | 195 |
| 159 SECKEYPrivateKey* key() { return key_.get(); } | 196 SECKEYPrivateKey* key() { return key_.get(); } |
| 160 | 197 |
| 161 virtual SymKey* AsSymKey() OVERRIDE { return NULL; } | 198 virtual SymKey* AsSymKey() OVERRIDE { return NULL; } |
| 162 virtual PublicKey* AsPublicKey() OVERRIDE { return NULL; } | 199 virtual PublicKey* AsPublicKey() OVERRIDE { return NULL; } |
| 163 virtual PrivateKey* AsPrivateKey() OVERRIDE { return this; } | 200 virtual PrivateKey* AsPrivateKey() OVERRIDE { return this; } |
| 164 | 201 |
| 202 virtual bool ThreadSafeSerializeForClone( |
| 203 blink::WebVector<uint8>* key_data) OVERRIDE { |
| 204 key_data->assign(Uint8VectorStart(serialized_key_), serialized_key_.size()); |
| 205 return true; |
| 206 } |
| 207 |
| 165 private: | 208 private: |
| 209 explicit PrivateKey(crypto::ScopedSECKEYPrivateKey key) : key_(key.Pass()) {} |
| 210 |
| 166 crypto::ScopedSECKEYPrivateKey key_; | 211 crypto::ScopedSECKEYPrivateKey key_; |
| 212 std::vector<uint8> serialized_key_; |
| 167 | 213 |
| 168 DISALLOW_COPY_AND_ASSIGN(PrivateKey); | 214 DISALLOW_COPY_AND_ASSIGN(PrivateKey); |
| 169 }; | 215 }; |
| 170 | 216 |
| 171 namespace { | 217 namespace { |
| 172 | 218 |
| 173 // Creates a SECItem for the data in |buffer|. This does NOT make a copy, so | 219 // Creates a SECItem for the data in |buffer|. This does NOT make a copy, so |
| 174 // |buffer| should outlive the SECItem. | 220 // |buffer| should outlive the SECItem. |
| 175 SECItem MakeSECItemForBuffer(const CryptoData& buffer) { | 221 SECItem MakeSECItemForBuffer(const CryptoData& buffer) { |
| 176 SECItem item = { | 222 SECItem item = { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 211 default: | 257 default: |
| 212 // Not a supported algorithm. | 258 // Not a supported algorithm. |
| 213 return CKM_INVALID_MECHANISM; | 259 return CKM_INVALID_MECHANISM; |
| 214 } | 260 } |
| 215 } | 261 } |
| 216 | 262 |
| 217 Status AesCbcEncryptDecrypt(EncryptOrDecrypt mode, | 263 Status AesCbcEncryptDecrypt(EncryptOrDecrypt mode, |
| 218 SymKey* key, | 264 SymKey* key, |
| 219 const CryptoData& iv, | 265 const CryptoData& iv, |
| 220 const CryptoData& data, | 266 const CryptoData& data, |
| 221 blink::WebArrayBuffer* buffer) { | 267 std::vector<uint8>* buffer) { |
| 222 CK_ATTRIBUTE_TYPE operation = (mode == ENCRYPT) ? CKA_ENCRYPT : CKA_DECRYPT; | 268 CK_ATTRIBUTE_TYPE operation = (mode == ENCRYPT) ? CKA_ENCRYPT : CKA_DECRYPT; |
| 223 | 269 |
| 224 SECItem iv_item = MakeSECItemForBuffer(iv); | 270 SECItem iv_item = MakeSECItemForBuffer(iv); |
| 225 | 271 |
| 226 crypto::ScopedSECItem param(PK11_ParamFromIV(CKM_AES_CBC_PAD, &iv_item)); | 272 crypto::ScopedSECItem param(PK11_ParamFromIV(CKM_AES_CBC_PAD, &iv_item)); |
| 227 if (!param) | 273 if (!param) |
| 228 return Status::Error(); | 274 return Status::Error(); |
| 229 | 275 |
| 230 crypto::ScopedPK11Context context(PK11_CreateContextBySymKey( | 276 crypto::ScopedPK11Context context(PK11_CreateContextBySymKey( |
| 231 CKM_AES_CBC_PAD, operation, key->key(), param.get())); | 277 CKM_AES_CBC_PAD, operation, key->key(), param.get())); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 248 if (operation == CKA_DECRYPT && | 294 if (operation == CKA_DECRYPT && |
| 249 (data.byte_length() == 0 || (data.byte_length() % AES_BLOCK_SIZE != 0))) { | 295 (data.byte_length() == 0 || (data.byte_length() % AES_BLOCK_SIZE != 0))) { |
| 250 return Status::Error(); | 296 return Status::Error(); |
| 251 } | 297 } |
| 252 | 298 |
| 253 // TODO(eroman): Refine the output buffer size. It can be computed exactly for | 299 // TODO(eroman): Refine the output buffer size. It can be computed exactly for |
| 254 // encryption, and can be smaller for decryption. | 300 // encryption, and can be smaller for decryption. |
| 255 unsigned int output_max_len = data.byte_length() + AES_BLOCK_SIZE; | 301 unsigned int output_max_len = data.byte_length() + AES_BLOCK_SIZE; |
| 256 CHECK_GT(output_max_len, data.byte_length()); | 302 CHECK_GT(output_max_len, data.byte_length()); |
| 257 | 303 |
| 258 *buffer = blink::WebArrayBuffer::create(output_max_len, 1); | 304 buffer->resize(output_max_len); |
| 259 | 305 |
| 260 unsigned char* buffer_data = reinterpret_cast<unsigned char*>(buffer->data()); | 306 unsigned char* buffer_data = Uint8VectorStart(buffer); |
| 261 | 307 |
| 262 int output_len; | 308 int output_len; |
| 263 if (SECSuccess != PK11_CipherOp(context.get(), | 309 if (SECSuccess != PK11_CipherOp(context.get(), |
| 264 buffer_data, | 310 buffer_data, |
| 265 &output_len, | 311 &output_len, |
| 266 buffer->byteLength(), | 312 buffer->size(), |
| 267 data.bytes(), | 313 data.bytes(), |
| 268 data.byte_length())) { | 314 data.byte_length())) { |
| 269 return Status::Error(); | 315 return Status::Error(); |
| 270 } | 316 } |
| 271 | 317 |
| 272 unsigned int final_output_chunk_len; | 318 unsigned int final_output_chunk_len; |
| 273 if (SECSuccess != PK11_DigestFinal(context.get(), | 319 if (SECSuccess != PK11_DigestFinal(context.get(), |
| 274 buffer_data + output_len, | 320 buffer_data + output_len, |
| 275 &final_output_chunk_len, | 321 &final_output_chunk_len, |
| 276 output_max_len - output_len)) { | 322 output_max_len - output_len)) { |
| 277 return Status::Error(); | 323 return Status::Error(); |
| 278 } | 324 } |
| 279 | 325 |
| 280 ShrinkBuffer(buffer, final_output_chunk_len + output_len); | 326 buffer->resize(final_output_chunk_len + output_len); |
| 281 return Status::Success(); | 327 return Status::Success(); |
| 282 } | 328 } |
| 283 | 329 |
| 284 // Helper to either encrypt or decrypt for AES-GCM. The result of encryption is | 330 // Helper to either encrypt or decrypt for AES-GCM. The result of encryption is |
| 285 // the concatenation of the ciphertext and the authentication tag. Similarly, | 331 // the concatenation of the ciphertext and the authentication tag. Similarly, |
| 286 // this is the expectation for the input to decryption. | 332 // this is the expectation for the input to decryption. |
| 287 Status AesGcmEncryptDecrypt(EncryptOrDecrypt mode, | 333 Status AesGcmEncryptDecrypt(EncryptOrDecrypt mode, |
| 288 SymKey* key, | 334 SymKey* key, |
| 289 const CryptoData& data, | 335 const CryptoData& data, |
| 290 const CryptoData& iv, | 336 const CryptoData& iv, |
| 291 const CryptoData& additional_data, | 337 const CryptoData& additional_data, |
| 292 unsigned int tag_length_bits, | 338 unsigned int tag_length_bits, |
| 293 blink::WebArrayBuffer* buffer) { | 339 std::vector<uint8>* buffer) { |
| 294 if (!g_aes_gcm_support.Get().IsSupported()) | 340 if (!g_aes_gcm_support.Get().IsSupported()) |
| 295 return Status::ErrorUnsupported(); | 341 return Status::ErrorUnsupported(); |
| 296 | 342 |
| 297 unsigned int tag_length_bytes = tag_length_bits / 8; | 343 unsigned int tag_length_bytes = tag_length_bits / 8; |
| 298 | 344 |
| 299 CK_GCM_PARAMS gcm_params = {0}; | 345 CK_GCM_PARAMS gcm_params = {0}; |
| 300 gcm_params.pIv = const_cast<unsigned char*>(iv.bytes()); | 346 gcm_params.pIv = const_cast<unsigned char*>(iv.bytes()); |
| 301 gcm_params.ulIvLen = iv.byte_length(); | 347 gcm_params.ulIvLen = iv.byte_length(); |
| 302 | 348 |
| 303 gcm_params.pAAD = const_cast<unsigned char*>(additional_data.bytes()); | 349 gcm_params.pAAD = const_cast<unsigned char*>(additional_data.bytes()); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 326 // not at least as large as the ciphertext: | 372 // not at least as large as the ciphertext: |
| 327 // | 373 // |
| 328 // https://bugzilla.mozilla.org/show_bug.cgi?id=%20853674 | 374 // https://bugzilla.mozilla.org/show_bug.cgi?id=%20853674 |
| 329 // | 375 // |
| 330 // From the analysis of that bug it looks like it might be safe to pass a | 376 // From the analysis of that bug it looks like it might be safe to pass a |
| 331 // correctly sized buffer but lie about its size. Since resizing the | 377 // correctly sized buffer but lie about its size. Since resizing the |
| 332 // WebCryptoArrayBuffer is expensive that hack may be worth looking into. | 378 // WebCryptoArrayBuffer is expensive that hack may be worth looking into. |
| 333 buffer_size = data.byte_length(); | 379 buffer_size = data.byte_length(); |
| 334 } | 380 } |
| 335 | 381 |
| 336 *buffer = blink::WebArrayBuffer::create(buffer_size, 1); | 382 buffer->resize(buffer_size); |
| 337 unsigned char* buffer_data = reinterpret_cast<unsigned char*>(buffer->data()); | 383 unsigned char* buffer_data = Uint8VectorStart(buffer); |
| 338 | 384 |
| 339 PK11_EncryptDecryptFunction func = | 385 PK11_EncryptDecryptFunction func = |
| 340 (mode == ENCRYPT) ? g_aes_gcm_support.Get().pk11_encrypt_func() | 386 (mode == ENCRYPT) ? g_aes_gcm_support.Get().pk11_encrypt_func() |
| 341 : g_aes_gcm_support.Get().pk11_decrypt_func(); | 387 : g_aes_gcm_support.Get().pk11_decrypt_func(); |
| 342 | 388 |
| 343 unsigned int output_len = 0; | 389 unsigned int output_len = 0; |
| 344 SECStatus result = func(key->key(), | 390 SECStatus result = func(key->key(), |
| 345 CKM_AES_GCM, | 391 CKM_AES_GCM, |
| 346 ¶m, | 392 ¶m, |
| 347 buffer_data, | 393 buffer_data, |
| 348 &output_len, | 394 &output_len, |
| 349 buffer->byteLength(), | 395 buffer->size(), |
| 350 data.bytes(), | 396 data.bytes(), |
| 351 data.byte_length()); | 397 data.byte_length()); |
| 352 | 398 |
| 353 if (result != SECSuccess) | 399 if (result != SECSuccess) |
| 354 return Status::Error(); | 400 return Status::Error(); |
| 355 | 401 |
| 356 // Unfortunately the buffer needs to be shrunk for decryption (see the NSS bug | 402 // Unfortunately the buffer needs to be shrunk for decryption (see the NSS bug |
| 357 // above). | 403 // above). |
| 358 ShrinkBuffer(buffer, output_len); | 404 buffer->resize(output_len); |
| 359 | 405 |
| 360 return Status::Success(); | 406 return Status::Success(); |
| 361 } | 407 } |
| 362 | 408 |
| 363 CK_MECHANISM_TYPE WebCryptoAlgorithmToGenMechanism( | 409 CK_MECHANISM_TYPE WebCryptoAlgorithmToGenMechanism( |
| 364 const blink::WebCryptoAlgorithm& algorithm) { | 410 const blink::WebCryptoAlgorithm& algorithm) { |
| 365 switch (algorithm.id()) { | 411 switch (algorithm.id()) { |
| 366 case blink::WebCryptoAlgorithmIdAesCbc: | 412 case blink::WebCryptoAlgorithmIdAesCbc: |
| 367 case blink::WebCryptoAlgorithmIdAesGcm: | 413 case blink::WebCryptoAlgorithmIdAesGcm: |
| 368 case blink::WebCryptoAlgorithmIdAesKw: | 414 case blink::WebCryptoAlgorithmIdAesKw: |
| (...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 696 | 742 |
| 697 virtual bool finish(unsigned char*& result_data, | 743 virtual bool finish(unsigned char*& result_data, |
| 698 unsigned int& result_data_size) { | 744 unsigned int& result_data_size) { |
| 699 Status error = FinishInternal(result_, &result_data_size); | 745 Status error = FinishInternal(result_, &result_data_size); |
| 700 if (!error.IsSuccess()) | 746 if (!error.IsSuccess()) |
| 701 return false; | 747 return false; |
| 702 result_data = result_; | 748 result_data = result_; |
| 703 return true; | 749 return true; |
| 704 } | 750 } |
| 705 | 751 |
| 706 Status FinishWithWebArrayAndStatus(blink::WebArrayBuffer* result) { | 752 Status FinishWithVectorAndStatus(std::vector<uint8>* result) { |
| 707 if (!hash_context_) | 753 if (!hash_context_) |
| 708 return Status::ErrorUnexpected(); | 754 return Status::ErrorUnexpected(); |
| 709 | 755 |
| 710 unsigned int result_length = HASH_ResultLenContext(hash_context_); | 756 unsigned int result_length = HASH_ResultLenContext(hash_context_); |
| 711 *result = blink::WebArrayBuffer::create(result_length, 1); | 757 result->resize(result_length); |
| 712 unsigned char* digest = reinterpret_cast<unsigned char*>(result->data()); | 758 unsigned char* digest = Uint8VectorStart(result); |
| 713 unsigned int digest_size; // ignored | 759 unsigned int digest_size; // ignored |
| 714 return FinishInternal(digest, &digest_size); | 760 return FinishInternal(digest, &digest_size); |
| 715 } | 761 } |
| 716 | 762 |
| 717 private: | 763 private: |
| 718 Status Init() { | 764 Status Init() { |
| 719 HASH_HashType hash_type = WebCryptoAlgorithmToNSSHashType(algorithm_id_); | 765 HASH_HashType hash_type = WebCryptoAlgorithmToNSSHashType(algorithm_id_); |
| 720 | 766 |
| 721 if (hash_type == HASH_AlgNULL) | 767 if (hash_type == HASH_AlgNULL) |
| 722 return Status::ErrorUnsupported(); | 768 return Status::ErrorUnsupported(); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 750 HASHContext* hash_context_; | 796 HASHContext* hash_context_; |
| 751 blink::WebCryptoAlgorithmId algorithm_id_; | 797 blink::WebCryptoAlgorithmId algorithm_id_; |
| 752 unsigned char result_[HASH_LENGTH_MAX]; | 798 unsigned char result_[HASH_LENGTH_MAX]; |
| 753 }; | 799 }; |
| 754 | 800 |
| 755 Status ImportKeyRaw(const blink::WebCryptoAlgorithm& algorithm, | 801 Status ImportKeyRaw(const blink::WebCryptoAlgorithm& algorithm, |
| 756 const CryptoData& key_data, | 802 const CryptoData& key_data, |
| 757 bool extractable, | 803 bool extractable, |
| 758 blink::WebCryptoKeyUsageMask usage_mask, | 804 blink::WebCryptoKeyUsageMask usage_mask, |
| 759 blink::WebCryptoKey* key) { | 805 blink::WebCryptoKey* key) { |
| 760 | |
| 761 DCHECK(!algorithm.isNull()); | 806 DCHECK(!algorithm.isNull()); |
| 762 | 807 |
| 763 CK_MECHANISM_TYPE mechanism; | 808 CK_MECHANISM_TYPE mechanism; |
| 764 CK_FLAGS flags; | 809 CK_FLAGS flags; |
| 765 Status status = | 810 Status status = |
| 766 WebCryptoAlgorithmToNssMechFlags(algorithm, &mechanism, &flags); | 811 WebCryptoAlgorithmToNssMechFlags(algorithm, &mechanism, &flags); |
| 767 if (status.IsError()) | 812 if (status.IsError()) |
| 768 return status; | 813 return status; |
| 769 | 814 |
| 770 SECItem key_item = MakeSECItemForBuffer(key_data); | 815 SECItem key_item = MakeSECItemForBuffer(key_data); |
| 771 | 816 |
| 772 crypto::ScopedPK11Slot slot(PK11_GetInternalSlot()); | 817 crypto::ScopedPK11Slot slot(PK11_GetInternalSlot()); |
| 773 crypto::ScopedPK11SymKey pk11_sym_key( | 818 crypto::ScopedPK11SymKey pk11_sym_key( |
| 774 PK11_ImportSymKeyWithFlags(slot.get(), | 819 PK11_ImportSymKeyWithFlags(slot.get(), |
| 775 mechanism, | 820 mechanism, |
| 776 PK11_OriginUnwrap, | 821 PK11_OriginUnwrap, |
| 777 CKA_FLAGS_ONLY, | 822 CKA_FLAGS_ONLY, |
| 778 &key_item, | 823 &key_item, |
| 779 flags, | 824 flags, |
| 780 false, | 825 false, |
| 781 NULL)); | 826 NULL)); |
| 782 if (!pk11_sym_key.get()) | 827 if (!pk11_sym_key.get()) |
| 783 return Status::Error(); | 828 return Status::Error(); |
| 784 | 829 |
| 785 blink::WebCryptoKeyAlgorithm key_algorithm; | 830 blink::WebCryptoKeyAlgorithm key_algorithm; |
| 786 if (!CreateSecretKeyAlgorithm( | 831 if (!CreateSecretKeyAlgorithm( |
| 787 algorithm, key_data.byte_length(), &key_algorithm)) | 832 algorithm, key_data.byte_length(), &key_algorithm)) |
| 788 return Status::ErrorUnexpected(); | 833 return Status::ErrorUnexpected(); |
| 789 | 834 |
| 790 *key = blink::WebCryptoKey::create(new SymKey(pk11_sym_key.Pass()), | 835 scoped_ptr<SymKey> key_handle; |
| 836 status = SymKey::Create(pk11_sym_key.Pass(), &key_handle); |
| 837 if (status.IsError()) |
| 838 return status; |
| 839 |
| 840 *key = blink::WebCryptoKey::create(key_handle.release(), |
| 791 blink::WebCryptoKeyTypeSecret, | 841 blink::WebCryptoKeyTypeSecret, |
| 792 extractable, | 842 extractable, |
| 793 key_algorithm, | 843 key_algorithm, |
| 794 usage_mask); | 844 usage_mask); |
| 795 return Status::Success(); | 845 return Status::Success(); |
| 796 } | 846 } |
| 797 | 847 |
| 798 Status ExportKeyRaw(SymKey* key, blink::WebArrayBuffer* buffer) { | 848 Status ExportKeyRaw(SymKey* key, std::vector<uint8>* buffer) { |
| 799 if (PK11_ExtractKeyValue(key->key()) != SECSuccess) | 849 if (PK11_ExtractKeyValue(key->key()) != SECSuccess) |
| 800 return Status::Error(); | 850 return Status::Error(); |
| 801 | 851 |
| 802 const SECItem* key_data = PK11_GetKeyData(key->key()); | 852 const SECItem* key_data = PK11_GetKeyData(key->key()); |
| 803 if (!key_data) | 853 if (!key_data) |
| 804 return Status::Error(); | 854 return Status::Error(); |
| 805 | 855 |
| 806 *buffer = CreateArrayBuffer(key_data->data, key_data->len); | 856 buffer->assign(key_data->data, key_data->data + key_data->len); |
| 807 | 857 |
| 808 return Status::Success(); | 858 return Status::Success(); |
| 809 } | 859 } |
| 810 | 860 |
| 811 namespace { | 861 namespace { |
| 812 | 862 |
| 813 typedef scoped_ptr<CERTSubjectPublicKeyInfo, | 863 typedef scoped_ptr<CERTSubjectPublicKeyInfo, |
| 814 crypto::NSSDestroyer<CERTSubjectPublicKeyInfo, | 864 crypto::NSSDestroyer<CERTSubjectPublicKeyInfo, |
| 815 SECKEY_DestroySubjectPublicKeyInfo> > | 865 SECKEY_DestroySubjectPublicKeyInfo> > |
| 816 ScopedCERTSubjectPublicKeyInfo; | 866 ScopedCERTSubjectPublicKeyInfo; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 834 return false; | 884 return false; |
| 835 } | 885 } |
| 836 | 886 |
| 837 } // namespace | 887 } // namespace |
| 838 | 888 |
| 839 Status ImportKeySpki(const blink::WebCryptoAlgorithm& algorithm, | 889 Status ImportKeySpki(const blink::WebCryptoAlgorithm& algorithm, |
| 840 const CryptoData& key_data, | 890 const CryptoData& key_data, |
| 841 bool extractable, | 891 bool extractable, |
| 842 blink::WebCryptoKeyUsageMask usage_mask, | 892 blink::WebCryptoKeyUsageMask usage_mask, |
| 843 blink::WebCryptoKey* key) { | 893 blink::WebCryptoKey* key) { |
| 844 | |
| 845 DCHECK(key); | 894 DCHECK(key); |
| 846 | 895 |
| 847 if (!key_data.byte_length()) | 896 if (!key_data.byte_length()) |
| 848 return Status::ErrorImportEmptyKeyData(); | 897 return Status::ErrorImportEmptyKeyData(); |
| 849 DCHECK(key_data.bytes()); | 898 DCHECK(key_data.bytes()); |
| 850 | 899 |
| 851 // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 Subject | 900 // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 Subject |
| 852 // Public Key Info. Decode this to a CERTSubjectPublicKeyInfo. | 901 // Public Key Info. Decode this to a CERTSubjectPublicKeyInfo. |
| 853 SECItem spki_item = MakeSECItemForBuffer(key_data); | 902 SECItem spki_item = MakeSECItemForBuffer(key_data); |
| 854 const ScopedCERTSubjectPublicKeyInfo spki( | 903 const ScopedCERTSubjectPublicKeyInfo spki( |
| 855 SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_item)); | 904 SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_item)); |
| 856 if (!spki) | 905 if (!spki) |
| 857 return Status::Error(); | 906 return Status::Error(); |
| 858 | 907 |
| 859 crypto::ScopedSECKEYPublicKey sec_public_key( | 908 crypto::ScopedSECKEYPublicKey sec_public_key( |
| 860 SECKEY_ExtractPublicKey(spki.get())); | 909 SECKEY_ExtractPublicKey(spki.get())); |
| 861 if (!sec_public_key) | 910 if (!sec_public_key) |
| 862 return Status::Error(); | 911 return Status::Error(); |
| 863 | 912 |
| 864 const KeyType sec_key_type = SECKEY_GetPublicKeyType(sec_public_key.get()); | 913 const KeyType sec_key_type = SECKEY_GetPublicKeyType(sec_public_key.get()); |
| 865 if (!ValidateNssKeyTypeAgainstInputAlgorithm(sec_key_type, algorithm)) | 914 if (!ValidateNssKeyTypeAgainstInputAlgorithm(sec_key_type, algorithm)) |
| 866 return Status::Error(); | 915 return Status::Error(); |
| 867 | 916 |
| 868 blink::WebCryptoKeyAlgorithm key_algorithm; | 917 blink::WebCryptoKeyAlgorithm key_algorithm; |
| 869 if (!CreatePublicKeyAlgorithm( | 918 if (!CreatePublicKeyAlgorithm( |
| 870 algorithm, sec_public_key.get(), &key_algorithm)) | 919 algorithm, sec_public_key.get(), &key_algorithm)) |
| 871 return Status::ErrorUnexpected(); | 920 return Status::ErrorUnexpected(); |
| 872 | 921 |
| 873 *key = blink::WebCryptoKey::create(new PublicKey(sec_public_key.Pass()), | 922 scoped_ptr<PublicKey> key_handle; |
| 923 Status status = PublicKey::Create(sec_public_key.Pass(), &key_handle); |
| 924 if (status.IsError()) |
| 925 return status; |
| 926 |
| 927 *key = blink::WebCryptoKey::create(key_handle.release(), |
| 874 blink::WebCryptoKeyTypePublic, | 928 blink::WebCryptoKeyTypePublic, |
| 875 extractable, | 929 extractable, |
| 876 key_algorithm, | 930 key_algorithm, |
| 877 usage_mask); | 931 usage_mask); |
| 878 | 932 |
| 879 return Status::Success(); | 933 return Status::Success(); |
| 880 } | 934 } |
| 881 | 935 |
| 882 Status ExportKeySpki(PublicKey* key, blink::WebArrayBuffer* buffer) { | 936 Status ExportKeySpki(PublicKey* key, std::vector<uint8>* buffer) { |
| 883 const crypto::ScopedSECItem spki_der( | 937 const crypto::ScopedSECItem spki_der( |
| 884 SECKEY_EncodeDERSubjectPublicKeyInfo(key->key())); | 938 SECKEY_EncodeDERSubjectPublicKeyInfo(key->key())); |
| 885 if (!spki_der) | 939 if (!spki_der) |
| 886 return Status::Error(); | 940 return Status::Error(); |
| 887 | 941 |
| 888 DCHECK(spki_der->data); | 942 DCHECK(spki_der->data); |
| 889 DCHECK(spki_der->len); | 943 DCHECK(spki_der->len); |
| 890 | 944 |
| 891 *buffer = CreateArrayBuffer(spki_der->data, spki_der->len); | 945 buffer->assign(spki_der->data, spki_der->data + spki_der->len); |
| 892 | 946 |
| 893 return Status::Success(); | 947 return Status::Success(); |
| 894 } | 948 } |
| 895 | 949 |
| 896 Status ExportRsaPublicKey(PublicKey* key, | 950 Status ExportRsaPublicKey(PublicKey* key, |
| 897 std::vector<uint8>* modulus, | 951 std::vector<uint8>* modulus, |
| 898 std::vector<uint8>* public_exponent) { | 952 std::vector<uint8>* public_exponent) { |
| 899 DCHECK(key); | 953 DCHECK(key); |
| 900 DCHECK(key->key()); | 954 DCHECK(key->key()); |
| 901 if (key->key()->keyType != rsaKey) | 955 if (key->key()->keyType != rsaKey) |
| 902 return Status::ErrorUnsupported(); | 956 return Status::ErrorUnsupported(); |
| 903 CopySECItemToVector(key->key()->u.rsa.modulus, modulus); | 957 CopySECItemToVector(key->key()->u.rsa.modulus, modulus); |
| 904 CopySECItemToVector(key->key()->u.rsa.publicExponent, public_exponent); | 958 CopySECItemToVector(key->key()->u.rsa.publicExponent, public_exponent); |
| 905 if (modulus->empty() || public_exponent->empty()) | 959 if (modulus->empty() || public_exponent->empty()) |
| 906 return Status::ErrorUnexpected(); | 960 return Status::ErrorUnexpected(); |
| 907 return Status::Success(); | 961 return Status::Success(); |
| 908 } | 962 } |
| 909 | 963 |
| 910 Status ExportKeyPkcs8(PrivateKey* key, | 964 Status ExportKeyPkcs8(PrivateKey* key, |
| 911 const blink::WebCryptoKeyAlgorithm& key_algorithm, | 965 const blink::WebCryptoKeyAlgorithm& key_algorithm, |
| 912 blink::WebArrayBuffer* buffer) { | 966 std::vector<uint8>* buffer) { |
| 913 // TODO(eroman): Support other RSA key types as they are added to Blink. | 967 // TODO(eroman): Support other RSA key types as they are added to Blink. |
| 914 if (key_algorithm.id() != blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 && | 968 if (key_algorithm.id() != blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 && |
| 915 key_algorithm.id() != blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5) | 969 key_algorithm.id() != blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5) |
| 916 return Status::ErrorUnsupported(); | 970 return Status::ErrorUnsupported(); |
| 917 | 971 |
| 918 #if defined(USE_NSS) | 972 #if defined(USE_NSS) |
| 919 // PK11_ExportDERPrivateKeyInfo isn't available. Use our fallback code. | 973 // PK11_ExportDERPrivateKeyInfo isn't available. Use our fallback code. |
| 920 const SECOidTag algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION; | 974 const SECOidTag algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION; |
| 921 const int kPrivateKeyInfoVersion = 0; | 975 const int kPrivateKeyInfoVersion = 0; |
| 922 | 976 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 945 | 999 |
| 946 if (!SEC_ASN1EncodeInteger( | 1000 if (!SEC_ASN1EncodeInteger( |
| 947 arena.get(), &private_key_info.version, kPrivateKeyInfoVersion)) | 1001 arena.get(), &private_key_info.version, kPrivateKeyInfoVersion)) |
| 948 return Status::Error(); | 1002 return Status::Error(); |
| 949 | 1003 |
| 950 crypto::ScopedSECItem encoded_key( | 1004 crypto::ScopedSECItem encoded_key( |
| 951 SEC_ASN1EncodeItem(NULL, | 1005 SEC_ASN1EncodeItem(NULL, |
| 952 NULL, | 1006 NULL, |
| 953 &private_key_info, | 1007 &private_key_info, |
| 954 SEC_ASN1_GET(SECKEY_PrivateKeyInfoTemplate))); | 1008 SEC_ASN1_GET(SECKEY_PrivateKeyInfoTemplate))); |
| 955 #else // defined(USE_NSS) | 1009 #else // defined(USE_NSS) |
| 956 crypto::ScopedSECItem encoded_key( | 1010 crypto::ScopedSECItem encoded_key( |
| 957 PK11_ExportDERPrivateKeyInfo(key->key(), NULL)); | 1011 PK11_ExportDERPrivateKeyInfo(key->key(), NULL)); |
| 958 #endif // defined(USE_NSS) | 1012 #endif // defined(USE_NSS) |
| 959 | 1013 |
| 960 if (!encoded_key.get()) | 1014 if (!encoded_key.get()) |
| 961 return Status::Error(); | 1015 return Status::Error(); |
| 962 | 1016 |
| 963 *buffer = CreateArrayBuffer(encoded_key->data, encoded_key->len); | 1017 buffer->assign(encoded_key->data, encoded_key->data + encoded_key->len); |
| 964 return Status::Success(); | 1018 return Status::Success(); |
| 965 } | 1019 } |
| 966 | 1020 |
| 967 Status ImportKeyPkcs8(const blink::WebCryptoAlgorithm& algorithm, | 1021 Status ImportKeyPkcs8(const blink::WebCryptoAlgorithm& algorithm, |
| 968 const CryptoData& key_data, | 1022 const CryptoData& key_data, |
| 969 bool extractable, | 1023 bool extractable, |
| 970 blink::WebCryptoKeyUsageMask usage_mask, | 1024 blink::WebCryptoKeyUsageMask usage_mask, |
| 971 blink::WebCryptoKey* key) { | 1025 blink::WebCryptoKey* key) { |
| 972 | |
| 973 DCHECK(key); | 1026 DCHECK(key); |
| 974 | 1027 |
| 975 if (!key_data.byte_length()) | 1028 if (!key_data.byte_length()) |
| 976 return Status::ErrorImportEmptyKeyData(); | 1029 return Status::ErrorImportEmptyKeyData(); |
| 977 DCHECK(key_data.bytes()); | 1030 DCHECK(key_data.bytes()); |
| 978 | 1031 |
| 979 // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 PKCS#8 | 1032 // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 PKCS#8 |
| 980 // private key info object. | 1033 // private key info object. |
| 981 SECItem pki_der = MakeSECItemForBuffer(key_data); | 1034 SECItem pki_der = MakeSECItemForBuffer(key_data); |
| 982 | 1035 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 997 crypto::ScopedSECKEYPrivateKey private_key(seckey_private_key); | 1050 crypto::ScopedSECKEYPrivateKey private_key(seckey_private_key); |
| 998 | 1051 |
| 999 const KeyType sec_key_type = SECKEY_GetPrivateKeyType(private_key.get()); | 1052 const KeyType sec_key_type = SECKEY_GetPrivateKeyType(private_key.get()); |
| 1000 if (!ValidateNssKeyTypeAgainstInputAlgorithm(sec_key_type, algorithm)) | 1053 if (!ValidateNssKeyTypeAgainstInputAlgorithm(sec_key_type, algorithm)) |
| 1001 return Status::Error(); | 1054 return Status::Error(); |
| 1002 | 1055 |
| 1003 blink::WebCryptoKeyAlgorithm key_algorithm; | 1056 blink::WebCryptoKeyAlgorithm key_algorithm; |
| 1004 if (!CreatePrivateKeyAlgorithm(algorithm, private_key.get(), &key_algorithm)) | 1057 if (!CreatePrivateKeyAlgorithm(algorithm, private_key.get(), &key_algorithm)) |
| 1005 return Status::ErrorUnexpected(); | 1058 return Status::ErrorUnexpected(); |
| 1006 | 1059 |
| 1007 *key = blink::WebCryptoKey::create(new PrivateKey(private_key.Pass()), | 1060 scoped_ptr<PrivateKey> key_handle; |
| 1061 Status status = |
| 1062 PrivateKey::Create(private_key.Pass(), key_algorithm, &key_handle); |
| 1063 if (status.IsError()) |
| 1064 return status; |
| 1065 |
| 1066 *key = blink::WebCryptoKey::create(key_handle.release(), |
| 1008 blink::WebCryptoKeyTypePrivate, | 1067 blink::WebCryptoKeyTypePrivate, |
| 1009 extractable, | 1068 extractable, |
| 1010 key_algorithm, | 1069 key_algorithm, |
| 1011 usage_mask); | 1070 usage_mask); |
| 1012 | 1071 |
| 1013 return Status::Success(); | 1072 return Status::Success(); |
| 1014 } | 1073 } |
| 1015 | 1074 |
| 1016 // ----------------------------------- | 1075 // ----------------------------------- |
| 1017 // Hmac | 1076 // Hmac |
| 1018 // ----------------------------------- | 1077 // ----------------------------------- |
| 1019 | 1078 |
| 1020 Status SignHmac(SymKey* key, | 1079 Status SignHmac(SymKey* key, |
| 1021 const blink::WebCryptoAlgorithm& hash, | 1080 const blink::WebCryptoAlgorithm& hash, |
| 1022 const CryptoData& data, | 1081 const CryptoData& data, |
| 1023 blink::WebArrayBuffer* buffer) { | 1082 std::vector<uint8>* buffer) { |
| 1024 DCHECK_EQ(PK11_GetMechanism(key->key()), WebCryptoHashToHMACMechanism(hash)); | 1083 DCHECK_EQ(PK11_GetMechanism(key->key()), WebCryptoHashToHMACMechanism(hash)); |
| 1025 | 1084 |
| 1026 SECItem param_item = {siBuffer, NULL, 0}; | 1085 SECItem param_item = {siBuffer, NULL, 0}; |
| 1027 SECItem data_item = MakeSECItemForBuffer(data); | 1086 SECItem data_item = MakeSECItemForBuffer(data); |
| 1028 // First call is to figure out the length. | 1087 // First call is to figure out the length. |
| 1029 SECItem signature_item = {siBuffer, NULL, 0}; | 1088 SECItem signature_item = {siBuffer, NULL, 0}; |
| 1030 | 1089 |
| 1031 if (PK11_SignWithSymKey(key->key(), | 1090 if (PK11_SignWithSymKey(key->key(), |
| 1032 PK11_GetMechanism(key->key()), | 1091 PK11_GetMechanism(key->key()), |
| 1033 ¶m_item, | 1092 ¶m_item, |
| 1034 &signature_item, | 1093 &signature_item, |
| 1035 &data_item) != SECSuccess) { | 1094 &data_item) != SECSuccess) { |
| 1036 return Status::Error(); | 1095 return Status::Error(); |
| 1037 } | 1096 } |
| 1038 | 1097 |
| 1039 DCHECK_NE(0u, signature_item.len); | 1098 DCHECK_NE(0u, signature_item.len); |
| 1040 | 1099 |
| 1041 *buffer = blink::WebArrayBuffer::create(signature_item.len, 1); | 1100 buffer->resize(signature_item.len); |
| 1042 signature_item.data = reinterpret_cast<unsigned char*>(buffer->data()); | 1101 signature_item.data = Uint8VectorStart(buffer); |
| 1043 | 1102 |
| 1044 if (PK11_SignWithSymKey(key->key(), | 1103 if (PK11_SignWithSymKey(key->key(), |
| 1045 PK11_GetMechanism(key->key()), | 1104 PK11_GetMechanism(key->key()), |
| 1046 ¶m_item, | 1105 ¶m_item, |
| 1047 &signature_item, | 1106 &signature_item, |
| 1048 &data_item) != SECSuccess) { | 1107 &data_item) != SECSuccess) { |
| 1049 return Status::Error(); | 1108 return Status::Error(); |
| 1050 } | 1109 } |
| 1051 | 1110 |
| 1052 DCHECK_EQ(buffer->byteLength(), signature_item.len); | 1111 DCHECK_EQ(buffer->size(), signature_item.len); |
| 1053 return Status::Success(); | 1112 return Status::Success(); |
| 1054 } | 1113 } |
| 1055 | 1114 |
| 1056 // ----------------------------------- | 1115 // ----------------------------------- |
| 1057 // RsaEsPkcs1v1_5 | 1116 // RsaEsPkcs1v1_5 |
| 1058 // ----------------------------------- | 1117 // ----------------------------------- |
| 1059 | 1118 |
| 1060 Status EncryptRsaEsPkcs1v1_5(PublicKey* key, | 1119 Status EncryptRsaEsPkcs1v1_5(PublicKey* key, |
| 1061 const CryptoData& data, | 1120 const CryptoData& data, |
| 1062 blink::WebArrayBuffer* buffer) { | 1121 std::vector<uint8>* buffer) { |
| 1063 const unsigned int encrypted_length_bytes = | 1122 const unsigned int encrypted_length_bytes = |
| 1064 SECKEY_PublicKeyStrength(key->key()); | 1123 SECKEY_PublicKeyStrength(key->key()); |
| 1065 | 1124 |
| 1066 // RSAES can operate on messages up to a length of k - 11, where k is the | 1125 // RSAES can operate on messages up to a length of k - 11, where k is the |
| 1067 // octet length of the RSA modulus. | 1126 // octet length of the RSA modulus. |
| 1068 if (encrypted_length_bytes < 11 || | 1127 if (encrypted_length_bytes < 11 || |
| 1069 encrypted_length_bytes - 11 < data.byte_length()) | 1128 encrypted_length_bytes - 11 < data.byte_length()) |
| 1070 return Status::ErrorDataTooLarge(); | 1129 return Status::ErrorDataTooLarge(); |
| 1071 | 1130 |
| 1072 *buffer = blink::WebArrayBuffer::create(encrypted_length_bytes, 1); | 1131 buffer->resize(encrypted_length_bytes); |
| 1073 unsigned char* const buffer_data = | 1132 unsigned char* const buffer_data = Uint8VectorStart(buffer); |
| 1074 reinterpret_cast<unsigned char*>(buffer->data()); | |
| 1075 | 1133 |
| 1076 if (PK11_PubEncryptPKCS1(key->key(), | 1134 if (PK11_PubEncryptPKCS1(key->key(), |
| 1077 buffer_data, | 1135 buffer_data, |
| 1078 const_cast<unsigned char*>(data.bytes()), | 1136 const_cast<unsigned char*>(data.bytes()), |
| 1079 data.byte_length(), | 1137 data.byte_length(), |
| 1080 NULL) != SECSuccess) { | 1138 NULL) != SECSuccess) { |
| 1081 return Status::Error(); | 1139 return Status::Error(); |
| 1082 } | 1140 } |
| 1083 return Status::Success(); | 1141 return Status::Success(); |
| 1084 } | 1142 } |
| 1085 | 1143 |
| 1086 Status DecryptRsaEsPkcs1v1_5(PrivateKey* key, | 1144 Status DecryptRsaEsPkcs1v1_5(PrivateKey* key, |
| 1087 const CryptoData& data, | 1145 const CryptoData& data, |
| 1088 blink::WebArrayBuffer* buffer) { | 1146 std::vector<uint8>* buffer) { |
| 1089 const int modulus_length_bytes = PK11_GetPrivateModulusLen(key->key()); | 1147 const int modulus_length_bytes = PK11_GetPrivateModulusLen(key->key()); |
| 1090 if (modulus_length_bytes <= 0) | 1148 if (modulus_length_bytes <= 0) |
| 1091 return Status::ErrorUnexpected(); | 1149 return Status::ErrorUnexpected(); |
| 1092 const unsigned int max_output_length_bytes = modulus_length_bytes; | 1150 const unsigned int max_output_length_bytes = modulus_length_bytes; |
| 1093 | 1151 |
| 1094 *buffer = blink::WebArrayBuffer::create(max_output_length_bytes, 1); | 1152 buffer->resize(max_output_length_bytes); |
| 1095 unsigned char* const buffer_data = | 1153 unsigned char* const buffer_data = Uint8VectorStart(buffer); |
| 1096 reinterpret_cast<unsigned char*>(buffer->data()); | |
| 1097 | 1154 |
| 1098 unsigned int output_length_bytes = 0; | 1155 unsigned int output_length_bytes = 0; |
| 1099 if (PK11_PrivDecryptPKCS1(key->key(), | 1156 if (PK11_PrivDecryptPKCS1(key->key(), |
| 1100 buffer_data, | 1157 buffer_data, |
| 1101 &output_length_bytes, | 1158 &output_length_bytes, |
| 1102 max_output_length_bytes, | 1159 max_output_length_bytes, |
| 1103 const_cast<unsigned char*>(data.bytes()), | 1160 const_cast<unsigned char*>(data.bytes()), |
| 1104 data.byte_length()) != SECSuccess) { | 1161 data.byte_length()) != SECSuccess) { |
| 1105 return Status::Error(); | 1162 return Status::Error(); |
| 1106 } | 1163 } |
| 1107 DCHECK_LE(output_length_bytes, max_output_length_bytes); | 1164 DCHECK_LE(output_length_bytes, max_output_length_bytes); |
| 1108 ShrinkBuffer(buffer, output_length_bytes); | 1165 buffer->resize(output_length_bytes); |
| 1109 return Status::Success(); | 1166 return Status::Success(); |
| 1110 } | 1167 } |
| 1111 | 1168 |
| 1112 // ----------------------------------- | 1169 // ----------------------------------- |
| 1113 // RsaSsaPkcs1v1_5 | 1170 // RsaSsaPkcs1v1_5 |
| 1114 // ----------------------------------- | 1171 // ----------------------------------- |
| 1115 | 1172 |
| 1116 Status SignRsaSsaPkcs1v1_5(PrivateKey* key, | 1173 Status SignRsaSsaPkcs1v1_5(PrivateKey* key, |
| 1117 const blink::WebCryptoAlgorithm& hash, | 1174 const blink::WebCryptoAlgorithm& hash, |
| 1118 const CryptoData& data, | 1175 const CryptoData& data, |
| 1119 blink::WebArrayBuffer* buffer) { | 1176 std::vector<uint8>* buffer) { |
| 1120 // Pick the NSS signing algorithm by combining RSA-SSA (RSA PKCS1) and the | 1177 // Pick the NSS signing algorithm by combining RSA-SSA (RSA PKCS1) and the |
| 1121 // inner hash of the input Web Crypto algorithm. | 1178 // inner hash of the input Web Crypto algorithm. |
| 1122 SECOidTag sign_alg_tag; | 1179 SECOidTag sign_alg_tag; |
| 1123 switch (hash.id()) { | 1180 switch (hash.id()) { |
| 1124 case blink::WebCryptoAlgorithmIdSha1: | 1181 case blink::WebCryptoAlgorithmIdSha1: |
| 1125 sign_alg_tag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; | 1182 sign_alg_tag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; |
| 1126 break; | 1183 break; |
| 1127 case blink::WebCryptoAlgorithmIdSha256: | 1184 case blink::WebCryptoAlgorithmIdSha256: |
| 1128 sign_alg_tag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION; | 1185 sign_alg_tag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION; |
| 1129 break; | 1186 break; |
| 1130 case blink::WebCryptoAlgorithmIdSha384: | 1187 case blink::WebCryptoAlgorithmIdSha384: |
| 1131 sign_alg_tag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION; | 1188 sign_alg_tag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION; |
| 1132 break; | 1189 break; |
| 1133 case blink::WebCryptoAlgorithmIdSha512: | 1190 case blink::WebCryptoAlgorithmIdSha512: |
| 1134 sign_alg_tag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION; | 1191 sign_alg_tag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION; |
| 1135 break; | 1192 break; |
| 1136 default: | 1193 default: |
| 1137 return Status::ErrorUnsupported(); | 1194 return Status::ErrorUnsupported(); |
| 1138 } | 1195 } |
| 1139 | 1196 |
| 1140 crypto::ScopedSECItem signature_item(SECITEM_AllocItem(NULL, NULL, 0)); | 1197 crypto::ScopedSECItem signature_item(SECITEM_AllocItem(NULL, NULL, 0)); |
| 1141 if (SEC_SignData(signature_item.get(), | 1198 if (SEC_SignData(signature_item.get(), |
| 1142 data.bytes(), | 1199 data.bytes(), |
| 1143 data.byte_length(), | 1200 data.byte_length(), |
| 1144 key->key(), | 1201 key->key(), |
| 1145 sign_alg_tag) != SECSuccess) { | 1202 sign_alg_tag) != SECSuccess) { |
| 1146 return Status::Error(); | 1203 return Status::Error(); |
| 1147 } | 1204 } |
| 1148 | 1205 |
| 1149 *buffer = CreateArrayBuffer(signature_item->data, signature_item->len); | 1206 buffer->assign(signature_item->data, |
| 1207 signature_item->data + signature_item->len); |
| 1150 return Status::Success(); | 1208 return Status::Success(); |
| 1151 } | 1209 } |
| 1152 | 1210 |
| 1153 Status VerifyRsaSsaPkcs1v1_5(PublicKey* key, | 1211 Status VerifyRsaSsaPkcs1v1_5(PublicKey* key, |
| 1154 const blink::WebCryptoAlgorithm& hash, | 1212 const blink::WebCryptoAlgorithm& hash, |
| 1155 const CryptoData& signature, | 1213 const CryptoData& signature, |
| 1156 const CryptoData& data, | 1214 const CryptoData& data, |
| 1157 bool* signature_match) { | 1215 bool* signature_match) { |
| 1158 const SECItem signature_item = MakeSECItemForBuffer(signature); | 1216 const SECItem signature_item = MakeSECItemForBuffer(signature); |
| 1159 | 1217 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1184 hash_alg_tag, | 1242 hash_alg_tag, |
| 1185 NULL, | 1243 NULL, |
| 1186 NULL); | 1244 NULL); |
| 1187 return Status::Success(); | 1245 return Status::Success(); |
| 1188 } | 1246 } |
| 1189 | 1247 |
| 1190 Status EncryptDecryptAesCbc(EncryptOrDecrypt mode, | 1248 Status EncryptDecryptAesCbc(EncryptOrDecrypt mode, |
| 1191 SymKey* key, | 1249 SymKey* key, |
| 1192 const CryptoData& data, | 1250 const CryptoData& data, |
| 1193 const CryptoData& iv, | 1251 const CryptoData& iv, |
| 1194 blink::WebArrayBuffer* buffer) { | 1252 std::vector<uint8>* buffer) { |
| 1195 // TODO(eroman): Inline. | 1253 // TODO(eroman): Inline. |
| 1196 return AesCbcEncryptDecrypt(mode, key, iv, data, buffer); | 1254 return AesCbcEncryptDecrypt(mode, key, iv, data, buffer); |
| 1197 } | 1255 } |
| 1198 | 1256 |
| 1199 Status EncryptDecryptAesGcm(EncryptOrDecrypt mode, | 1257 Status EncryptDecryptAesGcm(EncryptOrDecrypt mode, |
| 1200 SymKey* key, | 1258 SymKey* key, |
| 1201 const CryptoData& data, | 1259 const CryptoData& data, |
| 1202 const CryptoData& iv, | 1260 const CryptoData& iv, |
| 1203 const CryptoData& additional_data, | 1261 const CryptoData& additional_data, |
| 1204 unsigned int tag_length_bits, | 1262 unsigned int tag_length_bits, |
| 1205 blink::WebArrayBuffer* buffer) { | 1263 std::vector<uint8>* buffer) { |
| 1206 // TODO(eroman): Inline. | 1264 // TODO(eroman): Inline. |
| 1207 return AesGcmEncryptDecrypt( | 1265 return AesGcmEncryptDecrypt( |
| 1208 mode, key, data, iv, additional_data, tag_length_bits, buffer); | 1266 mode, key, data, iv, additional_data, tag_length_bits, buffer); |
| 1209 } | 1267 } |
| 1210 | 1268 |
| 1211 // ----------------------------------- | 1269 // ----------------------------------- |
| 1212 // Key generation | 1270 // Key generation |
| 1213 // ----------------------------------- | 1271 // ----------------------------------- |
| 1214 | 1272 |
| 1215 Status GenerateRsaKeyPair(const blink::WebCryptoAlgorithm& algorithm, | 1273 Status GenerateRsaKeyPair(const blink::WebCryptoAlgorithm& algorithm, |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1271 operation_flags, | 1329 operation_flags, |
| 1272 operation_flags_mask, | 1330 operation_flags_mask, |
| 1273 NULL)); | 1331 NULL)); |
| 1274 if (!private_key) | 1332 if (!private_key) |
| 1275 return Status::Error(); | 1333 return Status::Error(); |
| 1276 | 1334 |
| 1277 blink::WebCryptoKeyAlgorithm key_algorithm; | 1335 blink::WebCryptoKeyAlgorithm key_algorithm; |
| 1278 if (!CreatePublicKeyAlgorithm(algorithm, sec_public_key, &key_algorithm)) | 1336 if (!CreatePublicKeyAlgorithm(algorithm, sec_public_key, &key_algorithm)) |
| 1279 return Status::ErrorUnexpected(); | 1337 return Status::ErrorUnexpected(); |
| 1280 | 1338 |
| 1281 *public_key = blink::WebCryptoKey::create( | 1339 scoped_ptr<PublicKey> public_key_handle; |
| 1282 new PublicKey(crypto::ScopedSECKEYPublicKey(sec_public_key)), | 1340 Status status = PublicKey::Create( |
| 1283 blink::WebCryptoKeyTypePublic, | 1341 crypto::ScopedSECKEYPublicKey(sec_public_key), &public_key_handle); |
| 1284 true, | 1342 if (status.IsError()) |
| 1285 key_algorithm, | 1343 return status; |
| 1286 usage_mask); | 1344 |
| 1287 *private_key = | 1345 scoped_ptr<PrivateKey> private_key_handle; |
| 1288 blink::WebCryptoKey::create(new PrivateKey(scoped_sec_private_key.Pass()), | 1346 status = PrivateKey::Create( |
| 1289 blink::WebCryptoKeyTypePrivate, | 1347 scoped_sec_private_key.Pass(), key_algorithm, &private_key_handle); |
| 1290 extractable, | 1348 if (status.IsError()) |
| 1291 key_algorithm, | 1349 return status; |
| 1292 usage_mask); | 1350 |
| 1351 *public_key = blink::WebCryptoKey::create(public_key_handle.release(), |
| 1352 blink::WebCryptoKeyTypePublic, |
| 1353 true, |
| 1354 key_algorithm, |
| 1355 usage_mask); |
| 1356 *private_key = blink::WebCryptoKey::create(private_key_handle.release(), |
| 1357 blink::WebCryptoKeyTypePrivate, |
| 1358 extractable, |
| 1359 key_algorithm, |
| 1360 usage_mask); |
| 1293 | 1361 |
| 1294 return Status::Success(); | 1362 return Status::Success(); |
| 1295 } | 1363 } |
| 1296 | 1364 |
| 1297 void Init() { crypto::EnsureNSSInit(); } | 1365 void Init() { |
| 1366 crypto::EnsureNSSInit(); |
| 1367 } |
| 1298 | 1368 |
| 1299 Status DigestSha(blink::WebCryptoAlgorithmId algorithm, | 1369 Status DigestSha(blink::WebCryptoAlgorithmId algorithm, |
| 1300 const CryptoData& data, | 1370 const CryptoData& data, |
| 1301 blink::WebArrayBuffer* buffer) { | 1371 std::vector<uint8>* buffer) { |
| 1302 DigestorNSS digestor(algorithm); | 1372 DigestorNSS digestor(algorithm); |
| 1303 Status error = digestor.ConsumeWithStatus(data.bytes(), data.byte_length()); | 1373 Status error = digestor.ConsumeWithStatus(data.bytes(), data.byte_length()); |
| 1304 if (!error.IsSuccess()) | 1374 if (!error.IsSuccess()) |
| 1305 return error; | 1375 return error; |
| 1306 return digestor.FinishWithWebArrayAndStatus(buffer); | 1376 return digestor.FinishWithVectorAndStatus(buffer); |
| 1307 } | 1377 } |
| 1308 | 1378 |
| 1309 scoped_ptr<blink::WebCryptoDigestor> CreateDigestor( | 1379 scoped_ptr<blink::WebCryptoDigestor> CreateDigestor( |
| 1310 blink::WebCryptoAlgorithmId algorithm_id) { | 1380 blink::WebCryptoAlgorithmId algorithm_id) { |
| 1311 return scoped_ptr<blink::WebCryptoDigestor>(new DigestorNSS(algorithm_id)); | 1381 return scoped_ptr<blink::WebCryptoDigestor>(new DigestorNSS(algorithm_id)); |
| 1312 } | 1382 } |
| 1313 | 1383 |
| 1314 Status GenerateSecretKey(const blink::WebCryptoAlgorithm& algorithm, | 1384 Status GenerateSecretKey(const blink::WebCryptoAlgorithm& algorithm, |
| 1315 bool extractable, | 1385 bool extractable, |
| 1316 blink::WebCryptoKeyUsageMask usage_mask, | 1386 blink::WebCryptoKeyUsageMask usage_mask, |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1329 crypto::ScopedPK11SymKey pk11_key( | 1399 crypto::ScopedPK11SymKey pk11_key( |
| 1330 PK11_KeyGen(slot.get(), mech, NULL, keylen_bytes, NULL)); | 1400 PK11_KeyGen(slot.get(), mech, NULL, keylen_bytes, NULL)); |
| 1331 | 1401 |
| 1332 if (!pk11_key) | 1402 if (!pk11_key) |
| 1333 return Status::Error(); | 1403 return Status::Error(); |
| 1334 | 1404 |
| 1335 blink::WebCryptoKeyAlgorithm key_algorithm; | 1405 blink::WebCryptoKeyAlgorithm key_algorithm; |
| 1336 if (!CreateSecretKeyAlgorithm(algorithm, keylen_bytes, &key_algorithm)) | 1406 if (!CreateSecretKeyAlgorithm(algorithm, keylen_bytes, &key_algorithm)) |
| 1337 return Status::ErrorUnexpected(); | 1407 return Status::ErrorUnexpected(); |
| 1338 | 1408 |
| 1339 *key = blink::WebCryptoKey::create(new SymKey(pk11_key.Pass()), | 1409 scoped_ptr<SymKey> key_handle; |
| 1340 key_type, | 1410 Status status = SymKey::Create(pk11_key.Pass(), &key_handle); |
| 1341 extractable, | 1411 if (status.IsError()) |
| 1342 key_algorithm, | 1412 return status; |
| 1343 usage_mask); | 1413 |
| 1414 *key = blink::WebCryptoKey::create( |
| 1415 key_handle.release(), key_type, extractable, key_algorithm, usage_mask); |
| 1344 return Status::Success(); | 1416 return Status::Success(); |
| 1345 } | 1417 } |
| 1346 | 1418 |
| 1347 Status ImportRsaPublicKey(const blink::WebCryptoAlgorithm& algorithm, | 1419 Status ImportRsaPublicKey(const blink::WebCryptoAlgorithm& algorithm, |
| 1348 bool extractable, | 1420 bool extractable, |
| 1349 blink::WebCryptoKeyUsageMask usage_mask, | 1421 blink::WebCryptoKeyUsageMask usage_mask, |
| 1350 const CryptoData& modulus_data, | 1422 const CryptoData& modulus_data, |
| 1351 const CryptoData& exponent_data, | 1423 const CryptoData& exponent_data, |
| 1352 blink::WebCryptoKey* key) { | 1424 blink::WebCryptoKey* key) { |
| 1353 | |
| 1354 if (!modulus_data.byte_length()) | 1425 if (!modulus_data.byte_length()) |
| 1355 return Status::ErrorImportRsaEmptyModulus(); | 1426 return Status::ErrorImportRsaEmptyModulus(); |
| 1356 | 1427 |
| 1357 if (!exponent_data.byte_length()) | 1428 if (!exponent_data.byte_length()) |
| 1358 return Status::ErrorImportRsaEmptyExponent(); | 1429 return Status::ErrorImportRsaEmptyExponent(); |
| 1359 | 1430 |
| 1360 DCHECK(modulus_data.bytes()); | 1431 DCHECK(modulus_data.bytes()); |
| 1361 DCHECK(exponent_data.bytes()); | 1432 DCHECK(exponent_data.bytes()); |
| 1362 | 1433 |
| 1363 // NSS does not provide a way to create an RSA public key directly from the | 1434 // NSS does not provide a way to create an RSA public key directly from the |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1392 // Import the DER-encoded public key to create an RSA SECKEYPublicKey. | 1463 // Import the DER-encoded public key to create an RSA SECKEYPublicKey. |
| 1393 crypto::ScopedSECKEYPublicKey pubkey( | 1464 crypto::ScopedSECKEYPublicKey pubkey( |
| 1394 SECKEY_ImportDERPublicKey(pubkey_der.get(), CKK_RSA)); | 1465 SECKEY_ImportDERPublicKey(pubkey_der.get(), CKK_RSA)); |
| 1395 if (!pubkey) | 1466 if (!pubkey) |
| 1396 return Status::Error(); | 1467 return Status::Error(); |
| 1397 | 1468 |
| 1398 blink::WebCryptoKeyAlgorithm key_algorithm; | 1469 blink::WebCryptoKeyAlgorithm key_algorithm; |
| 1399 if (!CreatePublicKeyAlgorithm(algorithm, pubkey.get(), &key_algorithm)) | 1470 if (!CreatePublicKeyAlgorithm(algorithm, pubkey.get(), &key_algorithm)) |
| 1400 return Status::ErrorUnexpected(); | 1471 return Status::ErrorUnexpected(); |
| 1401 | 1472 |
| 1402 *key = blink::WebCryptoKey::create(new PublicKey(pubkey.Pass()), | 1473 scoped_ptr<PublicKey> key_handle; |
| 1474 Status status = PublicKey::Create(pubkey.Pass(), &key_handle); |
| 1475 if (status.IsError()) |
| 1476 return status; |
| 1477 |
| 1478 *key = blink::WebCryptoKey::create(key_handle.release(), |
| 1403 blink::WebCryptoKeyTypePublic, | 1479 blink::WebCryptoKeyTypePublic, |
| 1404 extractable, | 1480 extractable, |
| 1405 key_algorithm, | 1481 key_algorithm, |
| 1406 usage_mask); | 1482 usage_mask); |
| 1407 return Status::Success(); | 1483 return Status::Success(); |
| 1408 } | 1484 } |
| 1409 | 1485 |
| 1410 Status WrapSymKeyAesKw(SymKey* wrapping_key, | 1486 Status WrapSymKeyAesKw(SymKey* wrapping_key, |
| 1411 SymKey* key, | 1487 SymKey* key, |
| 1412 blink::WebArrayBuffer* buffer) { | 1488 std::vector<uint8>* buffer) { |
| 1413 // The data size must be at least 16 bytes and a multiple of 8 bytes. | 1489 // The data size must be at least 16 bytes and a multiple of 8 bytes. |
| 1414 // RFC 3394 does not specify a maximum allowed data length, but since only | 1490 // RFC 3394 does not specify a maximum allowed data length, but since only |
| 1415 // keys are being wrapped in this application (which are small), a reasonable | 1491 // keys are being wrapped in this application (which are small), a reasonable |
| 1416 // max limit is whatever will fit into an unsigned. For the max size test, | 1492 // max limit is whatever will fit into an unsigned. For the max size test, |
| 1417 // note that AES Key Wrap always adds 8 bytes to the input data size. | 1493 // note that AES Key Wrap always adds 8 bytes to the input data size. |
| 1418 const unsigned int input_length = PK11_GetKeyLength(key->key()); | 1494 const unsigned int input_length = PK11_GetKeyLength(key->key()); |
| 1419 if (input_length < 16) | 1495 if (input_length < 16) |
| 1420 return Status::ErrorDataTooSmall(); | 1496 return Status::ErrorDataTooSmall(); |
| 1421 if (input_length > UINT_MAX - 8) | 1497 if (input_length > UINT_MAX - 8) |
| 1422 return Status::ErrorDataTooLarge(); | 1498 return Status::ErrorDataTooLarge(); |
| 1423 if (input_length % 8) | 1499 if (input_length % 8) |
| 1424 return Status::ErrorInvalidAesKwDataLength(); | 1500 return Status::ErrorInvalidAesKwDataLength(); |
| 1425 | 1501 |
| 1426 SECItem iv_item = MakeSECItemForBuffer(CryptoData(kAesIv, sizeof(kAesIv))); | 1502 SECItem iv_item = MakeSECItemForBuffer(CryptoData(kAesIv, sizeof(kAesIv))); |
| 1427 crypto::ScopedSECItem param_item( | 1503 crypto::ScopedSECItem param_item( |
| 1428 PK11_ParamFromIV(CKM_NSS_AES_KEY_WRAP, &iv_item)); | 1504 PK11_ParamFromIV(CKM_NSS_AES_KEY_WRAP, &iv_item)); |
| 1429 if (!param_item) | 1505 if (!param_item) |
| 1430 return Status::ErrorUnexpected(); | 1506 return Status::ErrorUnexpected(); |
| 1431 | 1507 |
| 1432 const unsigned int output_length = input_length + 8; | 1508 const unsigned int output_length = input_length + 8; |
| 1433 *buffer = blink::WebArrayBuffer::create(output_length, 1); | 1509 buffer->resize(output_length); |
| 1434 SECItem wrapped_key_item = MakeSECItemForBuffer(CryptoData(*buffer)); | 1510 SECItem wrapped_key_item = MakeSECItemForBuffer(CryptoData(*buffer)); |
| 1435 | 1511 |
| 1436 if (SECSuccess != PK11_WrapSymKey(CKM_NSS_AES_KEY_WRAP, | 1512 if (SECSuccess != PK11_WrapSymKey(CKM_NSS_AES_KEY_WRAP, |
| 1437 param_item.get(), | 1513 param_item.get(), |
| 1438 wrapping_key->key(), | 1514 wrapping_key->key(), |
| 1439 key->key(), | 1515 key->key(), |
| 1440 &wrapped_key_item)) { | 1516 &wrapped_key_item)) { |
| 1441 return Status::Error(); | 1517 return Status::Error(); |
| 1442 } | 1518 } |
| 1443 if (output_length != wrapped_key_item.len) | 1519 if (output_length != wrapped_key_item.len) |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1464 status = DoUnwrapSymKeyAesKw( | 1540 status = DoUnwrapSymKeyAesKw( |
| 1465 wrapped_key_data, wrapping_key, mechanism, flags, &unwrapped_key); | 1541 wrapped_key_data, wrapping_key, mechanism, flags, &unwrapped_key); |
| 1466 if (status.IsError()) | 1542 if (status.IsError()) |
| 1467 return status; | 1543 return status; |
| 1468 | 1544 |
| 1469 blink::WebCryptoKeyAlgorithm key_algorithm; | 1545 blink::WebCryptoKeyAlgorithm key_algorithm; |
| 1470 if (!CreateSecretKeyAlgorithm( | 1546 if (!CreateSecretKeyAlgorithm( |
| 1471 algorithm, PK11_GetKeyLength(unwrapped_key.get()), &key_algorithm)) | 1547 algorithm, PK11_GetKeyLength(unwrapped_key.get()), &key_algorithm)) |
| 1472 return Status::ErrorUnexpected(); | 1548 return Status::ErrorUnexpected(); |
| 1473 | 1549 |
| 1474 *key = blink::WebCryptoKey::create(new SymKey(unwrapped_key.Pass()), | 1550 scoped_ptr<SymKey> key_handle; |
| 1551 status = SymKey::Create(unwrapped_key.Pass(), &key_handle); |
| 1552 if (status.IsError()) |
| 1553 return status; |
| 1554 |
| 1555 *key = blink::WebCryptoKey::create(key_handle.release(), |
| 1475 blink::WebCryptoKeyTypeSecret, | 1556 blink::WebCryptoKeyTypeSecret, |
| 1476 extractable, | 1557 extractable, |
| 1477 key_algorithm, | 1558 key_algorithm, |
| 1478 usage_mask); | 1559 usage_mask); |
| 1479 return Status::Success(); | 1560 return Status::Success(); |
| 1480 } | 1561 } |
| 1481 | 1562 |
| 1482 Status DecryptAesKw(SymKey* wrapping_key, | 1563 Status DecryptAesKw(SymKey* wrapping_key, |
| 1483 const CryptoData& data, | 1564 const CryptoData& data, |
| 1484 blink::WebArrayBuffer* buffer) { | 1565 std::vector<uint8>* buffer) { |
| 1485 // Due to limitations in the NSS API for the AES-KW algorithm, |data| must be | 1566 // Due to limitations in the NSS API for the AES-KW algorithm, |data| must be |
| 1486 // temporarily viewed as a symmetric key to be unwrapped (decrypted). | 1567 // temporarily viewed as a symmetric key to be unwrapped (decrypted). |
| 1487 crypto::ScopedPK11SymKey decrypted; | 1568 crypto::ScopedPK11SymKey decrypted; |
| 1488 Status status = DoUnwrapSymKeyAesKw( | 1569 Status status = DoUnwrapSymKeyAesKw( |
| 1489 data, wrapping_key, CKK_GENERIC_SECRET, CKA_ENCRYPT, &decrypted); | 1570 data, wrapping_key, CKK_GENERIC_SECRET, CKA_ENCRYPT, &decrypted); |
| 1490 if (status.IsError()) | 1571 if (status.IsError()) |
| 1491 return status; | 1572 return status; |
| 1492 | 1573 |
| 1493 // Once the decrypt is complete, extract the resultant raw bytes from NSS and | 1574 // Once the decrypt is complete, extract the resultant raw bytes from NSS and |
| 1494 // return them to the caller. | 1575 // return them to the caller. |
| 1495 if (PK11_ExtractKeyValue(decrypted.get()) != SECSuccess) | 1576 if (PK11_ExtractKeyValue(decrypted.get()) != SECSuccess) |
| 1496 return Status::Error(); | 1577 return Status::Error(); |
| 1497 const SECItem* const key_data = PK11_GetKeyData(decrypted.get()); | 1578 const SECItem* const key_data = PK11_GetKeyData(decrypted.get()); |
| 1498 if (!key_data) | 1579 if (!key_data) |
| 1499 return Status::Error(); | 1580 return Status::Error(); |
| 1500 *buffer = webcrypto::CreateArrayBuffer(key_data->data, key_data->len); | 1581 buffer->assign(key_data->data, key_data->data + key_data->len); |
| 1501 | 1582 |
| 1502 return Status::Success(); | 1583 return Status::Success(); |
| 1503 } | 1584 } |
| 1504 | 1585 |
| 1505 Status WrapSymKeyRsaEs(PublicKey* wrapping_key, | 1586 Status WrapSymKeyRsaEs(PublicKey* wrapping_key, |
| 1506 SymKey* key, | 1587 SymKey* key, |
| 1507 blink::WebArrayBuffer* buffer) { | 1588 std::vector<uint8>* buffer) { |
| 1508 // Check the raw length of the key to be wrapped against the max size allowed | 1589 // Check the raw length of the key to be wrapped against the max size allowed |
| 1509 // by the RSA wrapping key. With PKCS#1 v1.5 padding used in this function, | 1590 // by the RSA wrapping key. With PKCS#1 v1.5 padding used in this function, |
| 1510 // the maximum data length that can be encrypted is the wrapping_key's modulus | 1591 // the maximum data length that can be encrypted is the wrapping_key's modulus |
| 1511 // byte length minus eleven bytes. | 1592 // byte length minus eleven bytes. |
| 1512 const unsigned int input_length_bytes = PK11_GetKeyLength(key->key()); | 1593 const unsigned int input_length_bytes = PK11_GetKeyLength(key->key()); |
| 1513 const unsigned int modulus_length_bytes = | 1594 const unsigned int modulus_length_bytes = |
| 1514 SECKEY_PublicKeyStrength(wrapping_key->key()); | 1595 SECKEY_PublicKeyStrength(wrapping_key->key()); |
| 1515 if (modulus_length_bytes < 11 || | 1596 if (modulus_length_bytes < 11 || |
| 1516 modulus_length_bytes - 11 < input_length_bytes) | 1597 modulus_length_bytes - 11 < input_length_bytes) |
| 1517 return Status::ErrorDataTooLarge(); | 1598 return Status::ErrorDataTooLarge(); |
| 1518 | 1599 |
| 1519 *buffer = blink::WebArrayBuffer::create(modulus_length_bytes, 1); | 1600 buffer->resize(modulus_length_bytes); |
| 1520 SECItem wrapped_key_item = MakeSECItemForBuffer(CryptoData(*buffer)); | 1601 SECItem wrapped_key_item = MakeSECItemForBuffer(CryptoData(*buffer)); |
| 1521 | 1602 |
| 1522 if (SECSuccess != | 1603 if (SECSuccess != |
| 1523 PK11_PubWrapSymKey( | 1604 PK11_PubWrapSymKey( |
| 1524 CKM_RSA_PKCS, wrapping_key->key(), key->key(), &wrapped_key_item)) { | 1605 CKM_RSA_PKCS, wrapping_key->key(), key->key(), &wrapped_key_item)) { |
| 1525 return Status::Error(); | 1606 return Status::Error(); |
| 1526 } | 1607 } |
| 1527 if (wrapped_key_item.len != modulus_length_bytes) | 1608 if (wrapped_key_item.len != modulus_length_bytes) |
| 1528 return Status::ErrorUnexpected(); | 1609 return Status::ErrorUnexpected(); |
| 1529 | 1610 |
| 1530 return Status::Success(); | 1611 return Status::Success(); |
| 1531 } | 1612 } |
| 1532 | 1613 |
| 1533 Status UnwrapSymKeyRsaEs(const CryptoData& wrapped_key_data, | 1614 Status UnwrapSymKeyRsaEs(const CryptoData& wrapped_key_data, |
| 1534 PrivateKey* wrapping_key, | 1615 PrivateKey* wrapping_key, |
| 1535 const blink::WebCryptoAlgorithm& algorithm, | 1616 const blink::WebCryptoAlgorithm& algorithm, |
| 1536 bool extractable, | 1617 bool extractable, |
| 1537 blink::WebCryptoKeyUsageMask usage_mask, | 1618 blink::WebCryptoKeyUsageMask usage_mask, |
| 1538 blink::WebCryptoKey* key) { | 1619 blink::WebCryptoKey* key) { |
| 1539 | |
| 1540 // Verify wrapped_key_data size does not exceed the modulus of the RSA key. | 1620 // Verify wrapped_key_data size does not exceed the modulus of the RSA key. |
| 1541 const int modulus_length_bytes = | 1621 const int modulus_length_bytes = |
| 1542 PK11_GetPrivateModulusLen(wrapping_key->key()); | 1622 PK11_GetPrivateModulusLen(wrapping_key->key()); |
| 1543 if (modulus_length_bytes <= 0) | 1623 if (modulus_length_bytes <= 0) |
| 1544 return Status::ErrorUnexpected(); | 1624 return Status::ErrorUnexpected(); |
| 1545 if (wrapped_key_data.byte_length() > | 1625 if (wrapped_key_data.byte_length() > |
| 1546 static_cast<unsigned int>(modulus_length_bytes)) | 1626 static_cast<unsigned int>(modulus_length_bytes)) |
| 1547 return Status::ErrorDataTooLarge(); | 1627 return Status::ErrorDataTooLarge(); |
| 1548 | 1628 |
| 1549 // Determine the proper NSS key properties from the input algorithm. | 1629 // Determine the proper NSS key properties from the input algorithm. |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1566 false)); | 1646 false)); |
| 1567 if (!unwrapped_key) | 1647 if (!unwrapped_key) |
| 1568 return Status::Error(); | 1648 return Status::Error(); |
| 1569 | 1649 |
| 1570 const unsigned int key_length = PK11_GetKeyLength(unwrapped_key.get()); | 1650 const unsigned int key_length = PK11_GetKeyLength(unwrapped_key.get()); |
| 1571 | 1651 |
| 1572 blink::WebCryptoKeyAlgorithm key_algorithm; | 1652 blink::WebCryptoKeyAlgorithm key_algorithm; |
| 1573 if (!CreateSecretKeyAlgorithm(algorithm, key_length, &key_algorithm)) | 1653 if (!CreateSecretKeyAlgorithm(algorithm, key_length, &key_algorithm)) |
| 1574 return Status::ErrorUnexpected(); | 1654 return Status::ErrorUnexpected(); |
| 1575 | 1655 |
| 1576 *key = blink::WebCryptoKey::create(new SymKey(unwrapped_key.Pass()), | 1656 scoped_ptr<SymKey> key_handle; |
| 1657 status = SymKey::Create(unwrapped_key.Pass(), &key_handle); |
| 1658 if (status.IsError()) |
| 1659 return status; |
| 1660 |
| 1661 *key = blink::WebCryptoKey::create(key_handle.release(), |
| 1577 blink::WebCryptoKeyTypeSecret, | 1662 blink::WebCryptoKeyTypeSecret, |
| 1578 extractable, | 1663 extractable, |
| 1579 key_algorithm, | 1664 key_algorithm, |
| 1580 usage_mask); | 1665 usage_mask); |
| 1581 return Status::Success(); | 1666 return Status::Success(); |
| 1582 } | 1667 } |
| 1583 | 1668 |
| 1584 } // namespace platform | 1669 } // namespace platform |
| 1585 | 1670 |
| 1586 } // namespace webcrypto | 1671 } // namespace webcrypto |
| 1587 | 1672 |
| 1588 } // namespace content | 1673 } // namespace content |
| OLD | NEW |