| OLD | NEW | 
|     1 // Copyright 2014 The Chromium Authors. All rights reserved. |     1 // Copyright 2014 The Chromium Authors. All rights reserved. | 
|     2 // Use of this source code is governed by a BSD-style license that can be |     2 // Use of this source code is governed by a BSD-style license that can be | 
|     3 // found in the LICENSE file. |     3 // found in the LICENSE file. | 
|     4  |     4  | 
|     5 #include "content/child/webcrypto/platform_crypto.h" |     5 #include "content/child/webcrypto/platform_crypto.h" | 
|     6  |     6  | 
|     7 #include <cryptohi.h> |     7 #include <cryptohi.h> | 
|     8 #include <pk11pub.h> |     8 #include <pk11pub.h> | 
 |     9 #include <secerr.h> | 
|     9 #include <sechash.h> |    10 #include <sechash.h> | 
|    10 #include <secoid.h> |    11 #include <secoid.h> | 
|    11  |    12  | 
|    12 #include <vector> |    13 #include <vector> | 
|    13  |    14  | 
|    14 #include "base/lazy_instance.h" |    15 #include "base/lazy_instance.h" | 
|    15 #include "base/logging.h" |    16 #include "base/logging.h" | 
|    16 #include "content/child/webcrypto/crypto_data.h" |    17 #include "content/child/webcrypto/crypto_data.h" | 
|    17 #include "content/child/webcrypto/status.h" |    18 #include "content/child/webcrypto/status.h" | 
|    18 #include "content/child/webcrypto/webcrypto_util.h" |    19 #include "content/child/webcrypto/webcrypto_util.h" | 
| (...skipping 481 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   500   crypto::ScopedSECItem param_item( |   501   crypto::ScopedSECItem param_item( | 
|   501       PK11_ParamFromIV(CKM_NSS_AES_KEY_WRAP, &iv_item)); |   502       PK11_ParamFromIV(CKM_NSS_AES_KEY_WRAP, &iv_item)); | 
|   502   if (!param_item) |   503   if (!param_item) | 
|   503     return Status::ErrorUnexpected(); |   504     return Status::ErrorUnexpected(); | 
|   504  |   505  | 
|   505   SECItem cipher_text = MakeSECItemForBuffer(wrapped_key_data); |   506   SECItem cipher_text = MakeSECItemForBuffer(wrapped_key_data); | 
|   506  |   507  | 
|   507   // The plaintext length is always 64 bits less than the data size. |   508   // The plaintext length is always 64 bits less than the data size. | 
|   508   const unsigned int plaintext_length = wrapped_key_data.byte_length() - 8; |   509   const unsigned int plaintext_length = wrapped_key_data.byte_length() - 8; | 
|   509  |   510  | 
 |   511 #if defined(USE_NSS) | 
 |   512   // Part of workaround for | 
 |   513   // https://bugzilla.mozilla.org/show_bug.cgi?id=981170. See the explanation | 
 |   514   // later in this function. | 
 |   515   PORT_SetError(0); | 
 |   516 #endif | 
 |   517  | 
|   510   crypto::ScopedPK11SymKey new_key(PK11_UnwrapSymKey(wrapping_key->key(), |   518   crypto::ScopedPK11SymKey new_key(PK11_UnwrapSymKey(wrapping_key->key(), | 
|   511                                                      CKM_NSS_AES_KEY_WRAP, |   519                                                      CKM_NSS_AES_KEY_WRAP, | 
|   512                                                      param_item.get(), |   520                                                      param_item.get(), | 
|   513                                                      &cipher_text, |   521                                                      &cipher_text, | 
|   514                                                      mechanism, |   522                                                      mechanism, | 
|   515                                                      flags, |   523                                                      flags, | 
|   516                                                      plaintext_length)); |   524                                                      plaintext_length)); | 
|   517   // TODO(padolph): Use NSS PORT_GetError() and friends to report a more |   525   // TODO(padolph): Use NSS PORT_GetError() and friends to report a more | 
|   518   // accurate error, providing if doesn't leak any information to web pages |   526   // accurate error, providing if doesn't leak any information to web pages | 
|   519   // about other web crypto users, key details, etc. |   527   // about other web crypto users, key details, etc. | 
|   520   if (!new_key) |   528   if (!new_key) | 
|   521     return Status::Error(); |   529     return Status::Error(); | 
|   522  |   530  | 
|   523 // TODO(padolph): Change to "defined(USE_NSS)" once the NSS fix for |   531 #if defined(USE_NSS) | 
|   524 // https://bugzilla.mozilla.org/show_bug.cgi?id=981170 rolls into chromium. |   532   // Workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=981170 | 
|   525 #if 1 |   533   // which was fixed in NSS 3.16.0. | 
|   526   // ------- Start NSS bug workaround |   534   // If unwrap fails, NSS nevertheless returns a valid-looking PK11SymKey, | 
|   527   // Workaround for https://code.google.com/p/chromium/issues/detail?id=349939 |   535   // with a reasonable length but with key data pointing to uninitialized | 
|   528   // If unwrap fails, NSS nevertheless returns a valid-looking PK11SymKey, with |   536   // memory. | 
|   529   // a reasonable length but with key data pointing to uninitialized memory. |   537   // To understand this workaround see the fix for 981170: | 
|   530   // This workaround re-wraps the key and compares the result with the incoming |   538   // https://hg.mozilla.org/projects/nss/rev/753bb69e543c | 
|   531   // data, and fails if there is a difference. This prevents returning a bad key |   539   if (!NSS_VersionCheck("3.16") && PORT_GetError() == SEC_ERROR_BAD_DATA) | 
|   532   // to the caller. |  | 
|   533   const unsigned int output_length = wrapped_key_data.byte_length(); |  | 
|   534   std::vector<unsigned char> buffer(output_length, 0); |  | 
|   535   SECItem wrapped_key_item = MakeSECItemForBuffer(CryptoData(buffer)); |  | 
|   536   if (SECSuccess != PK11_WrapSymKey(CKM_NSS_AES_KEY_WRAP, |  | 
|   537                                     param_item.get(), |  | 
|   538                                     wrapping_key->key(), |  | 
|   539                                     new_key.get(), |  | 
|   540                                     &wrapped_key_item)) { |  | 
|   541     return Status::Error(); |   540     return Status::Error(); | 
|   542   } |  | 
|   543   if (wrapped_key_item.len != wrapped_key_data.byte_length() || |  | 
|   544       memcmp(wrapped_key_item.data, |  | 
|   545              wrapped_key_data.bytes(), |  | 
|   546              wrapped_key_item.len) != 0) { |  | 
|   547     return Status::Error(); |  | 
|   548   } |  | 
|   549 // ------- End NSS bug workaround |  | 
|   550 #endif |   541 #endif | 
|   551  |   542  | 
|   552   *unwrapped_key = new_key.Pass(); |   543   *unwrapped_key = new_key.Pass(); | 
|   553   return Status::Success(); |   544   return Status::Success(); | 
|   554 } |   545 } | 
|   555  |   546  | 
|   556 // From PKCS#1 [http://tools.ietf.org/html/rfc3447]: |   547 // From PKCS#1 [http://tools.ietf.org/html/rfc3447]: | 
|   557 // |   548 // | 
|   558 //    RSAPrivateKey ::= SEQUENCE { |   549 //    RSAPrivateKey ::= SEQUENCE { | 
|   559 //      version           Version, |   550 //      version           Version, | 
| (...skipping 925 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1485                                      key_algorithm, |  1476                                      key_algorithm, | 
|  1486                                      usage_mask); |  1477                                      usage_mask); | 
|  1487   return Status::Success(); |  1478   return Status::Success(); | 
|  1488 } |  1479 } | 
|  1489  |  1480  | 
|  1490 }  // namespace platform |  1481 }  // namespace platform | 
|  1491  |  1482  | 
|  1492 }  // namespace webcrypto |  1483 }  // namespace webcrypto | 
|  1493  |  1484  | 
|  1494 }  // namespace content |  1485 }  // namespace content | 
| OLD | NEW |