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