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"
9 #include "base/logging.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/string_util.h"
13 #pragma comment(lib, "crypt32.lib")
16 // Helper for error handling during key import.
17 #define READ_ASSERT(truth) \
27 RSAPrivateKey
* RSAPrivateKey::Create(uint16 num_bits
) {
28 scoped_ptr
<RSAPrivateKey
> result(new RSAPrivateKey
);
29 if (!result
->InitProvider())
32 DWORD flags
= CRYPT_EXPORTABLE
;
34 // The size is encoded as the upper 16 bits of the flags. :: sigh ::.
35 flags
|= (num_bits
<< 16);
36 if (!CryptGenKey(result
->provider_
, CALG_RSA_SIGN
, flags
,
37 result
->key_
.receive()))
40 return result
.release();
44 RSAPrivateKey
* RSAPrivateKey::CreateSensitive(uint16 num_bits
) {
50 RSAPrivateKey
* RSAPrivateKey::CreateFromPrivateKeyInfo(
51 const std::vector
<uint8
>& input
) {
52 scoped_ptr
<RSAPrivateKey
> result(new RSAPrivateKey
);
53 if (!result
->InitProvider())
56 PrivateKeyInfoCodec
pki(false); // Little-Endian
59 int blob_size
= sizeof(PUBLICKEYSTRUC
) +
61 pki
.modulus()->size() +
62 pki
.prime1()->size() +
63 pki
.prime2()->size() +
64 pki
.exponent1()->size() +
65 pki
.exponent2()->size() +
66 pki
.coefficient()->size() +
67 pki
.private_exponent()->size();
68 scoped_array
<BYTE
> blob(new BYTE
[blob_size
]);
70 uint8
* dest
= blob
.get();
71 PUBLICKEYSTRUC
* public_key_struc
= reinterpret_cast<PUBLICKEYSTRUC
*>(dest
);
72 public_key_struc
->bType
= PRIVATEKEYBLOB
;
73 public_key_struc
->bVersion
= 0x02;
74 public_key_struc
->reserved
= 0;
75 public_key_struc
->aiKeyAlg
= CALG_RSA_SIGN
;
76 dest
+= sizeof(PUBLICKEYSTRUC
);
78 RSAPUBKEY
* rsa_pub_key
= reinterpret_cast<RSAPUBKEY
*>(dest
);
79 rsa_pub_key
->magic
= 0x32415352;
80 rsa_pub_key
->bitlen
= pki
.modulus()->size() * 8;
81 int public_exponent_int
= 0;
82 for (size_t i
= pki
.public_exponent()->size(); i
> 0; --i
) {
83 public_exponent_int
<<= 8;
84 public_exponent_int
|= (*pki
.public_exponent())[i
- 1];
86 rsa_pub_key
->pubexp
= public_exponent_int
;
87 dest
+= sizeof(RSAPUBKEY
);
89 memcpy(dest
, &pki
.modulus()->front(), pki
.modulus()->size());
90 dest
+= pki
.modulus()->size();
91 memcpy(dest
, &pki
.prime1()->front(), pki
.prime1()->size());
92 dest
+= pki
.prime1()->size();
93 memcpy(dest
, &pki
.prime2()->front(), pki
.prime2()->size());
94 dest
+= pki
.prime2()->size();
95 memcpy(dest
, &pki
.exponent1()->front(), pki
.exponent1()->size());
96 dest
+= pki
.exponent1()->size();
97 memcpy(dest
, &pki
.exponent2()->front(), pki
.exponent2()->size());
98 dest
+= pki
.exponent2()->size();
99 memcpy(dest
, &pki
.coefficient()->front(), pki
.coefficient()->size());
100 dest
+= pki
.coefficient()->size();
101 memcpy(dest
, &pki
.private_exponent()->front(),
102 pki
.private_exponent()->size());
103 dest
+= pki
.private_exponent()->size();
105 READ_ASSERT(dest
== blob
.get() + blob_size
);
106 if (!CryptImportKey(result
->provider_
,
107 reinterpret_cast<uint8
*>(public_key_struc
), blob_size
, 0,
108 CRYPT_EXPORTABLE
, result
->key_
.receive()))
111 return result
.release();
115 RSAPrivateKey
* RSAPrivateKey::CreateSensitiveFromPrivateKeyInfo(
116 const std::vector
<uint8
>& input
) {
122 RSAPrivateKey
* RSAPrivateKey::FindFromPublicKeyInfo(
123 const std::vector
<uint8
>& input
) {
128 RSAPrivateKey::RSAPrivateKey() : provider_(NULL
), key_(NULL
) {}
130 RSAPrivateKey::~RSAPrivateKey() {}
132 bool RSAPrivateKey::InitProvider() {
133 return FALSE
!= CryptAcquireContext(provider_
.receive(), NULL
, NULL
,
134 PROV_RSA_FULL
, CRYPT_VERIFYCONTEXT
);
137 bool RSAPrivateKey::ExportPrivateKey(std::vector
<uint8
>* output
) {
139 DWORD blob_length
= 0;
140 if (!CryptExportKey(key_
, 0, PRIVATEKEYBLOB
, 0, NULL
, &blob_length
)) {
145 scoped_array
<uint8
> blob(new uint8
[blob_length
]);
146 if (!CryptExportKey(key_
, 0, PRIVATEKEYBLOB
, 0, blob
.get(), &blob_length
)) {
151 uint8
* pos
= blob
.get();
152 PUBLICKEYSTRUC
*publickey_struct
= reinterpret_cast<PUBLICKEYSTRUC
*>(pos
);
153 pos
+= sizeof(PUBLICKEYSTRUC
);
155 RSAPUBKEY
*rsa_pub_key
= reinterpret_cast<RSAPUBKEY
*>(pos
);
156 pos
+= sizeof(RSAPUBKEY
);
158 int mod_size
= rsa_pub_key
->bitlen
/ 8;
159 int primes_size
= rsa_pub_key
->bitlen
/ 16;
161 PrivateKeyInfoCodec
pki(false); // Little-Endian
163 pki
.modulus()->assign(pos
, pos
+ mod_size
);
166 pki
.prime1()->assign(pos
, pos
+ primes_size
);
168 pki
.prime2()->assign(pos
, pos
+ primes_size
);
171 pki
.exponent1()->assign(pos
, pos
+ primes_size
);
173 pki
.exponent2()->assign(pos
, pos
+ primes_size
);
176 pki
.coefficient()->assign(pos
, pos
+ primes_size
);
179 pki
.private_exponent()->assign(pos
, pos
+ mod_size
);
182 pki
.public_exponent()->assign(reinterpret_cast<uint8
*>(&rsa_pub_key
->pubexp
),
183 reinterpret_cast<uint8
*>(&rsa_pub_key
->pubexp
) + 4);
185 CHECK_EQ(pos
- blob_length
, reinterpret_cast<BYTE
*>(publickey_struct
));
187 return pki
.Export(output
);
190 bool RSAPrivateKey::ExportPublicKey(std::vector
<uint8
>* output
) {
192 if (!CryptExportPublicKeyInfo(
193 provider_
, AT_SIGNATURE
, X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
,
194 NULL
, &key_info_len
)) {
199 scoped_array
<uint8
> key_info(new uint8
[key_info_len
]);
200 if (!CryptExportPublicKeyInfo(
201 provider_
, AT_SIGNATURE
, X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
,
202 reinterpret_cast<CERT_PUBLIC_KEY_INFO
*>(key_info
.get()), &key_info_len
)) {
207 DWORD encoded_length
;
208 if (!CryptEncodeObject(
209 X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
, X509_PUBLIC_KEY_INFO
,
210 reinterpret_cast<CERT_PUBLIC_KEY_INFO
*>(key_info
.get()), NULL
,
216 scoped_array
<BYTE
> encoded(new BYTE
[encoded_length
]);
217 if (!CryptEncodeObject(
218 X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
, X509_PUBLIC_KEY_INFO
,
219 reinterpret_cast<CERT_PUBLIC_KEY_INFO
*>(key_info
.get()), encoded
.get(),
225 for (size_t i
= 0; i
< encoded_length
; ++i
)
226 output
->push_back(encoded
[i
]);
231 } // namespace crypto