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

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

Issue 155623005: Refactor to share more code between OpenSSL and NSS implementations. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Make CryptoData ctors explicit, and other comments Created 6 years, 10 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 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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/renderer/webcrypto/webcrypto_impl.h" 5 #include "content/renderer/webcrypto/platform_crypto.h"
6 6
7 #include <cryptohi.h> 7 #include <cryptohi.h>
8 #include <pk11pub.h> 8 #include <pk11pub.h>
9 #include <sechash.h> 9 #include <sechash.h>
10 10
11 #include <vector> 11 #include <vector>
12 12
13 #include "base/lazy_instance.h" 13 #include "base/lazy_instance.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "content/renderer/webcrypto/crypto_data.h"
15 #include "content/renderer/webcrypto/webcrypto_util.h" 16 #include "content/renderer/webcrypto/webcrypto_util.h"
16 #include "crypto/nss_util.h" 17 #include "crypto/nss_util.h"
17 #include "crypto/scoped_nss_types.h" 18 #include "crypto/scoped_nss_types.h"
18 #include "crypto/secure_util.h"
19 #include "third_party/WebKit/public/platform/WebArrayBuffer.h" 19 #include "third_party/WebKit/public/platform/WebArrayBuffer.h"
20 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" 20 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h"
21 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" 21 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
22 22
23 #if defined(USE_NSS) 23 #if defined(USE_NSS)
24 #include <dlfcn.h> 24 #include <dlfcn.h>
25 #endif 25 #endif
26 26
27 // At the time of this writing: 27 // At the time of this writing:
28 // * Windows and Mac builds ship with their own copy of NSS (3.15+) 28 // * Windows and Mac builds ship with their own copy of NSS (3.15+)
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 } 104 }
105 105
106 PK11_EncryptDecryptFunction pk11_encrypt_func_; 106 PK11_EncryptDecryptFunction pk11_encrypt_func_;
107 PK11_EncryptDecryptFunction pk11_decrypt_func_; 107 PK11_EncryptDecryptFunction pk11_decrypt_func_;
108 }; 108 };
109 109
110 base::LazyInstance<AesGcmSupport>::Leaky g_aes_gcm_support = 110 base::LazyInstance<AesGcmSupport>::Leaky g_aes_gcm_support =
111 LAZY_INSTANCE_INITIALIZER; 111 LAZY_INSTANCE_INITIALIZER;
112 112
113 namespace content { 113 namespace content {
114 namespace webcrypto {
115 namespace platform {
Ryan Sleevi 2014/02/13 04:24:24 Compare with your OpenSSL implementation, where yo
eroman 2014/02/13 23:05:38 Done.
114 116
115 using webcrypto::Status; 117 class Key : public blink::WebCryptoKeyHandle {
118 public:
119 virtual SymKey* AsSymKey() { return NULL; }
120 virtual PublicKey* AsPublicKey() { return NULL; }
121 virtual PrivateKey* AsPrivateKey() { return NULL; }
122 };
Ryan Sleevi 2014/02/13 04:24:24 Why do you declare this duplicate interface in bot
eroman 2014/02/13 23:05:38 Done.
116 123
117 namespace { 124 class SymKey : public Key {
118
119 class SymKeyHandle : public blink::WebCryptoKeyHandle {
120 public: 125 public:
121 explicit SymKeyHandle(crypto::ScopedPK11SymKey key) : key_(key.Pass()) {} 126 explicit SymKey(crypto::ScopedPK11SymKey key) : key_(key.Pass()) {}
122 127
123 PK11SymKey* key() { return key_.get(); } 128 PK11SymKey* key() { return key_.get(); }
124 129
130 virtual SymKey* AsSymKey() OVERRIDE { return this; }
131
125 private: 132 private:
126 crypto::ScopedPK11SymKey key_; 133 crypto::ScopedPK11SymKey key_;
127 134
128 DISALLOW_COPY_AND_ASSIGN(SymKeyHandle); 135 DISALLOW_COPY_AND_ASSIGN(SymKey);
129 }; 136 };
130 137
131 class PublicKeyHandle : public blink::WebCryptoKeyHandle { 138 class PublicKey : public Key {
132 public: 139 public:
133 explicit PublicKeyHandle(crypto::ScopedSECKEYPublicKey key) 140 explicit PublicKey(crypto::ScopedSECKEYPublicKey key) : key_(key.Pass()) {}
134 : key_(key.Pass()) {}
135 141
136 SECKEYPublicKey* key() { return key_.get(); } 142 SECKEYPublicKey* key() { return key_.get(); }
137 143
144 virtual PublicKey* AsPublicKey() OVERRIDE { return this; }
145
138 private: 146 private:
139 crypto::ScopedSECKEYPublicKey key_; 147 crypto::ScopedSECKEYPublicKey key_;
140 148
141 DISALLOW_COPY_AND_ASSIGN(PublicKeyHandle); 149 DISALLOW_COPY_AND_ASSIGN(PublicKey);
142 }; 150 };
143 151
144 class PrivateKeyHandle : public blink::WebCryptoKeyHandle { 152 class PrivateKey : public Key {
145 public: 153 public:
146 explicit PrivateKeyHandle(crypto::ScopedSECKEYPrivateKey key) 154 explicit PrivateKey(crypto::ScopedSECKEYPrivateKey key) : key_(key.Pass()) {}
147 : key_(key.Pass()) {}
148 155
149 SECKEYPrivateKey* key() { return key_.get(); } 156 SECKEYPrivateKey* key() { return key_.get(); }
150 157
158 virtual PrivateKey* AsPrivateKey() OVERRIDE { return this; }
159
151 private: 160 private:
152 crypto::ScopedSECKEYPrivateKey key_; 161 crypto::ScopedSECKEYPrivateKey key_;
153 162
154 DISALLOW_COPY_AND_ASSIGN(PrivateKeyHandle); 163 DISALLOW_COPY_AND_ASSIGN(PrivateKey);
155 }; 164 };
156 165
166 SymKey* ToSymKey(const blink::WebCryptoKey& key) {
167 return static_cast<Key*>(key.handle())->AsSymKey();
168 }
169
170 PublicKey* ToPublicKey(const blink::WebCryptoKey& key) {
171 return static_cast<Key*>(key.handle())->AsPublicKey();
172 }
173
174 PrivateKey* ToPrivateKey(const blink::WebCryptoKey& key) {
175 return static_cast<Key*>(key.handle())->AsPrivateKey();
176 }
177
178 namespace {
179
180 // Creates a SECItem for the data in |buffer|. This does NOT make a copy, so
181 // |buffer| should outlive the SECItem.
182 SECItem MakeSECItemForBuffer(const CryptoData& buffer) {
183 SECItem item = {
184 siBuffer,
185 // NSS requires non-const data even though it is just for input.
186 const_cast<unsigned char*>(buffer.bytes()),
187 buffer.byte_length()
188 };
189 return item;
190 }
191
157 HASH_HashType WebCryptoAlgorithmToNSSHashType( 192 HASH_HashType WebCryptoAlgorithmToNSSHashType(
158 const blink::WebCryptoAlgorithm& algorithm) { 193 blink::WebCryptoAlgorithmId algorithm) {
159 switch (algorithm.id()) { 194 switch (algorithm) {
160 case blink::WebCryptoAlgorithmIdSha1: 195 case blink::WebCryptoAlgorithmIdSha1:
161 return HASH_AlgSHA1; 196 return HASH_AlgSHA1;
162 case blink::WebCryptoAlgorithmIdSha224: 197 case blink::WebCryptoAlgorithmIdSha224:
163 return HASH_AlgSHA224; 198 return HASH_AlgSHA224;
164 case blink::WebCryptoAlgorithmIdSha256: 199 case blink::WebCryptoAlgorithmIdSha256:
165 return HASH_AlgSHA256; 200 return HASH_AlgSHA256;
166 case blink::WebCryptoAlgorithmIdSha384: 201 case blink::WebCryptoAlgorithmIdSha384:
167 return HASH_AlgSHA384; 202 return HASH_AlgSHA384;
168 case blink::WebCryptoAlgorithmIdSha512: 203 case blink::WebCryptoAlgorithmIdSha512:
169 return HASH_AlgSHA512; 204 return HASH_AlgSHA512;
(...skipping 17 matching lines...) Expand all
187 case blink::WebCryptoAlgorithmIdSha512: 222 case blink::WebCryptoAlgorithmIdSha512:
188 return CKM_SHA512_HMAC; 223 return CKM_SHA512_HMAC;
189 default: 224 default:
190 // Not a supported algorithm. 225 // Not a supported algorithm.
191 return CKM_INVALID_MECHANISM; 226 return CKM_INVALID_MECHANISM;
192 } 227 }
193 } 228 }
194 229
195 Status AesCbcEncryptDecrypt( 230 Status AesCbcEncryptDecrypt(
196 CK_ATTRIBUTE_TYPE operation, 231 CK_ATTRIBUTE_TYPE operation,
197 const blink::WebCryptoAlgorithm& algorithm, 232 SymKey* key,
198 const blink::WebCryptoKey& key, 233 const CryptoData& iv,
199 const unsigned char* data, 234 const CryptoData& data,
200 unsigned int data_size,
201 blink::WebArrayBuffer* buffer) { 235 blink::WebArrayBuffer* buffer) {
202 DCHECK_EQ(blink::WebCryptoAlgorithmIdAesCbc, algorithm.id());
203 DCHECK_EQ(algorithm.id(), key.algorithm().id());
204 DCHECK_EQ(blink::WebCryptoKeyTypeSecret, key.type());
205 DCHECK(operation == CKA_ENCRYPT || operation == CKA_DECRYPT); 236 DCHECK(operation == CKA_ENCRYPT || operation == CKA_DECRYPT);
206 237
207 SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle()); 238 SECItem iv_item = MakeSECItemForBuffer(iv);
208
209 const blink::WebCryptoAesCbcParams* params = algorithm.aesCbcParams();
210 if (params->iv().size() != AES_BLOCK_SIZE)
211 return Status::ErrorIncorrectSizeAesCbcIv();
212
213 SECItem iv_item;
214 iv_item.type = siBuffer;
215 iv_item.data = const_cast<unsigned char*>(params->iv().data());
216 iv_item.len = params->iv().size();
217 239
218 crypto::ScopedSECItem param(PK11_ParamFromIV(CKM_AES_CBC_PAD, &iv_item)); 240 crypto::ScopedSECItem param(PK11_ParamFromIV(CKM_AES_CBC_PAD, &iv_item));
219 if (!param) 241 if (!param)
220 return Status::Error(); 242 return Status::Error();
221 243
222 crypto::ScopedPK11Context context(PK11_CreateContextBySymKey( 244 crypto::ScopedPK11Context context(PK11_CreateContextBySymKey(
223 CKM_AES_CBC_PAD, operation, sym_key->key(), param.get())); 245 CKM_AES_CBC_PAD, operation, key->key(), param.get()));
224 246
225 if (!context.get()) 247 if (!context.get())
226 return Status::Error(); 248 return Status::Error();
227 249
228 // Oddly PK11_CipherOp takes input and output lengths as "int" rather than 250 // Oddly PK11_CipherOp takes input and output lengths as "int" rather than
229 // "unsigned int". Do some checks now to avoid integer overflowing. 251 // "unsigned int". Do some checks now to avoid integer overflowing.
230 if (data_size >= INT_MAX - AES_BLOCK_SIZE) { 252 if (data.byte_length() >= INT_MAX - AES_BLOCK_SIZE) {
231 // TODO(eroman): Handle this by chunking the input fed into NSS. Right now 253 // TODO(eroman): Handle this by chunking the input fed into NSS. Right now
232 // it doesn't make much difference since the one-shot API would end up 254 // it doesn't make much difference since the one-shot API would end up
233 // blowing out the memory and crashing anyway. 255 // blowing out the memory and crashing anyway.
234 return Status::ErrorDataTooLarge(); 256 return Status::ErrorDataTooLarge();
235 } 257 }
236 258
237 // PK11_CipherOp does an invalid memory access when given empty decryption 259 // PK11_CipherOp does an invalid memory access when given empty decryption
238 // input, or input which is not a multiple of the block size. See also 260 // input, or input which is not a multiple of the block size. See also
239 // https://bugzilla.mozilla.com/show_bug.cgi?id=921687. 261 // https://bugzilla.mozilla.com/show_bug.cgi?id=921687.
240 if (operation == CKA_DECRYPT && 262 if (operation == CKA_DECRYPT &&
241 (data_size == 0 || (data_size % AES_BLOCK_SIZE != 0))) { 263 (data.byte_length() == 0 || (data.byte_length() % AES_BLOCK_SIZE != 0))) {
242 return Status::Error(); 264 return Status::Error();
243 } 265 }
244 266
245 // TODO(eroman): Refine the output buffer size. It can be computed exactly for 267 // TODO(eroman): Refine the output buffer size. It can be computed exactly for
246 // encryption, and can be smaller for decryption. 268 // encryption, and can be smaller for decryption.
247 unsigned int output_max_len = data_size + AES_BLOCK_SIZE; 269 unsigned int output_max_len = data.byte_length() + AES_BLOCK_SIZE;
248 CHECK_GT(output_max_len, data_size); 270 CHECK_GT(output_max_len, data.byte_length());
249 271
250 *buffer = blink::WebArrayBuffer::create(output_max_len, 1); 272 *buffer = blink::WebArrayBuffer::create(output_max_len, 1);
251 273
252 unsigned char* buffer_data = reinterpret_cast<unsigned char*>(buffer->data()); 274 unsigned char* buffer_data = reinterpret_cast<unsigned char*>(buffer->data());
253 275
254 int output_len; 276 int output_len;
255 if (SECSuccess != PK11_CipherOp(context.get(), 277 if (SECSuccess != PK11_CipherOp(context.get(),
256 buffer_data, 278 buffer_data,
257 &output_len, 279 &output_len,
258 buffer->byteLength(), 280 buffer->byteLength(),
259 data, 281 data.bytes(),
260 data_size)) { 282 data.byte_length())) {
261 return Status::Error(); 283 return Status::Error();
262 } 284 }
263 285
264 unsigned int final_output_chunk_len; 286 unsigned int final_output_chunk_len;
265 if (SECSuccess != PK11_DigestFinal(context.get(), 287 if (SECSuccess != PK11_DigestFinal(context.get(),
266 buffer_data + output_len, 288 buffer_data + output_len,
267 &final_output_chunk_len, 289 &final_output_chunk_len,
268 output_max_len - output_len)) { 290 output_max_len - output_len)) {
269 return Status::Error(); 291 return Status::Error();
270 } 292 }
271 293
272 webcrypto::ShrinkBuffer(buffer, final_output_chunk_len + output_len); 294 ShrinkBuffer(buffer, final_output_chunk_len + output_len);
273 return Status::Success(); 295 return Status::Success();
274 } 296 }
275 297
276 // Helper to either encrypt or decrypt for AES-GCM. The result of encryption is 298 // Helper to either encrypt or decrypt for AES-GCM. The result of encryption is
277 // the concatenation of the ciphertext and the authentication tag. Similarly, 299 // the concatenation of the ciphertext and the authentication tag. Similarly,
278 // this is the expectation for the input to decryption. 300 // this is the expectation for the input to decryption.
279 Status AesGcmEncryptDecrypt( 301 Status AesGcmEncryptDecrypt(
280 bool encrypt, 302 bool encrypt,
281 const blink::WebCryptoAlgorithm& algorithm, 303 SymKey* key,
282 const blink::WebCryptoKey& key, 304 const blink::WebCryptoAesGcmParams* params,
Ryan Sleevi 2014/02/13 04:24:24 Do you mutate params here? If not, why not pass as
eroman 2014/02/13 23:05:38 Removed all together: Now passes in the parameters
283 const unsigned char* data, 305 const CryptoData& data,
284 unsigned int data_size,
285 blink::WebArrayBuffer* buffer) { 306 blink::WebArrayBuffer* buffer) {
286 DCHECK_EQ(blink::WebCryptoAlgorithmIdAesGcm, algorithm.id());
287 DCHECK_EQ(algorithm.id(), key.algorithm().id());
288 DCHECK_EQ(blink::WebCryptoKeyTypeSecret, key.type());
289
290 if (!g_aes_gcm_support.Get().IsSupported()) 307 if (!g_aes_gcm_support.Get().IsSupported())
291 return Status::ErrorUnsupported(); 308 return Status::ErrorUnsupported();
292 309
293 SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle());
294
295 const blink::WebCryptoAesGcmParams* params = algorithm.aesGcmParams();
296 if (!params)
297 return Status::ErrorUnexpected();
298
299 // TODO(eroman): The spec doesn't define the default value. Assume 128 for now 310 // TODO(eroman): The spec doesn't define the default value. Assume 128 for now
300 // since that is the maximum tag length: 311 // since that is the maximum tag length:
301 // http://www.w3.org/2012/webcrypto/track/issues/46 312 // http://www.w3.org/2012/webcrypto/track/issues/46
302 unsigned int tag_length_bits = 128; 313 unsigned int tag_length_bits = 128;
303 if (params->hasTagLengthBits()) 314 if (params->hasTagLengthBits())
304 tag_length_bits = params->optionalTagLengthBits(); 315 tag_length_bits = params->optionalTagLengthBits();
305 316
306 if (tag_length_bits > 128 || (tag_length_bits % 8) != 0) 317 if (tag_length_bits > 128 || (tag_length_bits % 8) != 0)
307 return Status::ErrorInvalidAesGcmTagLength(); 318 return Status::ErrorInvalidAesGcmTagLength();
308 319
309 unsigned int tag_length_bytes = tag_length_bits / 8; 320 unsigned int tag_length_bytes = tag_length_bits / 8;
310 321
311 CK_GCM_PARAMS gcm_params = {0}; 322 CK_GCM_PARAMS gcm_params = {0};
312 gcm_params.pIv = 323 gcm_params.pIv = const_cast<unsigned char*>(params->iv().data());
313 const_cast<unsigned char*>(algorithm.aesGcmParams()->iv().data()); 324 gcm_params.ulIvLen = params->iv().size();
314 gcm_params.ulIvLen = algorithm.aesGcmParams()->iv().size();
315 325
316 gcm_params.pAAD = 326 gcm_params.pAAD =
317 const_cast<unsigned char*>(params->optionalAdditionalData().data()); 327 const_cast<unsigned char*>(params->optionalAdditionalData().data());
318 gcm_params.ulAADLen = params->optionalAdditionalData().size(); 328 gcm_params.ulAADLen = params->optionalAdditionalData().size();
319 329
320 gcm_params.ulTagBits = tag_length_bits; 330 gcm_params.ulTagBits = tag_length_bits;
321 331
322 SECItem param; 332 SECItem param;
323 param.type = siBuffer; 333 param.type = siBuffer;
324 param.data = reinterpret_cast<unsigned char*>(&gcm_params); 334 param.data = reinterpret_cast<unsigned char*>(&gcm_params);
325 param.len = sizeof(gcm_params); 335 param.len = sizeof(gcm_params);
326 336
327 unsigned int buffer_size = 0; 337 unsigned int buffer_size = 0;
328 338
329 // Calculate the output buffer size. 339 // Calculate the output buffer size.
330 if (encrypt) { 340 if (encrypt) {
331 // TODO(eroman): This is ugly, abstract away the safe integer arithmetic. 341 // TODO(eroman): This is ugly, abstract away the safe integer arithmetic.
332 if (data_size > (UINT_MAX - tag_length_bytes)) 342 if (data.byte_length() > (UINT_MAX - tag_length_bytes))
333 return Status::ErrorDataTooLarge(); 343 return Status::ErrorDataTooLarge();
334 buffer_size = data_size + tag_length_bytes; 344 buffer_size = data.byte_length() + tag_length_bytes;
335 } else { 345 } else {
336 // TODO(eroman): In theory the buffer allocated for the plain text should be 346 // TODO(eroman): In theory the buffer allocated for the plain text should be
337 // sized as |data_size - tag_length_bytes|. 347 // sized as |data.byte_length() - tag_length_bytes|.
338 // 348 //
339 // However NSS has a bug whereby it will fail if the output buffer size is 349 // However NSS has a bug whereby it will fail if the output buffer size is
340 // not at least as large as the ciphertext: 350 // not at least as large as the ciphertext:
341 // 351 //
342 // https://bugzilla.mozilla.org/show_bug.cgi?id=%20853674 352 // https://bugzilla.mozilla.org/show_bug.cgi?id=%20853674
343 // 353 //
344 // From the analysis of that bug it looks like it might be safe to pass a 354 // From the analysis of that bug it looks like it might be safe to pass a
345 // correctly sized buffer but lie about its size. Since resizing the 355 // correctly sized buffer but lie about its size. Since resizing the
346 // WebCryptoArrayBuffer is expensive that hack may be worth looking into. 356 // WebCryptoArrayBuffer is expensive that hack may be worth looking into.
347 buffer_size = data_size; 357 buffer_size = data.byte_length();
348 } 358 }
349 359
350 *buffer = blink::WebArrayBuffer::create(buffer_size, 1); 360 *buffer = blink::WebArrayBuffer::create(buffer_size, 1);
351 unsigned char* buffer_data = reinterpret_cast<unsigned char*>(buffer->data()); 361 unsigned char* buffer_data = reinterpret_cast<unsigned char*>(buffer->data());
352 362
353 PK11_EncryptDecryptFunction func = 363 PK11_EncryptDecryptFunction func =
354 encrypt ? g_aes_gcm_support.Get().pk11_encrypt_func() : 364 encrypt ? g_aes_gcm_support.Get().pk11_encrypt_func() :
355 g_aes_gcm_support.Get().pk11_decrypt_func(); 365 g_aes_gcm_support.Get().pk11_decrypt_func();
356 366
357 unsigned int output_len = 0; 367 unsigned int output_len = 0;
358 SECStatus result = func(sym_key->key(), CKM_AES_GCM, &param, 368 SECStatus result = func(key->key(), CKM_AES_GCM, &param,
359 buffer_data, &output_len, buffer->byteLength(), 369 buffer_data, &output_len, buffer->byteLength(),
360 data, data_size); 370 data.bytes(), data.byte_length());
361 371
362 if (result != SECSuccess) 372 if (result != SECSuccess)
363 return Status::Error(); 373 return Status::Error();
364 374
365 // Unfortunately the buffer needs to be shrunk for decryption (see the NSS bug 375 // Unfortunately the buffer needs to be shrunk for decryption (see the NSS bug
366 // above). 376 // above).
367 webcrypto::ShrinkBuffer(buffer, output_len); 377 ShrinkBuffer(buffer, output_len);
368 378
369 return Status::Success(); 379 return Status::Success();
370 } 380 }
371 381
372 CK_MECHANISM_TYPE WebCryptoAlgorithmToGenMechanism( 382 CK_MECHANISM_TYPE WebCryptoAlgorithmToGenMechanism(
373 const blink::WebCryptoAlgorithm& algorithm) { 383 const blink::WebCryptoAlgorithm& algorithm) {
374 switch (algorithm.id()) { 384 switch (algorithm.id()) {
375 case blink::WebCryptoAlgorithmIdAesCbc: 385 case blink::WebCryptoAlgorithmIdAesCbc:
376 case blink::WebCryptoAlgorithmIdAesGcm: 386 case blink::WebCryptoAlgorithmIdAesGcm:
377 case blink::WebCryptoAlgorithmIdAesKw: 387 case blink::WebCryptoAlgorithmIdAesKw:
(...skipping 26 matching lines...) Expand all
404 } 414 }
405 return true; 415 return true;
406 } 416 }
407 417
408 bool IsAlgorithmRsa(const blink::WebCryptoAlgorithm& algorithm) { 418 bool IsAlgorithmRsa(const blink::WebCryptoAlgorithm& algorithm) {
409 return algorithm.id() == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 || 419 return algorithm.id() == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 ||
410 algorithm.id() == blink::WebCryptoAlgorithmIdRsaOaep || 420 algorithm.id() == blink::WebCryptoAlgorithmIdRsaOaep ||
411 algorithm.id() == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5; 421 algorithm.id() == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5;
412 } 422 }
413 423
414 Status ImportKeyInternalRaw( 424 } // namespace
415 const unsigned char* key_data, 425
416 unsigned int key_data_size, 426 Status ImportKeyRaw(
427 const CryptoData& key_data,
417 const blink::WebCryptoAlgorithm& algorithm, 428 const blink::WebCryptoAlgorithm& algorithm,
418 bool extractable, 429 bool extractable,
419 blink::WebCryptoKeyUsageMask usage_mask, 430 blink::WebCryptoKeyUsageMask usage_mask,
420 blink::WebCryptoKey* key) { 431 blink::WebCryptoKey* key) {
421 432
422 DCHECK(!algorithm.isNull()); 433 DCHECK(!algorithm.isNull());
423 434
424 blink::WebCryptoKeyType type;
425 switch (algorithm.id()) {
426 case blink::WebCryptoAlgorithmIdHmac:
427 case blink::WebCryptoAlgorithmIdAesCbc:
428 case blink::WebCryptoAlgorithmIdAesKw:
429 case blink::WebCryptoAlgorithmIdAesGcm:
430 type = blink::WebCryptoKeyTypeSecret;
431 break;
432 // TODO(bryaneyler): Support more key types.
433 default:
434 return Status::ErrorUnsupported();
435 }
436
437 // TODO(bryaneyler): Need to split handling for symmetric and asymmetric keys. 435 // TODO(bryaneyler): Need to split handling for symmetric and asymmetric keys.
438 // Currently only supporting symmetric. 436 // Currently only supporting symmetric.
439 CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM; 437 CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM;
440 // Flags are verified at the Blink layer; here the flags are set to all 438 // Flags are verified at the Blink layer; here the flags are set to all
441 // possible operations for this key type. 439 // possible operations for this key type.
442 CK_FLAGS flags = 0; 440 CK_FLAGS flags = 0;
443 441
444 switch (algorithm.id()) { 442 switch (algorithm.id()) {
445 case blink::WebCryptoAlgorithmIdHmac: { 443 case blink::WebCryptoAlgorithmIdHmac: {
446 const blink::WebCryptoHmacParams* params = algorithm.hmacParams(); 444 const blink::WebCryptoHmacParams* params = algorithm.hmacParams();
(...skipping 25 matching lines...) Expand all
472 flags |= CKF_ENCRYPT | CKF_DECRYPT; 470 flags |= CKF_ENCRYPT | CKF_DECRYPT;
473 break; 471 break;
474 } 472 }
475 default: 473 default:
476 return Status::ErrorUnsupported(); 474 return Status::ErrorUnsupported();
477 } 475 }
478 476
479 DCHECK_NE(CKM_INVALID_MECHANISM, mechanism); 477 DCHECK_NE(CKM_INVALID_MECHANISM, mechanism);
480 DCHECK_NE(0ul, flags); 478 DCHECK_NE(0ul, flags);
481 479
482 SECItem key_item = { 480 SECItem key_item = MakeSECItemForBuffer(key_data);
483 siBuffer,
484 const_cast<unsigned char*>(key_data),
485 key_data_size
486 };
487 481
488 crypto::ScopedPK11Slot slot(PK11_GetInternalSlot()); 482 crypto::ScopedPK11Slot slot(PK11_GetInternalSlot());
489 crypto::ScopedPK11SymKey pk11_sym_key( 483 crypto::ScopedPK11SymKey pk11_sym_key(
490 PK11_ImportSymKeyWithFlags(slot.get(), 484 PK11_ImportSymKeyWithFlags(slot.get(),
491 mechanism, 485 mechanism,
492 PK11_OriginUnwrap, 486 PK11_OriginUnwrap,
493 CKA_FLAGS_ONLY, 487 CKA_FLAGS_ONLY,
494 &key_item, 488 &key_item,
495 flags, 489 flags,
496 false, 490 false,
497 NULL)); 491 NULL));
498 if (!pk11_sym_key.get()) 492 if (!pk11_sym_key.get())
499 return Status::Error(); 493 return Status::Error();
500 494
501 *key = blink::WebCryptoKey::create(new SymKeyHandle(pk11_sym_key.Pass()), 495 *key = blink::WebCryptoKey::create(new SymKey(pk11_sym_key.Pass()),
502 type, extractable, algorithm, usage_mask); 496 blink::WebCryptoKeyTypeSecret,
497 extractable,
498 algorithm,
499 usage_mask);
503 return Status::Success(); 500 return Status::Success();
504 } 501 }
505 502
506 Status ExportKeyInternalRaw( 503 Status ExportKeyRaw(
507 const blink::WebCryptoKey& key, 504 SymKey* key,
508 blink::WebArrayBuffer* buffer) { 505 blink::WebArrayBuffer* buffer) {
509 506 if (PK11_ExtractKeyValue(key->key()) != SECSuccess)
510 DCHECK(key.handle());
511 DCHECK(buffer);
512
513 if (!key.extractable())
514 return Status::ErrorKeyNotExtractable();
515 if (key.type() != blink::WebCryptoKeyTypeSecret)
516 return Status::ErrorUnexpectedKeyType();
517
518 SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle());
519
520 if (PK11_ExtractKeyValue(sym_key->key()) != SECSuccess)
521 return Status::Error(); 507 return Status::Error();
522 508
523 const SECItem* key_data = PK11_GetKeyData(sym_key->key()); 509 const SECItem* key_data = PK11_GetKeyData(key->key());
524 if (!key_data) 510 if (!key_data)
525 return Status::Error(); 511 return Status::Error();
526 512
527 *buffer = webcrypto::CreateArrayBuffer(key_data->data, key_data->len); 513 *buffer = CreateArrayBuffer(key_data->data, key_data->len);
528 514
529 return Status::Success(); 515 return Status::Success();
530 } 516 }
531 517
518 namespace {
519
532 typedef scoped_ptr<CERTSubjectPublicKeyInfo, 520 typedef scoped_ptr<CERTSubjectPublicKeyInfo,
533 crypto::NSSDestroyer<CERTSubjectPublicKeyInfo, 521 crypto::NSSDestroyer<CERTSubjectPublicKeyInfo,
534 SECKEY_DestroySubjectPublicKeyInfo> > 522 SECKEY_DestroySubjectPublicKeyInfo> >
535 ScopedCERTSubjectPublicKeyInfo; 523 ScopedCERTSubjectPublicKeyInfo;
536 524
537 // Validates an NSS KeyType against a WebCrypto algorithm. Some NSS KeyTypes 525 // Validates an NSS KeyType against a WebCrypto algorithm. Some NSS KeyTypes
538 // contain enough information to fabricate a Web Crypto algorithm, which is 526 // contain enough information to fabricate a Web Crypto algorithm, which is
539 // returned if the input algorithm isNull(). This function indicates failure by 527 // returned if the input algorithm isNull(). This function indicates failure by
540 // returning a Null algorithm. 528 // returning a Null algorithm.
541 blink::WebCryptoAlgorithm ResolveNssKeyTypeWithInputAlgorithm( 529 blink::WebCryptoAlgorithm ResolveNssKeyTypeWithInputAlgorithm(
(...skipping 15 matching lines...) Expand all
557 case rsaPssKey: 545 case rsaPssKey:
558 case rsaOaepKey: 546 case rsaOaepKey:
559 // TODO(padolph): Handle other key types. 547 // TODO(padolph): Handle other key types.
560 break; 548 break;
561 default: 549 default:
562 break; 550 break;
563 } 551 }
564 return blink::WebCryptoAlgorithm::createNull(); 552 return blink::WebCryptoAlgorithm::createNull();
565 } 553 }
566 554
567 Status ImportKeyInternalSpki( 555 } // namespace
568 const unsigned char* key_data, 556
569 unsigned int key_data_size, 557 Status ImportKeySpki(
558 const CryptoData& key_data,
570 const blink::WebCryptoAlgorithm& algorithm_or_null, 559 const blink::WebCryptoAlgorithm& algorithm_or_null,
571 bool extractable, 560 bool extractable,
572 blink::WebCryptoKeyUsageMask usage_mask, 561 blink::WebCryptoKeyUsageMask usage_mask,
573 blink::WebCryptoKey* key) { 562 blink::WebCryptoKey* key) {
574 563
575 DCHECK(key); 564 DCHECK(key);
576 565
577 if (!key_data_size) 566 if (!key_data.byte_length())
578 return Status::ErrorImportEmptyKeyData(); 567 return Status::ErrorImportEmptyKeyData();
579 DCHECK(key_data); 568 DCHECK(key_data.bytes());
580 569
581 // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 Subject 570 // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 Subject
582 // Public Key Info. Decode this to a CERTSubjectPublicKeyInfo. 571 // Public Key Info. Decode this to a CERTSubjectPublicKeyInfo.
583 SECItem spki_item = {siBuffer, const_cast<uint8*>(key_data), key_data_size}; 572 SECItem spki_item = MakeSECItemForBuffer(key_data);
584 const ScopedCERTSubjectPublicKeyInfo spki( 573 const ScopedCERTSubjectPublicKeyInfo spki(
585 SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_item)); 574 SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_item));
586 if (!spki) 575 if (!spki)
587 return Status::Error(); 576 return Status::Error();
588 577
589 crypto::ScopedSECKEYPublicKey sec_public_key( 578 crypto::ScopedSECKEYPublicKey sec_public_key(
590 SECKEY_ExtractPublicKey(spki.get())); 579 SECKEY_ExtractPublicKey(spki.get()));
591 if (!sec_public_key) 580 if (!sec_public_key)
592 return Status::Error(); 581 return Status::Error();
593 582
594 const KeyType sec_key_type = SECKEY_GetPublicKeyType(sec_public_key.get()); 583 const KeyType sec_key_type = SECKEY_GetPublicKeyType(sec_public_key.get());
595 blink::WebCryptoAlgorithm algorithm = 584 blink::WebCryptoAlgorithm algorithm =
596 ResolveNssKeyTypeWithInputAlgorithm(sec_key_type, algorithm_or_null); 585 ResolveNssKeyTypeWithInputAlgorithm(sec_key_type, algorithm_or_null);
597 if (algorithm.isNull()) 586 if (algorithm.isNull())
598 return Status::Error(); 587 return Status::Error();
599 588
600 *key = blink::WebCryptoKey::create( 589 *key = blink::WebCryptoKey::create(
601 new PublicKeyHandle(sec_public_key.Pass()), 590 new PublicKey(sec_public_key.Pass()),
602 blink::WebCryptoKeyTypePublic, 591 blink::WebCryptoKeyTypePublic,
603 extractable, 592 extractable,
604 algorithm, 593 algorithm,
605 usage_mask); 594 usage_mask);
606 595
607 return Status::Success(); 596 return Status::Success();
608 } 597 }
609 598
610 Status ExportKeyInternalSpki( 599 Status ExportKeySpki(
611 const blink::WebCryptoKey& key, 600 PublicKey* key,
612 blink::WebArrayBuffer* buffer) { 601 blink::WebArrayBuffer* buffer) {
613
614 DCHECK(key.handle());
615 DCHECK(buffer);
616
617 if (!key.extractable())
618 return Status::ErrorKeyNotExtractable();
619 if (key.type() != blink::WebCryptoKeyTypePublic)
620 return Status::ErrorUnexpectedKeyType();
621
622 PublicKeyHandle* const pub_key =
623 reinterpret_cast<PublicKeyHandle*>(key.handle());
624
625 const crypto::ScopedSECItem spki_der( 602 const crypto::ScopedSECItem spki_der(
626 SECKEY_EncodeDERSubjectPublicKeyInfo(pub_key->key())); 603 SECKEY_EncodeDERSubjectPublicKeyInfo(key->key()));
627 if (!spki_der) 604 if (!spki_der)
628 return Status::Error(); 605 return Status::Error();
629 606
630 DCHECK(spki_der->data); 607 DCHECK(spki_der->data);
631 DCHECK(spki_der->len); 608 DCHECK(spki_der->len);
632 609
633 *buffer = webcrypto::CreateArrayBuffer(spki_der->data, spki_der->len); 610 *buffer = CreateArrayBuffer(spki_der->data, spki_der->len);
634 611
635 return Status::Success(); 612 return Status::Success();
636 } 613 }
637 614
638 Status ImportKeyInternalPkcs8( 615 Status ImportKeyPkcs8(
639 const unsigned char* key_data, 616 const CryptoData& key_data,
640 unsigned int key_data_size,
641 const blink::WebCryptoAlgorithm& algorithm_or_null, 617 const blink::WebCryptoAlgorithm& algorithm_or_null,
642 bool extractable, 618 bool extractable,
643 blink::WebCryptoKeyUsageMask usage_mask, 619 blink::WebCryptoKeyUsageMask usage_mask,
644 blink::WebCryptoKey* key) { 620 blink::WebCryptoKey* key) {
645 621
646 DCHECK(key); 622 DCHECK(key);
647 623
648 if (!key_data_size) 624 if (!key_data.byte_length())
649 return Status::ErrorImportEmptyKeyData(); 625 return Status::ErrorImportEmptyKeyData();
650 DCHECK(key_data); 626 DCHECK(key_data.bytes());
651 627
652 // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 PKCS#8 628 // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 PKCS#8
653 // private key info object. 629 // private key info object.
654 SECItem pki_der = {siBuffer, const_cast<uint8*>(key_data), key_data_size}; 630 SECItem pki_der = MakeSECItemForBuffer(key_data);
655 631
656 SECKEYPrivateKey* seckey_private_key = NULL; 632 SECKEYPrivateKey* seckey_private_key = NULL;
657 crypto::ScopedPK11Slot slot(PK11_GetInternalSlot()); 633 crypto::ScopedPK11Slot slot(PK11_GetInternalSlot());
658 if (PK11_ImportDERPrivateKeyInfoAndReturnKey( 634 if (PK11_ImportDERPrivateKeyInfoAndReturnKey(
659 slot.get(), 635 slot.get(),
660 &pki_der, 636 &pki_der,
661 NULL, // nickname 637 NULL, // nickname
662 NULL, // publicValue 638 NULL, // publicValue
663 false, // isPerm 639 false, // isPerm
664 false, // isPrivate 640 false, // isPrivate
665 KU_ALL, // usage 641 KU_ALL, // usage
666 &seckey_private_key, 642 &seckey_private_key,
667 NULL) != SECSuccess) { 643 NULL) != SECSuccess) {
668 return Status::Error(); 644 return Status::Error();
669 } 645 }
670 DCHECK(seckey_private_key); 646 DCHECK(seckey_private_key);
671 crypto::ScopedSECKEYPrivateKey private_key(seckey_private_key); 647 crypto::ScopedSECKEYPrivateKey private_key(seckey_private_key);
672 648
673 const KeyType sec_key_type = SECKEY_GetPrivateKeyType(private_key.get()); 649 const KeyType sec_key_type = SECKEY_GetPrivateKeyType(private_key.get());
674 blink::WebCryptoAlgorithm algorithm = 650 blink::WebCryptoAlgorithm algorithm =
675 ResolveNssKeyTypeWithInputAlgorithm(sec_key_type, algorithm_or_null); 651 ResolveNssKeyTypeWithInputAlgorithm(sec_key_type, algorithm_or_null);
676 if (algorithm.isNull()) 652 if (algorithm.isNull())
677 return Status::Error(); 653 return Status::Error();
678 654
679 *key = blink::WebCryptoKey::create( 655 *key = blink::WebCryptoKey::create(
680 new PrivateKeyHandle(private_key.Pass()), 656 new PrivateKey(private_key.Pass()),
681 blink::WebCryptoKeyTypePrivate, 657 blink::WebCryptoKeyTypePrivate,
682 extractable, 658 extractable,
683 algorithm, 659 algorithm,
684 usage_mask); 660 usage_mask);
685 661
686 return Status::Success(); 662 return Status::Success();
687 } 663 }
688 664
689 // ----------------------------------- 665 // -----------------------------------
690 // Hmac 666 // Hmac
691 // ----------------------------------- 667 // -----------------------------------
692 668
693 Status SignHmac( 669 Status SignHmac(
694 const blink::WebCryptoAlgorithm& algorithm, 670 SymKey* key,
695 const blink::WebCryptoKey& key, 671 const blink::WebCryptoAlgorithm& hash,
696 const unsigned char* data, 672 const CryptoData& data,
697 unsigned int data_size,
698 blink::WebArrayBuffer* buffer) { 673 blink::WebArrayBuffer* buffer) {
699 DCHECK_EQ(blink::WebCryptoAlgorithmIdHmac, algorithm.id()); 674 DCHECK_EQ(PK11_GetMechanism(key->key()), WebCryptoHashToHMACMechanism(hash));
700
701 const blink::WebCryptoHmacParams* params = algorithm.hmacParams();
702 if (!params)
703 return Status::ErrorUnexpected();
704
705 SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle());
706
707 DCHECK_EQ(PK11_GetMechanism(sym_key->key()),
708 WebCryptoHashToHMACMechanism(params->hash()));
709 675
710 SECItem param_item = { siBuffer, NULL, 0 }; 676 SECItem param_item = { siBuffer, NULL, 0 };
711 SECItem data_item = { 677 SECItem data_item = MakeSECItemForBuffer(data);
712 siBuffer,
713 const_cast<unsigned char*>(data),
714 data_size
715 };
716 // First call is to figure out the length. 678 // First call is to figure out the length.
717 SECItem signature_item = { siBuffer, NULL, 0 }; 679 SECItem signature_item = { siBuffer, NULL, 0 };
718 680
719 if (PK11_SignWithSymKey(sym_key->key(), 681 if (PK11_SignWithSymKey(key->key(),
720 PK11_GetMechanism(sym_key->key()), 682 PK11_GetMechanism(key->key()),
721 &param_item, 683 &param_item,
722 &signature_item, 684 &signature_item,
723 &data_item) != SECSuccess) { 685 &data_item) != SECSuccess) {
724 return Status::Error(); 686 return Status::Error();
725 } 687 }
726 688
727 DCHECK_NE(0u, signature_item.len); 689 DCHECK_NE(0u, signature_item.len);
728 690
729 *buffer = blink::WebArrayBuffer::create(signature_item.len, 1); 691 *buffer = blink::WebArrayBuffer::create(signature_item.len, 1);
730 signature_item.data = reinterpret_cast<unsigned char*>(buffer->data()); 692 signature_item.data = reinterpret_cast<unsigned char*>(buffer->data());
731 693
732 if (PK11_SignWithSymKey(sym_key->key(), 694 if (PK11_SignWithSymKey(key->key(),
733 PK11_GetMechanism(sym_key->key()), 695 PK11_GetMechanism(key->key()),
734 &param_item, 696 &param_item,
735 &signature_item, 697 &signature_item,
736 &data_item) != SECSuccess) { 698 &data_item) != SECSuccess) {
737 return Status::Error(); 699 return Status::Error();
738 } 700 }
739 701
740 DCHECK_EQ(buffer->byteLength(), signature_item.len); 702 DCHECK_EQ(buffer->byteLength(), signature_item.len);
741 return Status::Success(); 703 return Status::Success();
742 } 704 }
743 705
744 Status VerifyHmac(
745 const blink::WebCryptoAlgorithm& algorithm,
746 const blink::WebCryptoKey& key,
747 const unsigned char* signature,
748 unsigned int signature_size,
749 const unsigned char* data,
750 unsigned int data_size,
751 bool* signature_match) {
752 DCHECK_EQ(blink::WebCryptoAlgorithmIdHmac, algorithm.id());
753
754 blink::WebArrayBuffer result;
755 Status status = SignHmac(algorithm, key, data, data_size, &result);
756 if (status.IsError())
757 return status;
758
759 // Handling of truncated signatures is underspecified in the WebCrypto
760 // spec, so here we fail verification if a truncated signature is being
761 // verified.
762 // See https://www.w3.org/Bugs/Public/show_bug.cgi?id=23097
763 *signature_match =
764 result.byteLength() == signature_size &&
765 crypto::SecureMemEqual(result.data(), signature, signature_size);
766
767 return Status::Success();
768 }
769
770 // ----------------------------------- 706 // -----------------------------------
771 // RsaEsPkcs1v1_5 707 // RsaEsPkcs1v1_5
772 // ----------------------------------- 708 // -----------------------------------
773 709
774 Status EncryptRsaEsPkcs1v1_5( 710 Status EncryptRsaEsPkcs1v1_5(
775 const blink::WebCryptoAlgorithm& algorithm, 711 PublicKey* key,
776 const blink::WebCryptoKey& key, 712 const CryptoData& data,
777 const unsigned char* data,
778 unsigned int data_size,
779 blink::WebArrayBuffer* buffer) { 713 blink::WebArrayBuffer* buffer) {
780 DCHECK_EQ(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, algorithm.id());
781
782 // RSAES encryption does not support empty input
783 if (!data_size)
784 return Status::Error();
785 DCHECK(data);
786
787 if (key.type() != blink::WebCryptoKeyTypePublic)
788 return Status::ErrorUnexpectedKeyType();
789
790 PublicKeyHandle* const public_key =
791 reinterpret_cast<PublicKeyHandle*>(key.handle());
792
793 const unsigned int encrypted_length_bytes = 714 const unsigned int encrypted_length_bytes =
794 SECKEY_PublicKeyStrength(public_key->key()); 715 SECKEY_PublicKeyStrength(key->key());
795 716
796 // RSAES can operate on messages up to a length of k - 11, where k is the 717 // RSAES can operate on messages up to a length of k - 11, where k is the
797 // octet length of the RSA modulus. 718 // octet length of the RSA modulus.
798 if (encrypted_length_bytes < 11 || encrypted_length_bytes - 11 < data_size) 719 if (encrypted_length_bytes < 11 ||
720 encrypted_length_bytes - 11 < data.byte_length())
799 return Status::ErrorDataTooLarge(); 721 return Status::ErrorDataTooLarge();
800 722
801 *buffer = blink::WebArrayBuffer::create(encrypted_length_bytes, 1); 723 *buffer = blink::WebArrayBuffer::create(encrypted_length_bytes, 1);
802 unsigned char* const buffer_data = 724 unsigned char* const buffer_data =
803 reinterpret_cast<unsigned char*>(buffer->data()); 725 reinterpret_cast<unsigned char*>(buffer->data());
804 726
805 if (PK11_PubEncryptPKCS1(public_key->key(), 727 if (PK11_PubEncryptPKCS1(key->key(),
806 buffer_data, 728 buffer_data,
807 const_cast<unsigned char*>(data), 729 const_cast<unsigned char*>(data.bytes()),
808 data_size, 730 data.byte_length(),
809 NULL) != SECSuccess) { 731 NULL) != SECSuccess) {
810 return Status::Error(); 732 return Status::Error();
811 } 733 }
812 return Status::Success(); 734 return Status::Success();
813 } 735 }
814 736
815 Status DecryptRsaEsPkcs1v1_5( 737 Status DecryptRsaEsPkcs1v1_5(
816 const blink::WebCryptoAlgorithm& algorithm, 738 PrivateKey* key,
817 const blink::WebCryptoKey& key, 739 const CryptoData& data,
818 const unsigned char* data,
819 unsigned int data_size,
820 blink::WebArrayBuffer* buffer) { 740 blink::WebArrayBuffer* buffer) {
821 DCHECK_EQ(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, algorithm.id()); 741 const int modulus_length_bytes = PK11_GetPrivateModulusLen(key->key());
822
823 // RSAES decryption does not support empty input
824 if (!data_size)
825 return Status::Error();
826 DCHECK(data);
827
828 if (key.type() != blink::WebCryptoKeyTypePrivate)
829 return Status::ErrorUnexpectedKeyType();
830
831 PrivateKeyHandle* const private_key =
832 reinterpret_cast<PrivateKeyHandle*>(key.handle());
833
834 const int modulus_length_bytes =
835 PK11_GetPrivateModulusLen(private_key->key());
836 if (modulus_length_bytes <= 0) 742 if (modulus_length_bytes <= 0)
837 return Status::ErrorUnexpected(); 743 return Status::ErrorUnexpected();
838 const unsigned int max_output_length_bytes = modulus_length_bytes; 744 const unsigned int max_output_length_bytes = modulus_length_bytes;
839 745
840 *buffer = blink::WebArrayBuffer::create(max_output_length_bytes, 1); 746 *buffer = blink::WebArrayBuffer::create(max_output_length_bytes, 1);
841 unsigned char* const buffer_data = 747 unsigned char* const buffer_data =
842 reinterpret_cast<unsigned char*>(buffer->data()); 748 reinterpret_cast<unsigned char*>(buffer->data());
843 749
844 unsigned int output_length_bytes = 0; 750 unsigned int output_length_bytes = 0;
845 if (PK11_PrivDecryptPKCS1(private_key->key(), 751 if (PK11_PrivDecryptPKCS1(key->key(),
846 buffer_data, 752 buffer_data,
847 &output_length_bytes, 753 &output_length_bytes,
848 max_output_length_bytes, 754 max_output_length_bytes,
849 const_cast<unsigned char*>(data), 755 const_cast<unsigned char*>(data.bytes()),
850 data_size) != SECSuccess) { 756 data.byte_length()) != SECSuccess) {
851 return Status::Error(); 757 return Status::Error();
852 } 758 }
853 DCHECK_LE(output_length_bytes, max_output_length_bytes); 759 DCHECK_LE(output_length_bytes, max_output_length_bytes);
854 webcrypto::ShrinkBuffer(buffer, output_length_bytes); 760 ShrinkBuffer(buffer, output_length_bytes);
855 return Status::Success(); 761 return Status::Success();
856 } 762 }
857 763
858 // ----------------------------------- 764 // -----------------------------------
859 // RsaSsaPkcs1v1_5 765 // RsaSsaPkcs1v1_5
860 // ----------------------------------- 766 // -----------------------------------
861 767
862 Status SignRsaSsaPkcs1v1_5( 768 Status SignRsaSsaPkcs1v1_5(
863 const blink::WebCryptoAlgorithm& algorithm, 769 PrivateKey* key,
864 const blink::WebCryptoKey& key, 770 const blink::WebCryptoAlgorithm& hash,
865 const unsigned char* data, 771 const CryptoData& data,
866 unsigned int data_size,
867 blink::WebArrayBuffer* buffer) { 772 blink::WebArrayBuffer* buffer) {
868 DCHECK_EQ(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, algorithm.id());
869
870 if (key.type() != blink::WebCryptoKeyTypePrivate)
871 return Status::ErrorUnexpectedKeyType();
872
873 if (webcrypto::GetInnerHashAlgorithm(algorithm).isNull())
874 return Status::ErrorUnexpected();
875
876 PrivateKeyHandle* const private_key =
877 reinterpret_cast<PrivateKeyHandle*>(key.handle());
878 DCHECK(private_key);
879 DCHECK(private_key->key());
880
881 // Pick the NSS signing algorithm by combining RSA-SSA (RSA PKCS1) and the 773 // Pick the NSS signing algorithm by combining RSA-SSA (RSA PKCS1) and the
882 // inner hash of the input Web Crypto algorithm. 774 // inner hash of the input Web Crypto algorithm.
883 SECOidTag sign_alg_tag; 775 SECOidTag sign_alg_tag;
884 switch (webcrypto::GetInnerHashAlgorithm(algorithm).id()) { 776 switch (hash.id()) {
885 case blink::WebCryptoAlgorithmIdSha1: 777 case blink::WebCryptoAlgorithmIdSha1:
886 sign_alg_tag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; 778 sign_alg_tag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
887 break; 779 break;
888 case blink::WebCryptoAlgorithmIdSha224: 780 case blink::WebCryptoAlgorithmIdSha224:
889 sign_alg_tag = SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION; 781 sign_alg_tag = SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION;
890 break; 782 break;
891 case blink::WebCryptoAlgorithmIdSha256: 783 case blink::WebCryptoAlgorithmIdSha256:
892 sign_alg_tag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION; 784 sign_alg_tag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
893 break; 785 break;
894 case blink::WebCryptoAlgorithmIdSha384: 786 case blink::WebCryptoAlgorithmIdSha384:
895 sign_alg_tag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION; 787 sign_alg_tag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;
896 break; 788 break;
897 case blink::WebCryptoAlgorithmIdSha512: 789 case blink::WebCryptoAlgorithmIdSha512:
898 sign_alg_tag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION; 790 sign_alg_tag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
899 break; 791 break;
900 default: 792 default:
901 return Status::ErrorUnsupported(); 793 return Status::ErrorUnsupported();
902 } 794 }
903 795
904 crypto::ScopedSECItem signature_item(SECITEM_AllocItem(NULL, NULL, 0)); 796 crypto::ScopedSECItem signature_item(SECITEM_AllocItem(NULL, NULL, 0));
905 if (SEC_SignData(signature_item.get(), 797 if (SEC_SignData(signature_item.get(),
906 data, 798 data.bytes(),
907 data_size, 799 data.byte_length(),
908 private_key->key(), 800 key->key(),
909 sign_alg_tag) != SECSuccess) { 801 sign_alg_tag) != SECSuccess) {
910 return Status::Error(); 802 return Status::Error();
911 } 803 }
912 804
913 *buffer = webcrypto::CreateArrayBuffer(signature_item->data, 805 *buffer = CreateArrayBuffer(signature_item->data, signature_item->len);
914 signature_item->len);
915 return Status::Success(); 806 return Status::Success();
916 } 807 }
917 808
918 Status VerifyRsaSsaPkcs1v1_5( 809 Status VerifyRsaSsaPkcs1v1_5(
919 const blink::WebCryptoAlgorithm& algorithm, 810 PublicKey* key,
920 const blink::WebCryptoKey& key, 811 const blink::WebCryptoAlgorithm& hash,
921 const unsigned char* signature, 812 const CryptoData& signature,
922 unsigned int signature_size, 813 const CryptoData& data,
923 const unsigned char* data,
924 unsigned int data_size,
925 bool* signature_match) { 814 bool* signature_match) {
926 DCHECK_EQ(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, algorithm.id()); 815 const SECItem signature_item = MakeSECItemForBuffer(signature);
927
928 if (key.type() != blink::WebCryptoKeyTypePublic)
929 return Status::ErrorUnexpectedKeyType();
930
931 PublicKeyHandle* const public_key =
932 reinterpret_cast<PublicKeyHandle*>(key.handle());
933 DCHECK(public_key);
934 DCHECK(public_key->key());
935
936 const SECItem signature_item = {
937 siBuffer,
938 const_cast<unsigned char*>(signature),
939 signature_size
940 };
941 816
942 SECOidTag hash_alg_tag; 817 SECOidTag hash_alg_tag;
943 switch (webcrypto::GetInnerHashAlgorithm(algorithm).id()) { 818 switch (hash.id()) {
944 case blink::WebCryptoAlgorithmIdSha1: 819 case blink::WebCryptoAlgorithmIdSha1:
945 hash_alg_tag = SEC_OID_SHA1; 820 hash_alg_tag = SEC_OID_SHA1;
946 break; 821 break;
947 case blink::WebCryptoAlgorithmIdSha224: 822 case blink::WebCryptoAlgorithmIdSha224:
948 hash_alg_tag = SEC_OID_SHA224; 823 hash_alg_tag = SEC_OID_SHA224;
949 break; 824 break;
950 case blink::WebCryptoAlgorithmIdSha256: 825 case blink::WebCryptoAlgorithmIdSha256:
951 hash_alg_tag = SEC_OID_SHA256; 826 hash_alg_tag = SEC_OID_SHA256;
952 break; 827 break;
953 case blink::WebCryptoAlgorithmIdSha384: 828 case blink::WebCryptoAlgorithmIdSha384:
954 hash_alg_tag = SEC_OID_SHA384; 829 hash_alg_tag = SEC_OID_SHA384;
955 break; 830 break;
956 case blink::WebCryptoAlgorithmIdSha512: 831 case blink::WebCryptoAlgorithmIdSha512:
957 hash_alg_tag = SEC_OID_SHA512; 832 hash_alg_tag = SEC_OID_SHA512;
958 break; 833 break;
959 default: 834 default:
960 return Status::ErrorUnsupported(); 835 return Status::ErrorUnsupported();
961 } 836 }
962 837
963 *signature_match = 838 *signature_match =
964 SECSuccess == VFY_VerifyDataDirect(data, 839 SECSuccess == VFY_VerifyDataDirect(data.bytes(),
965 data_size, 840 data.byte_length(),
966 public_key->key(), 841 key->key(),
967 &signature_item, 842 &signature_item,
968 SEC_OID_PKCS1_RSA_ENCRYPTION, 843 SEC_OID_PKCS1_RSA_ENCRYPTION,
969 hash_alg_tag, 844 hash_alg_tag,
970 NULL, 845 NULL,
971 NULL); 846 NULL);
972 return Status::Success(); 847 return Status::Success();
973 } 848 }
974 849
850 Status EncryptAesCbc(SymKey* key,
851 const CryptoData& iv,
852 const CryptoData& data,
853 blink::WebArrayBuffer* buffer) {
854 return AesCbcEncryptDecrypt(CKA_ENCRYPT, key, iv, data, buffer);
855 }
856
857 Status DecryptAesCbc(SymKey* key,
858 const CryptoData& iv,
859 const CryptoData& data,
860 blink::WebArrayBuffer* buffer) {
861 return AesCbcEncryptDecrypt(CKA_DECRYPT, key, iv, data, buffer);
862 }
863
864 Status EncryptAesGcm(
865 SymKey* key,
866 const blink::WebCryptoAesGcmParams* params,
867 const CryptoData& data,
868 blink::WebArrayBuffer* buffer) {
869 return AesGcmEncryptDecrypt(true, key, params, data, buffer);
870 }
871
872 Status DecryptAesGcm(
873 SymKey* key,
874 const blink::WebCryptoAesGcmParams* params,
875 const CryptoData& data,
876 blink::WebArrayBuffer* buffer) {
877 return AesGcmEncryptDecrypt(false, key, params, data, buffer);
878 }
879
975 // ----------------------------------- 880 // -----------------------------------
976 // Key generation 881 // Key generation
977 // ----------------------------------- 882 // -----------------------------------
978 883
979 Status GenerateRsaKeyPair( 884 Status GenerateRsaKeyPair(
980 const blink::WebCryptoAlgorithm& algorithm, 885 const blink::WebCryptoAlgorithm& algorithm,
981 bool extractable, 886 bool extractable,
982 blink::WebCryptoKeyUsageMask usage_mask, 887 blink::WebCryptoKeyUsageMask usage_mask,
983 blink::WebCryptoKey* public_key, 888 blink::WebCryptoKey* public_key,
984 blink::WebCryptoKey* private_key) { 889 blink::WebCryptoKey* private_key) {
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1033 &rsa_gen_params, 938 &rsa_gen_params,
1034 &sec_public_key, 939 &sec_public_key,
1035 attribute_flags, 940 attribute_flags,
1036 operation_flags, 941 operation_flags,
1037 operation_flags_mask, 942 operation_flags_mask,
1038 NULL)); 943 NULL));
1039 if (!private_key) 944 if (!private_key)
1040 return Status::Error(); 945 return Status::Error();
1041 946
1042 *public_key = blink::WebCryptoKey::create( 947 *public_key = blink::WebCryptoKey::create(
1043 new PublicKeyHandle(crypto::ScopedSECKEYPublicKey(sec_public_key)), 948 new PublicKey(crypto::ScopedSECKEYPublicKey(sec_public_key)),
1044 blink::WebCryptoKeyTypePublic, 949 blink::WebCryptoKeyTypePublic,
1045 true, 950 true,
1046 algorithm, 951 algorithm,
1047 usage_mask); 952 usage_mask);
1048 *private_key = blink::WebCryptoKey::create( 953 *private_key = blink::WebCryptoKey::create(
1049 new PrivateKeyHandle(scoped_sec_private_key.Pass()), 954 new PrivateKey(scoped_sec_private_key.Pass()),
1050 blink::WebCryptoKeyTypePrivate, 955 blink::WebCryptoKeyTypePrivate,
1051 extractable, 956 extractable,
1052 algorithm, 957 algorithm,
1053 usage_mask); 958 usage_mask);
1054 959
1055 return Status::Success(); 960 return Status::Success();
1056 } 961 }
1057 962
1058 // Get the secret key length in bytes from generation parameters. This resolves 963 void Init() {
1059 // any defaults.
1060 Status GetGenerateSecretKeyLength(const blink::WebCryptoAlgorithm& algorithm,
1061 unsigned int* keylen_bytes) {
1062 *keylen_bytes = 0;
1063
1064 switch (algorithm.id()) {
1065 case blink::WebCryptoAlgorithmIdAesCbc:
1066 case blink::WebCryptoAlgorithmIdAesGcm:
1067 case blink::WebCryptoAlgorithmIdAesKw: {
1068 const blink::WebCryptoAesKeyGenParams* params =
1069 algorithm.aesKeyGenParams();
1070 DCHECK(params);
1071 // Ensure the key length is a multiple of 8 bits. Let NSS verify further
1072 // algorithm-specific length restrictions.
1073 if (params->lengthBits() % 8)
1074 return Status::ErrorGenerateKeyLength();
1075 *keylen_bytes = params->lengthBits() / 8;
1076 break;
1077 }
1078 case blink::WebCryptoAlgorithmIdHmac: {
1079 const blink::WebCryptoHmacKeyParams* params = algorithm.hmacKeyParams();
1080 DCHECK(params);
1081 if (params->hasLengthBytes())
1082 *keylen_bytes = params->optionalLengthBytes();
1083 else
1084 *keylen_bytes = webcrypto::ShaBlockSizeBytes(params->hash().id());
1085 break;
1086 }
1087
1088 default:
1089 return Status::ErrorUnsupported();
1090 }
1091
1092 if (*keylen_bytes == 0)
1093 return Status::ErrorGenerateKeyLength();
1094
1095 return Status::Success();
1096 }
1097
1098 } // namespace
1099
1100 void WebCryptoImpl::Init() {
1101 crypto::EnsureNSSInit(); 964 crypto::EnsureNSSInit();
1102 } 965 }
1103 966
1104 Status WebCryptoImpl::EncryptInternal( 967 Status DigestSha(
1105 const blink::WebCryptoAlgorithm& algorithm, 968 blink::WebCryptoAlgorithmId algorithm,
1106 const blink::WebCryptoKey& key, 969 const CryptoData& data,
1107 const unsigned char* data,
1108 unsigned int data_size,
1109 blink::WebArrayBuffer* buffer) {
1110
1111 DCHECK_EQ(algorithm.id(), key.algorithm().id());
1112 DCHECK(key.handle());
1113 DCHECK(buffer);
1114
1115 switch (algorithm.id()) {
1116 case blink::WebCryptoAlgorithmIdAesCbc:
1117 return AesCbcEncryptDecrypt(
1118 CKA_ENCRYPT, algorithm, key, data, data_size, buffer);
1119 case blink::WebCryptoAlgorithmIdAesGcm:
1120 return AesGcmEncryptDecrypt(
1121 true, algorithm, key, data, data_size, buffer);
1122 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5:
1123 return EncryptRsaEsPkcs1v1_5(algorithm, key, data, data_size, buffer);
1124 default:
1125 return Status::ErrorUnsupported();
1126 }
1127 }
1128
1129 Status WebCryptoImpl::DecryptInternal(
1130 const blink::WebCryptoAlgorithm& algorithm,
1131 const blink::WebCryptoKey& key,
1132 const unsigned char* data,
1133 unsigned int data_size,
1134 blink::WebArrayBuffer* buffer) {
1135
1136 DCHECK_EQ(algorithm.id(), key.algorithm().id());
1137 DCHECK(key.handle());
1138 DCHECK(buffer);
1139
1140 switch (algorithm.id()) {
1141 case blink::WebCryptoAlgorithmIdAesCbc:
1142 return AesCbcEncryptDecrypt(
1143 CKA_DECRYPT, algorithm, key, data, data_size, buffer);
1144 case blink::WebCryptoAlgorithmIdAesGcm:
1145 return AesGcmEncryptDecrypt(
1146 false, algorithm, key, data, data_size, buffer);
1147 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5:
1148 return DecryptRsaEsPkcs1v1_5(algorithm, key, data, data_size, buffer);
1149 default:
1150 return Status::ErrorUnsupported();
1151 }
1152 }
1153
1154 Status WebCryptoImpl::DigestInternal(
1155 const blink::WebCryptoAlgorithm& algorithm,
1156 const unsigned char* data,
1157 unsigned int data_size,
1158 blink::WebArrayBuffer* buffer) { 970 blink::WebArrayBuffer* buffer) {
1159 HASH_HashType hash_type = WebCryptoAlgorithmToNSSHashType(algorithm); 971 HASH_HashType hash_type = WebCryptoAlgorithmToNSSHashType(algorithm);
1160 if (hash_type == HASH_AlgNULL) 972 if (hash_type == HASH_AlgNULL)
1161 return Status::ErrorUnsupported(); 973 return Status::ErrorUnsupported();
1162 974
1163 HASHContext* context = HASH_Create(hash_type); 975 HASHContext* context = HASH_Create(hash_type);
1164 if (!context) 976 if (!context)
1165 return Status::Error(); 977 return Status::Error();
1166 978
1167 HASH_Begin(context); 979 HASH_Begin(context);
1168 980
1169 HASH_Update(context, data, data_size); 981 HASH_Update(context, data.bytes(), data.byte_length());
1170 982
1171 unsigned int hash_result_length = HASH_ResultLenContext(context); 983 unsigned int hash_result_length = HASH_ResultLenContext(context);
1172 DCHECK_LE(hash_result_length, static_cast<size_t>(HASH_LENGTH_MAX)); 984 DCHECK_LE(hash_result_length, static_cast<size_t>(HASH_LENGTH_MAX));
1173 985
1174 *buffer = blink::WebArrayBuffer::create(hash_result_length, 1); 986 *buffer = blink::WebArrayBuffer::create(hash_result_length, 1);
1175 987
1176 unsigned char* digest = reinterpret_cast<unsigned char*>(buffer->data()); 988 unsigned char* digest = reinterpret_cast<unsigned char*>(buffer->data());
1177 989
1178 unsigned int result_length = 0; 990 unsigned int result_length = 0;
1179 HASH_End(context, digest, &result_length, hash_result_length); 991 HASH_End(context, digest, &result_length, hash_result_length);
1180 992
1181 HASH_Destroy(context); 993 HASH_Destroy(context);
1182 994
1183 if (result_length != hash_result_length) 995 if (result_length != hash_result_length)
1184 return Status::ErrorUnexpected(); 996 return Status::ErrorUnexpected();
1185 return Status::Success(); 997 return Status::Success();
1186 } 998 }
1187 999
1188 Status WebCryptoImpl::GenerateSecretKeyInternal( 1000 Status GenerateSecretKey(
1189 const blink::WebCryptoAlgorithm& algorithm, 1001 const blink::WebCryptoAlgorithm& algorithm,
1190 bool extractable, 1002 bool extractable,
1191 blink::WebCryptoKeyUsageMask usage_mask, 1003 blink::WebCryptoKeyUsageMask usage_mask,
1004 unsigned keylen_bytes,
1192 blink::WebCryptoKey* key) { 1005 blink::WebCryptoKey* key) {
1193
1194 CK_MECHANISM_TYPE mech = WebCryptoAlgorithmToGenMechanism(algorithm); 1006 CK_MECHANISM_TYPE mech = WebCryptoAlgorithmToGenMechanism(algorithm);
1195 blink::WebCryptoKeyType key_type = blink::WebCryptoKeyTypeSecret; 1007 blink::WebCryptoKeyType key_type = blink::WebCryptoKeyTypeSecret;
1196 1008
1197 if (mech == CKM_INVALID_MECHANISM) 1009 if (mech == CKM_INVALID_MECHANISM)
1198 return Status::ErrorUnsupported(); 1010 return Status::ErrorUnsupported();
1199 1011
1200 unsigned int keylen_bytes = 0;
1201 Status status = GetGenerateSecretKeyLength(algorithm, &keylen_bytes);
1202 if (status.IsError())
1203 return status;
1204
1205 crypto::ScopedPK11Slot slot(PK11_GetInternalKeySlot()); 1012 crypto::ScopedPK11Slot slot(PK11_GetInternalKeySlot());
1206 if (!slot) 1013 if (!slot)
1207 return Status::Error(); 1014 return Status::Error();
1208 1015
1209 crypto::ScopedPK11SymKey pk11_key( 1016 crypto::ScopedPK11SymKey pk11_key(
1210 PK11_KeyGen(slot.get(), mech, NULL, keylen_bytes, NULL)); 1017 PK11_KeyGen(slot.get(), mech, NULL, keylen_bytes, NULL));
1211 1018
1212 if (!pk11_key) 1019 if (!pk11_key)
1213 return Status::Error(); 1020 return Status::Error();
1214 1021
1215 *key = blink::WebCryptoKey::create( 1022 *key = blink::WebCryptoKey::create(new SymKey(pk11_key.Pass()),
1216 new SymKeyHandle(pk11_key.Pass()), 1023 key_type,
1217 key_type, extractable, algorithm, usage_mask); 1024 extractable,
1025 algorithm,
1026 usage_mask);
1218 return Status::Success(); 1027 return Status::Success();
1219 } 1028 }
1220 1029
1221 Status WebCryptoImpl::GenerateKeyPairInternal( 1030 Status ImportRsaPublicKey(
1222 const blink::WebCryptoAlgorithm& algorithm, 1031 const CryptoData& modulus_data,
1223 bool extractable, 1032 const CryptoData& exponent_data,
1224 blink::WebCryptoKeyUsageMask usage_mask,
1225 blink::WebCryptoKey* public_key,
1226 blink::WebCryptoKey* private_key) {
1227
1228 // TODO(padolph): Handle other asymmetric algorithm key generation.
1229 switch (algorithm.id()) {
1230 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5:
1231 case blink::WebCryptoAlgorithmIdRsaOaep:
1232 case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5:
1233 return GenerateRsaKeyPair(algorithm, extractable, usage_mask,
1234 public_key, private_key);
1235 default:
1236 return Status::ErrorUnsupported();
1237 }
1238 }
1239
1240 Status WebCryptoImpl::ImportKeyInternal(
1241 blink::WebCryptoKeyFormat format,
1242 const unsigned char* key_data,
1243 unsigned int key_data_size,
1244 const blink::WebCryptoAlgorithm& algorithm_or_null,
1245 bool extractable,
1246 blink::WebCryptoKeyUsageMask usage_mask,
1247 blink::WebCryptoKey* key) {
1248
1249 switch (format) {
1250 case blink::WebCryptoKeyFormatRaw:
1251 // A 'raw'-formatted key import requires an input algorithm.
1252 if (algorithm_or_null.isNull())
1253 return Status::ErrorMissingAlgorithmImportRawKey();
1254 return ImportKeyInternalRaw(key_data,
1255 key_data_size,
1256 algorithm_or_null,
1257 extractable,
1258 usage_mask,
1259 key);
1260 case blink::WebCryptoKeyFormatSpki:
1261 return ImportKeyInternalSpki(key_data,
1262 key_data_size,
1263 algorithm_or_null,
1264 extractable,
1265 usage_mask,
1266 key);
1267 case blink::WebCryptoKeyFormatPkcs8:
1268 return ImportKeyInternalPkcs8(key_data,
1269 key_data_size,
1270 algorithm_or_null,
1271 extractable,
1272 usage_mask,
1273 key);
1274 default:
1275 // NOTE: blink::WebCryptoKeyFormatJwk is handled one level above.
1276 return Status::ErrorUnsupported();
1277 }
1278 }
1279
1280 Status WebCryptoImpl::ExportKeyInternal(
1281 blink::WebCryptoKeyFormat format,
1282 const blink::WebCryptoKey& key,
1283 blink::WebArrayBuffer* buffer) {
1284 switch (format) {
1285 case blink::WebCryptoKeyFormatRaw:
1286 return ExportKeyInternalRaw(key, buffer);
1287 case blink::WebCryptoKeyFormatSpki:
1288 return ExportKeyInternalSpki(key, buffer);
1289 case blink::WebCryptoKeyFormatPkcs8:
1290 // TODO(padolph): Implement pkcs8 export
1291 return Status::ErrorUnsupported();
1292 default:
1293 return Status::ErrorUnsupported();
1294 }
1295 }
1296
1297 Status WebCryptoImpl::SignInternal(
1298 const blink::WebCryptoAlgorithm& algorithm,
1299 const blink::WebCryptoKey& key,
1300 const unsigned char* data,
1301 unsigned int data_size,
1302 blink::WebArrayBuffer* buffer) {
1303
1304 // Note: It is not an error to sign empty data.
1305
1306 DCHECK(buffer);
1307 DCHECK_NE(0, key.usages() & blink::WebCryptoKeyUsageSign);
1308
1309 switch (algorithm.id()) {
1310 case blink::WebCryptoAlgorithmIdHmac:
1311 return SignHmac(algorithm, key, data, data_size, buffer);
1312 case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5:
1313 return SignRsaSsaPkcs1v1_5(algorithm, key, data, data_size, buffer);
1314 default:
1315 return Status::ErrorUnsupported();
1316 }
1317 }
1318
1319 Status WebCryptoImpl::VerifySignatureInternal(
1320 const blink::WebCryptoAlgorithm& algorithm,
1321 const blink::WebCryptoKey& key,
1322 const unsigned char* signature,
1323 unsigned int signature_size,
1324 const unsigned char* data,
1325 unsigned int data_size,
1326 bool* signature_match) {
1327
1328 if (!signature_size) {
1329 // None of the algorithms generate valid zero-length signatures so this
1330 // will necessarily fail verification. Early return to protect
1331 // implementations from dealing with a NULL signature pointer.
1332 *signature_match = false;
1333 return Status::Success();
1334 }
1335
1336 DCHECK(signature);
1337
1338 switch (algorithm.id()) {
1339 case blink::WebCryptoAlgorithmIdHmac:
1340 return VerifyHmac(algorithm, key, signature, signature_size,
1341 data, data_size, signature_match);
1342 case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5:
1343 return VerifyRsaSsaPkcs1v1_5(algorithm, key, signature, signature_size,
1344 data, data_size, signature_match);
1345 default:
1346 return Status::ErrorUnsupported();
1347 }
1348 }
1349
1350 Status WebCryptoImpl::ImportRsaPublicKeyInternal(
1351 const unsigned char* modulus_data,
1352 unsigned int modulus_size,
1353 const unsigned char* exponent_data,
1354 unsigned int exponent_size,
1355 const blink::WebCryptoAlgorithm& algorithm, 1033 const blink::WebCryptoAlgorithm& algorithm,
1356 bool extractable, 1034 bool extractable,
1357 blink::WebCryptoKeyUsageMask usage_mask, 1035 blink::WebCryptoKeyUsageMask usage_mask,
1358 blink::WebCryptoKey* key) { 1036 blink::WebCryptoKey* key) {
1359 1037
1360 if (!modulus_size) 1038 if (!modulus_data.byte_length())
1361 return Status::ErrorImportRsaEmptyModulus(); 1039 return Status::ErrorImportRsaEmptyModulus();
1362 1040
1363 if (!exponent_size) 1041 if (!exponent_data.byte_length())
1364 return Status::ErrorImportRsaEmptyExponent(); 1042 return Status::ErrorImportRsaEmptyExponent();
1365 1043
1366 DCHECK(modulus_data); 1044 DCHECK(modulus_data.bytes());
1367 DCHECK(exponent_data); 1045 DCHECK(exponent_data.bytes());
1368 1046
1369 // NSS does not provide a way to create an RSA public key directly from the 1047 // NSS does not provide a way to create an RSA public key directly from the
1370 // modulus and exponent values, but it can import an DER-encoded ASN.1 blob 1048 // modulus and exponent values, but it can import an DER-encoded ASN.1 blob
1371 // with these values and create the public key from that. The code below 1049 // with these values and create the public key from that. The code below
1372 // follows the recommendation described in 1050 // follows the recommendation described in
1373 // https://developer.mozilla.org/en-US/docs/NSS/NSS_Tech_Notes/nss_tech_note7 1051 // https://developer.mozilla.org/en-US/docs/NSS/NSS_Tech_Notes/nss_tech_note7
1374 1052
1375 // Pack the input values into a struct compatible with NSS ASN.1 encoding, and 1053 // Pack the input values into a struct compatible with NSS ASN.1 encoding, and
1376 // set up an ASN.1 encoder template for it. 1054 // set up an ASN.1 encoder template for it.
1377 struct RsaPublicKeyData { 1055 struct RsaPublicKeyData {
1378 SECItem modulus; 1056 SECItem modulus;
1379 SECItem exponent; 1057 SECItem exponent;
1380 }; 1058 };
1381 const RsaPublicKeyData pubkey_in = { 1059 const RsaPublicKeyData pubkey_in = {
1382 {siUnsignedInteger, const_cast<unsigned char*>(modulus_data), 1060 {siUnsignedInteger, const_cast<unsigned char*>(modulus_data.bytes()),
1383 modulus_size}, 1061 modulus_data.byte_length()},
1384 {siUnsignedInteger, const_cast<unsigned char*>(exponent_data), 1062 {siUnsignedInteger, const_cast<unsigned char*>(exponent_data.bytes()),
1385 exponent_size}}; 1063 exponent_data.byte_length()}};
1386 const SEC_ASN1Template rsa_public_key_template[] = { 1064 const SEC_ASN1Template rsa_public_key_template[] = {
1387 {SEC_ASN1_SEQUENCE, 0, NULL, sizeof(RsaPublicKeyData)}, 1065 {SEC_ASN1_SEQUENCE, 0, NULL, sizeof(RsaPublicKeyData)},
1388 {SEC_ASN1_INTEGER, offsetof(RsaPublicKeyData, modulus), }, 1066 {SEC_ASN1_INTEGER, offsetof(RsaPublicKeyData, modulus), },
1389 {SEC_ASN1_INTEGER, offsetof(RsaPublicKeyData, exponent), }, 1067 {SEC_ASN1_INTEGER, offsetof(RsaPublicKeyData, exponent), },
1390 {0, }}; 1068 {0, }};
1391 1069
1392 // DER-encode the public key. 1070 // DER-encode the public key.
1393 crypto::ScopedSECItem pubkey_der(SEC_ASN1EncodeItem( 1071 crypto::ScopedSECItem pubkey_der(
1394 NULL, NULL, &pubkey_in, rsa_public_key_template)); 1072 SEC_ASN1EncodeItem(NULL, NULL, &pubkey_in, rsa_public_key_template));
1395 if (!pubkey_der) 1073 if (!pubkey_der)
1396 return Status::Error(); 1074 return Status::Error();
1397 1075
1398 // Import the DER-encoded public key to create an RSA SECKEYPublicKey. 1076 // Import the DER-encoded public key to create an RSA SECKEYPublicKey.
1399 crypto::ScopedSECKEYPublicKey pubkey( 1077 crypto::ScopedSECKEYPublicKey pubkey(
1400 SECKEY_ImportDERPublicKey(pubkey_der.get(), CKK_RSA)); 1078 SECKEY_ImportDERPublicKey(pubkey_der.get(), CKK_RSA));
1401 if (!pubkey) 1079 if (!pubkey)
1402 return Status::Error(); 1080 return Status::Error();
1403 1081
1404 *key = blink::WebCryptoKey::create(new PublicKeyHandle(pubkey.Pass()), 1082 *key = blink::WebCryptoKey::create(new PublicKey(pubkey.Pass()),
1405 blink::WebCryptoKeyTypePublic, 1083 blink::WebCryptoKeyTypePublic,
1406 extractable, 1084 extractable,
1407 algorithm, 1085 algorithm,
1408 usage_mask); 1086 usage_mask);
1409 return Status::Success(); 1087 return Status::Success();
1410 } 1088 }
1411 1089
1090 } // namespace platform
1091 } // namespace webcrypto
1412 } // namespace content 1092 } // namespace content
1093
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698