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.
4
5 #include "crypto/rsa_private_key.h"
6
7 #include <cryptohi.h>
8 #include <keyhi.h>
9 #include <pk11pub.h>
10 #include <stdint.h>
11
12 #include <list>
13
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"
20
21 // TODO(rafaelw): Consider using NSS's ASN.1 encoder.
22 namespace {
23
ReadAttribute(SECKEYPrivateKey * key,CK_ATTRIBUTE_TYPE type,std::vector<uint8_t> * output)24 static bool ReadAttribute(SECKEYPrivateKey* key,
25 CK_ATTRIBUTE_TYPE type,
26 std::vector<uint8_t>* output) {
27 SECItem item;
28 SECStatus rv;
29 rv = PK11_ReadRawAttribute(PK11_TypePrivKey, key, type, &item);
30 if (rv != SECSuccess) {
31 NOTREACHED();
32 return false;
33 }
34
35 output->assign(item.data, item.data + item.len);
36 SECITEM_FreeItem(&item, PR_FALSE);
37 return true;
38 }
39
40 } // namespace
41
42 namespace crypto {
43
~RSAPrivateKey()44 RSAPrivateKey::~RSAPrivateKey() {
45 if (key_)
46 SECKEY_DestroyPrivateKey(key_);
47 if (public_key_)
48 SECKEY_DestroyPublicKey(public_key_);
49 }
50
51 // static
Create(uint16_t num_bits)52 RSAPrivateKey* RSAPrivateKey::Create(uint16_t num_bits) {
53 EnsureNSSInit();
54
55 ScopedPK11Slot slot(PK11_GetInternalSlot());
56 if (!slot) {
57 NOTREACHED();
58 return nullptr;
59 }
60
61 ScopedSECKEYPublicKey public_key;
62 ScopedSECKEYPrivateKey private_key;
63 if (!GenerateRSAKeyPairNSS(slot.get(), num_bits, false /* not permanent */,
64 &public_key, &private_key)) {
65 return nullptr;
66 }
67
68 RSAPrivateKey* rsa_key = new RSAPrivateKey;
69 rsa_key->public_key_ = public_key.release();
70 rsa_key->key_ = private_key.release();
71 return rsa_key;
72 }
73
74 // static
CreateFromPrivateKeyInfo(const std::vector<uint8_t> & input)75 RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo(
76 const std::vector<uint8_t>& input) {
77 EnsureNSSInit();
78
79 ScopedPK11Slot slot(PK11_GetInternalSlot());
80 if (!slot) {
81 NOTREACHED();
82 return nullptr;
83 }
84 ScopedSECKEYPrivateKey key(ImportNSSKeyFromPrivateKeyInfo(
85 slot.get(), input, false /* not permanent */));
86 if (!key || SECKEY_GetPrivateKeyType(key.get()) != rsaKey)
87 return nullptr;
88 return RSAPrivateKey::CreateFromKey(key.get());
89 }
90
91 // static
CreateFromKey(SECKEYPrivateKey * key)92 RSAPrivateKey* RSAPrivateKey::CreateFromKey(SECKEYPrivateKey* key) {
93 DCHECK(key);
94 if (SECKEY_GetPrivateKeyType(key) != rsaKey)
95 return NULL;
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_) {
100 NOTREACHED();
101 delete copy;
102 return NULL;
103 }
104 return copy;
105 }
106
Copy() const107 RSAPrivateKey* RSAPrivateKey::Copy() const {
108 RSAPrivateKey* copy = new RSAPrivateKey();
109 copy->key_ = SECKEY_CopyPrivateKey(key_);
110 copy->public_key_ = SECKEY_CopyPublicKey(public_key_);
111 return copy;
112 }
113
ExportPrivateKey(std::vector<uint8_t> * output) const114 bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8_t>* output) const {
115 PrivateKeyInfoCodec private_key_info(true);
116
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())) {
129 NOTREACHED();
130 return false;
131 }
132
133 return private_key_info.Export(output);
134 }
135
ExportPublicKey(std::vector<uint8_t> * output) const136 bool RSAPrivateKey::ExportPublicKey(std::vector<uint8_t>* output) const {
137 ScopedSECItem der_pubkey(SECKEY_EncodeDERSubjectPublicKeyInfo(public_key_));
138 if (!der_pubkey.get()) {
139 NOTREACHED();
140 return false;
141 }
142
143 output->assign(der_pubkey->data, der_pubkey->data + der_pubkey->len);
144 return true;
145 }
146
RSAPrivateKey()147 RSAPrivateKey::RSAPrivateKey() : key_(NULL), public_key_(NULL) {
148 EnsureNSSInit();
149 }
150
151 } // namespace crypto
152