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 <stdint.h>
     11 
     12 #include <list>
     13 
     14 #include "base/logging.h"
     15 #include "base/memory/scoped_ptr.h"
     16 #include "base/strings/string_util.h"
     17 #include "crypto/nss_key_util.h"
     18 #include "crypto/nss_util.h"
     19 #include "crypto/scoped_nss_types.h"
     20 
     21 // TODO(rafaelw): Consider using NSS's ASN.1 encoder.
     22 namespace {
     23 
     24 static bool ReadAttribute(SECKEYPrivateKey* key,
     25                           CK_ATTRIBUTE_TYPE type,
     26                           std::vector<uint8_t>* output) {
     27   SECItem item;
     28   SECStatus rv;
     29   rv = PK11_ReadRawAttribute(PK11_TypePrivKey, key, type, &item);
     30   if (rv != SECSuccess) {
     31     NOTREACHED();
     32     return false;
     33   }
     34 
     35   output->assign(item.data, item.data + item.len);
     36   SECITEM_FreeItem(&item, PR_FALSE);
     37   return true;
     38 }
     39 
     40 }  // namespace
     41 
     42 namespace crypto {
     43 
     44 RSAPrivateKey::~RSAPrivateKey() {
     45   if (key_)
     46     SECKEY_DestroyPrivateKey(key_);
     47   if (public_key_)
     48     SECKEY_DestroyPublicKey(public_key_);
     49 }
     50 
     51 // static
     52 RSAPrivateKey* RSAPrivateKey::Create(uint16_t num_bits) {
     53   EnsureNSSInit();
     54 
     55   ScopedPK11Slot slot(PK11_GetInternalSlot());
     56   if (!slot) {
     57     NOTREACHED();
     58     return nullptr;
     59   }
     60 
     61   ScopedSECKEYPublicKey public_key;
     62   ScopedSECKEYPrivateKey private_key;
     63   if (!GenerateRSAKeyPairNSS(slot.get(), num_bits, false /* not permanent */,
     64                              &public_key, &private_key)) {
     65     return nullptr;
     66   }
     67 
     68   RSAPrivateKey* rsa_key = new RSAPrivateKey;
     69   rsa_key->public_key_ = public_key.release();
     70   rsa_key->key_ = private_key.release();
     71   return rsa_key;
     72 }
     73 
     74 // static
     75 RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo(
     76     const std::vector<uint8_t>& input) {
     77   EnsureNSSInit();
     78 
     79   ScopedPK11Slot slot(PK11_GetInternalSlot());
     80   if (!slot) {
     81     NOTREACHED();
     82     return nullptr;
     83   }
     84   ScopedSECKEYPrivateKey key(ImportNSSKeyFromPrivateKeyInfo(
     85       slot.get(), input, false /* not permanent */));
     86   if (!key || SECKEY_GetPrivateKeyType(key.get()) != rsaKey)
     87     return nullptr;
     88   return RSAPrivateKey::CreateFromKey(key.get());
     89 }
     90 
     91 // static
     92 RSAPrivateKey* RSAPrivateKey::CreateFromKey(SECKEYPrivateKey* key) {
     93   DCHECK(key);
     94   if (SECKEY_GetPrivateKeyType(key) != rsaKey)
     95     return NULL;
     96   RSAPrivateKey* copy = new RSAPrivateKey();
     97   copy->key_ = SECKEY_CopyPrivateKey(key);
     98   copy->public_key_ = SECKEY_ConvertToPublicKey(key);
     99   if (!copy->key_ || !copy->public_key_) {
    100     NOTREACHED();
    101     delete copy;
    102     return NULL;
    103   }
    104   return copy;
    105 }
    106 
    107 RSAPrivateKey* RSAPrivateKey::Copy() const {
    108   RSAPrivateKey* copy = new RSAPrivateKey();
    109   copy->key_ = SECKEY_CopyPrivateKey(key_);
    110   copy->public_key_ = SECKEY_CopyPublicKey(public_key_);
    111   return copy;
    112 }
    113 
    114 bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8_t>* output) const {
    115   PrivateKeyInfoCodec private_key_info(true);
    116 
    117   // Manually read the component attributes of the private key and build up
    118   // the PrivateKeyInfo.
    119   if (!ReadAttribute(key_, CKA_MODULUS, private_key_info.modulus()) ||
    120       !ReadAttribute(key_, CKA_PUBLIC_EXPONENT,
    121           private_key_info.public_exponent()) ||
    122       !ReadAttribute(key_, CKA_PRIVATE_EXPONENT,
    123           private_key_info.private_exponent()) ||
    124       !ReadAttribute(key_, CKA_PRIME_1, private_key_info.prime1()) ||
    125       !ReadAttribute(key_, CKA_PRIME_2, private_key_info.prime2()) ||
    126       !ReadAttribute(key_, CKA_EXPONENT_1, private_key_info.exponent1()) ||
    127       !ReadAttribute(key_, CKA_EXPONENT_2, private_key_info.exponent2()) ||
    128       !ReadAttribute(key_, CKA_COEFFICIENT, private_key_info.coefficient())) {
    129     NOTREACHED();
    130     return false;
    131   }
    132 
    133   return private_key_info.Export(output);
    134 }
    135 
    136 bool RSAPrivateKey::ExportPublicKey(std::vector<uint8_t>* output) const {
    137   ScopedSECItem der_pubkey(SECKEY_EncodeDERSubjectPublicKeyInfo(public_key_));
    138   if (!der_pubkey.get()) {
    139     NOTREACHED();
    140     return false;
    141   }
    142 
    143   output->assign(der_pubkey->data, der_pubkey->data + der_pubkey->len);
    144   return true;
    145 }
    146 
    147 RSAPrivateKey::RSAPrivateKey() : key_(NULL), public_key_(NULL) {
    148   EnsureNSSInit();
    149 }
    150 
    151 }  // namespace crypto
    152