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

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: Change header guard 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 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 114
115 using webcrypto::Status; 115 namespace webcrypto {
116 116
117 namespace { 117 namespace platform {
118 118
119 class SymKeyHandle : public blink::WebCryptoKeyHandle { 119 class SymKey : public Key {
120 public: 120 public:
121 explicit SymKeyHandle(crypto::ScopedPK11SymKey key) : key_(key.Pass()) {} 121 explicit SymKey(crypto::ScopedPK11SymKey key) : key_(key.Pass()) {}
122 122
123 PK11SymKey* key() { return key_.get(); } 123 PK11SymKey* key() { return key_.get(); }
124 124
125 virtual SymKey* AsSymKey() OVERRIDE { return this; }
126 virtual PublicKey* AsPublicKey() OVERRIDE { return NULL; }
127 virtual PrivateKey* AsPrivateKey() OVERRIDE { return NULL; }
128
125 private: 129 private:
126 crypto::ScopedPK11SymKey key_; 130 crypto::ScopedPK11SymKey key_;
127 131
128 DISALLOW_COPY_AND_ASSIGN(SymKeyHandle); 132 DISALLOW_COPY_AND_ASSIGN(SymKey);
129 }; 133 };
130 134
131 class PublicKeyHandle : public blink::WebCryptoKeyHandle { 135 class PublicKey : public Key {
132 public: 136 public:
133 explicit PublicKeyHandle(crypto::ScopedSECKEYPublicKey key) 137 explicit PublicKey(crypto::ScopedSECKEYPublicKey key) : key_(key.Pass()) {}
134 : key_(key.Pass()) {}
135 138
136 SECKEYPublicKey* key() { return key_.get(); } 139 SECKEYPublicKey* key() { return key_.get(); }
137 140
141 virtual SymKey* AsSymKey() OVERRIDE { return NULL; }
142 virtual PublicKey* AsPublicKey() OVERRIDE { return this; }
143 virtual PrivateKey* AsPrivateKey() OVERRIDE { return NULL; }
144
138 private: 145 private:
139 crypto::ScopedSECKEYPublicKey key_; 146 crypto::ScopedSECKEYPublicKey key_;
140 147
141 DISALLOW_COPY_AND_ASSIGN(PublicKeyHandle); 148 DISALLOW_COPY_AND_ASSIGN(PublicKey);
142 }; 149 };
143 150
144 class PrivateKeyHandle : public blink::WebCryptoKeyHandle { 151 class PrivateKey : public Key {
145 public: 152 public:
146 explicit PrivateKeyHandle(crypto::ScopedSECKEYPrivateKey key) 153 explicit PrivateKey(crypto::ScopedSECKEYPrivateKey key) : key_(key.Pass()) {}
147 : key_(key.Pass()) {}
148 154
149 SECKEYPrivateKey* key() { return key_.get(); } 155 SECKEYPrivateKey* key() { return key_.get(); }
150 156
157 virtual SymKey* AsSymKey() OVERRIDE { return NULL; }
158 virtual PublicKey* AsPublicKey() OVERRIDE { return NULL; }
159 virtual PrivateKey* AsPrivateKey() OVERRIDE { return this; }
160
151 private: 161 private:
152 crypto::ScopedSECKEYPrivateKey key_; 162 crypto::ScopedSECKEYPrivateKey key_;
153 163
154 DISALLOW_COPY_AND_ASSIGN(PrivateKeyHandle); 164 DISALLOW_COPY_AND_ASSIGN(PrivateKey);
155 }; 165 };
156 166
167 namespace {
168
169 // Creates a SECItem for the data in |buffer|. This does NOT make a copy, so
170 // |buffer| should outlive the SECItem.
171 SECItem MakeSECItemForBuffer(const CryptoData& buffer) {
172 SECItem item = {
173 siBuffer,
174 // NSS requires non-const data even though it is just for input.
175 const_cast<unsigned char*>(buffer.bytes()),
176 buffer.byte_length()
177 };
178 return item;
179 }
180
157 HASH_HashType WebCryptoAlgorithmToNSSHashType( 181 HASH_HashType WebCryptoAlgorithmToNSSHashType(
158 const blink::WebCryptoAlgorithm& algorithm) { 182 blink::WebCryptoAlgorithmId algorithm) {
159 switch (algorithm.id()) { 183 switch (algorithm) {
160 case blink::WebCryptoAlgorithmIdSha1: 184 case blink::WebCryptoAlgorithmIdSha1:
161 return HASH_AlgSHA1; 185 return HASH_AlgSHA1;
162 case blink::WebCryptoAlgorithmIdSha224: 186 case blink::WebCryptoAlgorithmIdSha224:
163 return HASH_AlgSHA224; 187 return HASH_AlgSHA224;
164 case blink::WebCryptoAlgorithmIdSha256: 188 case blink::WebCryptoAlgorithmIdSha256:
165 return HASH_AlgSHA256; 189 return HASH_AlgSHA256;
166 case blink::WebCryptoAlgorithmIdSha384: 190 case blink::WebCryptoAlgorithmIdSha384:
167 return HASH_AlgSHA384; 191 return HASH_AlgSHA384;
168 case blink::WebCryptoAlgorithmIdSha512: 192 case blink::WebCryptoAlgorithmIdSha512:
169 return HASH_AlgSHA512; 193 return HASH_AlgSHA512;
(...skipping 15 matching lines...) Expand all
185 case blink::WebCryptoAlgorithmIdSha384: 209 case blink::WebCryptoAlgorithmIdSha384:
186 return CKM_SHA384_HMAC; 210 return CKM_SHA384_HMAC;
187 case blink::WebCryptoAlgorithmIdSha512: 211 case blink::WebCryptoAlgorithmIdSha512:
188 return CKM_SHA512_HMAC; 212 return CKM_SHA512_HMAC;
189 default: 213 default:
190 // Not a supported algorithm. 214 // Not a supported algorithm.
191 return CKM_INVALID_MECHANISM; 215 return CKM_INVALID_MECHANISM;
192 } 216 }
193 } 217 }
194 218
195 Status AesCbcEncryptDecrypt( 219 Status AesCbcEncryptDecrypt(EncryptOrDecrypt mode,
196 CK_ATTRIBUTE_TYPE operation, 220 SymKey* key,
197 const blink::WebCryptoAlgorithm& algorithm, 221 const CryptoData& iv,
198 const blink::WebCryptoKey& key, 222 const CryptoData& data,
199 const unsigned char* data, 223 blink::WebArrayBuffer* buffer) {
200 unsigned int data_size, 224 CK_ATTRIBUTE_TYPE operation = (mode == ENCRYPT) ? CKA_ENCRYPT : CKA_DECRYPT;
201 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);
206 225
207 SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle()); 226 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 227
218 crypto::ScopedSECItem param(PK11_ParamFromIV(CKM_AES_CBC_PAD, &iv_item)); 228 crypto::ScopedSECItem param(PK11_ParamFromIV(CKM_AES_CBC_PAD, &iv_item));
219 if (!param) 229 if (!param)
220 return Status::Error(); 230 return Status::Error();
221 231
222 crypto::ScopedPK11Context context(PK11_CreateContextBySymKey( 232 crypto::ScopedPK11Context context(PK11_CreateContextBySymKey(
223 CKM_AES_CBC_PAD, operation, sym_key->key(), param.get())); 233 CKM_AES_CBC_PAD, operation, key->key(), param.get()));
224 234
225 if (!context.get()) 235 if (!context.get())
226 return Status::Error(); 236 return Status::Error();
227 237
228 // Oddly PK11_CipherOp takes input and output lengths as "int" rather than 238 // Oddly PK11_CipherOp takes input and output lengths as "int" rather than
229 // "unsigned int". Do some checks now to avoid integer overflowing. 239 // "unsigned int". Do some checks now to avoid integer overflowing.
230 if (data_size >= INT_MAX - AES_BLOCK_SIZE) { 240 if (data.byte_length() >= INT_MAX - AES_BLOCK_SIZE) {
231 // TODO(eroman): Handle this by chunking the input fed into NSS. Right now 241 // 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 242 // it doesn't make much difference since the one-shot API would end up
233 // blowing out the memory and crashing anyway. 243 // blowing out the memory and crashing anyway.
234 return Status::ErrorDataTooLarge(); 244 return Status::ErrorDataTooLarge();
235 } 245 }
236 246
237 // PK11_CipherOp does an invalid memory access when given empty decryption 247 // 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 248 // input, or input which is not a multiple of the block size. See also
239 // https://bugzilla.mozilla.com/show_bug.cgi?id=921687. 249 // https://bugzilla.mozilla.com/show_bug.cgi?id=921687.
240 if (operation == CKA_DECRYPT && 250 if (operation == CKA_DECRYPT &&
241 (data_size == 0 || (data_size % AES_BLOCK_SIZE != 0))) { 251 (data.byte_length() == 0 || (data.byte_length() % AES_BLOCK_SIZE != 0))) {
242 return Status::Error(); 252 return Status::Error();
243 } 253 }
244 254
245 // TODO(eroman): Refine the output buffer size. It can be computed exactly for 255 // TODO(eroman): Refine the output buffer size. It can be computed exactly for
246 // encryption, and can be smaller for decryption. 256 // encryption, and can be smaller for decryption.
247 unsigned int output_max_len = data_size + AES_BLOCK_SIZE; 257 unsigned int output_max_len = data.byte_length() + AES_BLOCK_SIZE;
248 CHECK_GT(output_max_len, data_size); 258 CHECK_GT(output_max_len, data.byte_length());
249 259
250 *buffer = blink::WebArrayBuffer::create(output_max_len, 1); 260 *buffer = blink::WebArrayBuffer::create(output_max_len, 1);
251 261
252 unsigned char* buffer_data = reinterpret_cast<unsigned char*>(buffer->data()); 262 unsigned char* buffer_data = reinterpret_cast<unsigned char*>(buffer->data());
253 263
254 int output_len; 264 int output_len;
255 if (SECSuccess != PK11_CipherOp(context.get(), 265 if (SECSuccess != PK11_CipherOp(context.get(),
256 buffer_data, 266 buffer_data,
257 &output_len, 267 &output_len,
258 buffer->byteLength(), 268 buffer->byteLength(),
259 data, 269 data.bytes(),
260 data_size)) { 270 data.byte_length())) {
261 return Status::Error(); 271 return Status::Error();
262 } 272 }
263 273
264 unsigned int final_output_chunk_len; 274 unsigned int final_output_chunk_len;
265 if (SECSuccess != PK11_DigestFinal(context.get(), 275 if (SECSuccess != PK11_DigestFinal(context.get(),
266 buffer_data + output_len, 276 buffer_data + output_len,
267 &final_output_chunk_len, 277 &final_output_chunk_len,
268 output_max_len - output_len)) { 278 output_max_len - output_len)) {
269 return Status::Error(); 279 return Status::Error();
270 } 280 }
271 281
272 webcrypto::ShrinkBuffer(buffer, final_output_chunk_len + output_len); 282 ShrinkBuffer(buffer, final_output_chunk_len + output_len);
273 return Status::Success(); 283 return Status::Success();
274 } 284 }
275 285
276 // Helper to either encrypt or decrypt for AES-GCM. The result of encryption is 286 // 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, 287 // the concatenation of the ciphertext and the authentication tag. Similarly,
278 // this is the expectation for the input to decryption. 288 // this is the expectation for the input to decryption.
279 Status AesGcmEncryptDecrypt( 289 Status AesGcmEncryptDecrypt(
280 bool encrypt, 290 EncryptOrDecrypt mode,
281 const blink::WebCryptoAlgorithm& algorithm, 291 SymKey* key,
282 const blink::WebCryptoKey& key, 292 const CryptoData& data,
283 const unsigned char* data, 293 const CryptoData& iv,
284 unsigned int data_size, 294 const CryptoData& additional_data,
295 unsigned int tag_length_bits,
285 blink::WebArrayBuffer* buffer) { 296 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()) 297 if (!g_aes_gcm_support.Get().IsSupported())
291 return Status::ErrorUnsupported(); 298 return Status::ErrorUnsupported();
292 299
293 SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle()); 300 // TODO(eroman): Is this necessary?
294 301 if ((tag_length_bits % 8) != 0)
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
300 // since that is the maximum tag length:
301 // http://www.w3.org/2012/webcrypto/track/issues/46
302 unsigned int tag_length_bits = 128;
303 if (params->hasTagLengthBits())
304 tag_length_bits = params->optionalTagLengthBits();
305
306 if (tag_length_bits > 128 || (tag_length_bits % 8) != 0)
307 return Status::ErrorInvalidAesGcmTagLength(); 302 return Status::ErrorInvalidAesGcmTagLength();
308
309 unsigned int tag_length_bytes = tag_length_bits / 8; 303 unsigned int tag_length_bytes = tag_length_bits / 8;
310 304
311 CK_GCM_PARAMS gcm_params = {0}; 305 CK_GCM_PARAMS gcm_params = {0};
312 gcm_params.pIv = 306 gcm_params.pIv = const_cast<unsigned char*>(iv.bytes());
313 const_cast<unsigned char*>(algorithm.aesGcmParams()->iv().data()); 307 gcm_params.ulIvLen = iv.byte_length();
314 gcm_params.ulIvLen = algorithm.aesGcmParams()->iv().size();
315 308
316 gcm_params.pAAD = 309 gcm_params.pAAD = const_cast<unsigned char*>(additional_data.bytes());
317 const_cast<unsigned char*>(params->optionalAdditionalData().data()); 310 gcm_params.ulAADLen = additional_data.byte_length();
318 gcm_params.ulAADLen = params->optionalAdditionalData().size();
319 311
320 gcm_params.ulTagBits = tag_length_bits; 312 gcm_params.ulTagBits = tag_length_bits;
321 313
322 SECItem param; 314 SECItem param;
323 param.type = siBuffer; 315 param.type = siBuffer;
324 param.data = reinterpret_cast<unsigned char*>(&gcm_params); 316 param.data = reinterpret_cast<unsigned char*>(&gcm_params);
325 param.len = sizeof(gcm_params); 317 param.len = sizeof(gcm_params);
326 318
327 unsigned int buffer_size = 0; 319 unsigned int buffer_size = 0;
328 320
329 // Calculate the output buffer size. 321 // Calculate the output buffer size.
330 if (encrypt) { 322 if (mode == ENCRYPT) {
331 // TODO(eroman): This is ugly, abstract away the safe integer arithmetic. 323 // TODO(eroman): This is ugly, abstract away the safe integer arithmetic.
332 if (data_size > (UINT_MAX - tag_length_bytes)) 324 if (data.byte_length() > (UINT_MAX - tag_length_bytes))
333 return Status::ErrorDataTooLarge(); 325 return Status::ErrorDataTooLarge();
334 buffer_size = data_size + tag_length_bytes; 326 buffer_size = data.byte_length() + tag_length_bytes;
335 } else { 327 } else {
336 // TODO(eroman): In theory the buffer allocated for the plain text should be 328 // TODO(eroman): In theory the buffer allocated for the plain text should be
337 // sized as |data_size - tag_length_bytes|. 329 // sized as |data.byte_length() - tag_length_bytes|.
338 // 330 //
339 // However NSS has a bug whereby it will fail if the output buffer size is 331 // However NSS has a bug whereby it will fail if the output buffer size is
340 // not at least as large as the ciphertext: 332 // not at least as large as the ciphertext:
341 // 333 //
342 // https://bugzilla.mozilla.org/show_bug.cgi?id=%20853674 334 // https://bugzilla.mozilla.org/show_bug.cgi?id=%20853674
343 // 335 //
344 // From the analysis of that bug it looks like it might be safe to pass a 336 // 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 337 // correctly sized buffer but lie about its size. Since resizing the
346 // WebCryptoArrayBuffer is expensive that hack may be worth looking into. 338 // WebCryptoArrayBuffer is expensive that hack may be worth looking into.
347 buffer_size = data_size; 339 buffer_size = data.byte_length();
348 } 340 }
349 341
350 *buffer = blink::WebArrayBuffer::create(buffer_size, 1); 342 *buffer = blink::WebArrayBuffer::create(buffer_size, 1);
351 unsigned char* buffer_data = reinterpret_cast<unsigned char*>(buffer->data()); 343 unsigned char* buffer_data = reinterpret_cast<unsigned char*>(buffer->data());
352 344
353 PK11_EncryptDecryptFunction func = 345 PK11_EncryptDecryptFunction func =
354 encrypt ? g_aes_gcm_support.Get().pk11_encrypt_func() : 346 (mode == ENCRYPT) ? g_aes_gcm_support.Get().pk11_encrypt_func() :
355 g_aes_gcm_support.Get().pk11_decrypt_func(); 347 g_aes_gcm_support.Get().pk11_decrypt_func();
356 348
357 unsigned int output_len = 0; 349 unsigned int output_len = 0;
358 SECStatus result = func(sym_key->key(), CKM_AES_GCM, &param, 350 SECStatus result = func(key->key(), CKM_AES_GCM, &param,
359 buffer_data, &output_len, buffer->byteLength(), 351 buffer_data, &output_len, buffer->byteLength(),
360 data, data_size); 352 data.bytes(), data.byte_length());
361 353
362 if (result != SECSuccess) 354 if (result != SECSuccess)
363 return Status::Error(); 355 return Status::Error();
364 356
365 // Unfortunately the buffer needs to be shrunk for decryption (see the NSS bug 357 // Unfortunately the buffer needs to be shrunk for decryption (see the NSS bug
366 // above). 358 // above).
367 webcrypto::ShrinkBuffer(buffer, output_len); 359 ShrinkBuffer(buffer, output_len);
368 360
369 return Status::Success(); 361 return Status::Success();
370 } 362 }
371 363
372 CK_MECHANISM_TYPE WebCryptoAlgorithmToGenMechanism( 364 CK_MECHANISM_TYPE WebCryptoAlgorithmToGenMechanism(
373 const blink::WebCryptoAlgorithm& algorithm) { 365 const blink::WebCryptoAlgorithm& algorithm) {
374 switch (algorithm.id()) { 366 switch (algorithm.id()) {
375 case blink::WebCryptoAlgorithmIdAesCbc: 367 case blink::WebCryptoAlgorithmIdAesCbc:
376 case blink::WebCryptoAlgorithmIdAesGcm: 368 case blink::WebCryptoAlgorithmIdAesGcm:
377 case blink::WebCryptoAlgorithmIdAesKw: 369 case blink::WebCryptoAlgorithmIdAesKw:
(...skipping 26 matching lines...) Expand all
404 } 396 }
405 return true; 397 return true;
406 } 398 }
407 399
408 bool IsAlgorithmRsa(const blink::WebCryptoAlgorithm& algorithm) { 400 bool IsAlgorithmRsa(const blink::WebCryptoAlgorithm& algorithm) {
409 return algorithm.id() == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 || 401 return algorithm.id() == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 ||
410 algorithm.id() == blink::WebCryptoAlgorithmIdRsaOaep || 402 algorithm.id() == blink::WebCryptoAlgorithmIdRsaOaep ||
411 algorithm.id() == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5; 403 algorithm.id() == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5;
412 } 404 }
413 405
414 Status ImportKeyInternalRaw( 406 } // namespace
415 const unsigned char* key_data, 407
416 unsigned int key_data_size, 408 Status ImportKeyRaw(
417 const blink::WebCryptoAlgorithm& algorithm, 409 const blink::WebCryptoAlgorithm& algorithm,
410 const CryptoData& key_data,
418 bool extractable, 411 bool extractable,
419 blink::WebCryptoKeyUsageMask usage_mask, 412 blink::WebCryptoKeyUsageMask usage_mask,
420 blink::WebCryptoKey* key) { 413 blink::WebCryptoKey* key) {
421 414
422 DCHECK(!algorithm.isNull()); 415 DCHECK(!algorithm.isNull());
423 416
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. 417 // TODO(bryaneyler): Need to split handling for symmetric and asymmetric keys.
438 // Currently only supporting symmetric. 418 // Currently only supporting symmetric.
439 CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM; 419 CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM;
440 // Flags are verified at the Blink layer; here the flags are set to all 420 // Flags are verified at the Blink layer; here the flags are set to all
441 // possible operations for this key type. 421 // possible operations for this key type.
442 CK_FLAGS flags = 0; 422 CK_FLAGS flags = 0;
443 423
444 switch (algorithm.id()) { 424 switch (algorithm.id()) {
445 case blink::WebCryptoAlgorithmIdHmac: { 425 case blink::WebCryptoAlgorithmIdHmac: {
446 const blink::WebCryptoHmacParams* params = algorithm.hmacParams(); 426 const blink::WebCryptoHmacParams* params = algorithm.hmacParams();
(...skipping 25 matching lines...) Expand all
472 flags |= CKF_ENCRYPT | CKF_DECRYPT; 452 flags |= CKF_ENCRYPT | CKF_DECRYPT;
473 break; 453 break;
474 } 454 }
475 default: 455 default:
476 return Status::ErrorUnsupported(); 456 return Status::ErrorUnsupported();
477 } 457 }
478 458
479 DCHECK_NE(CKM_INVALID_MECHANISM, mechanism); 459 DCHECK_NE(CKM_INVALID_MECHANISM, mechanism);
480 DCHECK_NE(0ul, flags); 460 DCHECK_NE(0ul, flags);
481 461
482 SECItem key_item = { 462 SECItem key_item = MakeSECItemForBuffer(key_data);
483 siBuffer,
484 const_cast<unsigned char*>(key_data),
485 key_data_size
486 };
487 463
488 crypto::ScopedPK11Slot slot(PK11_GetInternalSlot()); 464 crypto::ScopedPK11Slot slot(PK11_GetInternalSlot());
489 crypto::ScopedPK11SymKey pk11_sym_key( 465 crypto::ScopedPK11SymKey pk11_sym_key(
490 PK11_ImportSymKeyWithFlags(slot.get(), 466 PK11_ImportSymKeyWithFlags(slot.get(),
491 mechanism, 467 mechanism,
492 PK11_OriginUnwrap, 468 PK11_OriginUnwrap,
493 CKA_FLAGS_ONLY, 469 CKA_FLAGS_ONLY,
494 &key_item, 470 &key_item,
495 flags, 471 flags,
496 false, 472 false,
497 NULL)); 473 NULL));
498 if (!pk11_sym_key.get()) 474 if (!pk11_sym_key.get())
499 return Status::Error(); 475 return Status::Error();
500 476
501 *key = blink::WebCryptoKey::create(new SymKeyHandle(pk11_sym_key.Pass()), 477 *key = blink::WebCryptoKey::create(new SymKey(pk11_sym_key.Pass()),
502 type, extractable, algorithm, usage_mask); 478 blink::WebCryptoKeyTypeSecret,
479 extractable,
480 algorithm,
481 usage_mask);
503 return Status::Success(); 482 return Status::Success();
504 } 483 }
505 484
506 Status ExportKeyInternalRaw( 485 Status ExportKeyRaw(
507 const blink::WebCryptoKey& key, 486 SymKey* key,
508 blink::WebArrayBuffer* buffer) { 487 blink::WebArrayBuffer* buffer) {
509 488 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(); 489 return Status::Error();
522 490
523 const SECItem* key_data = PK11_GetKeyData(sym_key->key()); 491 const SECItem* key_data = PK11_GetKeyData(key->key());
524 if (!key_data) 492 if (!key_data)
525 return Status::Error(); 493 return Status::Error();
526 494
527 *buffer = webcrypto::CreateArrayBuffer(key_data->data, key_data->len); 495 *buffer = CreateArrayBuffer(key_data->data, key_data->len);
528 496
529 return Status::Success(); 497 return Status::Success();
530 } 498 }
531 499
500 namespace {
501
532 typedef scoped_ptr<CERTSubjectPublicKeyInfo, 502 typedef scoped_ptr<CERTSubjectPublicKeyInfo,
533 crypto::NSSDestroyer<CERTSubjectPublicKeyInfo, 503 crypto::NSSDestroyer<CERTSubjectPublicKeyInfo,
534 SECKEY_DestroySubjectPublicKeyInfo> > 504 SECKEY_DestroySubjectPublicKeyInfo> >
535 ScopedCERTSubjectPublicKeyInfo; 505 ScopedCERTSubjectPublicKeyInfo;
536 506
537 // Validates an NSS KeyType against a WebCrypto algorithm. Some NSS KeyTypes 507 // Validates an NSS KeyType against a WebCrypto algorithm. Some NSS KeyTypes
538 // contain enough information to fabricate a Web Crypto algorithm, which is 508 // contain enough information to fabricate a Web Crypto algorithm, which is
539 // returned if the input algorithm isNull(). This function indicates failure by 509 // returned if the input algorithm isNull(). This function indicates failure by
540 // returning a Null algorithm. 510 // returning a Null algorithm.
541 blink::WebCryptoAlgorithm ResolveNssKeyTypeWithInputAlgorithm( 511 blink::WebCryptoAlgorithm ResolveNssKeyTypeWithInputAlgorithm(
(...skipping 15 matching lines...) Expand all
557 case rsaPssKey: 527 case rsaPssKey:
558 case rsaOaepKey: 528 case rsaOaepKey:
559 // TODO(padolph): Handle other key types. 529 // TODO(padolph): Handle other key types.
560 break; 530 break;
561 default: 531 default:
562 break; 532 break;
563 } 533 }
564 return blink::WebCryptoAlgorithm::createNull(); 534 return blink::WebCryptoAlgorithm::createNull();
565 } 535 }
566 536
567 Status ImportKeyInternalSpki( 537 } // namespace
568 const unsigned char* key_data, 538
569 unsigned int key_data_size, 539 Status ImportKeySpki(
570 const blink::WebCryptoAlgorithm& algorithm_or_null, 540 const blink::WebCryptoAlgorithm& algorithm_or_null,
541 const CryptoData& key_data,
571 bool extractable, 542 bool extractable,
572 blink::WebCryptoKeyUsageMask usage_mask, 543 blink::WebCryptoKeyUsageMask usage_mask,
573 blink::WebCryptoKey* key) { 544 blink::WebCryptoKey* key) {
574 545
575 DCHECK(key); 546 DCHECK(key);
576 547
577 if (!key_data_size) 548 if (!key_data.byte_length())
578 return Status::ErrorImportEmptyKeyData(); 549 return Status::ErrorImportEmptyKeyData();
579 DCHECK(key_data); 550 DCHECK(key_data.bytes());
580 551
581 // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 Subject 552 // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 Subject
582 // Public Key Info. Decode this to a CERTSubjectPublicKeyInfo. 553 // Public Key Info. Decode this to a CERTSubjectPublicKeyInfo.
583 SECItem spki_item = {siBuffer, const_cast<uint8*>(key_data), key_data_size}; 554 SECItem spki_item = MakeSECItemForBuffer(key_data);
584 const ScopedCERTSubjectPublicKeyInfo spki( 555 const ScopedCERTSubjectPublicKeyInfo spki(
585 SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_item)); 556 SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_item));
586 if (!spki) 557 if (!spki)
587 return Status::Error(); 558 return Status::Error();
588 559
589 crypto::ScopedSECKEYPublicKey sec_public_key( 560 crypto::ScopedSECKEYPublicKey sec_public_key(
590 SECKEY_ExtractPublicKey(spki.get())); 561 SECKEY_ExtractPublicKey(spki.get()));
591 if (!sec_public_key) 562 if (!sec_public_key)
592 return Status::Error(); 563 return Status::Error();
593 564
594 const KeyType sec_key_type = SECKEY_GetPublicKeyType(sec_public_key.get()); 565 const KeyType sec_key_type = SECKEY_GetPublicKeyType(sec_public_key.get());
595 blink::WebCryptoAlgorithm algorithm = 566 blink::WebCryptoAlgorithm algorithm =
596 ResolveNssKeyTypeWithInputAlgorithm(sec_key_type, algorithm_or_null); 567 ResolveNssKeyTypeWithInputAlgorithm(sec_key_type, algorithm_or_null);
597 if (algorithm.isNull()) 568 if (algorithm.isNull())
598 return Status::Error(); 569 return Status::Error();
599 570
600 *key = blink::WebCryptoKey::create( 571 *key = blink::WebCryptoKey::create(
601 new PublicKeyHandle(sec_public_key.Pass()), 572 new PublicKey(sec_public_key.Pass()),
602 blink::WebCryptoKeyTypePublic, 573 blink::WebCryptoKeyTypePublic,
603 extractable, 574 extractable,
604 algorithm, 575 algorithm,
605 usage_mask); 576 usage_mask);
606 577
607 return Status::Success(); 578 return Status::Success();
608 } 579 }
609 580
610 Status ExportKeyInternalSpki( 581 Status ExportKeySpki(
611 const blink::WebCryptoKey& key, 582 PublicKey* key,
612 blink::WebArrayBuffer* buffer) { 583 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( 584 const crypto::ScopedSECItem spki_der(
626 SECKEY_EncodeDERSubjectPublicKeyInfo(pub_key->key())); 585 SECKEY_EncodeDERSubjectPublicKeyInfo(key->key()));
627 if (!spki_der) 586 if (!spki_der)
628 return Status::Error(); 587 return Status::Error();
629 588
630 DCHECK(spki_der->data); 589 DCHECK(spki_der->data);
631 DCHECK(spki_der->len); 590 DCHECK(spki_der->len);
632 591
633 *buffer = webcrypto::CreateArrayBuffer(spki_der->data, spki_der->len); 592 *buffer = CreateArrayBuffer(spki_der->data, spki_der->len);
634 593
635 return Status::Success(); 594 return Status::Success();
636 } 595 }
637 596
638 Status ImportKeyInternalPkcs8( 597 Status ImportKeyPkcs8(
639 const unsigned char* key_data,
640 unsigned int key_data_size,
641 const blink::WebCryptoAlgorithm& algorithm_or_null, 598 const blink::WebCryptoAlgorithm& algorithm_or_null,
599 const CryptoData& key_data,
642 bool extractable, 600 bool extractable,
643 blink::WebCryptoKeyUsageMask usage_mask, 601 blink::WebCryptoKeyUsageMask usage_mask,
644 blink::WebCryptoKey* key) { 602 blink::WebCryptoKey* key) {
645 603
646 DCHECK(key); 604 DCHECK(key);
647 605
648 if (!key_data_size) 606 if (!key_data.byte_length())
649 return Status::ErrorImportEmptyKeyData(); 607 return Status::ErrorImportEmptyKeyData();
650 DCHECK(key_data); 608 DCHECK(key_data.bytes());
651 609
652 // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 PKCS#8 610 // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 PKCS#8
653 // private key info object. 611 // private key info object.
654 SECItem pki_der = {siBuffer, const_cast<uint8*>(key_data), key_data_size}; 612 SECItem pki_der = MakeSECItemForBuffer(key_data);
655 613
656 SECKEYPrivateKey* seckey_private_key = NULL; 614 SECKEYPrivateKey* seckey_private_key = NULL;
657 crypto::ScopedPK11Slot slot(PK11_GetInternalSlot()); 615 crypto::ScopedPK11Slot slot(PK11_GetInternalSlot());
658 if (PK11_ImportDERPrivateKeyInfoAndReturnKey( 616 if (PK11_ImportDERPrivateKeyInfoAndReturnKey(
659 slot.get(), 617 slot.get(),
660 &pki_der, 618 &pki_der,
661 NULL, // nickname 619 NULL, // nickname
662 NULL, // publicValue 620 NULL, // publicValue
663 false, // isPerm 621 false, // isPerm
664 false, // isPrivate 622 false, // isPrivate
665 KU_ALL, // usage 623 KU_ALL, // usage
666 &seckey_private_key, 624 &seckey_private_key,
667 NULL) != SECSuccess) { 625 NULL) != SECSuccess) {
668 return Status::Error(); 626 return Status::Error();
669 } 627 }
670 DCHECK(seckey_private_key); 628 DCHECK(seckey_private_key);
671 crypto::ScopedSECKEYPrivateKey private_key(seckey_private_key); 629 crypto::ScopedSECKEYPrivateKey private_key(seckey_private_key);
672 630
673 const KeyType sec_key_type = SECKEY_GetPrivateKeyType(private_key.get()); 631 const KeyType sec_key_type = SECKEY_GetPrivateKeyType(private_key.get());
674 blink::WebCryptoAlgorithm algorithm = 632 blink::WebCryptoAlgorithm algorithm =
675 ResolveNssKeyTypeWithInputAlgorithm(sec_key_type, algorithm_or_null); 633 ResolveNssKeyTypeWithInputAlgorithm(sec_key_type, algorithm_or_null);
676 if (algorithm.isNull()) 634 if (algorithm.isNull())
677 return Status::Error(); 635 return Status::Error();
678 636
679 *key = blink::WebCryptoKey::create( 637 *key = blink::WebCryptoKey::create(
680 new PrivateKeyHandle(private_key.Pass()), 638 new PrivateKey(private_key.Pass()),
681 blink::WebCryptoKeyTypePrivate, 639 blink::WebCryptoKeyTypePrivate,
682 extractable, 640 extractable,
683 algorithm, 641 algorithm,
684 usage_mask); 642 usage_mask);
685 643
686 return Status::Success(); 644 return Status::Success();
687 } 645 }
688 646
689 // ----------------------------------- 647 // -----------------------------------
690 // Hmac 648 // Hmac
691 // ----------------------------------- 649 // -----------------------------------
692 650
693 Status SignHmac( 651 Status SignHmac(
694 const blink::WebCryptoAlgorithm& algorithm, 652 SymKey* key,
695 const blink::WebCryptoKey& key, 653 const blink::WebCryptoAlgorithm& hash,
696 const unsigned char* data, 654 const CryptoData& data,
697 unsigned int data_size,
698 blink::WebArrayBuffer* buffer) { 655 blink::WebArrayBuffer* buffer) {
699 DCHECK_EQ(blink::WebCryptoAlgorithmIdHmac, algorithm.id()); 656 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 657
710 SECItem param_item = { siBuffer, NULL, 0 }; 658 SECItem param_item = { siBuffer, NULL, 0 };
711 SECItem data_item = { 659 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. 660 // First call is to figure out the length.
717 SECItem signature_item = { siBuffer, NULL, 0 }; 661 SECItem signature_item = { siBuffer, NULL, 0 };
718 662
719 if (PK11_SignWithSymKey(sym_key->key(), 663 if (PK11_SignWithSymKey(key->key(),
720 PK11_GetMechanism(sym_key->key()), 664 PK11_GetMechanism(key->key()),
721 &param_item, 665 &param_item,
722 &signature_item, 666 &signature_item,
723 &data_item) != SECSuccess) { 667 &data_item) != SECSuccess) {
724 return Status::Error(); 668 return Status::Error();
725 } 669 }
726 670
727 DCHECK_NE(0u, signature_item.len); 671 DCHECK_NE(0u, signature_item.len);
728 672
729 *buffer = blink::WebArrayBuffer::create(signature_item.len, 1); 673 *buffer = blink::WebArrayBuffer::create(signature_item.len, 1);
730 signature_item.data = reinterpret_cast<unsigned char*>(buffer->data()); 674 signature_item.data = reinterpret_cast<unsigned char*>(buffer->data());
731 675
732 if (PK11_SignWithSymKey(sym_key->key(), 676 if (PK11_SignWithSymKey(key->key(),
733 PK11_GetMechanism(sym_key->key()), 677 PK11_GetMechanism(key->key()),
734 &param_item, 678 &param_item,
735 &signature_item, 679 &signature_item,
736 &data_item) != SECSuccess) { 680 &data_item) != SECSuccess) {
737 return Status::Error(); 681 return Status::Error();
738 } 682 }
739 683
740 DCHECK_EQ(buffer->byteLength(), signature_item.len); 684 DCHECK_EQ(buffer->byteLength(), signature_item.len);
741 return Status::Success(); 685 return Status::Success();
742 } 686 }
743 687
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 // ----------------------------------- 688 // -----------------------------------
771 // RsaEsPkcs1v1_5 689 // RsaEsPkcs1v1_5
772 // ----------------------------------- 690 // -----------------------------------
773 691
774 Status EncryptRsaEsPkcs1v1_5( 692 Status EncryptRsaEsPkcs1v1_5(
775 const blink::WebCryptoAlgorithm& algorithm, 693 PublicKey* key,
776 const blink::WebCryptoKey& key, 694 const CryptoData& data,
777 const unsigned char* data,
778 unsigned int data_size,
779 blink::WebArrayBuffer* buffer) { 695 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 = 696 const unsigned int encrypted_length_bytes =
794 SECKEY_PublicKeyStrength(public_key->key()); 697 SECKEY_PublicKeyStrength(key->key());
795 698
796 // RSAES can operate on messages up to a length of k - 11, where k is the 699 // RSAES can operate on messages up to a length of k - 11, where k is the
797 // octet length of the RSA modulus. 700 // octet length of the RSA modulus.
798 if (encrypted_length_bytes < 11 || encrypted_length_bytes - 11 < data_size) 701 if (encrypted_length_bytes < 11 ||
702 encrypted_length_bytes - 11 < data.byte_length())
799 return Status::ErrorDataTooLarge(); 703 return Status::ErrorDataTooLarge();
800 704
801 *buffer = blink::WebArrayBuffer::create(encrypted_length_bytes, 1); 705 *buffer = blink::WebArrayBuffer::create(encrypted_length_bytes, 1);
802 unsigned char* const buffer_data = 706 unsigned char* const buffer_data =
803 reinterpret_cast<unsigned char*>(buffer->data()); 707 reinterpret_cast<unsigned char*>(buffer->data());
804 708
805 if (PK11_PubEncryptPKCS1(public_key->key(), 709 if (PK11_PubEncryptPKCS1(key->key(),
806 buffer_data, 710 buffer_data,
807 const_cast<unsigned char*>(data), 711 const_cast<unsigned char*>(data.bytes()),
808 data_size, 712 data.byte_length(),
809 NULL) != SECSuccess) { 713 NULL) != SECSuccess) {
810 return Status::Error(); 714 return Status::Error();
811 } 715 }
812 return Status::Success(); 716 return Status::Success();
813 } 717 }
814 718
815 Status DecryptRsaEsPkcs1v1_5( 719 Status DecryptRsaEsPkcs1v1_5(
816 const blink::WebCryptoAlgorithm& algorithm, 720 PrivateKey* key,
817 const blink::WebCryptoKey& key, 721 const CryptoData& data,
818 const unsigned char* data,
819 unsigned int data_size,
820 blink::WebArrayBuffer* buffer) { 722 blink::WebArrayBuffer* buffer) {
821 DCHECK_EQ(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, algorithm.id()); 723 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) 724 if (modulus_length_bytes <= 0)
837 return Status::ErrorUnexpected(); 725 return Status::ErrorUnexpected();
838 const unsigned int max_output_length_bytes = modulus_length_bytes; 726 const unsigned int max_output_length_bytes = modulus_length_bytes;
839 727
840 *buffer = blink::WebArrayBuffer::create(max_output_length_bytes, 1); 728 *buffer = blink::WebArrayBuffer::create(max_output_length_bytes, 1);
841 unsigned char* const buffer_data = 729 unsigned char* const buffer_data =
842 reinterpret_cast<unsigned char*>(buffer->data()); 730 reinterpret_cast<unsigned char*>(buffer->data());
843 731
844 unsigned int output_length_bytes = 0; 732 unsigned int output_length_bytes = 0;
845 if (PK11_PrivDecryptPKCS1(private_key->key(), 733 if (PK11_PrivDecryptPKCS1(key->key(),
846 buffer_data, 734 buffer_data,
847 &output_length_bytes, 735 &output_length_bytes,
848 max_output_length_bytes, 736 max_output_length_bytes,
849 const_cast<unsigned char*>(data), 737 const_cast<unsigned char*>(data.bytes()),
850 data_size) != SECSuccess) { 738 data.byte_length()) != SECSuccess) {
851 return Status::Error(); 739 return Status::Error();
852 } 740 }
853 DCHECK_LE(output_length_bytes, max_output_length_bytes); 741 DCHECK_LE(output_length_bytes, max_output_length_bytes);
854 webcrypto::ShrinkBuffer(buffer, output_length_bytes); 742 ShrinkBuffer(buffer, output_length_bytes);
855 return Status::Success(); 743 return Status::Success();
856 } 744 }
857 745
858 // ----------------------------------- 746 // -----------------------------------
859 // RsaSsaPkcs1v1_5 747 // RsaSsaPkcs1v1_5
860 // ----------------------------------- 748 // -----------------------------------
861 749
862 Status SignRsaSsaPkcs1v1_5( 750 Status SignRsaSsaPkcs1v1_5(
863 const blink::WebCryptoAlgorithm& algorithm, 751 PrivateKey* key,
864 const blink::WebCryptoKey& key, 752 const blink::WebCryptoAlgorithm& hash,
865 const unsigned char* data, 753 const CryptoData& data,
866 unsigned int data_size,
867 blink::WebArrayBuffer* buffer) { 754 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 755 // Pick the NSS signing algorithm by combining RSA-SSA (RSA PKCS1) and the
882 // inner hash of the input Web Crypto algorithm. 756 // inner hash of the input Web Crypto algorithm.
883 SECOidTag sign_alg_tag; 757 SECOidTag sign_alg_tag;
884 switch (webcrypto::GetInnerHashAlgorithm(algorithm).id()) { 758 switch (hash.id()) {
885 case blink::WebCryptoAlgorithmIdSha1: 759 case blink::WebCryptoAlgorithmIdSha1:
886 sign_alg_tag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; 760 sign_alg_tag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
887 break; 761 break;
888 case blink::WebCryptoAlgorithmIdSha224: 762 case blink::WebCryptoAlgorithmIdSha224:
889 sign_alg_tag = SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION; 763 sign_alg_tag = SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION;
890 break; 764 break;
891 case blink::WebCryptoAlgorithmIdSha256: 765 case blink::WebCryptoAlgorithmIdSha256:
892 sign_alg_tag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION; 766 sign_alg_tag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
893 break; 767 break;
894 case blink::WebCryptoAlgorithmIdSha384: 768 case blink::WebCryptoAlgorithmIdSha384:
895 sign_alg_tag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION; 769 sign_alg_tag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;
896 break; 770 break;
897 case blink::WebCryptoAlgorithmIdSha512: 771 case blink::WebCryptoAlgorithmIdSha512:
898 sign_alg_tag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION; 772 sign_alg_tag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
899 break; 773 break;
900 default: 774 default:
901 return Status::ErrorUnsupported(); 775 return Status::ErrorUnsupported();
902 } 776 }
903 777
904 crypto::ScopedSECItem signature_item(SECITEM_AllocItem(NULL, NULL, 0)); 778 crypto::ScopedSECItem signature_item(SECITEM_AllocItem(NULL, NULL, 0));
905 if (SEC_SignData(signature_item.get(), 779 if (SEC_SignData(signature_item.get(),
906 data, 780 data.bytes(),
907 data_size, 781 data.byte_length(),
908 private_key->key(), 782 key->key(),
909 sign_alg_tag) != SECSuccess) { 783 sign_alg_tag) != SECSuccess) {
910 return Status::Error(); 784 return Status::Error();
911 } 785 }
912 786
913 *buffer = webcrypto::CreateArrayBuffer(signature_item->data, 787 *buffer = CreateArrayBuffer(signature_item->data, signature_item->len);
914 signature_item->len);
915 return Status::Success(); 788 return Status::Success();
916 } 789 }
917 790
918 Status VerifyRsaSsaPkcs1v1_5( 791 Status VerifyRsaSsaPkcs1v1_5(
919 const blink::WebCryptoAlgorithm& algorithm, 792 PublicKey* key,
920 const blink::WebCryptoKey& key, 793 const blink::WebCryptoAlgorithm& hash,
921 const unsigned char* signature, 794 const CryptoData& signature,
922 unsigned int signature_size, 795 const CryptoData& data,
923 const unsigned char* data,
924 unsigned int data_size,
925 bool* signature_match) { 796 bool* signature_match) {
926 DCHECK_EQ(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, algorithm.id()); 797 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 798
942 SECOidTag hash_alg_tag; 799 SECOidTag hash_alg_tag;
943 switch (webcrypto::GetInnerHashAlgorithm(algorithm).id()) { 800 switch (hash.id()) {
944 case blink::WebCryptoAlgorithmIdSha1: 801 case blink::WebCryptoAlgorithmIdSha1:
945 hash_alg_tag = SEC_OID_SHA1; 802 hash_alg_tag = SEC_OID_SHA1;
946 break; 803 break;
947 case blink::WebCryptoAlgorithmIdSha224: 804 case blink::WebCryptoAlgorithmIdSha224:
948 hash_alg_tag = SEC_OID_SHA224; 805 hash_alg_tag = SEC_OID_SHA224;
949 break; 806 break;
950 case blink::WebCryptoAlgorithmIdSha256: 807 case blink::WebCryptoAlgorithmIdSha256:
951 hash_alg_tag = SEC_OID_SHA256; 808 hash_alg_tag = SEC_OID_SHA256;
952 break; 809 break;
953 case blink::WebCryptoAlgorithmIdSha384: 810 case blink::WebCryptoAlgorithmIdSha384:
954 hash_alg_tag = SEC_OID_SHA384; 811 hash_alg_tag = SEC_OID_SHA384;
955 break; 812 break;
956 case blink::WebCryptoAlgorithmIdSha512: 813 case blink::WebCryptoAlgorithmIdSha512:
957 hash_alg_tag = SEC_OID_SHA512; 814 hash_alg_tag = SEC_OID_SHA512;
958 break; 815 break;
959 default: 816 default:
960 return Status::ErrorUnsupported(); 817 return Status::ErrorUnsupported();
961 } 818 }
962 819
963 *signature_match = 820 *signature_match =
964 SECSuccess == VFY_VerifyDataDirect(data, 821 SECSuccess == VFY_VerifyDataDirect(data.bytes(),
965 data_size, 822 data.byte_length(),
966 public_key->key(), 823 key->key(),
967 &signature_item, 824 &signature_item,
968 SEC_OID_PKCS1_RSA_ENCRYPTION, 825 SEC_OID_PKCS1_RSA_ENCRYPTION,
969 hash_alg_tag, 826 hash_alg_tag,
970 NULL, 827 NULL,
971 NULL); 828 NULL);
972 return Status::Success(); 829 return Status::Success();
973 } 830 }
974 831
832 Status EncryptDecryptAesCbc(EncryptOrDecrypt mode,
833 SymKey* key,
834 const CryptoData& data,
835 const CryptoData& iv,
836 blink::WebArrayBuffer* buffer) {
837 // TODO(eroman): Inline.
838 return AesCbcEncryptDecrypt(mode, key, iv, data, buffer);
839 }
840
841 Status EncryptDecryptAesGcm(EncryptOrDecrypt mode,
842 SymKey* key,
843 const CryptoData& data,
844 const CryptoData& iv,
845 const CryptoData& additional_data,
846 unsigned int tag_length_bits,
847 blink::WebArrayBuffer* buffer) {
848 // TODO(eroman): Inline.
849 return AesGcmEncryptDecrypt(
850 mode, key, data, iv, additional_data, tag_length_bits, buffer);
851 }
852
975 // ----------------------------------- 853 // -----------------------------------
976 // Key generation 854 // Key generation
977 // ----------------------------------- 855 // -----------------------------------
978 856
979 Status GenerateRsaKeyPair( 857 Status GenerateRsaKeyPair(
980 const blink::WebCryptoAlgorithm& algorithm, 858 const blink::WebCryptoAlgorithm& algorithm,
981 bool extractable, 859 bool extractable,
982 blink::WebCryptoKeyUsageMask usage_mask, 860 blink::WebCryptoKeyUsageMask usage_mask,
983 blink::WebCryptoKey* public_key, 861 blink::WebCryptoKey* public_key,
984 blink::WebCryptoKey* private_key) { 862 blink::WebCryptoKey* private_key) {
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1033 &rsa_gen_params, 911 &rsa_gen_params,
1034 &sec_public_key, 912 &sec_public_key,
1035 attribute_flags, 913 attribute_flags,
1036 operation_flags, 914 operation_flags,
1037 operation_flags_mask, 915 operation_flags_mask,
1038 NULL)); 916 NULL));
1039 if (!private_key) 917 if (!private_key)
1040 return Status::Error(); 918 return Status::Error();
1041 919
1042 *public_key = blink::WebCryptoKey::create( 920 *public_key = blink::WebCryptoKey::create(
1043 new PublicKeyHandle(crypto::ScopedSECKEYPublicKey(sec_public_key)), 921 new PublicKey(crypto::ScopedSECKEYPublicKey(sec_public_key)),
1044 blink::WebCryptoKeyTypePublic, 922 blink::WebCryptoKeyTypePublic,
1045 true, 923 true,
1046 algorithm, 924 algorithm,
1047 usage_mask); 925 usage_mask);
1048 *private_key = blink::WebCryptoKey::create( 926 *private_key = blink::WebCryptoKey::create(
1049 new PrivateKeyHandle(scoped_sec_private_key.Pass()), 927 new PrivateKey(scoped_sec_private_key.Pass()),
1050 blink::WebCryptoKeyTypePrivate, 928 blink::WebCryptoKeyTypePrivate,
1051 extractable, 929 extractable,
1052 algorithm, 930 algorithm,
1053 usage_mask); 931 usage_mask);
1054 932
1055 return Status::Success(); 933 return Status::Success();
1056 } 934 }
1057 935
1058 // Get the secret key length in bytes from generation parameters. This resolves 936 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(); 937 crypto::EnsureNSSInit();
1102 } 938 }
1103 939
1104 Status WebCryptoImpl::EncryptInternal( 940 Status DigestSha(
1105 const blink::WebCryptoAlgorithm& algorithm, 941 blink::WebCryptoAlgorithmId algorithm,
1106 const blink::WebCryptoKey& key, 942 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) { 943 blink::WebArrayBuffer* buffer) {
1159 HASH_HashType hash_type = WebCryptoAlgorithmToNSSHashType(algorithm); 944 HASH_HashType hash_type = WebCryptoAlgorithmToNSSHashType(algorithm);
1160 if (hash_type == HASH_AlgNULL) 945 if (hash_type == HASH_AlgNULL)
1161 return Status::ErrorUnsupported(); 946 return Status::ErrorUnsupported();
1162 947
1163 HASHContext* context = HASH_Create(hash_type); 948 HASHContext* context = HASH_Create(hash_type);
1164 if (!context) 949 if (!context)
1165 return Status::Error(); 950 return Status::Error();
1166 951
1167 HASH_Begin(context); 952 HASH_Begin(context);
1168 953
1169 HASH_Update(context, data, data_size); 954 HASH_Update(context, data.bytes(), data.byte_length());
1170 955
1171 unsigned int hash_result_length = HASH_ResultLenContext(context); 956 unsigned int hash_result_length = HASH_ResultLenContext(context);
1172 DCHECK_LE(hash_result_length, static_cast<size_t>(HASH_LENGTH_MAX)); 957 DCHECK_LE(hash_result_length, static_cast<size_t>(HASH_LENGTH_MAX));
1173 958
1174 *buffer = blink::WebArrayBuffer::create(hash_result_length, 1); 959 *buffer = blink::WebArrayBuffer::create(hash_result_length, 1);
1175 960
1176 unsigned char* digest = reinterpret_cast<unsigned char*>(buffer->data()); 961 unsigned char* digest = reinterpret_cast<unsigned char*>(buffer->data());
1177 962
1178 unsigned int result_length = 0; 963 unsigned int result_length = 0;
1179 HASH_End(context, digest, &result_length, hash_result_length); 964 HASH_End(context, digest, &result_length, hash_result_length);
1180 965
1181 HASH_Destroy(context); 966 HASH_Destroy(context);
1182 967
1183 if (result_length != hash_result_length) 968 if (result_length != hash_result_length)
1184 return Status::ErrorUnexpected(); 969 return Status::ErrorUnexpected();
1185 return Status::Success(); 970 return Status::Success();
1186 } 971 }
1187 972
1188 Status WebCryptoImpl::GenerateSecretKeyInternal( 973 Status GenerateSecretKey(
1189 const blink::WebCryptoAlgorithm& algorithm, 974 const blink::WebCryptoAlgorithm& algorithm,
1190 bool extractable, 975 bool extractable,
1191 blink::WebCryptoKeyUsageMask usage_mask, 976 blink::WebCryptoKeyUsageMask usage_mask,
977 unsigned keylen_bytes,
1192 blink::WebCryptoKey* key) { 978 blink::WebCryptoKey* key) {
1193
1194 CK_MECHANISM_TYPE mech = WebCryptoAlgorithmToGenMechanism(algorithm); 979 CK_MECHANISM_TYPE mech = WebCryptoAlgorithmToGenMechanism(algorithm);
1195 blink::WebCryptoKeyType key_type = blink::WebCryptoKeyTypeSecret; 980 blink::WebCryptoKeyType key_type = blink::WebCryptoKeyTypeSecret;
1196 981
1197 if (mech == CKM_INVALID_MECHANISM) 982 if (mech == CKM_INVALID_MECHANISM)
1198 return Status::ErrorUnsupported(); 983 return Status::ErrorUnsupported();
1199 984
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()); 985 crypto::ScopedPK11Slot slot(PK11_GetInternalKeySlot());
1206 if (!slot) 986 if (!slot)
1207 return Status::Error(); 987 return Status::Error();
1208 988
1209 crypto::ScopedPK11SymKey pk11_key( 989 crypto::ScopedPK11SymKey pk11_key(
1210 PK11_KeyGen(slot.get(), mech, NULL, keylen_bytes, NULL)); 990 PK11_KeyGen(slot.get(), mech, NULL, keylen_bytes, NULL));
1211 991
1212 if (!pk11_key) 992 if (!pk11_key)
1213 return Status::Error(); 993 return Status::Error();
1214 994
1215 *key = blink::WebCryptoKey::create( 995 *key = blink::WebCryptoKey::create(new SymKey(pk11_key.Pass()),
1216 new SymKeyHandle(pk11_key.Pass()), 996 key_type,
1217 key_type, extractable, algorithm, usage_mask); 997 extractable,
998 algorithm,
999 usage_mask);
1218 return Status::Success(); 1000 return Status::Success();
1219 } 1001 }
1220 1002
1221 Status WebCryptoImpl::GenerateKeyPairInternal( 1003 Status ImportRsaPublicKey(
1222 const blink::WebCryptoAlgorithm& algorithm, 1004 const blink::WebCryptoAlgorithm& algorithm,
1223 bool extractable, 1005 bool extractable,
1224 blink::WebCryptoKeyUsageMask usage_mask, 1006 blink::WebCryptoKeyUsageMask usage_mask,
1225 blink::WebCryptoKey* public_key, 1007 const CryptoData& modulus_data,
1226 blink::WebCryptoKey* private_key) { 1008 const CryptoData& exponent_data,
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) { 1009 blink::WebCryptoKey* key) {
1248 1010
1249 switch (format) { 1011 if (!modulus_data.byte_length())
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,
1356 bool extractable,
1357 blink::WebCryptoKeyUsageMask usage_mask,
1358 blink::WebCryptoKey* key) {
1359
1360 if (!modulus_size)
1361 return Status::ErrorImportRsaEmptyModulus(); 1012 return Status::ErrorImportRsaEmptyModulus();
1362 1013
1363 if (!exponent_size) 1014 if (!exponent_data.byte_length())
1364 return Status::ErrorImportRsaEmptyExponent(); 1015 return Status::ErrorImportRsaEmptyExponent();
1365 1016
1366 DCHECK(modulus_data); 1017 DCHECK(modulus_data.bytes());
1367 DCHECK(exponent_data); 1018 DCHECK(exponent_data.bytes());
1368 1019
1369 // NSS does not provide a way to create an RSA public key directly from the 1020 // 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 1021 // 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 1022 // with these values and create the public key from that. The code below
1372 // follows the recommendation described in 1023 // follows the recommendation described in
1373 // https://developer.mozilla.org/en-US/docs/NSS/NSS_Tech_Notes/nss_tech_note7 1024 // https://developer.mozilla.org/en-US/docs/NSS/NSS_Tech_Notes/nss_tech_note7
1374 1025
1375 // Pack the input values into a struct compatible with NSS ASN.1 encoding, and 1026 // Pack the input values into a struct compatible with NSS ASN.1 encoding, and
1376 // set up an ASN.1 encoder template for it. 1027 // set up an ASN.1 encoder template for it.
1377 struct RsaPublicKeyData { 1028 struct RsaPublicKeyData {
1378 SECItem modulus; 1029 SECItem modulus;
1379 SECItem exponent; 1030 SECItem exponent;
1380 }; 1031 };
1381 const RsaPublicKeyData pubkey_in = { 1032 const RsaPublicKeyData pubkey_in = {
1382 {siUnsignedInteger, const_cast<unsigned char*>(modulus_data), 1033 {siUnsignedInteger, const_cast<unsigned char*>(modulus_data.bytes()),
1383 modulus_size}, 1034 modulus_data.byte_length()},
1384 {siUnsignedInteger, const_cast<unsigned char*>(exponent_data), 1035 {siUnsignedInteger, const_cast<unsigned char*>(exponent_data.bytes()),
1385 exponent_size}}; 1036 exponent_data.byte_length()}};
1386 const SEC_ASN1Template rsa_public_key_template[] = { 1037 const SEC_ASN1Template rsa_public_key_template[] = {
1387 {SEC_ASN1_SEQUENCE, 0, NULL, sizeof(RsaPublicKeyData)}, 1038 {SEC_ASN1_SEQUENCE, 0, NULL, sizeof(RsaPublicKeyData)},
1388 {SEC_ASN1_INTEGER, offsetof(RsaPublicKeyData, modulus), }, 1039 {SEC_ASN1_INTEGER, offsetof(RsaPublicKeyData, modulus), },
1389 {SEC_ASN1_INTEGER, offsetof(RsaPublicKeyData, exponent), }, 1040 {SEC_ASN1_INTEGER, offsetof(RsaPublicKeyData, exponent), },
1390 {0, }}; 1041 {0, }};
1391 1042
1392 // DER-encode the public key. 1043 // DER-encode the public key.
1393 crypto::ScopedSECItem pubkey_der(SEC_ASN1EncodeItem( 1044 crypto::ScopedSECItem pubkey_der(
1394 NULL, NULL, &pubkey_in, rsa_public_key_template)); 1045 SEC_ASN1EncodeItem(NULL, NULL, &pubkey_in, rsa_public_key_template));
1395 if (!pubkey_der) 1046 if (!pubkey_der)
1396 return Status::Error(); 1047 return Status::Error();
1397 1048
1398 // Import the DER-encoded public key to create an RSA SECKEYPublicKey. 1049 // Import the DER-encoded public key to create an RSA SECKEYPublicKey.
1399 crypto::ScopedSECKEYPublicKey pubkey( 1050 crypto::ScopedSECKEYPublicKey pubkey(
1400 SECKEY_ImportDERPublicKey(pubkey_der.get(), CKK_RSA)); 1051 SECKEY_ImportDERPublicKey(pubkey_der.get(), CKK_RSA));
1401 if (!pubkey) 1052 if (!pubkey)
1402 return Status::Error(); 1053 return Status::Error();
1403 1054
1404 *key = blink::WebCryptoKey::create(new PublicKeyHandle(pubkey.Pass()), 1055 *key = blink::WebCryptoKey::create(new PublicKey(pubkey.Pass()),
1405 blink::WebCryptoKeyTypePublic, 1056 blink::WebCryptoKeyTypePublic,
1406 extractable, 1057 extractable,
1407 algorithm, 1058 algorithm,
1408 usage_mask); 1059 usage_mask);
1409 return Status::Success(); 1060 return Status::Success();
1410 } 1061 }
1411 1062
1063 } // namespace platform
1064
1065 } // namespace webcrypto
1066
1412 } // namespace content 1067 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/webcrypto/platform_crypto.h ('k') | content/renderer/webcrypto/platform_crypto_openssl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698