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::OperationError(); | 274 return Status::OperationError(); |
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::OperationError(); | 296 return Status::OperationError(); |
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::OperationError(); | 315 return Status::OperationError(); |
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::OperationError(); | 323 return Status::OperationError(); |
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::OperationError(); | 400 return Status::OperationError(); |
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::OperationError(); | 828 return Status::OperationError(); |
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::OperationError(); | 850 return Status::OperationError(); |
801 | 851 |
802 // http://crbug.com/366427: the spec does not define any other failures for | 852 // http://crbug.com/366427: the spec does not define any other failures for |
803 // exporting, so none of the subsequent errors are spec compliant. | 853 // exporting, so none of the subsequent errors are spec compliant. |
804 const SECItem* key_data = PK11_GetKeyData(key->key()); | 854 const SECItem* key_data = PK11_GetKeyData(key->key()); |
805 if (!key_data) | 855 if (!key_data) |
806 return Status::OperationError(); | 856 return Status::OperationError(); |
807 | 857 |
808 *buffer = CreateArrayBuffer(key_data->data, key_data->len); | 858 buffer->assign(key_data->data, key_data->data + key_data->len); |
809 | 859 |
810 return Status::Success(); | 860 return Status::Success(); |
811 } | 861 } |
812 | 862 |
813 namespace { | 863 namespace { |
814 | 864 |
815 typedef scoped_ptr<CERTSubjectPublicKeyInfo, | 865 typedef scoped_ptr<CERTSubjectPublicKeyInfo, |
816 crypto::NSSDestroyer<CERTSubjectPublicKeyInfo, | 866 crypto::NSSDestroyer<CERTSubjectPublicKeyInfo, |
817 SECKEY_DestroySubjectPublicKeyInfo> > | 867 SECKEY_DestroySubjectPublicKeyInfo> > |
818 ScopedCERTSubjectPublicKeyInfo; | 868 ScopedCERTSubjectPublicKeyInfo; |
(...skipping 17 matching lines...) Expand all Loading... |
836 return false; | 886 return false; |
837 } | 887 } |
838 | 888 |
839 } // namespace | 889 } // namespace |
840 | 890 |
841 Status ImportKeySpki(const blink::WebCryptoAlgorithm& algorithm, | 891 Status ImportKeySpki(const blink::WebCryptoAlgorithm& algorithm, |
842 const CryptoData& key_data, | 892 const CryptoData& key_data, |
843 bool extractable, | 893 bool extractable, |
844 blink::WebCryptoKeyUsageMask usage_mask, | 894 blink::WebCryptoKeyUsageMask usage_mask, |
845 blink::WebCryptoKey* key) { | 895 blink::WebCryptoKey* key) { |
846 | |
847 DCHECK(key); | 896 DCHECK(key); |
848 | 897 |
849 if (!key_data.byte_length()) | 898 if (!key_data.byte_length()) |
850 return Status::ErrorImportEmptyKeyData(); | 899 return Status::ErrorImportEmptyKeyData(); |
851 DCHECK(key_data.bytes()); | 900 DCHECK(key_data.bytes()); |
852 | 901 |
853 // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 Subject | 902 // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 Subject |
854 // Public Key Info. Decode this to a CERTSubjectPublicKeyInfo. | 903 // Public Key Info. Decode this to a CERTSubjectPublicKeyInfo. |
855 SECItem spki_item = MakeSECItemForBuffer(key_data); | 904 SECItem spki_item = MakeSECItemForBuffer(key_data); |
856 const ScopedCERTSubjectPublicKeyInfo spki( | 905 const ScopedCERTSubjectPublicKeyInfo spki( |
857 SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_item)); | 906 SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_item)); |
858 if (!spki) | 907 if (!spki) |
859 return Status::DataError(); | 908 return Status::DataError(); |
860 | 909 |
861 crypto::ScopedSECKEYPublicKey sec_public_key( | 910 crypto::ScopedSECKEYPublicKey sec_public_key( |
862 SECKEY_ExtractPublicKey(spki.get())); | 911 SECKEY_ExtractPublicKey(spki.get())); |
863 if (!sec_public_key) | 912 if (!sec_public_key) |
864 return Status::DataError(); | 913 return Status::DataError(); |
865 | 914 |
866 const KeyType sec_key_type = SECKEY_GetPublicKeyType(sec_public_key.get()); | 915 const KeyType sec_key_type = SECKEY_GetPublicKeyType(sec_public_key.get()); |
867 if (!ValidateNssKeyTypeAgainstInputAlgorithm(sec_key_type, algorithm)) | 916 if (!ValidateNssKeyTypeAgainstInputAlgorithm(sec_key_type, algorithm)) |
868 return Status::DataError(); | 917 return Status::DataError(); |
869 | 918 |
870 blink::WebCryptoKeyAlgorithm key_algorithm; | 919 blink::WebCryptoKeyAlgorithm key_algorithm; |
871 if (!CreatePublicKeyAlgorithm( | 920 if (!CreatePublicKeyAlgorithm( |
872 algorithm, sec_public_key.get(), &key_algorithm)) | 921 algorithm, sec_public_key.get(), &key_algorithm)) |
873 return Status::ErrorUnexpected(); | 922 return Status::ErrorUnexpected(); |
874 | 923 |
875 *key = blink::WebCryptoKey::create(new PublicKey(sec_public_key.Pass()), | 924 scoped_ptr<PublicKey> key_handle; |
| 925 Status status = PublicKey::Create(sec_public_key.Pass(), &key_handle); |
| 926 if (status.IsError()) |
| 927 return status; |
| 928 |
| 929 *key = blink::WebCryptoKey::create(key_handle.release(), |
876 blink::WebCryptoKeyTypePublic, | 930 blink::WebCryptoKeyTypePublic, |
877 extractable, | 931 extractable, |
878 key_algorithm, | 932 key_algorithm, |
879 usage_mask); | 933 usage_mask); |
880 | 934 |
881 return Status::Success(); | 935 return Status::Success(); |
882 } | 936 } |
883 | 937 |
884 Status ExportKeySpki(PublicKey* key, blink::WebArrayBuffer* buffer) { | 938 Status ExportKeySpki(PublicKey* key, std::vector<uint8>* buffer) { |
885 const crypto::ScopedSECItem spki_der( | 939 const crypto::ScopedSECItem spki_der( |
886 SECKEY_EncodeDERSubjectPublicKeyInfo(key->key())); | 940 SECKEY_EncodeDERSubjectPublicKeyInfo(key->key())); |
887 // http://crbug.com/366427: the spec does not define any other failures for | 941 // http://crbug.com/366427: the spec does not define any other failures for |
888 // exporting, so none of the subsequent errors are spec compliant. | 942 // exporting, so none of the subsequent errors are spec compliant. |
889 if (!spki_der) | 943 if (!spki_der) |
890 return Status::OperationError(); | 944 return Status::OperationError(); |
891 | 945 |
892 DCHECK(spki_der->data); | 946 DCHECK(spki_der->data); |
893 DCHECK(spki_der->len); | 947 DCHECK(spki_der->len); |
894 | 948 |
895 *buffer = CreateArrayBuffer(spki_der->data, spki_der->len); | 949 buffer->assign(spki_der->data, spki_der->data + spki_der->len); |
896 | 950 |
897 return Status::Success(); | 951 return Status::Success(); |
898 } | 952 } |
899 | 953 |
900 Status ExportRsaPublicKey(PublicKey* key, | 954 Status ExportRsaPublicKey(PublicKey* key, |
901 std::vector<uint8>* modulus, | 955 std::vector<uint8>* modulus, |
902 std::vector<uint8>* public_exponent) { | 956 std::vector<uint8>* public_exponent) { |
903 DCHECK(key); | 957 DCHECK(key); |
904 DCHECK(key->key()); | 958 DCHECK(key->key()); |
905 if (key->key()->keyType != rsaKey) | 959 if (key->key()->keyType != rsaKey) |
906 return Status::ErrorUnsupported(); | 960 return Status::ErrorUnsupported(); |
907 CopySECItemToVector(key->key()->u.rsa.modulus, modulus); | 961 CopySECItemToVector(key->key()->u.rsa.modulus, modulus); |
908 CopySECItemToVector(key->key()->u.rsa.publicExponent, public_exponent); | 962 CopySECItemToVector(key->key()->u.rsa.publicExponent, public_exponent); |
909 if (modulus->empty() || public_exponent->empty()) | 963 if (modulus->empty() || public_exponent->empty()) |
910 return Status::ErrorUnexpected(); | 964 return Status::ErrorUnexpected(); |
911 return Status::Success(); | 965 return Status::Success(); |
912 } | 966 } |
913 | 967 |
914 Status ExportKeyPkcs8(PrivateKey* key, | 968 Status ExportKeyPkcs8(PrivateKey* key, |
915 const blink::WebCryptoKeyAlgorithm& key_algorithm, | 969 const blink::WebCryptoKeyAlgorithm& key_algorithm, |
916 blink::WebArrayBuffer* buffer) { | 970 std::vector<uint8>* buffer) { |
917 // TODO(eroman): Support other RSA key types as they are added to Blink. | 971 // TODO(eroman): Support other RSA key types as they are added to Blink. |
918 if (key_algorithm.id() != blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 && | 972 if (key_algorithm.id() != blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 && |
919 key_algorithm.id() != blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5) | 973 key_algorithm.id() != blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5) |
920 return Status::ErrorUnsupported(); | 974 return Status::ErrorUnsupported(); |
921 | 975 |
922 #if defined(USE_NSS) | 976 #if defined(USE_NSS) |
923 // PK11_ExportDERPrivateKeyInfo isn't available. Use our fallback code. | 977 // PK11_ExportDERPrivateKeyInfo isn't available. Use our fallback code. |
924 const SECOidTag algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION; | 978 const SECOidTag algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION; |
925 const int kPrivateKeyInfoVersion = 0; | 979 const int kPrivateKeyInfoVersion = 0; |
926 | 980 |
(...skipping 24 matching lines...) Expand all Loading... |
951 | 1005 |
952 if (!SEC_ASN1EncodeInteger( | 1006 if (!SEC_ASN1EncodeInteger( |
953 arena.get(), &private_key_info.version, kPrivateKeyInfoVersion)) | 1007 arena.get(), &private_key_info.version, kPrivateKeyInfoVersion)) |
954 return Status::OperationError(); | 1008 return Status::OperationError(); |
955 | 1009 |
956 crypto::ScopedSECItem encoded_key( | 1010 crypto::ScopedSECItem encoded_key( |
957 SEC_ASN1EncodeItem(NULL, | 1011 SEC_ASN1EncodeItem(NULL, |
958 NULL, | 1012 NULL, |
959 &private_key_info, | 1013 &private_key_info, |
960 SEC_ASN1_GET(SECKEY_PrivateKeyInfoTemplate))); | 1014 SEC_ASN1_GET(SECKEY_PrivateKeyInfoTemplate))); |
961 #else // defined(USE_NSS) | 1015 #else // defined(USE_NSS) |
962 crypto::ScopedSECItem encoded_key( | 1016 crypto::ScopedSECItem encoded_key( |
963 PK11_ExportDERPrivateKeyInfo(key->key(), NULL)); | 1017 PK11_ExportDERPrivateKeyInfo(key->key(), NULL)); |
964 #endif // defined(USE_NSS) | 1018 #endif // defined(USE_NSS) |
965 | 1019 |
966 if (!encoded_key.get()) | 1020 if (!encoded_key.get()) |
967 return Status::OperationError(); | 1021 return Status::OperationError(); |
968 | 1022 |
969 *buffer = CreateArrayBuffer(encoded_key->data, encoded_key->len); | 1023 buffer->assign(encoded_key->data, encoded_key->data + encoded_key->len); |
970 return Status::Success(); | 1024 return Status::Success(); |
971 } | 1025 } |
972 | 1026 |
973 Status ImportKeyPkcs8(const blink::WebCryptoAlgorithm& algorithm, | 1027 Status ImportKeyPkcs8(const blink::WebCryptoAlgorithm& algorithm, |
974 const CryptoData& key_data, | 1028 const CryptoData& key_data, |
975 bool extractable, | 1029 bool extractable, |
976 blink::WebCryptoKeyUsageMask usage_mask, | 1030 blink::WebCryptoKeyUsageMask usage_mask, |
977 blink::WebCryptoKey* key) { | 1031 blink::WebCryptoKey* key) { |
978 | |
979 DCHECK(key); | 1032 DCHECK(key); |
980 | 1033 |
981 if (!key_data.byte_length()) | 1034 if (!key_data.byte_length()) |
982 return Status::ErrorImportEmptyKeyData(); | 1035 return Status::ErrorImportEmptyKeyData(); |
983 DCHECK(key_data.bytes()); | 1036 DCHECK(key_data.bytes()); |
984 | 1037 |
985 // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 PKCS#8 | 1038 // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 PKCS#8 |
986 // private key info object. | 1039 // private key info object. |
987 SECItem pki_der = MakeSECItemForBuffer(key_data); | 1040 SECItem pki_der = MakeSECItemForBuffer(key_data); |
988 | 1041 |
(...skipping 14 matching lines...) Expand all Loading... |
1003 crypto::ScopedSECKEYPrivateKey private_key(seckey_private_key); | 1056 crypto::ScopedSECKEYPrivateKey private_key(seckey_private_key); |
1004 | 1057 |
1005 const KeyType sec_key_type = SECKEY_GetPrivateKeyType(private_key.get()); | 1058 const KeyType sec_key_type = SECKEY_GetPrivateKeyType(private_key.get()); |
1006 if (!ValidateNssKeyTypeAgainstInputAlgorithm(sec_key_type, algorithm)) | 1059 if (!ValidateNssKeyTypeAgainstInputAlgorithm(sec_key_type, algorithm)) |
1007 return Status::DataError(); | 1060 return Status::DataError(); |
1008 | 1061 |
1009 blink::WebCryptoKeyAlgorithm key_algorithm; | 1062 blink::WebCryptoKeyAlgorithm key_algorithm; |
1010 if (!CreatePrivateKeyAlgorithm(algorithm, private_key.get(), &key_algorithm)) | 1063 if (!CreatePrivateKeyAlgorithm(algorithm, private_key.get(), &key_algorithm)) |
1011 return Status::ErrorUnexpected(); | 1064 return Status::ErrorUnexpected(); |
1012 | 1065 |
1013 *key = blink::WebCryptoKey::create(new PrivateKey(private_key.Pass()), | 1066 scoped_ptr<PrivateKey> key_handle; |
| 1067 Status status = |
| 1068 PrivateKey::Create(private_key.Pass(), key_algorithm, &key_handle); |
| 1069 if (status.IsError()) |
| 1070 return status; |
| 1071 |
| 1072 *key = blink::WebCryptoKey::create(key_handle.release(), |
1014 blink::WebCryptoKeyTypePrivate, | 1073 blink::WebCryptoKeyTypePrivate, |
1015 extractable, | 1074 extractable, |
1016 key_algorithm, | 1075 key_algorithm, |
1017 usage_mask); | 1076 usage_mask); |
1018 | 1077 |
1019 return Status::Success(); | 1078 return Status::Success(); |
1020 } | 1079 } |
1021 | 1080 |
1022 // ----------------------------------- | 1081 // ----------------------------------- |
1023 // Hmac | 1082 // Hmac |
1024 // ----------------------------------- | 1083 // ----------------------------------- |
1025 | 1084 |
1026 Status SignHmac(SymKey* key, | 1085 Status SignHmac(SymKey* key, |
1027 const blink::WebCryptoAlgorithm& hash, | 1086 const blink::WebCryptoAlgorithm& hash, |
1028 const CryptoData& data, | 1087 const CryptoData& data, |
1029 blink::WebArrayBuffer* buffer) { | 1088 std::vector<uint8>* buffer) { |
1030 DCHECK_EQ(PK11_GetMechanism(key->key()), WebCryptoHashToHMACMechanism(hash)); | 1089 DCHECK_EQ(PK11_GetMechanism(key->key()), WebCryptoHashToHMACMechanism(hash)); |
1031 | 1090 |
1032 SECItem param_item = {siBuffer, NULL, 0}; | 1091 SECItem param_item = {siBuffer, NULL, 0}; |
1033 SECItem data_item = MakeSECItemForBuffer(data); | 1092 SECItem data_item = MakeSECItemForBuffer(data); |
1034 // First call is to figure out the length. | 1093 // First call is to figure out the length. |
1035 SECItem signature_item = {siBuffer, NULL, 0}; | 1094 SECItem signature_item = {siBuffer, NULL, 0}; |
1036 | 1095 |
1037 if (PK11_SignWithSymKey(key->key(), | 1096 if (PK11_SignWithSymKey(key->key(), |
1038 PK11_GetMechanism(key->key()), | 1097 PK11_GetMechanism(key->key()), |
1039 ¶m_item, | 1098 ¶m_item, |
1040 &signature_item, | 1099 &signature_item, |
1041 &data_item) != SECSuccess) { | 1100 &data_item) != SECSuccess) { |
1042 return Status::OperationError(); | 1101 return Status::OperationError(); |
1043 } | 1102 } |
1044 | 1103 |
1045 DCHECK_NE(0u, signature_item.len); | 1104 DCHECK_NE(0u, signature_item.len); |
1046 | 1105 |
1047 *buffer = blink::WebArrayBuffer::create(signature_item.len, 1); | 1106 buffer->resize(signature_item.len); |
1048 signature_item.data = reinterpret_cast<unsigned char*>(buffer->data()); | 1107 signature_item.data = Uint8VectorStart(buffer); |
1049 | 1108 |
1050 if (PK11_SignWithSymKey(key->key(), | 1109 if (PK11_SignWithSymKey(key->key(), |
1051 PK11_GetMechanism(key->key()), | 1110 PK11_GetMechanism(key->key()), |
1052 ¶m_item, | 1111 ¶m_item, |
1053 &signature_item, | 1112 &signature_item, |
1054 &data_item) != SECSuccess) { | 1113 &data_item) != SECSuccess) { |
1055 return Status::OperationError(); | 1114 return Status::OperationError(); |
1056 } | 1115 } |
1057 | 1116 |
1058 DCHECK_EQ(buffer->byteLength(), signature_item.len); | 1117 DCHECK_EQ(buffer->size(), signature_item.len); |
1059 return Status::Success(); | 1118 return Status::Success(); |
1060 } | 1119 } |
1061 | 1120 |
1062 // ----------------------------------- | 1121 // ----------------------------------- |
1063 // RsaEsPkcs1v1_5 | 1122 // RsaEsPkcs1v1_5 |
1064 // ----------------------------------- | 1123 // ----------------------------------- |
1065 | 1124 |
1066 Status EncryptRsaEsPkcs1v1_5(PublicKey* key, | 1125 Status EncryptRsaEsPkcs1v1_5(PublicKey* key, |
1067 const CryptoData& data, | 1126 const CryptoData& data, |
1068 blink::WebArrayBuffer* buffer) { | 1127 std::vector<uint8>* buffer) { |
1069 const unsigned int encrypted_length_bytes = | 1128 const unsigned int encrypted_length_bytes = |
1070 SECKEY_PublicKeyStrength(key->key()); | 1129 SECKEY_PublicKeyStrength(key->key()); |
1071 | 1130 |
1072 // RSAES can operate on messages up to a length of k - 11, where k is the | 1131 // RSAES can operate on messages up to a length of k - 11, where k is the |
1073 // octet length of the RSA modulus. | 1132 // octet length of the RSA modulus. |
1074 if (encrypted_length_bytes < 11 || | 1133 if (encrypted_length_bytes < 11 || |
1075 encrypted_length_bytes - 11 < data.byte_length()) | 1134 encrypted_length_bytes - 11 < data.byte_length()) |
1076 return Status::ErrorDataTooLarge(); | 1135 return Status::ErrorDataTooLarge(); |
1077 | 1136 |
1078 *buffer = blink::WebArrayBuffer::create(encrypted_length_bytes, 1); | 1137 buffer->resize(encrypted_length_bytes); |
1079 unsigned char* const buffer_data = | 1138 unsigned char* const buffer_data = Uint8VectorStart(buffer); |
1080 reinterpret_cast<unsigned char*>(buffer->data()); | |
1081 | 1139 |
1082 if (PK11_PubEncryptPKCS1(key->key(), | 1140 if (PK11_PubEncryptPKCS1(key->key(), |
1083 buffer_data, | 1141 buffer_data, |
1084 const_cast<unsigned char*>(data.bytes()), | 1142 const_cast<unsigned char*>(data.bytes()), |
1085 data.byte_length(), | 1143 data.byte_length(), |
1086 NULL) != SECSuccess) { | 1144 NULL) != SECSuccess) { |
1087 return Status::OperationError(); | 1145 return Status::OperationError(); |
1088 } | 1146 } |
1089 return Status::Success(); | 1147 return Status::Success(); |
1090 } | 1148 } |
1091 | 1149 |
1092 Status DecryptRsaEsPkcs1v1_5(PrivateKey* key, | 1150 Status DecryptRsaEsPkcs1v1_5(PrivateKey* key, |
1093 const CryptoData& data, | 1151 const CryptoData& data, |
1094 blink::WebArrayBuffer* buffer) { | 1152 std::vector<uint8>* buffer) { |
1095 const int modulus_length_bytes = PK11_GetPrivateModulusLen(key->key()); | 1153 const int modulus_length_bytes = PK11_GetPrivateModulusLen(key->key()); |
1096 if (modulus_length_bytes <= 0) | 1154 if (modulus_length_bytes <= 0) |
1097 return Status::ErrorUnexpected(); | 1155 return Status::ErrorUnexpected(); |
1098 const unsigned int max_output_length_bytes = modulus_length_bytes; | 1156 const unsigned int max_output_length_bytes = modulus_length_bytes; |
1099 | 1157 |
1100 *buffer = blink::WebArrayBuffer::create(max_output_length_bytes, 1); | 1158 buffer->resize(max_output_length_bytes); |
1101 unsigned char* const buffer_data = | 1159 unsigned char* const buffer_data = Uint8VectorStart(buffer); |
1102 reinterpret_cast<unsigned char*>(buffer->data()); | |
1103 | 1160 |
1104 unsigned int output_length_bytes = 0; | 1161 unsigned int output_length_bytes = 0; |
1105 if (PK11_PrivDecryptPKCS1(key->key(), | 1162 if (PK11_PrivDecryptPKCS1(key->key(), |
1106 buffer_data, | 1163 buffer_data, |
1107 &output_length_bytes, | 1164 &output_length_bytes, |
1108 max_output_length_bytes, | 1165 max_output_length_bytes, |
1109 const_cast<unsigned char*>(data.bytes()), | 1166 const_cast<unsigned char*>(data.bytes()), |
1110 data.byte_length()) != SECSuccess) { | 1167 data.byte_length()) != SECSuccess) { |
1111 return Status::OperationError(); | 1168 return Status::OperationError(); |
1112 } | 1169 } |
1113 DCHECK_LE(output_length_bytes, max_output_length_bytes); | 1170 DCHECK_LE(output_length_bytes, max_output_length_bytes); |
1114 ShrinkBuffer(buffer, output_length_bytes); | 1171 buffer->resize(output_length_bytes); |
1115 return Status::Success(); | 1172 return Status::Success(); |
1116 } | 1173 } |
1117 | 1174 |
1118 // ----------------------------------- | 1175 // ----------------------------------- |
1119 // RsaSsaPkcs1v1_5 | 1176 // RsaSsaPkcs1v1_5 |
1120 // ----------------------------------- | 1177 // ----------------------------------- |
1121 | 1178 |
1122 Status SignRsaSsaPkcs1v1_5(PrivateKey* key, | 1179 Status SignRsaSsaPkcs1v1_5(PrivateKey* key, |
1123 const blink::WebCryptoAlgorithm& hash, | 1180 const blink::WebCryptoAlgorithm& hash, |
1124 const CryptoData& data, | 1181 const CryptoData& data, |
1125 blink::WebArrayBuffer* buffer) { | 1182 std::vector<uint8>* buffer) { |
1126 // Pick the NSS signing algorithm by combining RSA-SSA (RSA PKCS1) and the | 1183 // Pick the NSS signing algorithm by combining RSA-SSA (RSA PKCS1) and the |
1127 // inner hash of the input Web Crypto algorithm. | 1184 // inner hash of the input Web Crypto algorithm. |
1128 SECOidTag sign_alg_tag; | 1185 SECOidTag sign_alg_tag; |
1129 switch (hash.id()) { | 1186 switch (hash.id()) { |
1130 case blink::WebCryptoAlgorithmIdSha1: | 1187 case blink::WebCryptoAlgorithmIdSha1: |
1131 sign_alg_tag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; | 1188 sign_alg_tag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; |
1132 break; | 1189 break; |
1133 case blink::WebCryptoAlgorithmIdSha256: | 1190 case blink::WebCryptoAlgorithmIdSha256: |
1134 sign_alg_tag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION; | 1191 sign_alg_tag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION; |
1135 break; | 1192 break; |
1136 case blink::WebCryptoAlgorithmIdSha384: | 1193 case blink::WebCryptoAlgorithmIdSha384: |
1137 sign_alg_tag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION; | 1194 sign_alg_tag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION; |
1138 break; | 1195 break; |
1139 case blink::WebCryptoAlgorithmIdSha512: | 1196 case blink::WebCryptoAlgorithmIdSha512: |
1140 sign_alg_tag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION; | 1197 sign_alg_tag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION; |
1141 break; | 1198 break; |
1142 default: | 1199 default: |
1143 return Status::ErrorUnsupported(); | 1200 return Status::ErrorUnsupported(); |
1144 } | 1201 } |
1145 | 1202 |
1146 crypto::ScopedSECItem signature_item(SECITEM_AllocItem(NULL, NULL, 0)); | 1203 crypto::ScopedSECItem signature_item(SECITEM_AllocItem(NULL, NULL, 0)); |
1147 if (SEC_SignData(signature_item.get(), | 1204 if (SEC_SignData(signature_item.get(), |
1148 data.bytes(), | 1205 data.bytes(), |
1149 data.byte_length(), | 1206 data.byte_length(), |
1150 key->key(), | 1207 key->key(), |
1151 sign_alg_tag) != SECSuccess) { | 1208 sign_alg_tag) != SECSuccess) { |
1152 return Status::OperationError(); | 1209 return Status::OperationError(); |
1153 } | 1210 } |
1154 | 1211 |
1155 *buffer = CreateArrayBuffer(signature_item->data, signature_item->len); | 1212 buffer->assign(signature_item->data, |
| 1213 signature_item->data + signature_item->len); |
1156 return Status::Success(); | 1214 return Status::Success(); |
1157 } | 1215 } |
1158 | 1216 |
1159 Status VerifyRsaSsaPkcs1v1_5(PublicKey* key, | 1217 Status VerifyRsaSsaPkcs1v1_5(PublicKey* key, |
1160 const blink::WebCryptoAlgorithm& hash, | 1218 const blink::WebCryptoAlgorithm& hash, |
1161 const CryptoData& signature, | 1219 const CryptoData& signature, |
1162 const CryptoData& data, | 1220 const CryptoData& data, |
1163 bool* signature_match) { | 1221 bool* signature_match) { |
1164 const SECItem signature_item = MakeSECItemForBuffer(signature); | 1222 const SECItem signature_item = MakeSECItemForBuffer(signature); |
1165 | 1223 |
(...skipping 24 matching lines...) Expand all Loading... |
1190 hash_alg_tag, | 1248 hash_alg_tag, |
1191 NULL, | 1249 NULL, |
1192 NULL); | 1250 NULL); |
1193 return Status::Success(); | 1251 return Status::Success(); |
1194 } | 1252 } |
1195 | 1253 |
1196 Status EncryptDecryptAesCbc(EncryptOrDecrypt mode, | 1254 Status EncryptDecryptAesCbc(EncryptOrDecrypt mode, |
1197 SymKey* key, | 1255 SymKey* key, |
1198 const CryptoData& data, | 1256 const CryptoData& data, |
1199 const CryptoData& iv, | 1257 const CryptoData& iv, |
1200 blink::WebArrayBuffer* buffer) { | 1258 std::vector<uint8>* buffer) { |
1201 // TODO(eroman): Inline. | 1259 // TODO(eroman): Inline. |
1202 return AesCbcEncryptDecrypt(mode, key, iv, data, buffer); | 1260 return AesCbcEncryptDecrypt(mode, key, iv, data, buffer); |
1203 } | 1261 } |
1204 | 1262 |
1205 Status EncryptDecryptAesGcm(EncryptOrDecrypt mode, | 1263 Status EncryptDecryptAesGcm(EncryptOrDecrypt mode, |
1206 SymKey* key, | 1264 SymKey* key, |
1207 const CryptoData& data, | 1265 const CryptoData& data, |
1208 const CryptoData& iv, | 1266 const CryptoData& iv, |
1209 const CryptoData& additional_data, | 1267 const CryptoData& additional_data, |
1210 unsigned int tag_length_bits, | 1268 unsigned int tag_length_bits, |
1211 blink::WebArrayBuffer* buffer) { | 1269 std::vector<uint8>* buffer) { |
1212 // TODO(eroman): Inline. | 1270 // TODO(eroman): Inline. |
1213 return AesGcmEncryptDecrypt( | 1271 return AesGcmEncryptDecrypt( |
1214 mode, key, data, iv, additional_data, tag_length_bits, buffer); | 1272 mode, key, data, iv, additional_data, tag_length_bits, buffer); |
1215 } | 1273 } |
1216 | 1274 |
1217 // ----------------------------------- | 1275 // ----------------------------------- |
1218 // Key generation | 1276 // Key generation |
1219 // ----------------------------------- | 1277 // ----------------------------------- |
1220 | 1278 |
1221 Status GenerateRsaKeyPair(const blink::WebCryptoAlgorithm& algorithm, | 1279 Status GenerateRsaKeyPair(const blink::WebCryptoAlgorithm& algorithm, |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1277 operation_flags, | 1335 operation_flags, |
1278 operation_flags_mask, | 1336 operation_flags_mask, |
1279 NULL)); | 1337 NULL)); |
1280 if (!private_key) | 1338 if (!private_key) |
1281 return Status::OperationError(); | 1339 return Status::OperationError(); |
1282 | 1340 |
1283 blink::WebCryptoKeyAlgorithm key_algorithm; | 1341 blink::WebCryptoKeyAlgorithm key_algorithm; |
1284 if (!CreatePublicKeyAlgorithm(algorithm, sec_public_key, &key_algorithm)) | 1342 if (!CreatePublicKeyAlgorithm(algorithm, sec_public_key, &key_algorithm)) |
1285 return Status::ErrorUnexpected(); | 1343 return Status::ErrorUnexpected(); |
1286 | 1344 |
1287 *public_key = blink::WebCryptoKey::create( | 1345 scoped_ptr<PublicKey> public_key_handle; |
1288 new PublicKey(crypto::ScopedSECKEYPublicKey(sec_public_key)), | 1346 Status status = PublicKey::Create( |
1289 blink::WebCryptoKeyTypePublic, | 1347 crypto::ScopedSECKEYPublicKey(sec_public_key), &public_key_handle); |
1290 true, | 1348 if (status.IsError()) |
1291 key_algorithm, | 1349 return status; |
1292 usage_mask); | 1350 |
1293 *private_key = | 1351 scoped_ptr<PrivateKey> private_key_handle; |
1294 blink::WebCryptoKey::create(new PrivateKey(scoped_sec_private_key.Pass()), | 1352 status = PrivateKey::Create( |
1295 blink::WebCryptoKeyTypePrivate, | 1353 scoped_sec_private_key.Pass(), key_algorithm, &private_key_handle); |
1296 extractable, | 1354 if (status.IsError()) |
1297 key_algorithm, | 1355 return status; |
1298 usage_mask); | 1356 |
| 1357 *public_key = blink::WebCryptoKey::create(public_key_handle.release(), |
| 1358 blink::WebCryptoKeyTypePublic, |
| 1359 true, |
| 1360 key_algorithm, |
| 1361 usage_mask); |
| 1362 *private_key = blink::WebCryptoKey::create(private_key_handle.release(), |
| 1363 blink::WebCryptoKeyTypePrivate, |
| 1364 extractable, |
| 1365 key_algorithm, |
| 1366 usage_mask); |
1299 | 1367 |
1300 return Status::Success(); | 1368 return Status::Success(); |
1301 } | 1369 } |
1302 | 1370 |
1303 void Init() { crypto::EnsureNSSInit(); } | 1371 void Init() { |
| 1372 crypto::EnsureNSSInit(); |
| 1373 } |
1304 | 1374 |
1305 Status DigestSha(blink::WebCryptoAlgorithmId algorithm, | 1375 Status DigestSha(blink::WebCryptoAlgorithmId algorithm, |
1306 const CryptoData& data, | 1376 const CryptoData& data, |
1307 blink::WebArrayBuffer* buffer) { | 1377 std::vector<uint8>* buffer) { |
1308 DigestorNSS digestor(algorithm); | 1378 DigestorNSS digestor(algorithm); |
1309 Status error = digestor.ConsumeWithStatus(data.bytes(), data.byte_length()); | 1379 Status error = digestor.ConsumeWithStatus(data.bytes(), data.byte_length()); |
1310 // http://crbug.com/366427: the spec does not define any other failures for | 1380 // http://crbug.com/366427: the spec does not define any other failures for |
1311 // digest, so none of the subsequent errors are spec compliant. | 1381 // digest, so none of the subsequent errors are spec compliant. |
1312 if (!error.IsSuccess()) | 1382 if (!error.IsSuccess()) |
1313 return error; | 1383 return error; |
1314 return digestor.FinishWithWebArrayAndStatus(buffer); | 1384 return digestor.FinishWithVectorAndStatus(buffer); |
1315 } | 1385 } |
1316 | 1386 |
1317 scoped_ptr<blink::WebCryptoDigestor> CreateDigestor( | 1387 scoped_ptr<blink::WebCryptoDigestor> CreateDigestor( |
1318 blink::WebCryptoAlgorithmId algorithm_id) { | 1388 blink::WebCryptoAlgorithmId algorithm_id) { |
1319 return scoped_ptr<blink::WebCryptoDigestor>(new DigestorNSS(algorithm_id)); | 1389 return scoped_ptr<blink::WebCryptoDigestor>(new DigestorNSS(algorithm_id)); |
1320 } | 1390 } |
1321 | 1391 |
1322 Status GenerateSecretKey(const blink::WebCryptoAlgorithm& algorithm, | 1392 Status GenerateSecretKey(const blink::WebCryptoAlgorithm& algorithm, |
1323 bool extractable, | 1393 bool extractable, |
1324 blink::WebCryptoKeyUsageMask usage_mask, | 1394 blink::WebCryptoKeyUsageMask usage_mask, |
(...skipping 12 matching lines...) Expand all Loading... |
1337 crypto::ScopedPK11SymKey pk11_key( | 1407 crypto::ScopedPK11SymKey pk11_key( |
1338 PK11_KeyGen(slot.get(), mech, NULL, keylen_bytes, NULL)); | 1408 PK11_KeyGen(slot.get(), mech, NULL, keylen_bytes, NULL)); |
1339 | 1409 |
1340 if (!pk11_key) | 1410 if (!pk11_key) |
1341 return Status::OperationError(); | 1411 return Status::OperationError(); |
1342 | 1412 |
1343 blink::WebCryptoKeyAlgorithm key_algorithm; | 1413 blink::WebCryptoKeyAlgorithm key_algorithm; |
1344 if (!CreateSecretKeyAlgorithm(algorithm, keylen_bytes, &key_algorithm)) | 1414 if (!CreateSecretKeyAlgorithm(algorithm, keylen_bytes, &key_algorithm)) |
1345 return Status::ErrorUnexpected(); | 1415 return Status::ErrorUnexpected(); |
1346 | 1416 |
1347 *key = blink::WebCryptoKey::create(new SymKey(pk11_key.Pass()), | 1417 scoped_ptr<SymKey> key_handle; |
1348 key_type, | 1418 Status status = SymKey::Create(pk11_key.Pass(), &key_handle); |
1349 extractable, | 1419 if (status.IsError()) |
1350 key_algorithm, | 1420 return status; |
1351 usage_mask); | 1421 |
| 1422 *key = blink::WebCryptoKey::create( |
| 1423 key_handle.release(), key_type, extractable, key_algorithm, usage_mask); |
1352 return Status::Success(); | 1424 return Status::Success(); |
1353 } | 1425 } |
1354 | 1426 |
1355 Status ImportRsaPublicKey(const blink::WebCryptoAlgorithm& algorithm, | 1427 Status ImportRsaPublicKey(const blink::WebCryptoAlgorithm& algorithm, |
1356 bool extractable, | 1428 bool extractable, |
1357 blink::WebCryptoKeyUsageMask usage_mask, | 1429 blink::WebCryptoKeyUsageMask usage_mask, |
1358 const CryptoData& modulus_data, | 1430 const CryptoData& modulus_data, |
1359 const CryptoData& exponent_data, | 1431 const CryptoData& exponent_data, |
1360 blink::WebCryptoKey* key) { | 1432 blink::WebCryptoKey* key) { |
1361 | |
1362 if (!modulus_data.byte_length()) | 1433 if (!modulus_data.byte_length()) |
1363 return Status::ErrorImportRsaEmptyModulus(); | 1434 return Status::ErrorImportRsaEmptyModulus(); |
1364 | 1435 |
1365 if (!exponent_data.byte_length()) | 1436 if (!exponent_data.byte_length()) |
1366 return Status::ErrorImportRsaEmptyExponent(); | 1437 return Status::ErrorImportRsaEmptyExponent(); |
1367 | 1438 |
1368 DCHECK(modulus_data.bytes()); | 1439 DCHECK(modulus_data.bytes()); |
1369 DCHECK(exponent_data.bytes()); | 1440 DCHECK(exponent_data.bytes()); |
1370 | 1441 |
1371 // NSS does not provide a way to create an RSA public key directly from the | 1442 // NSS does not provide a way to create an RSA public key directly from the |
(...skipping 28 matching lines...) Expand all Loading... |
1400 // Import the DER-encoded public key to create an RSA SECKEYPublicKey. | 1471 // Import the DER-encoded public key to create an RSA SECKEYPublicKey. |
1401 crypto::ScopedSECKEYPublicKey pubkey( | 1472 crypto::ScopedSECKEYPublicKey pubkey( |
1402 SECKEY_ImportDERPublicKey(pubkey_der.get(), CKK_RSA)); | 1473 SECKEY_ImportDERPublicKey(pubkey_der.get(), CKK_RSA)); |
1403 if (!pubkey) | 1474 if (!pubkey) |
1404 return Status::OperationError(); | 1475 return Status::OperationError(); |
1405 | 1476 |
1406 blink::WebCryptoKeyAlgorithm key_algorithm; | 1477 blink::WebCryptoKeyAlgorithm key_algorithm; |
1407 if (!CreatePublicKeyAlgorithm(algorithm, pubkey.get(), &key_algorithm)) | 1478 if (!CreatePublicKeyAlgorithm(algorithm, pubkey.get(), &key_algorithm)) |
1408 return Status::ErrorUnexpected(); | 1479 return Status::ErrorUnexpected(); |
1409 | 1480 |
1410 *key = blink::WebCryptoKey::create(new PublicKey(pubkey.Pass()), | 1481 scoped_ptr<PublicKey> key_handle; |
| 1482 Status status = PublicKey::Create(pubkey.Pass(), &key_handle); |
| 1483 if (status.IsError()) |
| 1484 return status; |
| 1485 |
| 1486 *key = blink::WebCryptoKey::create(key_handle.release(), |
1411 blink::WebCryptoKeyTypePublic, | 1487 blink::WebCryptoKeyTypePublic, |
1412 extractable, | 1488 extractable, |
1413 key_algorithm, | 1489 key_algorithm, |
1414 usage_mask); | 1490 usage_mask); |
1415 return Status::Success(); | 1491 return Status::Success(); |
1416 } | 1492 } |
1417 | 1493 |
1418 Status WrapSymKeyAesKw(SymKey* wrapping_key, | 1494 Status WrapSymKeyAesKw(SymKey* wrapping_key, |
1419 SymKey* key, | 1495 SymKey* key, |
1420 blink::WebArrayBuffer* buffer) { | 1496 std::vector<uint8>* buffer) { |
1421 // The data size must be at least 16 bytes and a multiple of 8 bytes. | 1497 // The data size must be at least 16 bytes and a multiple of 8 bytes. |
1422 // RFC 3394 does not specify a maximum allowed data length, but since only | 1498 // RFC 3394 does not specify a maximum allowed data length, but since only |
1423 // keys are being wrapped in this application (which are small), a reasonable | 1499 // keys are being wrapped in this application (which are small), a reasonable |
1424 // max limit is whatever will fit into an unsigned. For the max size test, | 1500 // max limit is whatever will fit into an unsigned. For the max size test, |
1425 // note that AES Key Wrap always adds 8 bytes to the input data size. | 1501 // note that AES Key Wrap always adds 8 bytes to the input data size. |
1426 const unsigned int input_length = PK11_GetKeyLength(key->key()); | 1502 const unsigned int input_length = PK11_GetKeyLength(key->key()); |
1427 if (input_length < 16) | 1503 if (input_length < 16) |
1428 return Status::ErrorDataTooSmall(); | 1504 return Status::ErrorDataTooSmall(); |
1429 if (input_length > UINT_MAX - 8) | 1505 if (input_length > UINT_MAX - 8) |
1430 return Status::ErrorDataTooLarge(); | 1506 return Status::ErrorDataTooLarge(); |
1431 if (input_length % 8) | 1507 if (input_length % 8) |
1432 return Status::ErrorInvalidAesKwDataLength(); | 1508 return Status::ErrorInvalidAesKwDataLength(); |
1433 | 1509 |
1434 SECItem iv_item = MakeSECItemForBuffer(CryptoData(kAesIv, sizeof(kAesIv))); | 1510 SECItem iv_item = MakeSECItemForBuffer(CryptoData(kAesIv, sizeof(kAesIv))); |
1435 crypto::ScopedSECItem param_item( | 1511 crypto::ScopedSECItem param_item( |
1436 PK11_ParamFromIV(CKM_NSS_AES_KEY_WRAP, &iv_item)); | 1512 PK11_ParamFromIV(CKM_NSS_AES_KEY_WRAP, &iv_item)); |
1437 if (!param_item) | 1513 if (!param_item) |
1438 return Status::ErrorUnexpected(); | 1514 return Status::ErrorUnexpected(); |
1439 | 1515 |
1440 const unsigned int output_length = input_length + 8; | 1516 const unsigned int output_length = input_length + 8; |
1441 *buffer = blink::WebArrayBuffer::create(output_length, 1); | 1517 buffer->resize(output_length); |
1442 SECItem wrapped_key_item = MakeSECItemForBuffer(CryptoData(*buffer)); | 1518 SECItem wrapped_key_item = MakeSECItemForBuffer(CryptoData(*buffer)); |
1443 | 1519 |
1444 if (SECSuccess != PK11_WrapSymKey(CKM_NSS_AES_KEY_WRAP, | 1520 if (SECSuccess != PK11_WrapSymKey(CKM_NSS_AES_KEY_WRAP, |
1445 param_item.get(), | 1521 param_item.get(), |
1446 wrapping_key->key(), | 1522 wrapping_key->key(), |
1447 key->key(), | 1523 key->key(), |
1448 &wrapped_key_item)) { | 1524 &wrapped_key_item)) { |
1449 return Status::OperationError(); | 1525 return Status::OperationError(); |
1450 } | 1526 } |
1451 if (output_length != wrapped_key_item.len) | 1527 if (output_length != wrapped_key_item.len) |
(...skipping 20 matching lines...) Expand all Loading... |
1472 status = DoUnwrapSymKeyAesKw( | 1548 status = DoUnwrapSymKeyAesKw( |
1473 wrapped_key_data, wrapping_key, mechanism, flags, &unwrapped_key); | 1549 wrapped_key_data, wrapping_key, mechanism, flags, &unwrapped_key); |
1474 if (status.IsError()) | 1550 if (status.IsError()) |
1475 return status; | 1551 return status; |
1476 | 1552 |
1477 blink::WebCryptoKeyAlgorithm key_algorithm; | 1553 blink::WebCryptoKeyAlgorithm key_algorithm; |
1478 if (!CreateSecretKeyAlgorithm( | 1554 if (!CreateSecretKeyAlgorithm( |
1479 algorithm, PK11_GetKeyLength(unwrapped_key.get()), &key_algorithm)) | 1555 algorithm, PK11_GetKeyLength(unwrapped_key.get()), &key_algorithm)) |
1480 return Status::ErrorUnexpected(); | 1556 return Status::ErrorUnexpected(); |
1481 | 1557 |
1482 *key = blink::WebCryptoKey::create(new SymKey(unwrapped_key.Pass()), | 1558 scoped_ptr<SymKey> key_handle; |
| 1559 status = SymKey::Create(unwrapped_key.Pass(), &key_handle); |
| 1560 if (status.IsError()) |
| 1561 return status; |
| 1562 |
| 1563 *key = blink::WebCryptoKey::create(key_handle.release(), |
1483 blink::WebCryptoKeyTypeSecret, | 1564 blink::WebCryptoKeyTypeSecret, |
1484 extractable, | 1565 extractable, |
1485 key_algorithm, | 1566 key_algorithm, |
1486 usage_mask); | 1567 usage_mask); |
1487 return Status::Success(); | 1568 return Status::Success(); |
1488 } | 1569 } |
1489 | 1570 |
1490 Status DecryptAesKw(SymKey* wrapping_key, | 1571 Status DecryptAesKw(SymKey* wrapping_key, |
1491 const CryptoData& data, | 1572 const CryptoData& data, |
1492 blink::WebArrayBuffer* buffer) { | 1573 std::vector<uint8>* buffer) { |
1493 // Due to limitations in the NSS API for the AES-KW algorithm, |data| must be | 1574 // Due to limitations in the NSS API for the AES-KW algorithm, |data| must be |
1494 // temporarily viewed as a symmetric key to be unwrapped (decrypted). | 1575 // temporarily viewed as a symmetric key to be unwrapped (decrypted). |
1495 crypto::ScopedPK11SymKey decrypted; | 1576 crypto::ScopedPK11SymKey decrypted; |
1496 Status status = DoUnwrapSymKeyAesKw( | 1577 Status status = DoUnwrapSymKeyAesKw( |
1497 data, wrapping_key, CKK_GENERIC_SECRET, CKA_ENCRYPT, &decrypted); | 1578 data, wrapping_key, CKK_GENERIC_SECRET, CKA_ENCRYPT, &decrypted); |
1498 if (status.IsError()) | 1579 if (status.IsError()) |
1499 return status; | 1580 return status; |
1500 | 1581 |
1501 // Once the decrypt is complete, extract the resultant raw bytes from NSS and | 1582 // Once the decrypt is complete, extract the resultant raw bytes from NSS and |
1502 // return them to the caller. | 1583 // return them to the caller. |
1503 if (PK11_ExtractKeyValue(decrypted.get()) != SECSuccess) | 1584 if (PK11_ExtractKeyValue(decrypted.get()) != SECSuccess) |
1504 return Status::OperationError(); | 1585 return Status::OperationError(); |
1505 const SECItem* const key_data = PK11_GetKeyData(decrypted.get()); | 1586 const SECItem* const key_data = PK11_GetKeyData(decrypted.get()); |
1506 if (!key_data) | 1587 if (!key_data) |
1507 return Status::OperationError(); | 1588 return Status::OperationError(); |
1508 *buffer = webcrypto::CreateArrayBuffer(key_data->data, key_data->len); | 1589 buffer->assign(key_data->data, key_data->data + key_data->len); |
1509 | 1590 |
1510 return Status::Success(); | 1591 return Status::Success(); |
1511 } | 1592 } |
1512 | 1593 |
1513 Status WrapSymKeyRsaEs(PublicKey* wrapping_key, | 1594 Status WrapSymKeyRsaEs(PublicKey* wrapping_key, |
1514 SymKey* key, | 1595 SymKey* key, |
1515 blink::WebArrayBuffer* buffer) { | 1596 std::vector<uint8>* buffer) { |
1516 // Check the raw length of the key to be wrapped against the max size allowed | 1597 // Check the raw length of the key to be wrapped against the max size allowed |
1517 // by the RSA wrapping key. With PKCS#1 v1.5 padding used in this function, | 1598 // by the RSA wrapping key. With PKCS#1 v1.5 padding used in this function, |
1518 // the maximum data length that can be encrypted is the wrapping_key's modulus | 1599 // the maximum data length that can be encrypted is the wrapping_key's modulus |
1519 // byte length minus eleven bytes. | 1600 // byte length minus eleven bytes. |
1520 const unsigned int input_length_bytes = PK11_GetKeyLength(key->key()); | 1601 const unsigned int input_length_bytes = PK11_GetKeyLength(key->key()); |
1521 const unsigned int modulus_length_bytes = | 1602 const unsigned int modulus_length_bytes = |
1522 SECKEY_PublicKeyStrength(wrapping_key->key()); | 1603 SECKEY_PublicKeyStrength(wrapping_key->key()); |
1523 if (modulus_length_bytes < 11 || | 1604 if (modulus_length_bytes < 11 || |
1524 modulus_length_bytes - 11 < input_length_bytes) | 1605 modulus_length_bytes - 11 < input_length_bytes) |
1525 return Status::ErrorDataTooLarge(); | 1606 return Status::ErrorDataTooLarge(); |
1526 | 1607 |
1527 *buffer = blink::WebArrayBuffer::create(modulus_length_bytes, 1); | 1608 buffer->resize(modulus_length_bytes); |
1528 SECItem wrapped_key_item = MakeSECItemForBuffer(CryptoData(*buffer)); | 1609 SECItem wrapped_key_item = MakeSECItemForBuffer(CryptoData(*buffer)); |
1529 | 1610 |
1530 if (SECSuccess != | 1611 if (SECSuccess != |
1531 PK11_PubWrapSymKey( | 1612 PK11_PubWrapSymKey( |
1532 CKM_RSA_PKCS, wrapping_key->key(), key->key(), &wrapped_key_item)) { | 1613 CKM_RSA_PKCS, wrapping_key->key(), key->key(), &wrapped_key_item)) { |
1533 return Status::OperationError(); | 1614 return Status::OperationError(); |
1534 } | 1615 } |
1535 if (wrapped_key_item.len != modulus_length_bytes) | 1616 if (wrapped_key_item.len != modulus_length_bytes) |
1536 return Status::ErrorUnexpected(); | 1617 return Status::ErrorUnexpected(); |
1537 | 1618 |
1538 return Status::Success(); | 1619 return Status::Success(); |
1539 } | 1620 } |
1540 | 1621 |
1541 Status UnwrapSymKeyRsaEs(const CryptoData& wrapped_key_data, | 1622 Status UnwrapSymKeyRsaEs(const CryptoData& wrapped_key_data, |
1542 PrivateKey* wrapping_key, | 1623 PrivateKey* wrapping_key, |
1543 const blink::WebCryptoAlgorithm& algorithm, | 1624 const blink::WebCryptoAlgorithm& algorithm, |
1544 bool extractable, | 1625 bool extractable, |
1545 blink::WebCryptoKeyUsageMask usage_mask, | 1626 blink::WebCryptoKeyUsageMask usage_mask, |
1546 blink::WebCryptoKey* key) { | 1627 blink::WebCryptoKey* key) { |
1547 | |
1548 // Verify wrapped_key_data size does not exceed the modulus of the RSA key. | 1628 // Verify wrapped_key_data size does not exceed the modulus of the RSA key. |
1549 const int modulus_length_bytes = | 1629 const int modulus_length_bytes = |
1550 PK11_GetPrivateModulusLen(wrapping_key->key()); | 1630 PK11_GetPrivateModulusLen(wrapping_key->key()); |
1551 if (modulus_length_bytes <= 0) | 1631 if (modulus_length_bytes <= 0) |
1552 return Status::ErrorUnexpected(); | 1632 return Status::ErrorUnexpected(); |
1553 if (wrapped_key_data.byte_length() > | 1633 if (wrapped_key_data.byte_length() > |
1554 static_cast<unsigned int>(modulus_length_bytes)) | 1634 static_cast<unsigned int>(modulus_length_bytes)) |
1555 return Status::ErrorDataTooLarge(); | 1635 return Status::ErrorDataTooLarge(); |
1556 | 1636 |
1557 // Determine the proper NSS key properties from the input algorithm. | 1637 // Determine the proper NSS key properties from the input algorithm. |
(...skipping 16 matching lines...) Expand all Loading... |
1574 false)); | 1654 false)); |
1575 if (!unwrapped_key) | 1655 if (!unwrapped_key) |
1576 return Status::OperationError(); | 1656 return Status::OperationError(); |
1577 | 1657 |
1578 const unsigned int key_length = PK11_GetKeyLength(unwrapped_key.get()); | 1658 const unsigned int key_length = PK11_GetKeyLength(unwrapped_key.get()); |
1579 | 1659 |
1580 blink::WebCryptoKeyAlgorithm key_algorithm; | 1660 blink::WebCryptoKeyAlgorithm key_algorithm; |
1581 if (!CreateSecretKeyAlgorithm(algorithm, key_length, &key_algorithm)) | 1661 if (!CreateSecretKeyAlgorithm(algorithm, key_length, &key_algorithm)) |
1582 return Status::ErrorUnexpected(); | 1662 return Status::ErrorUnexpected(); |
1583 | 1663 |
1584 *key = blink::WebCryptoKey::create(new SymKey(unwrapped_key.Pass()), | 1664 scoped_ptr<SymKey> key_handle; |
| 1665 status = SymKey::Create(unwrapped_key.Pass(), &key_handle); |
| 1666 if (status.IsError()) |
| 1667 return status; |
| 1668 |
| 1669 *key = blink::WebCryptoKey::create(key_handle.release(), |
1585 blink::WebCryptoKeyTypeSecret, | 1670 blink::WebCryptoKeyTypeSecret, |
1586 extractable, | 1671 extractable, |
1587 key_algorithm, | 1672 key_algorithm, |
1588 usage_mask); | 1673 usage_mask); |
1589 return Status::Success(); | 1674 return Status::Success(); |
1590 } | 1675 } |
1591 | 1676 |
1592 } // namespace platform | 1677 } // namespace platform |
1593 | 1678 |
1594 } // namespace webcrypto | 1679 } // namespace webcrypto |
1595 | 1680 |
1596 } // namespace content | 1681 } // namespace content |
OLD | NEW |