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