• 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 <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 
ReadAttribute(SECKEYPrivateKey * key,CK_ATTRIBUTE_TYPE type,std::vector<uint8> * output)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 {
operator ()__anonc80932010111::PublicKeyInfoDeleter43   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|.
GetRSAPublicKey(const std::vector<uint8> & 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 
~RSAPrivateKey()76 RSAPrivateKey::~RSAPrivateKey() {
77   if (key_)
78     SECKEY_DestroyPrivateKey(key_);
79   if (public_key_)
80     SECKEY_DestroyPublicKey(public_key_);
81 }
82 
83 // static
Create(uint16 num_bits)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
CreateFromPrivateKeyInfo(const std::vector<uint8> & input)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
CreateSensitive(PK11SlotInfo * slot,uint16 num_bits)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
CreateSensitiveFromPrivateKeyInfo(PK11SlotInfo * slot,const std::vector<uint8> & input)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
CreateFromKey(SECKEYPrivateKey * key)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
FindFromPublicKeyInfo(const std::vector<uint8> & input)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
FindFromPublicKeyInfoInSlot(const std::vector<uint8> & input,PK11SlotInfo * slot)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 
Copy() const200 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 
ExportPrivateKey(std::vector<uint8> * output) const207 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 
ExportPublicKey(std::vector<uint8> * output) const229 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 
RSAPrivateKey()240 RSAPrivateKey::RSAPrivateKey() : key_(NULL), public_key_(NULL) {
241   EnsureNSSInit();
242 }
243 
244 // static
CreateWithParams(PK11SlotInfo * slot,uint16 num_bits,bool permanent,bool sensitive)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
CreateFromPrivateKeyInfoWithParams(PK11SlotInfo * slot,const std::vector<uint8> & input,bool permanent,bool sensitive)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
InitPublicPart(const std::vector<uint8> & input)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