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

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

Powered by Google App Engine
This is Rietveld 408576698