Home | History | Annotate | Download | only in crypto
      1 // Copyright (c) 2011 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 "crypto/rsa_private_key.h"
      6 
      7 #include <cryptohi.h>
      8 #include <keyhi.h>
      9 #include <pk11pub.h>
     10 #include <secmod.h>
     11 
     12 #include <list>
     13 
     14 #include "base/debug/leak_annotations.h"
     15 #include "base/logging.h"
     16 #include "base/memory/scoped_ptr.h"
     17 #include "base/strings/string_util.h"
     18 #include "crypto/nss_util.h"
     19 #include "crypto/nss_util_internal.h"
     20 #include "crypto/scoped_nss_types.h"
     21 
     22 // TODO(rafaelw): Consider using NSS's ASN.1 encoder.
     23 namespace {
     24 
     25 static bool ReadAttribute(SECKEYPrivateKey* key,
     26                           CK_ATTRIBUTE_TYPE type,
     27                           std::vector<uint8>* output) {
     28   SECItem item;
     29   SECStatus rv;
     30   rv = PK11_ReadRawAttribute(PK11_TypePrivKey, key, type, &item);
     31   if (rv != SECSuccess) {
     32     NOTREACHED();
     33     return false;
     34   }
     35 
     36   output->assign(item.data, item.data + item.len);
     37   SECITEM_FreeItem(&item, PR_FALSE);
     38   return true;
     39 }
     40 
     41 #if defined(USE_NSS)
     42 struct PublicKeyInfoDeleter {
     43   inline void operator()(CERTSubjectPublicKeyInfo* spki) {
     44     SECKEY_DestroySubjectPublicKeyInfo(spki);
     45   }
     46 };
     47 
     48 typedef scoped_ptr<CERTSubjectPublicKeyInfo, PublicKeyInfoDeleter>
     49     ScopedPublicKeyInfo;
     50 
     51 // The function decodes RSA public key from the |input|.
     52 crypto::ScopedSECKEYPublicKey GetRSAPublicKey(const std::vector<uint8>& input) {
     53   // First, decode and save the public key.
     54   SECItem key_der;
     55   key_der.type = siBuffer;
     56   key_der.data = const_cast<unsigned char*>(&input[0]);
     57   key_der.len = input.size();
     58 
     59   ScopedPublicKeyInfo spki(SECKEY_DecodeDERSubjectPublicKeyInfo(&key_der));
     60   if (!spki)
     61     return crypto::ScopedSECKEYPublicKey();
     62 
     63   crypto::ScopedSECKEYPublicKey result(SECKEY_ExtractPublicKey(spki.get()));
     64 
     65   // Make sure the key is an RSA key.. If not, that's an error.
     66   if (!result || result->keyType != rsaKey)
     67     return crypto::ScopedSECKEYPublicKey();
     68   return result.Pass();
     69 }
     70 #endif  // defined(USE_NSS)
     71 
     72 }  // namespace
     73 
     74 namespace crypto {
     75 
     76 RSAPrivateKey::~RSAPrivateKey() {
     77   if (key_)
     78     SECKEY_DestroyPrivateKey(key_);
     79   if (public_key_)
     80     SECKEY_DestroyPublicKey(public_key_);
     81 }
     82 
     83 // static
     84 RSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) {
     85   EnsureNSSInit();
     86 
     87   ScopedPK11Slot slot(PK11_GetInternalSlot());
     88   return CreateWithParams(slot.get(),
     89                           num_bits,
     90                           false /* not permanent */,
     91                           false /* not sensitive */);
     92 }
     93 
     94 // static
     95 RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo(
     96     const std::vector<uint8>& input) {
     97   EnsureNSSInit();
     98 
     99   ScopedPK11Slot slot(PK11_GetInternalSlot());
    100   return CreateFromPrivateKeyInfoWithParams(
    101       slot.get(),
    102       input,
    103       false /* not permanent */,
    104       false /* not sensitive */);
    105 }
    106 
    107 #if defined(USE_NSS)
    108 // static
    109 RSAPrivateKey* RSAPrivateKey::CreateSensitive(PK11SlotInfo* slot,
    110                                               uint16 num_bits) {
    111   return CreateWithParams(slot,
    112                           num_bits,
    113                           true /* permanent */,
    114                           true /* sensitive */);
    115 }
    116 
    117 // static
    118 RSAPrivateKey* RSAPrivateKey::CreateSensitiveFromPrivateKeyInfo(
    119     PK11SlotInfo* slot,
    120     const std::vector<uint8>& input) {
    121   return CreateFromPrivateKeyInfoWithParams(slot,
    122                                             input,
    123                                             true /* permanent */,
    124                                             true /* sensitive */);
    125 }
    126 
    127 // static
    128 RSAPrivateKey* RSAPrivateKey::CreateFromKey(SECKEYPrivateKey* key) {
    129   DCHECK(key);
    130   if (SECKEY_GetPrivateKeyType(key) != rsaKey)
    131     return NULL;
    132   RSAPrivateKey* copy = new RSAPrivateKey();
    133   copy->key_ = SECKEY_CopyPrivateKey(key);
    134   copy->public_key_ = SECKEY_ConvertToPublicKey(key);
    135   if (!copy->key_ || !copy->public_key_) {
    136     NOTREACHED();
    137     delete copy;
    138     return NULL;
    139   }
    140   return copy;
    141 }
    142 
    143 // static
    144 RSAPrivateKey* RSAPrivateKey::FindFromPublicKeyInfo(
    145     const std::vector<uint8>& input) {
    146   scoped_ptr<RSAPrivateKey> result(InitPublicPart(input));
    147   if (!result)
    148     return NULL;
    149 
    150   ScopedSECItem ck_id(
    151       PK11_MakeIDFromPubKey(&(result->public_key_->u.rsa.modulus)));
    152   if (!ck_id.get()) {
    153     NOTREACHED();
    154     return NULL;
    155   }
    156 
    157   // Search all slots in all modules for the key with the given ID.
    158   AutoSECMODListReadLock auto_lock;
    159   SECMODModuleList* head = SECMOD_GetDefaultModuleList();
    160   for (SECMODModuleList* item = head; item != NULL; item = item->next) {
    161     int slot_count = item->module->loaded ? item->module->slotCount : 0;
    162     for (int i = 0; i < slot_count; i++) {
    163       // Finally...Look for the key!
    164       result->key_ = PK11_FindKeyByKeyID(item->module->slots[i],
    165                                          ck_id.get(), NULL);
    166       if (result->key_)
    167         return result.release();
    168     }
    169   }
    170 
    171   // We didn't find the key.
    172   return NULL;
    173 }
    174 
    175 // static
    176 RSAPrivateKey* RSAPrivateKey::FindFromPublicKeyInfoInSlot(
    177     const std::vector<uint8>& input,
    178     PK11SlotInfo* slot) {
    179   if (!slot)
    180     return NULL;
    181 
    182   scoped_ptr<RSAPrivateKey> result(InitPublicPart(input));
    183   if (!result)
    184     return NULL;
    185 
    186   ScopedSECItem ck_id(
    187       PK11_MakeIDFromPubKey(&(result->public_key_->u.rsa.modulus)));
    188   if (!ck_id.get()) {
    189     NOTREACHED();
    190     return NULL;
    191   }
    192 
    193   result->key_ = PK11_FindKeyByKeyID(slot, ck_id.get(), NULL);
    194   if (!result->key_)
    195     return NULL;
    196   return result.release();
    197 }
    198 #endif
    199 
    200 RSAPrivateKey* RSAPrivateKey::Copy() const {
    201   RSAPrivateKey* copy = new RSAPrivateKey();
    202   copy->key_ = SECKEY_CopyPrivateKey(key_);
    203   copy->public_key_ = SECKEY_CopyPublicKey(public_key_);
    204   return copy;
    205 }
    206 
    207 bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8>* output) const {
    208   PrivateKeyInfoCodec private_key_info(true);
    209 
    210   // Manually read the component attributes of the private key and build up
    211   // the PrivateKeyInfo.
    212   if (!ReadAttribute(key_, CKA_MODULUS, private_key_info.modulus()) ||
    213       !ReadAttribute(key_, CKA_PUBLIC_EXPONENT,
    214           private_key_info.public_exponent()) ||
    215       !ReadAttribute(key_, CKA_PRIVATE_EXPONENT,
    216           private_key_info.private_exponent()) ||
    217       !ReadAttribute(key_, CKA_PRIME_1, private_key_info.prime1()) ||
    218       !ReadAttribute(key_, CKA_PRIME_2, private_key_info.prime2()) ||
    219       !ReadAttribute(key_, CKA_EXPONENT_1, private_key_info.exponent1()) ||
    220       !ReadAttribute(key_, CKA_EXPONENT_2, private_key_info.exponent2()) ||
    221       !ReadAttribute(key_, CKA_COEFFICIENT, private_key_info.coefficient())) {
    222     NOTREACHED();
    223     return false;
    224   }
    225 
    226   return private_key_info.Export(output);
    227 }
    228 
    229 bool RSAPrivateKey::ExportPublicKey(std::vector<uint8>* output) const {
    230   ScopedSECItem der_pubkey(SECKEY_EncodeDERSubjectPublicKeyInfo(public_key_));
    231   if (!der_pubkey.get()) {
    232     NOTREACHED();
    233     return false;
    234   }
    235 
    236   output->assign(der_pubkey->data, der_pubkey->data + der_pubkey->len);
    237   return true;
    238 }
    239 
    240 RSAPrivateKey::RSAPrivateKey() : key_(NULL), public_key_(NULL) {
    241   EnsureNSSInit();
    242 }
    243 
    244 // static
    245 RSAPrivateKey* RSAPrivateKey::CreateWithParams(PK11SlotInfo* slot,
    246                                                uint16 num_bits,
    247                                                bool permanent,
    248                                                bool sensitive) {
    249   if (!slot)
    250     return NULL;
    251 
    252   scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey);
    253 
    254   PK11RSAGenParams param;
    255   param.keySizeInBits = num_bits;
    256   param.pe = 65537L;
    257   result->key_ = PK11_GenerateKeyPair(slot,
    258                                       CKM_RSA_PKCS_KEY_PAIR_GEN,
    259                                       &param,
    260                                       &result->public_key_,
    261                                       permanent,
    262                                       sensitive,
    263                                       NULL);
    264   if (!result->key_)
    265     return NULL;
    266 
    267   return result.release();
    268 }
    269 
    270 // static
    271 RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfoWithParams(
    272     PK11SlotInfo* slot,
    273     const std::vector<uint8>& input,
    274     bool permanent,
    275     bool sensitive) {
    276   if (!slot)
    277     return NULL;
    278 
    279   scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey);
    280 
    281   SECItem der_private_key_info;
    282   der_private_key_info.data = const_cast<unsigned char*>(&input.front());
    283   der_private_key_info.len = input.size();
    284   // Allow the private key to be used for key unwrapping, data decryption,
    285   // and signature generation.
    286   const unsigned int key_usage = KU_KEY_ENCIPHERMENT | KU_DATA_ENCIPHERMENT |
    287                                  KU_DIGITAL_SIGNATURE;
    288   SECStatus rv =  PK11_ImportDERPrivateKeyInfoAndReturnKey(
    289       slot, &der_private_key_info, NULL, NULL, permanent, sensitive,
    290       key_usage, &result->key_, NULL);
    291   if (rv != SECSuccess) {
    292     NOTREACHED();
    293     return NULL;
    294   }
    295 
    296   result->public_key_ = SECKEY_ConvertToPublicKey(result->key_);
    297   if (!result->public_key_) {
    298     NOTREACHED();
    299     return NULL;
    300   }
    301 
    302   return result.release();
    303 }
    304 
    305 #if defined(USE_NSS)
    306 // static
    307 RSAPrivateKey* RSAPrivateKey::InitPublicPart(const std::vector<uint8>& input) {
    308   EnsureNSSInit();
    309 
    310   scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey());
    311   result->public_key_ = GetRSAPublicKey(input).release();
    312   if (!result->public_key_) {
    313     NOTREACHED();
    314     return NULL;
    315   }
    316 
    317   return result.release();
    318 }
    319 #endif  // defined(USE_NSS)
    320 
    321 }  // namespace crypto
    322