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.
142 bool RSAPrivateKey::ExportPrivateKey(std::vector
<uint8
>* output
) {
143 PrivateKeyInfoCodec
private_key_info(true);
145 // 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())) {
161 return private_key_info
.Export(output
);
164 bool RSAPrivateKey::ExportPublicKey(std::vector
<uint8
>* output
) {
165 ScopedSECItem
der_pubkey(SECKEY_EncodeDERSubjectPublicKeyInfo(public_key_
));
166 if (!der_pubkey
.get()) {
171 output
->assign(der_pubkey
->data
, der_pubkey
->data
+ der_pubkey
->len
);
175 RSAPrivateKey::RSAPrivateKey() : key_(NULL
), public_key_(NULL
) {
180 RSAPrivateKey
* RSAPrivateKey::CreateWithParams(uint16 num_bits
,
185 scoped_ptr
<RSAPrivateKey
> result(new RSAPrivateKey
);
187 ScopedPK11Slot
slot(GetPrivateNSSKeySlot());
191 PK11RSAGenParams param
;
192 param
.keySizeInBits
= num_bits
;
194 result
->key_
= PK11_GenerateKeyPair(slot
.get(),
195 CKM_RSA_PKCS_KEY_PAIR_GEN
,
197 &result
->public_key_
,
204 return result
.release();
208 RSAPrivateKey
* RSAPrivateKey::CreateFromPrivateKeyInfoWithParams(
209 const std::vector
<uint8
>& input
, bool permanent
, bool sensitive
) {
210 // This method currently leaks some memory.
211 // See http://crbug.com/34742.
212 ANNOTATE_SCOPED_MEMORY_LEAK
;
215 scoped_ptr
<RSAPrivateKey
> result(new RSAPrivateKey
);
217 ScopedPK11Slot
slot(GetPrivateNSSKeySlot());
221 SECItem der_private_key_info
;
222 der_private_key_info
.data
= const_cast<unsigned char*>(&input
.front());
223 der_private_key_info
.len
= input
.size();
224 // Allow the private key to be used for key unwrapping, data decryption,
225 // and signature generation.
226 const unsigned int key_usage
= KU_KEY_ENCIPHERMENT
| KU_DATA_ENCIPHERMENT
|
227 KU_DIGITAL_SIGNATURE
;
228 SECStatus rv
= PK11_ImportDERPrivateKeyInfoAndReturnKey(
229 slot
.get(), &der_private_key_info
, NULL
, NULL
, permanent
, sensitive
,
230 key_usage
, &result
->key_
, NULL
);
231 if (rv
!= SECSuccess
) {
236 result
->public_key_
= SECKEY_ConvertToPublicKey(result
->key_
);
237 if (!result
->public_key_
) {
242 return result
.release();
245 } // namespace crypto