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.
5 #include "crypto/rsa_private_key.h"
13 #include "base/debug/leak_annotations.h"
14 #include "base/logging.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/string_util.h"
17 #include "crypto/nss_util.h"
18 #include "crypto/nss_util_internal.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
);
44 RSAPrivateKey::~RSAPrivateKey() {
46 SECKEY_DestroyPrivateKey(key_
);
48 SECKEY_DestroyPublicKey(public_key_
);
52 RSAPrivateKey
* RSAPrivateKey::Create(uint16 num_bits
) {
53 return CreateWithParams(num_bits
,
54 PR_FALSE
/* not permanent */,
55 PR_FALSE
/* not sensitive */);
59 RSAPrivateKey
* RSAPrivateKey::CreateSensitive(uint16 num_bits
) {
60 return CreateWithParams(num_bits
,
61 PR_TRUE
/* permanent */,
62 PR_TRUE
/* sensitive */);
66 RSAPrivateKey
* RSAPrivateKey::CreateFromPrivateKeyInfo(
67 const std::vector
<uint8
>& input
) {
68 return CreateFromPrivateKeyInfoWithParams(input
,
69 PR_FALSE
/* not permanent */,
70 PR_FALSE
/* not sensitive */);
74 RSAPrivateKey
* RSAPrivateKey::CreateSensitiveFromPrivateKeyInfo(
75 const std::vector
<uint8
>& input
) {
76 return CreateFromPrivateKeyInfoWithParams(input
,
77 PR_TRUE
/* permanent */,
78 PR_TRUE
/* sensitive */);
82 RSAPrivateKey
* RSAPrivateKey::FindFromPublicKeyInfo(
83 const std::vector
<uint8
>& input
) {
86 scoped_ptr
<RSAPrivateKey
> result(new RSAPrivateKey
);
88 // First, decode and save the public key.
90 key_der
.type
= siBuffer
;
91 key_der
.data
= const_cast<unsigned char*>(&input
[0]);
92 key_der
.len
= input
.size();
94 CERTSubjectPublicKeyInfo
*spki
=
95 SECKEY_DecodeDERSubjectPublicKeyInfo(&key_der
);
101 result
->public_key_
= SECKEY_ExtractPublicKey(spki
);
102 SECKEY_DestroySubjectPublicKeyInfo(spki
);
103 if (!result
->public_key_
) {
108 // Now, look for the associated private key in the user's
109 // hardware-backed NSS DB. If it's not there, consider that an
111 PK11SlotInfo
*slot
= GetPrivateNSSKeySlot();
117 // Make sure the key is an RSA key. If not, that's an error
118 if (result
->public_key_
->keyType
!= rsaKey
) {
124 SECItem
*ck_id
= PK11_MakeIDFromPubKey(&(result
->public_key_
->u
.rsa
.modulus
));
131 // Finally...Look for the key!
132 result
->key_
= PK11_FindKeyByKeyID(slot
, ck_id
, NULL
);
136 SECITEM_FreeItem(ck_id
, PR_TRUE
);
138 // If we didn't find it, that's ok.
142 return result
.release();
146 bool RSAPrivateKey::ExportPrivateKey(std::vector
<uint8
>* output
) {
147 PrivateKeyInfoCodec
private_key_info(true);
149 // Manually read the component attributes of the private key and build up
150 // the PrivateKeyInfo.
151 if (!ReadAttribute(key_
, CKA_MODULUS
, private_key_info
.modulus()) ||
152 !ReadAttribute(key_
, CKA_PUBLIC_EXPONENT
,
153 private_key_info
.public_exponent()) ||
154 !ReadAttribute(key_
, CKA_PRIVATE_EXPONENT
,
155 private_key_info
.private_exponent()) ||
156 !ReadAttribute(key_
, CKA_PRIME_1
, private_key_info
.prime1()) ||
157 !ReadAttribute(key_
, CKA_PRIME_2
, private_key_info
.prime2()) ||
158 !ReadAttribute(key_
, CKA_EXPONENT_1
, private_key_info
.exponent1()) ||
159 !ReadAttribute(key_
, CKA_EXPONENT_2
, private_key_info
.exponent2()) ||
160 !ReadAttribute(key_
, CKA_COEFFICIENT
, private_key_info
.coefficient())) {
165 return private_key_info
.Export(output
);
168 bool RSAPrivateKey::ExportPublicKey(std::vector
<uint8
>* output
) {
169 SECItem
* der_pubkey
= SECKEY_EncodeDERSubjectPublicKeyInfo(public_key_
);
175 for (size_t i
= 0; i
< der_pubkey
->len
; ++i
)
176 output
->push_back(der_pubkey
->data
[i
]);
178 SECITEM_FreeItem(der_pubkey
, PR_TRUE
);
182 RSAPrivateKey::RSAPrivateKey() : key_(NULL
), public_key_(NULL
) {
187 RSAPrivateKey
* RSAPrivateKey::CreateWithParams(uint16 num_bits
,
192 scoped_ptr
<RSAPrivateKey
> result(new RSAPrivateKey
);
194 PK11SlotInfo
*slot
= GetPrivateNSSKeySlot();
198 PK11RSAGenParams param
;
199 param
.keySizeInBits
= num_bits
;
201 result
->key_
= PK11_GenerateKeyPair(slot
, CKM_RSA_PKCS_KEY_PAIR_GEN
, ¶m
,
202 &result
->public_key_
, permanent
, sensitive
, NULL
);
207 return result
.release();
211 RSAPrivateKey
* RSAPrivateKey::CreateFromPrivateKeyInfoWithParams(
212 const std::vector
<uint8
>& input
, bool permanent
, bool sensitive
) {
213 // This method currently leaks some memory.
214 // See http://crbug.com/34742.
215 ANNOTATE_SCOPED_MEMORY_LEAK
;
218 scoped_ptr
<RSAPrivateKey
> result(new RSAPrivateKey
);
220 PK11SlotInfo
*slot
= GetPrivateNSSKeySlot();
224 SECItem der_private_key_info
;
225 der_private_key_info
.data
= const_cast<unsigned char*>(&input
.front());
226 der_private_key_info
.len
= input
.size();
227 // Allow the private key to be used for key unwrapping, data decryption,
228 // and signature generation.
229 const unsigned int key_usage
= KU_KEY_ENCIPHERMENT
| KU_DATA_ENCIPHERMENT
|
230 KU_DIGITAL_SIGNATURE
;
231 SECStatus rv
= PK11_ImportDERPrivateKeyInfoAndReturnKey(
232 slot
, &der_private_key_info
, NULL
, NULL
, permanent
, sensitive
,
233 key_usage
, &result
->key_
, NULL
);
235 if (rv
!= SECSuccess
) {
240 result
->public_key_
= SECKEY_ConvertToPublicKey(result
->key_
);
241 if (!result
->public_key_
) {
246 return result
.release();
249 } // namespace crypto