65dbb2f4643a255e013ab2686929aca57e1afc5c
[platform/framework/web/crosswalk.git] / src / content / child / webcrypto / platform_crypto_nss.cc
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/child/webcrypto/platform_crypto.h"
6
7 #include <cryptohi.h>
8 #include <pk11pub.h>
9 #include <secerr.h>
10 #include <sechash.h>
11
12 #include <vector>
13
14 #include "base/lazy_instance.h"
15 #include "base/logging.h"
16 #include "base/memory/scoped_ptr.h"
17 #include "content/child/webcrypto/crypto_data.h"
18 #include "content/child/webcrypto/status.h"
19 #include "content/child/webcrypto/webcrypto_util.h"
20 #include "crypto/nss_util.h"
21 #include "crypto/scoped_nss_types.h"
22 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h"
23 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
24 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
25
26 #if defined(USE_NSS)
27 #include <dlfcn.h>
28 #include <secoid.h>
29 #endif
30
31 // At the time of this writing:
32 //   * Windows and Mac builds ship with their own copy of NSS (3.15+)
33 //   * Linux builds use the system's libnss, which is 3.14 on Debian (but 3.15+
34 //     on other distros).
35 //
36 // Since NSS provides AES-GCM support starting in version 3.15, it may be
37 // unavailable for Linux Chrome users.
38 //
39 //  * !defined(CKM_AES_GCM)
40 //
41 //      This means that at build time, the NSS header pkcs11t.h is older than
42 //      3.15. However at runtime support may be present.
43 //
44 //  * !defined(USE_NSS)
45 //
46 //      This means that Chrome is being built with an embedded copy of NSS,
47 //      which can be assumed to be >= 3.15. On the other hand if USE_NSS is
48 //      defined, it also implies running on Linux.
49 //
50 // TODO(eroman): Simplify this once 3.15+ is required by Linux builds.
51 #if !defined(CKM_AES_GCM)
52 #define CKM_AES_GCM 0x00001087
53
54 struct CK_GCM_PARAMS {
55   CK_BYTE_PTR pIv;
56   CK_ULONG ulIvLen;
57   CK_BYTE_PTR pAAD;
58   CK_ULONG ulAADLen;
59   CK_ULONG ulTagBits;
60 };
61 #endif  // !defined(CKM_AES_GCM)
62
63 // Signature for PK11_Encrypt and PK11_Decrypt.
64 typedef SECStatus (*PK11_EncryptDecryptFunction)(PK11SymKey*,
65                                                  CK_MECHANISM_TYPE,
66                                                  SECItem*,
67                                                  unsigned char*,
68                                                  unsigned int*,
69                                                  unsigned int,
70                                                  const unsigned char*,
71                                                  unsigned int);
72
73 // Singleton to abstract away dynamically loading libnss3.so
74 class AesGcmSupport {
75  public:
76   bool IsSupported() const { return pk11_encrypt_func_ && pk11_decrypt_func_; }
77
78   // Returns NULL if unsupported.
79   PK11_EncryptDecryptFunction pk11_encrypt_func() const {
80     return pk11_encrypt_func_;
81   }
82
83   // Returns NULL if unsupported.
84   PK11_EncryptDecryptFunction pk11_decrypt_func() const {
85     return pk11_decrypt_func_;
86   }
87
88  private:
89   friend struct base::DefaultLazyInstanceTraits<AesGcmSupport>;
90
91   AesGcmSupport() {
92 #if !defined(USE_NSS)
93     // Using a bundled version of NSS that is guaranteed to have this symbol.
94     pk11_encrypt_func_ = PK11_Encrypt;
95     pk11_decrypt_func_ = PK11_Decrypt;
96 #else
97     // Using system NSS libraries and PCKS #11 modules, which may not have the
98     // necessary function (PK11_Encrypt) or mechanism support (CKM_AES_GCM).
99
100     // If PK11_Encrypt() was successfully resolved, then NSS will support
101     // AES-GCM directly. This was introduced in NSS 3.15.
102     pk11_encrypt_func_ = reinterpret_cast<PK11_EncryptDecryptFunction>(
103         dlsym(RTLD_DEFAULT, "PK11_Encrypt"));
104     pk11_decrypt_func_ = reinterpret_cast<PK11_EncryptDecryptFunction>(
105         dlsym(RTLD_DEFAULT, "PK11_Decrypt"));
106 #endif
107   }
108
109   PK11_EncryptDecryptFunction pk11_encrypt_func_;
110   PK11_EncryptDecryptFunction pk11_decrypt_func_;
111 };
112
113 base::LazyInstance<AesGcmSupport>::Leaky g_aes_gcm_support =
114     LAZY_INSTANCE_INITIALIZER;
115
116 namespace content {
117
118 namespace webcrypto {
119
120 namespace platform {
121
122 // Each key maintains a copy of its serialized form
123 // in either 'raw', 'pkcs8', or 'spki' format. This is to allow
124 // structured cloning of keys synchronously from the target Blink
125 // thread without having to lock access to the key.
126 //
127 // TODO(eroman): Take advantage of this for implementing exportKey(): no need
128 //               to call into NSS if the serialized form already exists.
129 //               http://crubg.com/366836
130 class SymKey : public Key {
131  public:
132   static Status Create(crypto::ScopedPK11SymKey key, scoped_ptr<SymKey>* out) {
133     out->reset(new SymKey(key.Pass()));
134     return ExportKeyRaw(out->get(), &(*out)->serialized_key_);
135   }
136
137   PK11SymKey* key() { return key_.get(); }
138
139   virtual SymKey* AsSymKey() OVERRIDE { return this; }
140   virtual PublicKey* AsPublicKey() OVERRIDE { return NULL; }
141   virtual PrivateKey* AsPrivateKey() OVERRIDE { return NULL; }
142
143   virtual bool ThreadSafeSerializeForClone(
144       blink::WebVector<uint8>* key_data) OVERRIDE {
145     key_data->assign(Uint8VectorStart(serialized_key_), serialized_key_.size());
146     return true;
147   }
148
149  private:
150   explicit SymKey(crypto::ScopedPK11SymKey key) : key_(key.Pass()) {}
151
152   crypto::ScopedPK11SymKey key_;
153   std::vector<uint8> serialized_key_;
154
155   DISALLOW_COPY_AND_ASSIGN(SymKey);
156 };
157
158 class PublicKey : public Key {
159  public:
160   static Status Create(crypto::ScopedSECKEYPublicKey key,
161                        scoped_ptr<PublicKey>* out) {
162     out->reset(new PublicKey(key.Pass()));
163     return ExportKeySpki(out->get(), &(*out)->serialized_key_);
164   }
165
166   SECKEYPublicKey* key() { return key_.get(); }
167
168   virtual SymKey* AsSymKey() OVERRIDE { return NULL; }
169   virtual PublicKey* AsPublicKey() OVERRIDE { return this; }
170   virtual PrivateKey* AsPrivateKey() OVERRIDE { return NULL; }
171
172   virtual bool ThreadSafeSerializeForClone(
173       blink::WebVector<uint8>* key_data) OVERRIDE {
174     key_data->assign(Uint8VectorStart(serialized_key_), serialized_key_.size());
175     return true;
176   }
177
178  private:
179   explicit PublicKey(crypto::ScopedSECKEYPublicKey key) : key_(key.Pass()) {}
180
181   crypto::ScopedSECKEYPublicKey key_;
182   std::vector<uint8> serialized_key_;
183
184   DISALLOW_COPY_AND_ASSIGN(PublicKey);
185 };
186
187 class PrivateKey : public Key {
188  public:
189   static Status Create(crypto::ScopedSECKEYPrivateKey key,
190                        const blink::WebCryptoKeyAlgorithm& algorithm,
191                        scoped_ptr<PrivateKey>* out) {
192     out->reset(new PrivateKey(key.Pass()));
193     return ExportKeyPkcs8(out->get(), algorithm, &(*out)->serialized_key_);
194   }
195
196   SECKEYPrivateKey* key() { return key_.get(); }
197
198   virtual SymKey* AsSymKey() OVERRIDE { return NULL; }
199   virtual PublicKey* AsPublicKey() OVERRIDE { return NULL; }
200   virtual PrivateKey* AsPrivateKey() OVERRIDE { return this; }
201
202   virtual bool ThreadSafeSerializeForClone(
203       blink::WebVector<uint8>* key_data) OVERRIDE {
204     key_data->assign(Uint8VectorStart(serialized_key_), serialized_key_.size());
205     return true;
206   }
207
208  private:
209   explicit PrivateKey(crypto::ScopedSECKEYPrivateKey key) : key_(key.Pass()) {}
210
211   crypto::ScopedSECKEYPrivateKey key_;
212   std::vector<uint8> serialized_key_;
213
214   DISALLOW_COPY_AND_ASSIGN(PrivateKey);
215 };
216
217 namespace {
218
219 // Creates a SECItem for the data in |buffer|. This does NOT make a copy, so
220 // |buffer| should outlive the SECItem.
221 SECItem MakeSECItemForBuffer(const CryptoData& buffer) {
222   SECItem item = {
223       siBuffer,
224       // NSS requires non-const data even though it is just for input.
225       const_cast<unsigned char*>(buffer.bytes()), buffer.byte_length()};
226   return item;
227 }
228
229 HASH_HashType WebCryptoAlgorithmToNSSHashType(
230     blink::WebCryptoAlgorithmId algorithm) {
231   switch (algorithm) {
232     case blink::WebCryptoAlgorithmIdSha1:
233       return HASH_AlgSHA1;
234     case blink::WebCryptoAlgorithmIdSha256:
235       return HASH_AlgSHA256;
236     case blink::WebCryptoAlgorithmIdSha384:
237       return HASH_AlgSHA384;
238     case blink::WebCryptoAlgorithmIdSha512:
239       return HASH_AlgSHA512;
240     default:
241       // Not a digest algorithm.
242       return HASH_AlgNULL;
243   }
244 }
245
246 CK_MECHANISM_TYPE WebCryptoHashToHMACMechanism(
247     const blink::WebCryptoAlgorithm& algorithm) {
248   switch (algorithm.id()) {
249     case blink::WebCryptoAlgorithmIdSha1:
250       return CKM_SHA_1_HMAC;
251     case blink::WebCryptoAlgorithmIdSha256:
252       return CKM_SHA256_HMAC;
253     case blink::WebCryptoAlgorithmIdSha384:
254       return CKM_SHA384_HMAC;
255     case blink::WebCryptoAlgorithmIdSha512:
256       return CKM_SHA512_HMAC;
257     default:
258       // Not a supported algorithm.
259       return CKM_INVALID_MECHANISM;
260   }
261 }
262
263 Status AesCbcEncryptDecrypt(EncryptOrDecrypt mode,
264                             SymKey* key,
265                             const CryptoData& iv,
266                             const CryptoData& data,
267                             std::vector<uint8>* buffer) {
268   CK_ATTRIBUTE_TYPE operation = (mode == ENCRYPT) ? CKA_ENCRYPT : CKA_DECRYPT;
269
270   SECItem iv_item = MakeSECItemForBuffer(iv);
271
272   crypto::ScopedSECItem param(PK11_ParamFromIV(CKM_AES_CBC_PAD, &iv_item));
273   if (!param)
274     return Status::OperationError();
275
276   crypto::ScopedPK11Context context(PK11_CreateContextBySymKey(
277       CKM_AES_CBC_PAD, operation, key->key(), param.get()));
278
279   if (!context.get())
280     return Status::OperationError();
281
282   // Oddly PK11_CipherOp takes input and output lengths as "int" rather than
283   // "unsigned int". Do some checks now to avoid integer overflowing.
284   if (data.byte_length() >= INT_MAX - AES_BLOCK_SIZE) {
285     // TODO(eroman): Handle this by chunking the input fed into NSS. Right now
286     // it doesn't make much difference since the one-shot API would end up
287     // blowing out the memory and crashing anyway.
288     return Status::ErrorDataTooLarge();
289   }
290
291   // PK11_CipherOp does an invalid memory access when given empty decryption
292   // input, or input which is not a multiple of the block size. See also
293   // https://bugzilla.mozilla.com/show_bug.cgi?id=921687.
294   if (operation == CKA_DECRYPT &&
295       (data.byte_length() == 0 || (data.byte_length() % AES_BLOCK_SIZE != 0))) {
296     return Status::OperationError();
297   }
298
299   // TODO(eroman): Refine the output buffer size. It can be computed exactly for
300   //               encryption, and can be smaller for decryption.
301   unsigned int output_max_len = data.byte_length() + AES_BLOCK_SIZE;
302   CHECK_GT(output_max_len, data.byte_length());
303
304   buffer->resize(output_max_len);
305
306   unsigned char* buffer_data = Uint8VectorStart(buffer);
307
308   int output_len;
309   if (SECSuccess != PK11_CipherOp(context.get(),
310                                   buffer_data,
311                                   &output_len,
312                                   buffer->size(),
313                                   data.bytes(),
314                                   data.byte_length())) {
315     return Status::OperationError();
316   }
317
318   unsigned int final_output_chunk_len;
319   if (SECSuccess != PK11_DigestFinal(context.get(),
320                                      buffer_data + output_len,
321                                      &final_output_chunk_len,
322                                      output_max_len - output_len)) {
323     return Status::OperationError();
324   }
325
326   buffer->resize(final_output_chunk_len + output_len);
327   return Status::Success();
328 }
329
330 // Helper to either encrypt or decrypt for AES-GCM. The result of encryption is
331 // the concatenation of the ciphertext and the authentication tag. Similarly,
332 // this is the expectation for the input to decryption.
333 Status AesGcmEncryptDecrypt(EncryptOrDecrypt mode,
334                             SymKey* key,
335                             const CryptoData& data,
336                             const CryptoData& iv,
337                             const CryptoData& additional_data,
338                             unsigned int tag_length_bits,
339                             std::vector<uint8>* buffer) {
340   if (!g_aes_gcm_support.Get().IsSupported())
341     return Status::ErrorUnsupported();
342
343   unsigned int tag_length_bytes = tag_length_bits / 8;
344
345   CK_GCM_PARAMS gcm_params = {0};
346   gcm_params.pIv = const_cast<unsigned char*>(iv.bytes());
347   gcm_params.ulIvLen = iv.byte_length();
348
349   gcm_params.pAAD = const_cast<unsigned char*>(additional_data.bytes());
350   gcm_params.ulAADLen = additional_data.byte_length();
351
352   gcm_params.ulTagBits = tag_length_bits;
353
354   SECItem param;
355   param.type = siBuffer;
356   param.data = reinterpret_cast<unsigned char*>(&gcm_params);
357   param.len = sizeof(gcm_params);
358
359   unsigned int buffer_size = 0;
360
361   // Calculate the output buffer size.
362   if (mode == ENCRYPT) {
363     // TODO(eroman): This is ugly, abstract away the safe integer arithmetic.
364     if (data.byte_length() > (UINT_MAX - tag_length_bytes))
365       return Status::ErrorDataTooLarge();
366     buffer_size = data.byte_length() + tag_length_bytes;
367   } else {
368     // TODO(eroman): In theory the buffer allocated for the plain text should be
369     // sized as |data.byte_length() - tag_length_bytes|.
370     //
371     // However NSS has a bug whereby it will fail if the output buffer size is
372     // not at least as large as the ciphertext:
373     //
374     // https://bugzilla.mozilla.org/show_bug.cgi?id=%20853674
375     //
376     // From the analysis of that bug it looks like it might be safe to pass a
377     // correctly sized buffer but lie about its size. Since resizing the
378     // WebCryptoArrayBuffer is expensive that hack may be worth looking into.
379     buffer_size = data.byte_length();
380   }
381
382   buffer->resize(buffer_size);
383   unsigned char* buffer_data = Uint8VectorStart(buffer);
384
385   PK11_EncryptDecryptFunction func =
386       (mode == ENCRYPT) ? g_aes_gcm_support.Get().pk11_encrypt_func()
387                         : g_aes_gcm_support.Get().pk11_decrypt_func();
388
389   unsigned int output_len = 0;
390   SECStatus result = func(key->key(),
391                           CKM_AES_GCM,
392                           &param,
393                           buffer_data,
394                           &output_len,
395                           buffer->size(),
396                           data.bytes(),
397                           data.byte_length());
398
399   if (result != SECSuccess)
400     return Status::OperationError();
401
402   // Unfortunately the buffer needs to be shrunk for decryption (see the NSS bug
403   // above).
404   buffer->resize(output_len);
405
406   return Status::Success();
407 }
408
409 CK_MECHANISM_TYPE WebCryptoAlgorithmToGenMechanism(
410     const blink::WebCryptoAlgorithm& algorithm) {
411   switch (algorithm.id()) {
412     case blink::WebCryptoAlgorithmIdAesCbc:
413     case blink::WebCryptoAlgorithmIdAesGcm:
414     case blink::WebCryptoAlgorithmIdAesKw:
415       return CKM_AES_KEY_GEN;
416     case blink::WebCryptoAlgorithmIdHmac:
417       return WebCryptoHashToHMACMechanism(algorithm.hmacKeyGenParams()->hash());
418     default:
419       return CKM_INVALID_MECHANISM;
420   }
421 }
422
423 // Converts a (big-endian) WebCrypto BigInteger, with or without leading zeros,
424 // to unsigned long.
425 bool BigIntegerToLong(const uint8* data,
426                       unsigned int data_size,
427                       unsigned long* result) {
428   // TODO(padolph): Is it correct to say that empty data is an error, or does it
429   // mean value 0? See https://www.w3.org/Bugs/Public/show_bug.cgi?id=23655
430   if (data_size == 0)
431     return false;
432
433   *result = 0;
434   for (size_t i = 0; i < data_size; ++i) {
435     size_t reverse_i = data_size - i - 1;
436
437     if (reverse_i >= sizeof(unsigned long) && data[i])
438       return false;  // Too large for a long.
439
440     *result |= data[i] << 8 * reverse_i;
441   }
442   return true;
443 }
444
445 bool IsAlgorithmRsa(const blink::WebCryptoAlgorithm& algorithm) {
446   return algorithm.id() == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 ||
447          algorithm.id() == blink::WebCryptoAlgorithmIdRsaOaep ||
448          algorithm.id() == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5;
449 }
450
451 bool CreatePublicKeyAlgorithm(const blink::WebCryptoAlgorithm& algorithm,
452                               SECKEYPublicKey* key,
453                               blink::WebCryptoKeyAlgorithm* key_algorithm) {
454   // TODO(eroman): What about other key types rsaPss, rsaOaep.
455   if (!key || key->keyType != rsaKey)
456     return false;
457
458   unsigned int modulus_length_bits = SECKEY_PublicKeyStrength(key) * 8;
459   CryptoData public_exponent(key->u.rsa.publicExponent.data,
460                              key->u.rsa.publicExponent.len);
461
462   switch (algorithm.paramsType()) {
463     case blink::WebCryptoAlgorithmParamsTypeRsaHashedImportParams:
464     case blink::WebCryptoAlgorithmParamsTypeRsaHashedKeyGenParams:
465       *key_algorithm = blink::WebCryptoKeyAlgorithm::createRsaHashed(
466           algorithm.id(),
467           modulus_length_bits,
468           public_exponent.bytes(),
469           public_exponent.byte_length(),
470           GetInnerHashAlgorithm(algorithm).id());
471       return true;
472     case blink::WebCryptoAlgorithmParamsTypeRsaKeyGenParams:
473     case blink::WebCryptoAlgorithmParamsTypeNone:
474       *key_algorithm = blink::WebCryptoKeyAlgorithm::createRsa(
475           algorithm.id(),
476           modulus_length_bits,
477           public_exponent.bytes(),
478           public_exponent.byte_length());
479       return true;
480     default:
481       return false;
482   }
483 }
484
485 bool CreatePrivateKeyAlgorithm(const blink::WebCryptoAlgorithm& algorithm,
486                                SECKEYPrivateKey* key,
487                                blink::WebCryptoKeyAlgorithm* key_algorithm) {
488   crypto::ScopedSECKEYPublicKey public_key(SECKEY_ConvertToPublicKey(key));
489   return CreatePublicKeyAlgorithm(algorithm, public_key.get(), key_algorithm);
490 }
491
492 // The Default IV for AES-KW. See http://www.ietf.org/rfc/rfc3394.txt
493 // Section 2.2.3.1.
494 // TODO(padolph): Move to common place to be shared with OpenSSL implementation.
495 const unsigned char kAesIv[] = {0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6};
496
497 // Sets NSS CK_MECHANISM_TYPE and CK_FLAGS corresponding to the input Web Crypto
498 // algorithm ID.
499 Status WebCryptoAlgorithmToNssMechFlags(
500     const blink::WebCryptoAlgorithm& algorithm,
501     CK_MECHANISM_TYPE* mechanism,
502     CK_FLAGS* flags) {
503   // Flags are verified at the Blink layer; here the flags are set to all
504   // possible operations of a key for the input algorithm type.
505   switch (algorithm.id()) {
506     case blink::WebCryptoAlgorithmIdHmac: {
507       const blink::WebCryptoAlgorithm hash = GetInnerHashAlgorithm(algorithm);
508       *mechanism = WebCryptoHashToHMACMechanism(hash);
509       if (*mechanism == CKM_INVALID_MECHANISM)
510         return Status::ErrorUnsupported();
511       *flags = CKF_SIGN | CKF_VERIFY;
512       break;
513     }
514     case blink::WebCryptoAlgorithmIdAesCbc: {
515       *mechanism = CKM_AES_CBC;
516       *flags = CKF_ENCRYPT | CKF_DECRYPT;
517       break;
518     }
519     case blink::WebCryptoAlgorithmIdAesKw: {
520       *mechanism = CKM_NSS_AES_KEY_WRAP;
521       *flags = CKF_WRAP | CKF_WRAP;
522       break;
523     }
524     case blink::WebCryptoAlgorithmIdAesGcm: {
525       if (!g_aes_gcm_support.Get().IsSupported())
526         return Status::ErrorUnsupported();
527       *mechanism = CKM_AES_GCM;
528       *flags = CKF_ENCRYPT | CKF_DECRYPT;
529       break;
530     }
531     default:
532       return Status::ErrorUnsupported();
533   }
534   return Status::Success();
535 }
536
537 Status DoUnwrapSymKeyAesKw(const CryptoData& wrapped_key_data,
538                            SymKey* wrapping_key,
539                            CK_MECHANISM_TYPE mechanism,
540                            CK_FLAGS flags,
541                            crypto::ScopedPK11SymKey* unwrapped_key) {
542   DCHECK_GE(wrapped_key_data.byte_length(), 24u);
543   DCHECK_EQ(wrapped_key_data.byte_length() % 8, 0u);
544
545   SECItem iv_item = MakeSECItemForBuffer(CryptoData(kAesIv, sizeof(kAesIv)));
546   crypto::ScopedSECItem param_item(
547       PK11_ParamFromIV(CKM_NSS_AES_KEY_WRAP, &iv_item));
548   if (!param_item)
549     return Status::ErrorUnexpected();
550
551   SECItem cipher_text = MakeSECItemForBuffer(wrapped_key_data);
552
553   // The plaintext length is always 64 bits less than the data size.
554   const unsigned int plaintext_length = wrapped_key_data.byte_length() - 8;
555
556 #if defined(USE_NSS)
557   // Part of workaround for
558   // https://bugzilla.mozilla.org/show_bug.cgi?id=981170. See the explanation
559   // later in this function.
560   PORT_SetError(0);
561 #endif
562
563   crypto::ScopedPK11SymKey new_key(
564       PK11_UnwrapSymKeyWithFlags(wrapping_key->key(),
565                                  CKM_NSS_AES_KEY_WRAP,
566                                  param_item.get(),
567                                  &cipher_text,
568                                  mechanism,
569                                  CKA_FLAGS_ONLY,
570                                  plaintext_length,
571                                  flags));
572
573   // TODO(padolph): Use NSS PORT_GetError() and friends to report a more
574   // accurate error, providing if doesn't leak any information to web pages
575   // about other web crypto users, key details, etc.
576   if (!new_key)
577     return Status::OperationError();
578
579 #if defined(USE_NSS)
580   // Workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=981170
581   // which was fixed in NSS 3.16.0.
582   // If unwrap fails, NSS nevertheless returns a valid-looking PK11SymKey,
583   // with a reasonable length but with key data pointing to uninitialized
584   // memory.
585   // To understand this workaround see the fix for 981170:
586   // https://hg.mozilla.org/projects/nss/rev/753bb69e543c
587   if (!NSS_VersionCheck("3.16") && PORT_GetError() == SEC_ERROR_BAD_DATA)
588     return Status::OperationError();
589 #endif
590
591   *unwrapped_key = new_key.Pass();
592   return Status::Success();
593 }
594
595 void CopySECItemToVector(const SECItem& item, std::vector<uint8>* out) {
596   out->assign(item.data, item.data + item.len);
597 }
598
599 // The system NSS library doesn't have the new PK11_ExportDERPrivateKeyInfo
600 // function yet (https://bugzilla.mozilla.org/show_bug.cgi?id=519255). So we
601 // provide a fallback implementation.
602 #if defined(USE_NSS)
603 // From PKCS#1 [http://tools.ietf.org/html/rfc3447]:
604 //
605 //    RSAPrivateKey ::= SEQUENCE {
606 //      version           Version,
607 //      modulus           INTEGER,  -- n
608 //      publicExponent    INTEGER,  -- e
609 //      privateExponent   INTEGER,  -- d
610 //      prime1            INTEGER,  -- p
611 //      prime2            INTEGER,  -- q
612 //      exponent1         INTEGER,  -- d mod (p-1)
613 //      exponent2         INTEGER,  -- d mod (q-1)
614 //      coefficient       INTEGER,  -- (inverse of q) mod p
615 //      otherPrimeInfos   OtherPrimeInfos OPTIONAL
616 //    }
617 //
618 // Note that otherPrimeInfos is only applicable for version=1. Since NSS
619 // doesn't use multi-prime can safely use version=0.
620 struct RSAPrivateKey {
621   SECItem version;
622   SECItem modulus;
623   SECItem public_exponent;
624   SECItem private_exponent;
625   SECItem prime1;
626   SECItem prime2;
627   SECItem exponent1;
628   SECItem exponent2;
629   SECItem coefficient;
630 };
631
632 const SEC_ASN1Template RSAPrivateKeyTemplate[] = {
633     {SEC_ASN1_SEQUENCE, 0, NULL, sizeof(RSAPrivateKey)},
634     {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, version)},
635     {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, modulus)},
636     {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, public_exponent)},
637     {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, private_exponent)},
638     {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, prime1)},
639     {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, prime2)},
640     {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, exponent1)},
641     {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, exponent2)},
642     {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, coefficient)},
643     {0}};
644
645 // On success |value| will be filled with data which must be freed by
646 // SECITEM_FreeItem(value, PR_FALSE);
647 bool ReadUint(SECKEYPrivateKey* key,
648               CK_ATTRIBUTE_TYPE attribute,
649               SECItem* value) {
650   SECStatus rv = PK11_ReadRawAttribute(PK11_TypePrivKey, key, attribute, value);
651
652   // PK11_ReadRawAttribute() returns items of type siBuffer. However in order
653   // for the ASN.1 encoding to be correct, the items must be of type
654   // siUnsignedInteger.
655   value->type = siUnsignedInteger;
656
657   return rv == SECSuccess;
658 }
659
660 // Fills |out| with the RSA private key properties. Returns true on success.
661 // Regardless of the return value, the caller must invoke FreeRSAPrivateKey()
662 // to free up any allocated memory.
663 //
664 // The passed in RSAPrivateKey must be zero-initialized.
665 bool InitRSAPrivateKey(SECKEYPrivateKey* key, RSAPrivateKey* out) {
666   if (key->keyType != rsaKey)
667     return false;
668
669   // Everything should be zero-ed out. These are just some spot checks.
670   DCHECK(!out->version.data);
671   DCHECK(!out->version.len);
672   DCHECK(!out->modulus.data);
673   DCHECK(!out->modulus.len);
674
675   // Always use version=0 since not using multi-prime.
676   if (!SEC_ASN1EncodeInteger(NULL, &out->version, 0))
677     return false;
678
679   if (!ReadUint(key, CKA_MODULUS, &out->modulus))
680     return false;
681   if (!ReadUint(key, CKA_PUBLIC_EXPONENT, &out->public_exponent))
682     return false;
683   if (!ReadUint(key, CKA_PRIVATE_EXPONENT, &out->private_exponent))
684     return false;
685   if (!ReadUint(key, CKA_PRIME_1, &out->prime1))
686     return false;
687   if (!ReadUint(key, CKA_PRIME_2, &out->prime2))
688     return false;
689   if (!ReadUint(key, CKA_EXPONENT_1, &out->exponent1))
690     return false;
691   if (!ReadUint(key, CKA_EXPONENT_2, &out->exponent2))
692     return false;
693   if (!ReadUint(key, CKA_COEFFICIENT, &out->coefficient))
694     return false;
695
696   return true;
697 }
698
699 struct FreeRsaPrivateKey {
700   void operator()(RSAPrivateKey* out) {
701     SECITEM_FreeItem(&out->version, PR_FALSE);
702     SECITEM_FreeItem(&out->modulus, PR_FALSE);
703     SECITEM_FreeItem(&out->public_exponent, PR_FALSE);
704     SECITEM_FreeItem(&out->private_exponent, PR_FALSE);
705     SECITEM_FreeItem(&out->prime1, PR_FALSE);
706     SECITEM_FreeItem(&out->prime2, PR_FALSE);
707     SECITEM_FreeItem(&out->exponent1, PR_FALSE);
708     SECITEM_FreeItem(&out->exponent2, PR_FALSE);
709     SECITEM_FreeItem(&out->coefficient, PR_FALSE);
710   }
711 };
712 #endif  // defined(USE_NSS)
713
714 }  // namespace
715
716 class DigestorNSS : public blink::WebCryptoDigestor {
717  public:
718   explicit DigestorNSS(blink::WebCryptoAlgorithmId algorithm_id)
719       : hash_context_(NULL), algorithm_id_(algorithm_id) {}
720
721   virtual ~DigestorNSS() {
722     if (!hash_context_)
723       return;
724
725     HASH_Destroy(hash_context_);
726     hash_context_ = NULL;
727   }
728
729   virtual bool consume(const unsigned char* data, unsigned int size) {
730     return ConsumeWithStatus(data, size).IsSuccess();
731   }
732
733   Status ConsumeWithStatus(const unsigned char* data, unsigned int size) {
734     // Initialize everything if the object hasn't been initialized yet.
735     if (!hash_context_) {
736       Status error = Init();
737       if (!error.IsSuccess())
738         return error;
739     }
740
741     HASH_Update(hash_context_, data, size);
742
743     return Status::Success();
744   }
745
746   virtual bool finish(unsigned char*& result_data,
747                       unsigned int& result_data_size) {
748     Status error = FinishInternal(result_, &result_data_size);
749     if (!error.IsSuccess())
750       return false;
751     result_data = result_;
752     return true;
753   }
754
755   Status FinishWithVectorAndStatus(std::vector<uint8>* result) {
756     if (!hash_context_)
757       return Status::ErrorUnexpected();
758
759     unsigned int result_length = HASH_ResultLenContext(hash_context_);
760     result->resize(result_length);
761     unsigned char* digest = Uint8VectorStart(result);
762     unsigned int digest_size;  // ignored
763     return FinishInternal(digest, &digest_size);
764   }
765
766  private:
767   Status Init() {
768     HASH_HashType hash_type = WebCryptoAlgorithmToNSSHashType(algorithm_id_);
769
770     if (hash_type == HASH_AlgNULL)
771       return Status::ErrorUnsupported();
772
773     hash_context_ = HASH_Create(hash_type);
774     if (!hash_context_)
775       return Status::OperationError();
776
777     HASH_Begin(hash_context_);
778
779     return Status::Success();
780   }
781
782   Status FinishInternal(unsigned char* result, unsigned int* result_size) {
783     if (!hash_context_) {
784       Status error = Init();
785       if (!error.IsSuccess())
786         return error;
787     }
788
789     unsigned int hash_result_length = HASH_ResultLenContext(hash_context_);
790     DCHECK_LE(hash_result_length, static_cast<size_t>(HASH_LENGTH_MAX));
791
792     HASH_End(hash_context_, result, result_size, hash_result_length);
793
794     if (*result_size != hash_result_length)
795       return Status::ErrorUnexpected();
796     return Status::Success();
797   }
798
799   HASHContext* hash_context_;
800   blink::WebCryptoAlgorithmId algorithm_id_;
801   unsigned char result_[HASH_LENGTH_MAX];
802 };
803
804 Status ImportKeyRaw(const blink::WebCryptoAlgorithm& algorithm,
805                     const CryptoData& key_data,
806                     bool extractable,
807                     blink::WebCryptoKeyUsageMask usage_mask,
808                     blink::WebCryptoKey* key) {
809   DCHECK(!algorithm.isNull());
810
811   CK_MECHANISM_TYPE mechanism;
812   CK_FLAGS flags;
813   Status status =
814       WebCryptoAlgorithmToNssMechFlags(algorithm, &mechanism, &flags);
815   if (status.IsError())
816     return status;
817
818   SECItem key_item = MakeSECItemForBuffer(key_data);
819
820   crypto::ScopedPK11Slot slot(PK11_GetInternalSlot());
821   crypto::ScopedPK11SymKey pk11_sym_key(
822       PK11_ImportSymKeyWithFlags(slot.get(),
823                                  mechanism,
824                                  PK11_OriginUnwrap,
825                                  CKA_FLAGS_ONLY,
826                                  &key_item,
827                                  flags,
828                                  false,
829                                  NULL));
830   if (!pk11_sym_key.get())
831     return Status::OperationError();
832
833   blink::WebCryptoKeyAlgorithm key_algorithm;
834   if (!CreateSecretKeyAlgorithm(
835           algorithm, key_data.byte_length(), &key_algorithm))
836     return Status::ErrorUnexpected();
837
838   scoped_ptr<SymKey> key_handle;
839   status = SymKey::Create(pk11_sym_key.Pass(), &key_handle);
840   if (status.IsError())
841     return status;
842
843   *key = blink::WebCryptoKey::create(key_handle.release(),
844                                      blink::WebCryptoKeyTypeSecret,
845                                      extractable,
846                                      key_algorithm,
847                                      usage_mask);
848   return Status::Success();
849 }
850
851 Status ExportKeyRaw(SymKey* key, std::vector<uint8>* buffer) {
852   if (PK11_ExtractKeyValue(key->key()) != SECSuccess)
853     return Status::OperationError();
854
855   // http://crbug.com/366427: the spec does not define any other failures for
856   // exporting, so none of the subsequent errors are spec compliant.
857   const SECItem* key_data = PK11_GetKeyData(key->key());
858   if (!key_data)
859     return Status::OperationError();
860
861   buffer->assign(key_data->data, key_data->data + key_data->len);
862
863   return Status::Success();
864 }
865
866 namespace {
867
868 typedef scoped_ptr<CERTSubjectPublicKeyInfo,
869                    crypto::NSSDestroyer<CERTSubjectPublicKeyInfo,
870                                         SECKEY_DestroySubjectPublicKeyInfo> >
871     ScopedCERTSubjectPublicKeyInfo;
872
873 // Validates an NSS KeyType against a WebCrypto import algorithm.
874 bool ValidateNssKeyTypeAgainstInputAlgorithm(
875     KeyType key_type,
876     const blink::WebCryptoAlgorithm& algorithm) {
877   switch (key_type) {
878     case rsaKey:
879       return IsAlgorithmRsa(algorithm);
880     case dsaKey:
881     case ecKey:
882     case rsaPssKey:
883     case rsaOaepKey:
884       // TODO(padolph): Handle other key types.
885       break;
886     default:
887       break;
888   }
889   return false;
890 }
891
892 }  // namespace
893
894 Status ImportKeySpki(const blink::WebCryptoAlgorithm& algorithm,
895                      const CryptoData& key_data,
896                      bool extractable,
897                      blink::WebCryptoKeyUsageMask usage_mask,
898                      blink::WebCryptoKey* key) {
899   DCHECK(key);
900
901   if (!key_data.byte_length())
902     return Status::ErrorImportEmptyKeyData();
903   DCHECK(key_data.bytes());
904
905   // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 Subject
906   // Public Key Info. Decode this to a CERTSubjectPublicKeyInfo.
907   SECItem spki_item = MakeSECItemForBuffer(key_data);
908   const ScopedCERTSubjectPublicKeyInfo spki(
909       SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_item));
910   if (!spki)
911     return Status::DataError();
912
913   crypto::ScopedSECKEYPublicKey sec_public_key(
914       SECKEY_ExtractPublicKey(spki.get()));
915   if (!sec_public_key)
916     return Status::DataError();
917
918   const KeyType sec_key_type = SECKEY_GetPublicKeyType(sec_public_key.get());
919   if (!ValidateNssKeyTypeAgainstInputAlgorithm(sec_key_type, algorithm))
920     return Status::DataError();
921
922   blink::WebCryptoKeyAlgorithm key_algorithm;
923   if (!CreatePublicKeyAlgorithm(
924           algorithm, sec_public_key.get(), &key_algorithm))
925     return Status::ErrorUnexpected();
926
927   scoped_ptr<PublicKey> key_handle;
928   Status status = PublicKey::Create(sec_public_key.Pass(), &key_handle);
929   if (status.IsError())
930     return status;
931
932   *key = blink::WebCryptoKey::create(key_handle.release(),
933                                      blink::WebCryptoKeyTypePublic,
934                                      extractable,
935                                      key_algorithm,
936                                      usage_mask);
937
938   return Status::Success();
939 }
940
941 Status ExportKeySpki(PublicKey* key, std::vector<uint8>* buffer) {
942   const crypto::ScopedSECItem spki_der(
943       SECKEY_EncodeDERSubjectPublicKeyInfo(key->key()));
944   // http://crbug.com/366427: the spec does not define any other failures for
945   // exporting, so none of the subsequent errors are spec compliant.
946   if (!spki_der)
947     return Status::OperationError();
948
949   DCHECK(spki_der->data);
950   DCHECK(spki_der->len);
951
952   buffer->assign(spki_der->data, spki_der->data + spki_der->len);
953
954   return Status::Success();
955 }
956
957 Status ExportRsaPublicKey(PublicKey* key,
958                           std::vector<uint8>* modulus,
959                           std::vector<uint8>* public_exponent) {
960   DCHECK(key);
961   DCHECK(key->key());
962   if (key->key()->keyType != rsaKey)
963     return Status::ErrorUnsupported();
964   CopySECItemToVector(key->key()->u.rsa.modulus, modulus);
965   CopySECItemToVector(key->key()->u.rsa.publicExponent, public_exponent);
966   if (modulus->empty() || public_exponent->empty())
967     return Status::ErrorUnexpected();
968   return Status::Success();
969 }
970
971 Status ExportKeyPkcs8(PrivateKey* key,
972                       const blink::WebCryptoKeyAlgorithm& key_algorithm,
973                       std::vector<uint8>* buffer) {
974   // TODO(eroman): Support other RSA key types as they are added to Blink.
975   if (key_algorithm.id() != blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 &&
976       key_algorithm.id() != blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5)
977     return Status::ErrorUnsupported();
978
979 #if defined(USE_NSS)
980   // PK11_ExportDERPrivateKeyInfo isn't available. Use our fallback code.
981   const SECOidTag algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION;
982   const int kPrivateKeyInfoVersion = 0;
983
984   SECKEYPrivateKeyInfo private_key_info = {};
985   RSAPrivateKey rsa_private_key = {};
986   scoped_ptr<RSAPrivateKey, FreeRsaPrivateKey> free_private_key(
987       &rsa_private_key);
988
989   // http://crbug.com/366427: the spec does not define any other failures for
990   // exporting, so none of the subsequent errors are spec compliant.
991   if (!InitRSAPrivateKey(key->key(), &rsa_private_key))
992     return Status::OperationError();
993
994   crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
995   if (!arena.get())
996     return Status::OperationError();
997
998   if (!SEC_ASN1EncodeItem(arena.get(),
999                           &private_key_info.privateKey,
1000                           &rsa_private_key,
1001                           RSAPrivateKeyTemplate))
1002     return Status::OperationError();
1003
1004   if (SECSuccess !=
1005       SECOID_SetAlgorithmID(
1006           arena.get(), &private_key_info.algorithm, algorithm, NULL))
1007     return Status::OperationError();
1008
1009   if (!SEC_ASN1EncodeInteger(
1010           arena.get(), &private_key_info.version, kPrivateKeyInfoVersion))
1011     return Status::OperationError();
1012
1013   crypto::ScopedSECItem encoded_key(
1014       SEC_ASN1EncodeItem(NULL,
1015                          NULL,
1016                          &private_key_info,
1017                          SEC_ASN1_GET(SECKEY_PrivateKeyInfoTemplate)));
1018 #else   // defined(USE_NSS)
1019   crypto::ScopedSECItem encoded_key(
1020       PK11_ExportDERPrivateKeyInfo(key->key(), NULL));
1021 #endif  // defined(USE_NSS)
1022
1023   if (!encoded_key.get())
1024     return Status::OperationError();
1025
1026   buffer->assign(encoded_key->data, encoded_key->data + encoded_key->len);
1027   return Status::Success();
1028 }
1029
1030 Status ImportKeyPkcs8(const blink::WebCryptoAlgorithm& algorithm,
1031                       const CryptoData& key_data,
1032                       bool extractable,
1033                       blink::WebCryptoKeyUsageMask usage_mask,
1034                       blink::WebCryptoKey* key) {
1035   DCHECK(key);
1036
1037   if (!key_data.byte_length())
1038     return Status::ErrorImportEmptyKeyData();
1039   DCHECK(key_data.bytes());
1040
1041   // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 PKCS#8
1042   // private key info object.
1043   SECItem pki_der = MakeSECItemForBuffer(key_data);
1044
1045   SECKEYPrivateKey* seckey_private_key = NULL;
1046   crypto::ScopedPK11Slot slot(PK11_GetInternalSlot());
1047   if (PK11_ImportDERPrivateKeyInfoAndReturnKey(slot.get(),
1048                                                &pki_der,
1049                                                NULL,    // nickname
1050                                                NULL,    // publicValue
1051                                                false,   // isPerm
1052                                                false,   // isPrivate
1053                                                KU_ALL,  // usage
1054                                                &seckey_private_key,
1055                                                NULL) != SECSuccess) {
1056     return Status::DataError();
1057   }
1058   DCHECK(seckey_private_key);
1059   crypto::ScopedSECKEYPrivateKey private_key(seckey_private_key);
1060
1061   const KeyType sec_key_type = SECKEY_GetPrivateKeyType(private_key.get());
1062   if (!ValidateNssKeyTypeAgainstInputAlgorithm(sec_key_type, algorithm))
1063     return Status::DataError();
1064
1065   blink::WebCryptoKeyAlgorithm key_algorithm;
1066   if (!CreatePrivateKeyAlgorithm(algorithm, private_key.get(), &key_algorithm))
1067     return Status::ErrorUnexpected();
1068
1069   scoped_ptr<PrivateKey> key_handle;
1070   Status status =
1071       PrivateKey::Create(private_key.Pass(), key_algorithm, &key_handle);
1072   if (status.IsError())
1073     return status;
1074
1075   *key = blink::WebCryptoKey::create(key_handle.release(),
1076                                      blink::WebCryptoKeyTypePrivate,
1077                                      extractable,
1078                                      key_algorithm,
1079                                      usage_mask);
1080
1081   return Status::Success();
1082 }
1083
1084 // -----------------------------------
1085 // Hmac
1086 // -----------------------------------
1087
1088 Status SignHmac(SymKey* key,
1089                 const blink::WebCryptoAlgorithm& hash,
1090                 const CryptoData& data,
1091                 std::vector<uint8>* buffer) {
1092   DCHECK_EQ(PK11_GetMechanism(key->key()), WebCryptoHashToHMACMechanism(hash));
1093
1094   SECItem param_item = {siBuffer, NULL, 0};
1095   SECItem data_item = MakeSECItemForBuffer(data);
1096   // First call is to figure out the length.
1097   SECItem signature_item = {siBuffer, NULL, 0};
1098
1099   if (PK11_SignWithSymKey(key->key(),
1100                           PK11_GetMechanism(key->key()),
1101                           &param_item,
1102                           &signature_item,
1103                           &data_item) != SECSuccess) {
1104     return Status::OperationError();
1105   }
1106
1107   DCHECK_NE(0u, signature_item.len);
1108
1109   buffer->resize(signature_item.len);
1110   signature_item.data = Uint8VectorStart(buffer);
1111
1112   if (PK11_SignWithSymKey(key->key(),
1113                           PK11_GetMechanism(key->key()),
1114                           &param_item,
1115                           &signature_item,
1116                           &data_item) != SECSuccess) {
1117     return Status::OperationError();
1118   }
1119
1120   DCHECK_EQ(buffer->size(), signature_item.len);
1121   return Status::Success();
1122 }
1123
1124 // -----------------------------------
1125 // RsaEsPkcs1v1_5
1126 // -----------------------------------
1127
1128 Status EncryptRsaEsPkcs1v1_5(PublicKey* key,
1129                              const CryptoData& data,
1130                              std::vector<uint8>* buffer) {
1131   const unsigned int encrypted_length_bytes =
1132       SECKEY_PublicKeyStrength(key->key());
1133
1134   // RSAES can operate on messages up to a length of k - 11, where k is the
1135   // octet length of the RSA modulus.
1136   if (encrypted_length_bytes < 11 ||
1137       encrypted_length_bytes - 11 < data.byte_length())
1138     return Status::ErrorDataTooLarge();
1139
1140   buffer->resize(encrypted_length_bytes);
1141   unsigned char* const buffer_data = Uint8VectorStart(buffer);
1142
1143   if (PK11_PubEncryptPKCS1(key->key(),
1144                            buffer_data,
1145                            const_cast<unsigned char*>(data.bytes()),
1146                            data.byte_length(),
1147                            NULL) != SECSuccess) {
1148     return Status::OperationError();
1149   }
1150   return Status::Success();
1151 }
1152
1153 Status DecryptRsaEsPkcs1v1_5(PrivateKey* key,
1154                              const CryptoData& data,
1155                              std::vector<uint8>* buffer) {
1156   const int modulus_length_bytes = PK11_GetPrivateModulusLen(key->key());
1157   if (modulus_length_bytes <= 0)
1158     return Status::ErrorUnexpected();
1159   const unsigned int max_output_length_bytes = modulus_length_bytes;
1160
1161   buffer->resize(max_output_length_bytes);
1162   unsigned char* const buffer_data = Uint8VectorStart(buffer);
1163
1164   unsigned int output_length_bytes = 0;
1165   if (PK11_PrivDecryptPKCS1(key->key(),
1166                             buffer_data,
1167                             &output_length_bytes,
1168                             max_output_length_bytes,
1169                             const_cast<unsigned char*>(data.bytes()),
1170                             data.byte_length()) != SECSuccess) {
1171     return Status::OperationError();
1172   }
1173   DCHECK_LE(output_length_bytes, max_output_length_bytes);
1174   buffer->resize(output_length_bytes);
1175   return Status::Success();
1176 }
1177
1178 // -----------------------------------
1179 // RsaSsaPkcs1v1_5
1180 // -----------------------------------
1181
1182 Status SignRsaSsaPkcs1v1_5(PrivateKey* key,
1183                            const blink::WebCryptoAlgorithm& hash,
1184                            const CryptoData& data,
1185                            std::vector<uint8>* buffer) {
1186   // Pick the NSS signing algorithm by combining RSA-SSA (RSA PKCS1) and the
1187   // inner hash of the input Web Crypto algorithm.
1188   SECOidTag sign_alg_tag;
1189   switch (hash.id()) {
1190     case blink::WebCryptoAlgorithmIdSha1:
1191       sign_alg_tag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
1192       break;
1193     case blink::WebCryptoAlgorithmIdSha256:
1194       sign_alg_tag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
1195       break;
1196     case blink::WebCryptoAlgorithmIdSha384:
1197       sign_alg_tag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;
1198       break;
1199     case blink::WebCryptoAlgorithmIdSha512:
1200       sign_alg_tag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
1201       break;
1202     default:
1203       return Status::ErrorUnsupported();
1204   }
1205
1206   crypto::ScopedSECItem signature_item(SECITEM_AllocItem(NULL, NULL, 0));
1207   if (SEC_SignData(signature_item.get(),
1208                    data.bytes(),
1209                    data.byte_length(),
1210                    key->key(),
1211                    sign_alg_tag) != SECSuccess) {
1212     return Status::OperationError();
1213   }
1214
1215   buffer->assign(signature_item->data,
1216                  signature_item->data + signature_item->len);
1217   return Status::Success();
1218 }
1219
1220 Status VerifyRsaSsaPkcs1v1_5(PublicKey* key,
1221                              const blink::WebCryptoAlgorithm& hash,
1222                              const CryptoData& signature,
1223                              const CryptoData& data,
1224                              bool* signature_match) {
1225   const SECItem signature_item = MakeSECItemForBuffer(signature);
1226
1227   SECOidTag hash_alg_tag;
1228   switch (hash.id()) {
1229     case blink::WebCryptoAlgorithmIdSha1:
1230       hash_alg_tag = SEC_OID_SHA1;
1231       break;
1232     case blink::WebCryptoAlgorithmIdSha256:
1233       hash_alg_tag = SEC_OID_SHA256;
1234       break;
1235     case blink::WebCryptoAlgorithmIdSha384:
1236       hash_alg_tag = SEC_OID_SHA384;
1237       break;
1238     case blink::WebCryptoAlgorithmIdSha512:
1239       hash_alg_tag = SEC_OID_SHA512;
1240       break;
1241     default:
1242       return Status::ErrorUnsupported();
1243   }
1244
1245   *signature_match =
1246       SECSuccess == VFY_VerifyDataDirect(data.bytes(),
1247                                          data.byte_length(),
1248                                          key->key(),
1249                                          &signature_item,
1250                                          SEC_OID_PKCS1_RSA_ENCRYPTION,
1251                                          hash_alg_tag,
1252                                          NULL,
1253                                          NULL);
1254   return Status::Success();
1255 }
1256
1257 Status EncryptDecryptAesCbc(EncryptOrDecrypt mode,
1258                             SymKey* key,
1259                             const CryptoData& data,
1260                             const CryptoData& iv,
1261                             std::vector<uint8>* buffer) {
1262   // TODO(eroman): Inline.
1263   return AesCbcEncryptDecrypt(mode, key, iv, data, buffer);
1264 }
1265
1266 Status EncryptDecryptAesGcm(EncryptOrDecrypt mode,
1267                             SymKey* key,
1268                             const CryptoData& data,
1269                             const CryptoData& iv,
1270                             const CryptoData& additional_data,
1271                             unsigned int tag_length_bits,
1272                             std::vector<uint8>* buffer) {
1273   // TODO(eroman): Inline.
1274   return AesGcmEncryptDecrypt(
1275       mode, key, data, iv, additional_data, tag_length_bits, buffer);
1276 }
1277
1278 // -----------------------------------
1279 // Key generation
1280 // -----------------------------------
1281
1282 Status GenerateRsaKeyPair(const blink::WebCryptoAlgorithm& algorithm,
1283                           bool extractable,
1284                           blink::WebCryptoKeyUsageMask usage_mask,
1285                           unsigned int modulus_length_bits,
1286                           const CryptoData& public_exponent,
1287                           const blink::WebCryptoAlgorithm& hash_or_null,
1288                           blink::WebCryptoKey* public_key,
1289                           blink::WebCryptoKey* private_key) {
1290   crypto::ScopedPK11Slot slot(PK11_GetInternalKeySlot());
1291   if (!slot)
1292     return Status::OperationError();
1293
1294   unsigned long public_exponent_long;
1295   if (!BigIntegerToLong(public_exponent.bytes(),
1296                         public_exponent.byte_length(),
1297                         &public_exponent_long) ||
1298       !public_exponent_long) {
1299     return Status::ErrorGenerateKeyPublicExponent();
1300   }
1301
1302   PK11RSAGenParams rsa_gen_params;
1303   rsa_gen_params.keySizeInBits = modulus_length_bits;
1304   rsa_gen_params.pe = public_exponent_long;
1305
1306   // Flags are verified at the Blink layer; here the flags are set to all
1307   // possible operations for the given key type.
1308   CK_FLAGS operation_flags;
1309   switch (algorithm.id()) {
1310     case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5:
1311     case blink::WebCryptoAlgorithmIdRsaOaep:
1312       operation_flags = CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP;
1313       break;
1314     case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5:
1315       operation_flags = CKF_SIGN | CKF_VERIFY;
1316       break;
1317     default:
1318       NOTREACHED();
1319       return Status::ErrorUnexpected();
1320   }
1321   const CK_FLAGS operation_flags_mask =
1322       CKF_ENCRYPT | CKF_DECRYPT | CKF_SIGN | CKF_VERIFY | CKF_WRAP | CKF_UNWRAP;
1323
1324   // The private key must be marked as insensitive and extractable, otherwise it
1325   // cannot later be exported in unencrypted form or structured-cloned.
1326   const PK11AttrFlags attribute_flags =
1327       PK11_ATTR_INSENSITIVE | PK11_ATTR_EXTRACTABLE;
1328
1329   // Note: NSS does not generate an sec_public_key if the call below fails,
1330   // so there is no danger of a leaked sec_public_key.
1331   SECKEYPublicKey* sec_public_key;
1332   crypto::ScopedSECKEYPrivateKey scoped_sec_private_key(
1333       PK11_GenerateKeyPairWithOpFlags(slot.get(),
1334                                       CKM_RSA_PKCS_KEY_PAIR_GEN,
1335                                       &rsa_gen_params,
1336                                       &sec_public_key,
1337                                       attribute_flags,
1338                                       operation_flags,
1339                                       operation_flags_mask,
1340                                       NULL));
1341   if (!private_key)
1342     return Status::OperationError();
1343
1344   blink::WebCryptoKeyAlgorithm key_algorithm;
1345   if (!CreatePublicKeyAlgorithm(algorithm, sec_public_key, &key_algorithm))
1346     return Status::ErrorUnexpected();
1347
1348   scoped_ptr<PublicKey> public_key_handle;
1349   Status status = PublicKey::Create(
1350       crypto::ScopedSECKEYPublicKey(sec_public_key), &public_key_handle);
1351   if (status.IsError())
1352     return status;
1353
1354   scoped_ptr<PrivateKey> private_key_handle;
1355   status = PrivateKey::Create(
1356       scoped_sec_private_key.Pass(), key_algorithm, &private_key_handle);
1357   if (status.IsError())
1358     return status;
1359
1360   *public_key = blink::WebCryptoKey::create(public_key_handle.release(),
1361                                             blink::WebCryptoKeyTypePublic,
1362                                             true,
1363                                             key_algorithm,
1364                                             usage_mask);
1365   *private_key = blink::WebCryptoKey::create(private_key_handle.release(),
1366                                              blink::WebCryptoKeyTypePrivate,
1367                                              extractable,
1368                                              key_algorithm,
1369                                              usage_mask);
1370
1371   return Status::Success();
1372 }
1373
1374 void Init() {
1375   crypto::EnsureNSSInit();
1376 }
1377
1378 Status DigestSha(blink::WebCryptoAlgorithmId algorithm,
1379                  const CryptoData& data,
1380                  std::vector<uint8>* buffer) {
1381   DigestorNSS digestor(algorithm);
1382   Status error = digestor.ConsumeWithStatus(data.bytes(), data.byte_length());
1383   // http://crbug.com/366427: the spec does not define any other failures for
1384   // digest, so none of the subsequent errors are spec compliant.
1385   if (!error.IsSuccess())
1386     return error;
1387   return digestor.FinishWithVectorAndStatus(buffer);
1388 }
1389
1390 scoped_ptr<blink::WebCryptoDigestor> CreateDigestor(
1391     blink::WebCryptoAlgorithmId algorithm_id) {
1392   return scoped_ptr<blink::WebCryptoDigestor>(new DigestorNSS(algorithm_id));
1393 }
1394
1395 Status GenerateSecretKey(const blink::WebCryptoAlgorithm& algorithm,
1396                          bool extractable,
1397                          blink::WebCryptoKeyUsageMask usage_mask,
1398                          unsigned keylen_bytes,
1399                          blink::WebCryptoKey* key) {
1400   CK_MECHANISM_TYPE mech = WebCryptoAlgorithmToGenMechanism(algorithm);
1401   blink::WebCryptoKeyType key_type = blink::WebCryptoKeyTypeSecret;
1402
1403   if (mech == CKM_INVALID_MECHANISM)
1404     return Status::ErrorUnsupported();
1405
1406   crypto::ScopedPK11Slot slot(PK11_GetInternalKeySlot());
1407   if (!slot)
1408     return Status::OperationError();
1409
1410   crypto::ScopedPK11SymKey pk11_key(
1411       PK11_KeyGen(slot.get(), mech, NULL, keylen_bytes, NULL));
1412
1413   if (!pk11_key)
1414     return Status::OperationError();
1415
1416   blink::WebCryptoKeyAlgorithm key_algorithm;
1417   if (!CreateSecretKeyAlgorithm(algorithm, keylen_bytes, &key_algorithm))
1418     return Status::ErrorUnexpected();
1419
1420   scoped_ptr<SymKey> key_handle;
1421   Status status = SymKey::Create(pk11_key.Pass(), &key_handle);
1422   if (status.IsError())
1423     return status;
1424
1425   *key = blink::WebCryptoKey::create(
1426       key_handle.release(), key_type, extractable, key_algorithm, usage_mask);
1427   return Status::Success();
1428 }
1429
1430 Status ImportRsaPublicKey(const blink::WebCryptoAlgorithm& algorithm,
1431                           bool extractable,
1432                           blink::WebCryptoKeyUsageMask usage_mask,
1433                           const CryptoData& modulus_data,
1434                           const CryptoData& exponent_data,
1435                           blink::WebCryptoKey* key) {
1436   if (!modulus_data.byte_length())
1437     return Status::ErrorImportRsaEmptyModulus();
1438
1439   if (!exponent_data.byte_length())
1440     return Status::ErrorImportRsaEmptyExponent();
1441
1442   DCHECK(modulus_data.bytes());
1443   DCHECK(exponent_data.bytes());
1444
1445   // NSS does not provide a way to create an RSA public key directly from the
1446   // modulus and exponent values, but it can import an DER-encoded ASN.1 blob
1447   // with these values and create the public key from that. The code below
1448   // follows the recommendation described in
1449   // https://developer.mozilla.org/en-US/docs/NSS/NSS_Tech_Notes/nss_tech_note7
1450
1451   // Pack the input values into a struct compatible with NSS ASN.1 encoding, and
1452   // set up an ASN.1 encoder template for it.
1453   struct RsaPublicKeyData {
1454     SECItem modulus;
1455     SECItem exponent;
1456   };
1457   const RsaPublicKeyData pubkey_in = {
1458       {siUnsignedInteger, const_cast<unsigned char*>(modulus_data.bytes()),
1459        modulus_data.byte_length()},
1460       {siUnsignedInteger, const_cast<unsigned char*>(exponent_data.bytes()),
1461        exponent_data.byte_length()}};
1462   const SEC_ASN1Template rsa_public_key_template[] = {
1463       {SEC_ASN1_SEQUENCE, 0, NULL, sizeof(RsaPublicKeyData)},
1464       {SEC_ASN1_INTEGER, offsetof(RsaPublicKeyData, modulus), },
1465       {SEC_ASN1_INTEGER, offsetof(RsaPublicKeyData, exponent), },
1466       {0, }};
1467
1468   // DER-encode the public key.
1469   crypto::ScopedSECItem pubkey_der(
1470       SEC_ASN1EncodeItem(NULL, NULL, &pubkey_in, rsa_public_key_template));
1471   if (!pubkey_der)
1472     return Status::OperationError();
1473
1474   // Import the DER-encoded public key to create an RSA SECKEYPublicKey.
1475   crypto::ScopedSECKEYPublicKey pubkey(
1476       SECKEY_ImportDERPublicKey(pubkey_der.get(), CKK_RSA));
1477   if (!pubkey)
1478     return Status::OperationError();
1479
1480   blink::WebCryptoKeyAlgorithm key_algorithm;
1481   if (!CreatePublicKeyAlgorithm(algorithm, pubkey.get(), &key_algorithm))
1482     return Status::ErrorUnexpected();
1483
1484   scoped_ptr<PublicKey> key_handle;
1485   Status status = PublicKey::Create(pubkey.Pass(), &key_handle);
1486   if (status.IsError())
1487     return status;
1488
1489   *key = blink::WebCryptoKey::create(key_handle.release(),
1490                                      blink::WebCryptoKeyTypePublic,
1491                                      extractable,
1492                                      key_algorithm,
1493                                      usage_mask);
1494   return Status::Success();
1495 }
1496
1497 Status WrapSymKeyAesKw(SymKey* wrapping_key,
1498                        SymKey* key,
1499                        std::vector<uint8>* buffer) {
1500   // The data size must be at least 16 bytes and a multiple of 8 bytes.
1501   // RFC 3394 does not specify a maximum allowed data length, but since only
1502   // keys are being wrapped in this application (which are small), a reasonable
1503   // max limit is whatever will fit into an unsigned. For the max size test,
1504   // note that AES Key Wrap always adds 8 bytes to the input data size.
1505   const unsigned int input_length = PK11_GetKeyLength(key->key());
1506   if (input_length < 16)
1507     return Status::ErrorDataTooSmall();
1508   if (input_length > UINT_MAX - 8)
1509     return Status::ErrorDataTooLarge();
1510   if (input_length % 8)
1511     return Status::ErrorInvalidAesKwDataLength();
1512
1513   SECItem iv_item = MakeSECItemForBuffer(CryptoData(kAesIv, sizeof(kAesIv)));
1514   crypto::ScopedSECItem param_item(
1515       PK11_ParamFromIV(CKM_NSS_AES_KEY_WRAP, &iv_item));
1516   if (!param_item)
1517     return Status::ErrorUnexpected();
1518
1519   const unsigned int output_length = input_length + 8;
1520   buffer->resize(output_length);
1521   SECItem wrapped_key_item = MakeSECItemForBuffer(CryptoData(*buffer));
1522
1523   if (SECSuccess != PK11_WrapSymKey(CKM_NSS_AES_KEY_WRAP,
1524                                     param_item.get(),
1525                                     wrapping_key->key(),
1526                                     key->key(),
1527                                     &wrapped_key_item)) {
1528     return Status::OperationError();
1529   }
1530   if (output_length != wrapped_key_item.len)
1531     return Status::ErrorUnexpected();
1532
1533   return Status::Success();
1534 }
1535
1536 Status UnwrapSymKeyAesKw(const CryptoData& wrapped_key_data,
1537                          SymKey* wrapping_key,
1538                          const blink::WebCryptoAlgorithm& algorithm,
1539                          bool extractable,
1540                          blink::WebCryptoKeyUsageMask usage_mask,
1541                          blink::WebCryptoKey* key) {
1542   // Determine the proper NSS key properties from the input algorithm.
1543   CK_MECHANISM_TYPE mechanism;
1544   CK_FLAGS flags;
1545   Status status =
1546       WebCryptoAlgorithmToNssMechFlags(algorithm, &mechanism, &flags);
1547   if (status.IsError())
1548     return status;
1549
1550   crypto::ScopedPK11SymKey unwrapped_key;
1551   status = DoUnwrapSymKeyAesKw(
1552       wrapped_key_data, wrapping_key, mechanism, flags, &unwrapped_key);
1553   if (status.IsError())
1554     return status;
1555
1556   blink::WebCryptoKeyAlgorithm key_algorithm;
1557   if (!CreateSecretKeyAlgorithm(
1558           algorithm, PK11_GetKeyLength(unwrapped_key.get()), &key_algorithm))
1559     return Status::ErrorUnexpected();
1560
1561   scoped_ptr<SymKey> key_handle;
1562   status = SymKey::Create(unwrapped_key.Pass(), &key_handle);
1563   if (status.IsError())
1564     return status;
1565
1566   *key = blink::WebCryptoKey::create(key_handle.release(),
1567                                      blink::WebCryptoKeyTypeSecret,
1568                                      extractable,
1569                                      key_algorithm,
1570                                      usage_mask);
1571   return Status::Success();
1572 }
1573
1574 Status DecryptAesKw(SymKey* wrapping_key,
1575                     const CryptoData& data,
1576                     std::vector<uint8>* buffer) {
1577   // Due to limitations in the NSS API for the AES-KW algorithm, |data| must be
1578   // temporarily viewed as a symmetric key to be unwrapped (decrypted).
1579   crypto::ScopedPK11SymKey decrypted;
1580   Status status = DoUnwrapSymKeyAesKw(
1581       data, wrapping_key, CKK_GENERIC_SECRET, 0, &decrypted);
1582   if (status.IsError())
1583     return status;
1584
1585   // Once the decrypt is complete, extract the resultant raw bytes from NSS and
1586   // return them to the caller.
1587   if (PK11_ExtractKeyValue(decrypted.get()) != SECSuccess)
1588     return Status::OperationError();
1589   const SECItem* const key_data = PK11_GetKeyData(decrypted.get());
1590   if (!key_data)
1591     return Status::OperationError();
1592   buffer->assign(key_data->data, key_data->data + key_data->len);
1593
1594   return Status::Success();
1595 }
1596
1597 Status WrapSymKeyRsaEs(PublicKey* wrapping_key,
1598                        SymKey* key,
1599                        std::vector<uint8>* buffer) {
1600   // Check the raw length of the key to be wrapped against the max size allowed
1601   // by the RSA wrapping key. With PKCS#1 v1.5 padding used in this function,
1602   // the maximum data length that can be encrypted is the wrapping_key's modulus
1603   // byte length minus eleven bytes.
1604   const unsigned int input_length_bytes = PK11_GetKeyLength(key->key());
1605   const unsigned int modulus_length_bytes =
1606       SECKEY_PublicKeyStrength(wrapping_key->key());
1607   if (modulus_length_bytes < 11 ||
1608       modulus_length_bytes - 11 < input_length_bytes)
1609     return Status::ErrorDataTooLarge();
1610
1611   buffer->resize(modulus_length_bytes);
1612   SECItem wrapped_key_item = MakeSECItemForBuffer(CryptoData(*buffer));
1613
1614   if (SECSuccess !=
1615       PK11_PubWrapSymKey(
1616           CKM_RSA_PKCS, wrapping_key->key(), key->key(), &wrapped_key_item)) {
1617     return Status::OperationError();
1618   }
1619   if (wrapped_key_item.len != modulus_length_bytes)
1620     return Status::ErrorUnexpected();
1621
1622   return Status::Success();
1623 }
1624
1625 Status UnwrapSymKeyRsaEs(const CryptoData& wrapped_key_data,
1626                          PrivateKey* wrapping_key,
1627                          const blink::WebCryptoAlgorithm& algorithm,
1628                          bool extractable,
1629                          blink::WebCryptoKeyUsageMask usage_mask,
1630                          blink::WebCryptoKey* key) {
1631   // Verify wrapped_key_data size does not exceed the modulus of the RSA key.
1632   const int modulus_length_bytes =
1633       PK11_GetPrivateModulusLen(wrapping_key->key());
1634   if (modulus_length_bytes <= 0)
1635     return Status::ErrorUnexpected();
1636   if (wrapped_key_data.byte_length() >
1637       static_cast<unsigned int>(modulus_length_bytes))
1638     return Status::ErrorDataTooLarge();
1639
1640   // Determine the proper NSS key properties from the input algorithm.
1641   CK_MECHANISM_TYPE mechanism;
1642   CK_FLAGS flags;
1643   Status status =
1644       WebCryptoAlgorithmToNssMechFlags(algorithm, &mechanism, &flags);
1645   if (status.IsError())
1646     return status;
1647
1648   SECItem wrapped_key_item = MakeSECItemForBuffer(wrapped_key_data);
1649
1650   crypto::ScopedPK11SymKey unwrapped_key(
1651       PK11_PubUnwrapSymKeyWithFlagsPerm(wrapping_key->key(),
1652                                         &wrapped_key_item,
1653                                         mechanism,
1654                                         CKA_DECRYPT,
1655                                         0,
1656                                         flags,
1657                                         false));
1658   if (!unwrapped_key)
1659     return Status::OperationError();
1660
1661   const unsigned int key_length = PK11_GetKeyLength(unwrapped_key.get());
1662
1663   blink::WebCryptoKeyAlgorithm key_algorithm;
1664   if (!CreateSecretKeyAlgorithm(algorithm, key_length, &key_algorithm))
1665     return Status::ErrorUnexpected();
1666
1667   scoped_ptr<SymKey> key_handle;
1668   status = SymKey::Create(unwrapped_key.Pass(), &key_handle);
1669   if (status.IsError())
1670     return status;
1671
1672   *key = blink::WebCryptoKey::create(key_handle.release(),
1673                                      blink::WebCryptoKeyTypeSecret,
1674                                      extractable,
1675                                      key_algorithm,
1676                                      usage_mask);
1677   return Status::Success();
1678 }
1679
1680 }  // namespace platform
1681
1682 }  // namespace webcrypto
1683
1684 }  // namespace content