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"
14 #include "base/debug/leak_annotations.h"
15 #include "base/logging.h"
16 #include "base/memory/scoped_ptr.h"
17 #include "base/string_util.h"
18 #include "crypto/nss_util.h"
19 #include "crypto/nss_util_internal.h"
20 #include "crypto/scoped_nss_types.h"
22 // TODO(rafaelw): Consider refactoring common functions and definitions from
23 // rsa_private_key_win.cc or using NSS's ASN.1 encoder.
26 static bool ReadAttribute(SECKEYPrivateKey
* key
,
27 CK_ATTRIBUTE_TYPE type
,
28 std::vector
<uint8
>* output
) {
31 rv
= PK11_ReadRawAttribute(PK11_TypePrivKey
, key
, type
, &item
);
32 if (rv
!= SECSuccess
) {
37 output
->assign(item
.data
, item
.data
+ item
.len
);
38 SECITEM_FreeItem(&item
, PR_FALSE
);
46 RSAPrivateKey::~RSAPrivateKey() {
48 SECKEY_DestroyPrivateKey(key_
);
50 SECKEY_DestroyPublicKey(public_key_
);
54 RSAPrivateKey
* RSAPrivateKey::Create(uint16 num_bits
) {
55 return CreateWithParams(num_bits
,
56 PR_FALSE
/* not permanent */,
57 PR_FALSE
/* not sensitive */);
61 RSAPrivateKey
* RSAPrivateKey::CreateSensitive(uint16 num_bits
) {
62 return CreateWithParams(num_bits
,
63 PR_TRUE
/* permanent */,
64 PR_TRUE
/* sensitive */);
68 RSAPrivateKey
* RSAPrivateKey::CreateFromPrivateKeyInfo(
69 const std::vector
<uint8
>& input
) {
70 return CreateFromPrivateKeyInfoWithParams(input
,
71 PR_FALSE
/* not permanent */,
72 PR_FALSE
/* not sensitive */);
76 RSAPrivateKey
* RSAPrivateKey::CreateSensitiveFromPrivateKeyInfo(
77 const std::vector
<uint8
>& input
) {
78 return CreateFromPrivateKeyInfoWithParams(input
,
79 PR_TRUE
/* permanent */,
80 PR_TRUE
/* sensitive */);
84 RSAPrivateKey
* RSAPrivateKey::FindFromPublicKeyInfo(
85 const std::vector
<uint8
>& input
) {
88 scoped_ptr
<RSAPrivateKey
> result(new RSAPrivateKey
);
90 // First, decode and save the public key.
92 key_der
.type
= siBuffer
;
93 key_der
.data
= const_cast<unsigned char*>(&input
[0]);
94 key_der
.len
= input
.size();
96 CERTSubjectPublicKeyInfo
* spki
=
97 SECKEY_DecodeDERSubjectPublicKeyInfo(&key_der
);
103 result
->public_key_
= SECKEY_ExtractPublicKey(spki
);
104 SECKEY_DestroySubjectPublicKeyInfo(spki
);
105 if (!result
->public_key_
) {
110 // Make sure the key is an RSA key. If not, that's an error
111 if (result
->public_key_
->keyType
!= rsaKey
) {
117 PK11_MakeIDFromPubKey(&(result
->public_key_
->u
.rsa
.modulus
)));
123 // 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
],
133 return result
.release();
137 // We didn't find the key.
141 RSAPrivateKey
* RSAPrivateKey::Copy() const {
142 RSAPrivateKey
* copy
= new RSAPrivateKey();
143 copy
->key_
= SECKEY_CopyPrivateKey(key_
);
144 copy
->public_key_
= SECKEY_CopyPublicKey(public_key_
);
148 bool RSAPrivateKey::ExportPrivateKey(std::vector
<uint8
>* output
) const {
149 PrivateKeyInfoCodec
private_key_info(true);
151 // Manually read the component attributes of the private key and build up
152 // the PrivateKeyInfo.
153 if (!ReadAttribute(key_
, CKA_MODULUS
, private_key_info
.modulus()) ||
154 !ReadAttribute(key_
, CKA_PUBLIC_EXPONENT
,
155 private_key_info
.public_exponent()) ||
156 !ReadAttribute(key_
, CKA_PRIVATE_EXPONENT
,
157 private_key_info
.private_exponent()) ||
158 !ReadAttribute(key_
, CKA_PRIME_1
, private_key_info
.prime1()) ||
159 !ReadAttribute(key_
, CKA_PRIME_2
, private_key_info
.prime2()) ||
160 !ReadAttribute(key_
, CKA_EXPONENT_1
, private_key_info
.exponent1()) ||
161 !ReadAttribute(key_
, CKA_EXPONENT_2
, private_key_info
.exponent2()) ||
162 !ReadAttribute(key_
, CKA_COEFFICIENT
, private_key_info
.coefficient())) {
167 return private_key_info
.Export(output
);
170 bool RSAPrivateKey::ExportPublicKey(std::vector
<uint8
>* output
) const {
171 ScopedSECItem
der_pubkey(SECKEY_EncodeDERSubjectPublicKeyInfo(public_key_
));
172 if (!der_pubkey
.get()) {
177 output
->assign(der_pubkey
->data
, der_pubkey
->data
+ der_pubkey
->len
);
181 RSAPrivateKey::RSAPrivateKey() : key_(NULL
), public_key_(NULL
) {
186 RSAPrivateKey
* RSAPrivateKey::CreateWithParams(uint16 num_bits
,
191 scoped_ptr
<RSAPrivateKey
> result(new RSAPrivateKey
);
193 ScopedPK11Slot
slot(GetPrivateNSSKeySlot());
197 PK11RSAGenParams param
;
198 param
.keySizeInBits
= num_bits
;
200 result
->key_
= PK11_GenerateKeyPair(slot
.get(),
201 CKM_RSA_PKCS_KEY_PAIR_GEN
,
203 &result
->public_key_
,
210 return result
.release();
214 RSAPrivateKey
* RSAPrivateKey::CreateFromPrivateKeyInfoWithParams(
215 const std::vector
<uint8
>& input
, bool permanent
, bool sensitive
) {
216 // This method currently leaks some memory.
217 // See http://crbug.com/34742.
218 ANNOTATE_SCOPED_MEMORY_LEAK
;
221 scoped_ptr
<RSAPrivateKey
> result(new RSAPrivateKey
);
223 ScopedPK11Slot
slot(GetPrivateNSSKeySlot());
227 SECItem der_private_key_info
;
228 der_private_key_info
.data
= const_cast<unsigned char*>(&input
.front());
229 der_private_key_info
.len
= input
.size();
230 // Allow the private key to be used for key unwrapping, data decryption,
231 // and signature generation.
232 const unsigned int key_usage
= KU_KEY_ENCIPHERMENT
| KU_DATA_ENCIPHERMENT
|
233 KU_DIGITAL_SIGNATURE
;
234 SECStatus rv
= PK11_ImportDERPrivateKeyInfoAndReturnKey(
235 slot
.get(), &der_private_key_info
, NULL
, NULL
, permanent
, sensitive
,
236 key_usage
, &result
->key_
, NULL
);
237 if (rv
!= SECSuccess
) {
242 result
->public_key_
= SECKEY_ConvertToPublicKey(result
->key_
);
243 if (!result
->public_key_
) {
248 return result
.release();
251 } // namespace crypto