• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ReadAttribute(SECKEYPrivateKey * key,CK_ATTRIBUTE_TYPE type,std::vector<uint8_t> * output)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 
~RSAPrivateKey()44 RSAPrivateKey::~RSAPrivateKey() {
45   if (key_)
46     SECKEY_DestroyPrivateKey(key_);
47   if (public_key_)
48     SECKEY_DestroyPublicKey(public_key_);
49 }
50 
51 // static
Create(uint16_t num_bits)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
CreateFromPrivateKeyInfo(const std::vector<uint8_t> & input)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
CreateFromKey(SECKEYPrivateKey * key)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 
Copy() const107 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 
ExportPrivateKey(std::vector<uint8_t> * output) const114 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 
ExportPublicKey(std::vector<uint8_t> * output) const136 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 
RSAPrivateKey()147 RSAPrivateKey::RSAPrivateKey() : key_(NULL), public_key_(NULL) {
148   EnsureNSSInit();
149 }
150 
151 }  // namespace crypto
152