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/strings/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 using NSS's ASN.1 encoder.
25 static bool ReadAttribute(SECKEYPrivateKey
* key
,
26 CK_ATTRIBUTE_TYPE type
,
27 std::vector
<uint8
>* output
) {
30 rv
= PK11_ReadRawAttribute(PK11_TypePrivKey
, key
, type
, &item
);
31 if (rv
!= SECSuccess
) {
36 output
->assign(item
.data
, item
.data
+ item
.len
);
37 SECITEM_FreeItem(&item
, PR_FALSE
);
42 struct PublicKeyInfoDeleter
{
43 inline void operator()(CERTSubjectPublicKeyInfo
* spki
) {
44 SECKEY_DestroySubjectPublicKeyInfo(spki
);
48 typedef scoped_ptr
<CERTSubjectPublicKeyInfo
, PublicKeyInfoDeleter
>
51 // The function decodes RSA public key from the |input|.
52 crypto::ScopedSECKEYPublicKey
GetRSAPublicKey(const std::vector
<uint8
>& input
) {
53 // First, decode and save the public key.
55 key_der
.type
= siBuffer
;
56 key_der
.data
= const_cast<unsigned char*>(&input
[0]);
57 key_der
.len
= input
.size();
59 ScopedPublicKeyInfo
spki(SECKEY_DecodeDERSubjectPublicKeyInfo(&key_der
));
61 return crypto::ScopedSECKEYPublicKey();
63 crypto::ScopedSECKEYPublicKey
result(SECKEY_ExtractPublicKey(spki
.get()));
65 // Make sure the key is an RSA key.. If not, that's an error.
66 if (!result
|| result
->keyType
!= rsaKey
)
67 return crypto::ScopedSECKEYPublicKey();
70 #endif // defined(USE_NSS)
76 RSAPrivateKey::~RSAPrivateKey() {
78 SECKEY_DestroyPrivateKey(key_
);
80 SECKEY_DestroyPublicKey(public_key_
);
84 RSAPrivateKey
* RSAPrivateKey::Create(uint16 num_bits
) {
87 ScopedPK11Slot
slot(PK11_GetInternalSlot());
88 return CreateWithParams(slot
.get(),
90 false /* not permanent */,
91 false /* not sensitive */);
95 RSAPrivateKey
* RSAPrivateKey::CreateFromPrivateKeyInfo(
96 const std::vector
<uint8
>& input
) {
99 ScopedPK11Slot
slot(PK11_GetInternalSlot());
100 return CreateFromPrivateKeyInfoWithParams(
103 false /* not permanent */,
104 false /* not sensitive */);
109 RSAPrivateKey
* RSAPrivateKey::CreateSensitive(PK11SlotInfo
* slot
,
111 return CreateWithParams(slot
,
113 true /* permanent */,
114 true /* sensitive */);
118 RSAPrivateKey
* RSAPrivateKey::CreateSensitiveFromPrivateKeyInfo(
120 const std::vector
<uint8
>& input
) {
121 return CreateFromPrivateKeyInfoWithParams(slot
,
123 true /* permanent */,
124 true /* sensitive */);
128 RSAPrivateKey
* RSAPrivateKey::CreateFromKey(SECKEYPrivateKey
* key
) {
130 if (SECKEY_GetPrivateKeyType(key
) != rsaKey
)
132 RSAPrivateKey
* copy
= new RSAPrivateKey();
133 copy
->key_
= SECKEY_CopyPrivateKey(key
);
134 copy
->public_key_
= SECKEY_ConvertToPublicKey(key
);
135 if (!copy
->key_
|| !copy
->public_key_
) {
144 RSAPrivateKey
* RSAPrivateKey::FindFromPublicKeyInfo(
145 const std::vector
<uint8
>& input
) {
146 scoped_ptr
<RSAPrivateKey
> result(InitPublicPart(input
));
151 PK11_MakeIDFromPubKey(&(result
->public_key_
->u
.rsa
.modulus
)));
157 // Search all slots in all modules for the key with the given ID.
158 AutoSECMODListReadLock auto_lock
;
159 SECMODModuleList
* head
= SECMOD_GetDefaultModuleList();
160 for (SECMODModuleList
* item
= head
; item
!= NULL
; item
= item
->next
) {
161 int slot_count
= item
->module
->loaded
? item
->module
->slotCount
: 0;
162 for (int i
= 0; i
< slot_count
; i
++) {
163 // Finally...Look for the key!
164 result
->key_
= PK11_FindKeyByKeyID(item
->module
->slots
[i
],
167 return result
.release();
171 // We didn't find the key.
176 RSAPrivateKey
* RSAPrivateKey::FindFromPublicKeyInfoInSlot(
177 const std::vector
<uint8
>& input
,
178 PK11SlotInfo
* slot
) {
182 scoped_ptr
<RSAPrivateKey
> result(InitPublicPart(input
));
187 PK11_MakeIDFromPubKey(&(result
->public_key_
->u
.rsa
.modulus
)));
193 result
->key_
= PK11_FindKeyByKeyID(slot
, ck_id
.get(), NULL
);
196 return result
.release();
200 RSAPrivateKey
* RSAPrivateKey::Copy() const {
201 RSAPrivateKey
* copy
= new RSAPrivateKey();
202 copy
->key_
= SECKEY_CopyPrivateKey(key_
);
203 copy
->public_key_
= SECKEY_CopyPublicKey(public_key_
);
207 bool RSAPrivateKey::ExportPrivateKey(std::vector
<uint8
>* output
) const {
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
) const {
230 ScopedSECItem
der_pubkey(SECKEY_EncodeDERSubjectPublicKeyInfo(public_key_
));
231 if (!der_pubkey
.get()) {
236 output
->assign(der_pubkey
->data
, der_pubkey
->data
+ der_pubkey
->len
);
240 RSAPrivateKey::RSAPrivateKey() : key_(NULL
), public_key_(NULL
) {
245 RSAPrivateKey
* RSAPrivateKey::CreateWithParams(PK11SlotInfo
* slot
,
252 scoped_ptr
<RSAPrivateKey
> result(new RSAPrivateKey
);
254 PK11RSAGenParams param
;
255 param
.keySizeInBits
= num_bits
;
257 result
->key_
= PK11_GenerateKeyPair(slot
,
258 CKM_RSA_PKCS_KEY_PAIR_GEN
,
260 &result
->public_key_
,
267 return result
.release();
271 RSAPrivateKey
* RSAPrivateKey::CreateFromPrivateKeyInfoWithParams(
273 const std::vector
<uint8
>& input
,
279 scoped_ptr
<RSAPrivateKey
> result(new RSAPrivateKey
);
281 SECItem der_private_key_info
;
282 der_private_key_info
.data
= const_cast<unsigned char*>(&input
.front());
283 der_private_key_info
.len
= input
.size();
284 // Allow the private key to be used for key unwrapping, data decryption,
285 // and signature generation.
286 const unsigned int key_usage
= KU_KEY_ENCIPHERMENT
| KU_DATA_ENCIPHERMENT
|
287 KU_DIGITAL_SIGNATURE
;
288 // TODO(davidben): PK11_ImportDERPrivateKeyInfoAndReturnKey calls NSS's
289 // SEC_ASN1DecodeItem which does not enforce that there is no trailing
291 SECStatus rv
= PK11_ImportDERPrivateKeyInfoAndReturnKey(
292 slot
, &der_private_key_info
, NULL
, NULL
, permanent
, sensitive
,
293 key_usage
, &result
->key_
, NULL
);
294 if (rv
!= SECSuccess
) {
299 result
->public_key_
= SECKEY_ConvertToPublicKey(result
->key_
);
300 if (!result
->public_key_
) {
305 return result
.release();
310 RSAPrivateKey
* RSAPrivateKey::InitPublicPart(const std::vector
<uint8
>& input
) {
313 scoped_ptr
<RSAPrivateKey
> result(new RSAPrivateKey());
314 result
->public_key_
= GetRSAPublicKey(input
).release();
315 if (!result
->public_key_
) {
320 return result
.release();
322 #endif // defined(USE_NSS)
324 } // namespace crypto