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/strings/string_util.h"
17 #include "crypto/nss_key_util.h"
18 #include "crypto/nss_util.h"
19 #include "crypto/scoped_nss_types.h"
21 // TODO(rafaelw): Consider 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
) {
55 ScopedPK11Slot
slot(PK11_GetInternalSlot());
61 ScopedSECKEYPublicKey public_key
;
62 ScopedSECKEYPrivateKey private_key
;
63 if (!GenerateRSAKeyPairNSS(slot
.get(), num_bits
, false /* not permanent */,
64 &public_key
, &private_key
)) {
68 RSAPrivateKey
* rsa_key
= new RSAPrivateKey
;
69 rsa_key
->public_key_
= public_key
.release();
70 rsa_key
->key_
= private_key
.release();
75 RSAPrivateKey
* RSAPrivateKey::CreateFromPrivateKeyInfo(
76 const std::vector
<uint8
>& input
) {
79 ScopedPK11Slot
slot(PK11_GetInternalSlot());
84 ScopedSECKEYPrivateKey
key(ImportNSSKeyFromPrivateKeyInfo(
85 slot
.get(), input
, false /* not permanent */));
86 if (!key
|| SECKEY_GetPrivateKeyType(key
.get()) != rsaKey
)
88 return RSAPrivateKey::CreateFromKey(key
.get());
92 RSAPrivateKey
* RSAPrivateKey::CreateFromKey(SECKEYPrivateKey
* key
) {
94 if (SECKEY_GetPrivateKeyType(key
) != rsaKey
)
96 RSAPrivateKey
* copy
= new RSAPrivateKey();
97 copy
->key_
= SECKEY_CopyPrivateKey(key
);
98 copy
->public_key_
= SECKEY_ConvertToPublicKey(key
);
99 if (!copy
->key_
|| !copy
->public_key_
) {
107 RSAPrivateKey
* RSAPrivateKey::Copy() const {
108 RSAPrivateKey
* copy
= new RSAPrivateKey();
109 copy
->key_
= SECKEY_CopyPrivateKey(key_
);
110 copy
->public_key_
= SECKEY_CopyPublicKey(public_key_
);
114 bool RSAPrivateKey::ExportPrivateKey(std::vector
<uint8
>* output
) const {
115 PrivateKeyInfoCodec
private_key_info(true);
117 // Manually read the component attributes of the private key and build up
118 // the PrivateKeyInfo.
119 if (!ReadAttribute(key_
, CKA_MODULUS
, private_key_info
.modulus()) ||
120 !ReadAttribute(key_
, CKA_PUBLIC_EXPONENT
,
121 private_key_info
.public_exponent()) ||
122 !ReadAttribute(key_
, CKA_PRIVATE_EXPONENT
,
123 private_key_info
.private_exponent()) ||
124 !ReadAttribute(key_
, CKA_PRIME_1
, private_key_info
.prime1()) ||
125 !ReadAttribute(key_
, CKA_PRIME_2
, private_key_info
.prime2()) ||
126 !ReadAttribute(key_
, CKA_EXPONENT_1
, private_key_info
.exponent1()) ||
127 !ReadAttribute(key_
, CKA_EXPONENT_2
, private_key_info
.exponent2()) ||
128 !ReadAttribute(key_
, CKA_COEFFICIENT
, private_key_info
.coefficient())) {
133 return private_key_info
.Export(output
);
136 bool RSAPrivateKey::ExportPublicKey(std::vector
<uint8
>* output
) const {
137 ScopedSECItem
der_pubkey(SECKEY_EncodeDERSubjectPublicKeyInfo(public_key_
));
138 if (!der_pubkey
.get()) {
143 output
->assign(der_pubkey
->data
, der_pubkey
->data
+ der_pubkey
->len
);
147 RSAPrivateKey::RSAPrivateKey() : key_(NULL
), public_key_(NULL
) {
151 } // namespace crypto