1 // Copyright (c) 2009 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.
5 #include "base/crypto/rsa_private_key.h"
13 #include "base/leak_annotations.h"
14 #include "base/logging.h"
15 #include "base/nss_util.h"
16 #include "base/nss_util_internal.h"
17 #include "base/scoped_ptr.h"
18 #include "base/string_util.h"
20 // TODO(rafaelw): Consider refactoring common functions and definitions from
21 // rsa_private_key_win.cc or using NSS's ASN.1 encoder.
24 static bool ReadAttribute(SECKEYPrivateKey
* key
,
25 CK_ATTRIBUTE_TYPE type
,
26 std::vector
<uint8
>* output
) {
29 rv
= PK11_ReadRawAttribute(PK11_TypePrivKey
, key
, type
, &item
);
30 if (rv
!= SECSuccess
) {
35 output
->assign(item
.data
, item
.data
+ item
.len
);
36 SECITEM_FreeItem(&item
, PR_FALSE
);
45 RSAPrivateKey
* RSAPrivateKey::CreateWithParams(uint16 num_bits
,
48 base::EnsureNSSInit();
50 scoped_ptr
<RSAPrivateKey
> result(new RSAPrivateKey
);
52 PK11SlotInfo
*slot
= GetDefaultNSSKeySlot();
56 PK11RSAGenParams param
;
57 param
.keySizeInBits
= num_bits
;
59 result
->key_
= PK11_GenerateKeyPair(slot
, CKM_RSA_PKCS_KEY_PAIR_GEN
, ¶m
,
60 &result
->public_key_
, permanent
, sensitive
, NULL
);
65 return result
.release();
69 RSAPrivateKey
* RSAPrivateKey::Create(uint16 num_bits
) {
70 return CreateWithParams(num_bits
,
71 PR_FALSE
/* not permanent */,
72 PR_FALSE
/* not sensitive */);
76 RSAPrivateKey
* RSAPrivateKey::CreateSensitive(uint16 num_bits
) {
77 return CreateWithParams(num_bits
,
78 PR_TRUE
/* permanent */,
79 PR_TRUE
/* sensitive */);
83 RSAPrivateKey
* RSAPrivateKey::CreateFromPrivateKeyInfoWithParams(
84 const std::vector
<uint8
>& input
, bool permanent
, bool sensitive
) {
85 // This method currently leaks some memory.
86 // See http://crbug.com/34742.
87 ANNOTATE_SCOPED_MEMORY_LEAK
;
88 base::EnsureNSSInit();
90 scoped_ptr
<RSAPrivateKey
> result(new RSAPrivateKey
);
92 PK11SlotInfo
*slot
= GetDefaultNSSKeySlot();
96 SECItem der_private_key_info
;
97 der_private_key_info
.data
= const_cast<unsigned char*>(&input
.front());
98 der_private_key_info
.len
= input
.size();
99 SECStatus rv
= PK11_ImportDERPrivateKeyInfoAndReturnKey(slot
,
100 &der_private_key_info
, NULL
, NULL
, permanent
, sensitive
,
101 KU_DIGITAL_SIGNATURE
, &result
->key_
, NULL
);
103 if (rv
!= SECSuccess
) {
108 result
->public_key_
= SECKEY_ConvertToPublicKey(result
->key_
);
109 if (!result
->public_key_
) {
114 return result
.release();
118 RSAPrivateKey
* RSAPrivateKey::CreateFromPrivateKeyInfo(
119 const std::vector
<uint8
>& input
) {
120 return CreateFromPrivateKeyInfoWithParams(input
,
121 PR_FALSE
/* not permanent */,
122 PR_FALSE
/* not sensitive */);
126 RSAPrivateKey
* RSAPrivateKey::CreateSensitiveFromPrivateKeyInfo(
127 const std::vector
<uint8
>& input
) {
128 return CreateFromPrivateKeyInfoWithParams(input
,
129 PR_TRUE
/* permanent */,
130 PR_TRUE
/* seneitive */);
134 RSAPrivateKey
* RSAPrivateKey::FindFromPublicKeyInfo(
135 const std::vector
<uint8
>& input
) {
136 base::EnsureNSSInit();
138 scoped_ptr
<RSAPrivateKey
> result(new RSAPrivateKey
);
140 // First, decode and save the public key.
142 key_der
.type
= siBuffer
;
143 key_der
.data
= const_cast<unsigned char*>(&input
[0]);
144 key_der
.len
= input
.size();
146 CERTSubjectPublicKeyInfo
*spki
=
147 SECKEY_DecodeDERSubjectPublicKeyInfo(&key_der
);
153 result
->public_key_
= SECKEY_ExtractPublicKey(spki
);
154 SECKEY_DestroySubjectPublicKeyInfo(spki
);
155 if (!result
->public_key_
) {
160 // Now, look for the associated private key in the user's NSS DB. If it's
161 // not there, consider that an error.
162 PK11SlotInfo
*slot
= GetDefaultNSSKeySlot();
168 // Make sure the key is an RSA key. If not, that's an error
169 if (result
->public_key_
->keyType
!= rsaKey
) {
175 SECItem
*ck_id
= PK11_MakeIDFromPubKey(&(result
->public_key_
->u
.rsa
.modulus
));
182 // Finally...Look for the key!
183 result
->key_
= PK11_FindKeyByKeyID(slot
, ck_id
, NULL
);
187 SECITEM_FreeItem(ck_id
, PR_TRUE
);
189 // If we didn't find it, that's ok.
193 return result
.release();
196 RSAPrivateKey::RSAPrivateKey() : key_(NULL
), public_key_(NULL
) {
200 RSAPrivateKey::~RSAPrivateKey() {
202 SECKEY_DestroyPrivateKey(key_
);
204 SECKEY_DestroyPublicKey(public_key_
);
207 bool RSAPrivateKey::ExportPrivateKey(std::vector
<uint8
>* output
) {
208 PrivateKeyInfoCodec
private_key_info(true);
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())) {
226 return private_key_info
.Export(output
);
229 bool RSAPrivateKey::ExportPublicKey(std::vector
<uint8
>* output
) {
230 SECItem
* der_pubkey
= SECKEY_EncodeDERSubjectPublicKeyInfo(public_key_
);
236 for (size_t i
= 0; i
< der_pubkey
->len
; ++i
)
237 output
->push_back(der_pubkey
->data
[i
]);
239 SECITEM_FreeItem(der_pubkey
, PR_TRUE
);