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
);
45 RSAPrivateKey::~RSAPrivateKey() {
47 SECKEY_DestroyPrivateKey(key_
);
49 SECKEY_DestroyPublicKey(public_key_
);
53 RSAPrivateKey
* RSAPrivateKey::Create(uint16 num_bits
) {
56 ScopedPK11Slot
slot(PK11_GetInternalSlot());
57 return CreateWithParams(slot
.get(),
59 false /* not permanent */,
60 false /* not sensitive */);
64 RSAPrivateKey
* RSAPrivateKey::CreateFromPrivateKeyInfo(
65 const std::vector
<uint8
>& input
) {
68 ScopedPK11Slot
slot(PK11_GetInternalSlot());
69 return CreateFromPrivateKeyInfoWithParams(
72 false /* not permanent */,
73 false /* not sensitive */);
78 RSAPrivateKey
* RSAPrivateKey::CreateSensitive(PK11SlotInfo
* slot
,
80 return CreateWithParams(slot
,
83 true /* sensitive */);
87 RSAPrivateKey
* RSAPrivateKey::CreateSensitiveFromPrivateKeyInfo(
89 const std::vector
<uint8
>& input
) {
90 return CreateFromPrivateKeyInfoWithParams(slot
,
93 true /* sensitive */);
97 RSAPrivateKey
* RSAPrivateKey::CreateFromKey(SECKEYPrivateKey
* key
) {
99 if (SECKEY_GetPrivateKeyType(key
) != rsaKey
)
101 RSAPrivateKey
* copy
= new RSAPrivateKey();
102 copy
->key_
= SECKEY_CopyPrivateKey(key
);
103 copy
->public_key_
= SECKEY_ConvertToPublicKey(key
);
104 if (!copy
->key_
|| !copy
->public_key_
) {
113 RSAPrivateKey
* RSAPrivateKey::FindFromPublicKeyInfo(
114 const std::vector
<uint8
>& input
) {
117 scoped_ptr
<RSAPrivateKey
> result(new RSAPrivateKey
);
119 // First, decode and save the public key.
121 key_der
.type
= siBuffer
;
122 key_der
.data
= const_cast<unsigned char*>(&input
[0]);
123 key_der
.len
= input
.size();
125 CERTSubjectPublicKeyInfo
* spki
=
126 SECKEY_DecodeDERSubjectPublicKeyInfo(&key_der
);
132 result
->public_key_
= SECKEY_ExtractPublicKey(spki
);
133 SECKEY_DestroySubjectPublicKeyInfo(spki
);
134 if (!result
->public_key_
) {
139 // Make sure the key is an RSA key. If not, that's an error
140 if (result
->public_key_
->keyType
!= rsaKey
) {
146 PK11_MakeIDFromPubKey(&(result
->public_key_
->u
.rsa
.modulus
)));
152 // Search all slots in all modules for the key with the given ID.
153 AutoSECMODListReadLock auto_lock
;
154 SECMODModuleList
* head
= SECMOD_GetDefaultModuleList();
155 for (SECMODModuleList
* item
= head
; item
!= NULL
; item
= item
->next
) {
156 int slot_count
= item
->module
->loaded
? item
->module
->slotCount
: 0;
157 for (int i
= 0; i
< slot_count
; i
++) {
158 // Finally...Look for the key!
159 result
->key_
= PK11_FindKeyByKeyID(item
->module
->slots
[i
],
162 return result
.release();
166 // We didn't find the key.
171 RSAPrivateKey
* RSAPrivateKey::Copy() const {
172 RSAPrivateKey
* copy
= new RSAPrivateKey();
173 copy
->key_
= SECKEY_CopyPrivateKey(key_
);
174 copy
->public_key_
= SECKEY_CopyPublicKey(public_key_
);
178 bool RSAPrivateKey::ExportPrivateKey(std::vector
<uint8
>* output
) const {
179 PrivateKeyInfoCodec
private_key_info(true);
181 // Manually read the component attributes of the private key and build up
182 // the PrivateKeyInfo.
183 if (!ReadAttribute(key_
, CKA_MODULUS
, private_key_info
.modulus()) ||
184 !ReadAttribute(key_
, CKA_PUBLIC_EXPONENT
,
185 private_key_info
.public_exponent()) ||
186 !ReadAttribute(key_
, CKA_PRIVATE_EXPONENT
,
187 private_key_info
.private_exponent()) ||
188 !ReadAttribute(key_
, CKA_PRIME_1
, private_key_info
.prime1()) ||
189 !ReadAttribute(key_
, CKA_PRIME_2
, private_key_info
.prime2()) ||
190 !ReadAttribute(key_
, CKA_EXPONENT_1
, private_key_info
.exponent1()) ||
191 !ReadAttribute(key_
, CKA_EXPONENT_2
, private_key_info
.exponent2()) ||
192 !ReadAttribute(key_
, CKA_COEFFICIENT
, private_key_info
.coefficient())) {
197 return private_key_info
.Export(output
);
200 bool RSAPrivateKey::ExportPublicKey(std::vector
<uint8
>* output
) const {
201 ScopedSECItem
der_pubkey(SECKEY_EncodeDERSubjectPublicKeyInfo(public_key_
));
202 if (!der_pubkey
.get()) {
207 output
->assign(der_pubkey
->data
, der_pubkey
->data
+ der_pubkey
->len
);
211 RSAPrivateKey::RSAPrivateKey() : key_(NULL
), public_key_(NULL
) {
216 RSAPrivateKey
* RSAPrivateKey::CreateWithParams(PK11SlotInfo
* slot
,
223 scoped_ptr
<RSAPrivateKey
> result(new RSAPrivateKey
);
225 PK11RSAGenParams param
;
226 param
.keySizeInBits
= num_bits
;
228 result
->key_
= PK11_GenerateKeyPair(slot
,
229 CKM_RSA_PKCS_KEY_PAIR_GEN
,
231 &result
->public_key_
,
238 return result
.release();
242 RSAPrivateKey
* RSAPrivateKey::CreateFromPrivateKeyInfoWithParams(
244 const std::vector
<uint8
>& input
,
250 scoped_ptr
<RSAPrivateKey
> result(new RSAPrivateKey
);
252 SECItem der_private_key_info
;
253 der_private_key_info
.data
= const_cast<unsigned char*>(&input
.front());
254 der_private_key_info
.len
= input
.size();
255 // Allow the private key to be used for key unwrapping, data decryption,
256 // and signature generation.
257 const unsigned int key_usage
= KU_KEY_ENCIPHERMENT
| KU_DATA_ENCIPHERMENT
|
258 KU_DIGITAL_SIGNATURE
;
259 SECStatus rv
= PK11_ImportDERPrivateKeyInfoAndReturnKey(
260 slot
, &der_private_key_info
, NULL
, NULL
, permanent
, sensitive
,
261 key_usage
, &result
->key_
, NULL
);
262 if (rv
!= SECSuccess
) {
267 result
->public_key_
= SECKEY_ConvertToPublicKey(result
->key_
);
268 if (!result
->public_key_
) {
273 return result
.release();
276 } // namespace crypto