blob: 0d79dbe84661831740ef43cdd66bf72696f26685 [file] [log] [blame]
[email protected]3b63f8f42011-03-28 01:54:151// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]71a9f842009-09-24 01:21:122// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]4b559b4d2011-04-14 17:37:145#include "crypto/rsa_private_key.h"
[email protected]71a9f842009-09-24 01:21:126
7#include <cryptohi.h>
8#include <keyhi.h>
9#include <pk11pub.h>
[email protected]dd24ffc2011-06-08 19:46:4210#include <secmod.h>
[email protected]71a9f842009-09-24 01:21:1211
[email protected]71a9f842009-09-24 01:21:1212#include <list>
13
[email protected]58580352010-10-26 04:07:5014#include "base/debug/leak_annotations.h"
[email protected]71a9f842009-09-24 01:21:1215#include "base/logging.h"
[email protected]3b63f8f42011-03-28 01:54:1516#include "base/memory/scoped_ptr.h"
[email protected]71a9f842009-09-24 01:21:1217#include "base/string_util.h"
[email protected]4b559b4d2011-04-14 17:37:1418#include "crypto/nss_util.h"
19#include "crypto/nss_util_internal.h"
[email protected]cfa46c02011-05-25 18:19:0820#include "crypto/scoped_nss_types.h"
[email protected]71a9f842009-09-24 01:21:1221
22// TODO(rafaelw): Consider refactoring common functions and definitions from
23// rsa_private_key_win.cc or using NSS's ASN.1 encoder.
24namespace {
25
[email protected]308379a52009-10-07 02:46:3126static bool ReadAttribute(SECKEYPrivateKey* key,
27 CK_ATTRIBUTE_TYPE type,
28 std::vector<uint8>* output) {
[email protected]71a9f842009-09-24 01:21:1229 SECItem item;
30 SECStatus rv;
31 rv = PK11_ReadRawAttribute(PK11_TypePrivKey, key, type, &item);
32 if (rv != SECSuccess) {
33 NOTREACHED();
34 return false;
35 }
36
[email protected]308379a52009-10-07 02:46:3137 output->assign(item.data, item.data + item.len);
[email protected]71a9f842009-09-24 01:21:1238 SECITEM_FreeItem(&item, PR_FALSE);
39 return true;
40}
41
42} // namespace
43
[email protected]4b559b4d2011-04-14 17:37:1444namespace crypto {
[email protected]71a9f842009-09-24 01:21:1245
[email protected]eae9c062011-01-11 00:50:5946RSAPrivateKey::~RSAPrivateKey() {
47 if (key_)
48 SECKEY_DestroyPrivateKey(key_);
49 if (public_key_)
50 SECKEY_DestroyPublicKey(public_key_);
[email protected]71a9f842009-09-24 01:21:1251}
52
53// static
[email protected]74648052010-08-10 19:37:5154RSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) {
55 return CreateWithParams(num_bits,
56 PR_FALSE /* not permanent */,
57 PR_FALSE /* not sensitive */);
58}
59
60// static
61RSAPrivateKey* RSAPrivateKey::CreateSensitive(uint16 num_bits) {
62 return CreateWithParams(num_bits,
63 PR_TRUE /* permanent */,
64 PR_TRUE /* sensitive */);
65}
66
67// static
[email protected]74648052010-08-10 19:37:5168RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo(
69 const std::vector<uint8>& input) {
70 return CreateFromPrivateKeyInfoWithParams(input,
71 PR_FALSE /* not permanent */,
72 PR_FALSE /* not sensitive */);
73}
74
75// static
76RSAPrivateKey* RSAPrivateKey::CreateSensitiveFromPrivateKeyInfo(
77 const std::vector<uint8>& input) {
78 return CreateFromPrivateKeyInfoWithParams(input,
79 PR_TRUE /* permanent */,
[email protected]c64b9142011-04-19 18:49:5480 PR_TRUE /* sensitive */);
[email protected]74648052010-08-10 19:37:5181}
82
83// static
84RSAPrivateKey* RSAPrivateKey::FindFromPublicKeyInfo(
85 const std::vector<uint8>& input) {
[email protected]4b559b4d2011-04-14 17:37:1486 EnsureNSSInit();
[email protected]74648052010-08-10 19:37:5187
88 scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey);
89
90 // First, decode and save the public key.
91 SECItem key_der;
92 key_der.type = siBuffer;
93 key_der.data = const_cast<unsigned char*>(&input[0]);
94 key_der.len = input.size();
95
[email protected]cfa46c02011-05-25 18:19:0896 CERTSubjectPublicKeyInfo* spki =
[email protected]74648052010-08-10 19:37:5197 SECKEY_DecodeDERSubjectPublicKeyInfo(&key_der);
98 if (!spki) {
99 NOTREACHED();
100 return NULL;
101 }
102
103 result->public_key_ = SECKEY_ExtractPublicKey(spki);
104 SECKEY_DestroySubjectPublicKeyInfo(spki);
105 if (!result->public_key_) {
106 NOTREACHED();
107 return NULL;
108 }
109
[email protected]74648052010-08-10 19:37:51110 // Make sure the key is an RSA key. If not, that's an error
111 if (result->public_key_->keyType != rsaKey) {
[email protected]74648052010-08-10 19:37:51112 NOTREACHED();
113 return NULL;
114 }
115
[email protected]cfa46c02011-05-25 18:19:08116 ScopedSECItem ck_id(
117 PK11_MakeIDFromPubKey(&(result->public_key_->u.rsa.modulus)));
118 if (!ck_id.get()) {
119 NOTREACHED();
120 return NULL;
121 }
122
[email protected]dd24ffc2011-06-08 19:46:42123 // Search all slots in all modules for the key with the given ID.
124 AutoSECMODListReadLock auto_lock;
125 SECMODModuleList* head = SECMOD_GetDefaultModuleList();
126 for (SECMODModuleList* item = head; item != NULL; item = item->next) {
127 int slot_count = item->module->loaded ? item->module->slotCount : 0;
128 for (int i = 0; i < slot_count; i++) {
129 // Finally...Look for the key!
130 result->key_ = PK11_FindKeyByKeyID(item->module->slots[i],
131 ck_id.get(), NULL);
132 if (result->key_)
133 return result.release();
[email protected]cfa46c02011-05-25 18:19:08134 }
[email protected]cfa46c02011-05-25 18:19:08135 }
[email protected]74648052010-08-10 19:37:51136
[email protected]dd24ffc2011-06-08 19:46:42137 // We didn't find the key.
138 return NULL;
[email protected]74648052010-08-10 19:37:51139}
140
[email protected]71a9f842009-09-24 01:21:12141
142bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8>* output) {
[email protected]308379a52009-10-07 02:46:31143 PrivateKeyInfoCodec private_key_info(true);
[email protected]71a9f842009-09-24 01:21:12144
[email protected]308379a52009-10-07 02:46:31145 // Manually read the component attributes of the private key and build up
146 // the PrivateKeyInfo.
147 if (!ReadAttribute(key_, CKA_MODULUS, private_key_info.modulus()) ||
148 !ReadAttribute(key_, CKA_PUBLIC_EXPONENT,
149 private_key_info.public_exponent()) ||
150 !ReadAttribute(key_, CKA_PRIVATE_EXPONENT,
151 private_key_info.private_exponent()) ||
152 !ReadAttribute(key_, CKA_PRIME_1, private_key_info.prime1()) ||
153 !ReadAttribute(key_, CKA_PRIME_2, private_key_info.prime2()) ||
154 !ReadAttribute(key_, CKA_EXPONENT_1, private_key_info.exponent1()) ||
155 !ReadAttribute(key_, CKA_EXPONENT_2, private_key_info.exponent2()) ||
156 !ReadAttribute(key_, CKA_COEFFICIENT, private_key_info.coefficient())) {
[email protected]71a9f842009-09-24 01:21:12157 NOTREACHED();
158 return false;
159 }
[email protected]71a9f842009-09-24 01:21:12160
[email protected]308379a52009-10-07 02:46:31161 return private_key_info.Export(output);
[email protected]71a9f842009-09-24 01:21:12162}
163
164bool RSAPrivateKey::ExportPublicKey(std::vector<uint8>* output) {
[email protected]cfa46c02011-05-25 18:19:08165 ScopedSECItem der_pubkey(SECKEY_EncodeDERSubjectPublicKeyInfo(public_key_));
166 if (!der_pubkey.get()) {
[email protected]71a9f842009-09-24 01:21:12167 NOTREACHED();
168 return false;
169 }
170
171 for (size_t i = 0; i < der_pubkey->len; ++i)
172 output->push_back(der_pubkey->data[i]);
173
[email protected]71a9f842009-09-24 01:21:12174 return true;
175}
176
[email protected]eae9c062011-01-11 00:50:59177RSAPrivateKey::RSAPrivateKey() : key_(NULL), public_key_(NULL) {
178 EnsureNSSInit();
179}
180
181// static
182RSAPrivateKey* RSAPrivateKey::CreateWithParams(uint16 num_bits,
183 bool permanent,
184 bool sensitive) {
[email protected]4b559b4d2011-04-14 17:37:14185 EnsureNSSInit();
[email protected]eae9c062011-01-11 00:50:59186
187 scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey);
188
[email protected]cfa46c02011-05-25 18:19:08189 ScopedPK11Slot slot(GetPrivateNSSKeySlot());
190 if (!slot.get())
[email protected]eae9c062011-01-11 00:50:59191 return NULL;
192
193 PK11RSAGenParams param;
194 param.keySizeInBits = num_bits;
195 param.pe = 65537L;
[email protected]cfa46c02011-05-25 18:19:08196 result->key_ = PK11_GenerateKeyPair(slot.get(),
197 CKM_RSA_PKCS_KEY_PAIR_GEN,
198 &param,
199 &result->public_key_,
200 permanent,
201 sensitive,
202 NULL);
[email protected]eae9c062011-01-11 00:50:59203 if (!result->key_)
204 return NULL;
205
206 return result.release();
207}
208
209// static
210RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfoWithParams(
211 const std::vector<uint8>& input, bool permanent, bool sensitive) {
212 // This method currently leaks some memory.
213 // See http://crbug.com/34742.
214 ANNOTATE_SCOPED_MEMORY_LEAK;
[email protected]4b559b4d2011-04-14 17:37:14215 EnsureNSSInit();
[email protected]eae9c062011-01-11 00:50:59216
217 scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey);
218
[email protected]cfa46c02011-05-25 18:19:08219 ScopedPK11Slot slot(GetPrivateNSSKeySlot());
220 if (!slot.get())
[email protected]eae9c062011-01-11 00:50:59221 return NULL;
222
223 SECItem der_private_key_info;
224 der_private_key_info.data = const_cast<unsigned char*>(&input.front());
225 der_private_key_info.len = input.size();
[email protected]302b6272011-01-19 01:27:22226 // Allow the private key to be used for key unwrapping, data decryption,
227 // and signature generation.
228 const unsigned int key_usage = KU_KEY_ENCIPHERMENT | KU_DATA_ENCIPHERMENT |
229 KU_DIGITAL_SIGNATURE;
230 SECStatus rv = PK11_ImportDERPrivateKeyInfoAndReturnKey(
[email protected]cfa46c02011-05-25 18:19:08231 slot.get(), &der_private_key_info, NULL, NULL, permanent, sensitive,
[email protected]302b6272011-01-19 01:27:22232 key_usage, &result->key_, NULL);
[email protected]eae9c062011-01-11 00:50:59233 if (rv != SECSuccess) {
234 NOTREACHED();
235 return NULL;
236 }
237
238 result->public_key_ = SECKEY_ConvertToPublicKey(result->key_);
239 if (!result->public_key_) {
240 NOTREACHED();
241 return NULL;
242 }
243
244 return result.release();
245}
246
[email protected]4b559b4d2011-04-14 17:37:14247} // namespace crypto