Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(356)

Side by Side Diff: content/child/webcrypto/platform_crypto_nss.cc

Issue 233733004: [webcrypto] Make operations run on worker threads. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address sleevi comments Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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 &param, 391 &param,
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
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
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
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
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
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 &param_item, 1094 &param_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 &param_item, 1107 &param_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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698