1 // Copyright (c) 2009 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 "base/crypto/rsa_private_key.h"
9 #include "base/logging.h"
10 #include "base/scoped_ptr.h"
11 #include "base/string_util.h"
14 // Helper for error handling during key import.
15 #define READ_ASSERT(truth) \
25 RSAPrivateKey
* RSAPrivateKey::Create(uint16 num_bits
) {
26 scoped_ptr
<RSAPrivateKey
> result(new RSAPrivateKey
);
27 if (!result
->InitProvider())
30 DWORD flags
= CRYPT_EXPORTABLE
;
32 // The size is encoded as the upper 16 bits of the flags. :: sigh ::.
33 flags
|= (num_bits
<< 16);
34 if (!CryptGenKey(result
->provider_
, CALG_RSA_SIGN
, flags
,
35 result
->key_
.receive()))
38 return result
.release();
42 RSAPrivateKey
* RSAPrivateKey::CreateSensitive(uint16 num_bits
) {
48 RSAPrivateKey
* RSAPrivateKey::CreateFromPrivateKeyInfo(
49 const std::vector
<uint8
>& input
) {
50 scoped_ptr
<RSAPrivateKey
> result(new RSAPrivateKey
);
51 if (!result
->InitProvider())
54 PrivateKeyInfoCodec
pki(false); // Little-Endian
57 int blob_size
= sizeof(PUBLICKEYSTRUC
) +
59 pki
.modulus()->size() +
60 pki
.prime1()->size() +
61 pki
.prime2()->size() +
62 pki
.exponent1()->size() +
63 pki
.exponent2()->size() +
64 pki
.coefficient()->size() +
65 pki
.private_exponent()->size();
66 scoped_array
<BYTE
> blob(new BYTE
[blob_size
]);
68 uint8
* dest
= blob
.get();
69 PUBLICKEYSTRUC
* public_key_struc
= reinterpret_cast<PUBLICKEYSTRUC
*>(dest
);
70 public_key_struc
->bType
= PRIVATEKEYBLOB
;
71 public_key_struc
->bVersion
= 0x02;
72 public_key_struc
->reserved
= 0;
73 public_key_struc
->aiKeyAlg
= CALG_RSA_SIGN
;
74 dest
+= sizeof(PUBLICKEYSTRUC
);
76 RSAPUBKEY
* rsa_pub_key
= reinterpret_cast<RSAPUBKEY
*>(dest
);
77 rsa_pub_key
->magic
= 0x32415352;
78 rsa_pub_key
->bitlen
= pki
.modulus()->size() * 8;
79 int public_exponent_int
= 0;
80 for (size_t i
= pki
.public_exponent()->size(); i
> 0; --i
) {
81 public_exponent_int
<<= 8;
82 public_exponent_int
|= (*pki
.public_exponent())[i
- 1];
84 rsa_pub_key
->pubexp
= public_exponent_int
;
85 dest
+= sizeof(RSAPUBKEY
);
87 memcpy(dest
, &pki
.modulus()->front(), pki
.modulus()->size());
88 dest
+= pki
.modulus()->size();
89 memcpy(dest
, &pki
.prime1()->front(), pki
.prime1()->size());
90 dest
+= pki
.prime1()->size();
91 memcpy(dest
, &pki
.prime2()->front(), pki
.prime2()->size());
92 dest
+= pki
.prime2()->size();
93 memcpy(dest
, &pki
.exponent1()->front(), pki
.exponent1()->size());
94 dest
+= pki
.exponent1()->size();
95 memcpy(dest
, &pki
.exponent2()->front(), pki
.exponent2()->size());
96 dest
+= pki
.exponent2()->size();
97 memcpy(dest
, &pki
.coefficient()->front(), pki
.coefficient()->size());
98 dest
+= pki
.coefficient()->size();
99 memcpy(dest
, &pki
.private_exponent()->front(), pki
.private_exponent()->size());
100 dest
+= pki
.private_exponent()->size();
102 READ_ASSERT(dest
== blob
.get() + blob_size
);
104 result
->provider_
, reinterpret_cast<uint8
*>(public_key_struc
),
105 blob_size
, NULL
, CRYPT_EXPORTABLE
, result
->key_
.receive())) {
109 return result
.release();
113 RSAPrivateKey
* RSAPrivateKey::CreateSensitiveFromPrivateKeyInfo(
114 const std::vector
<uint8
>& input
) {
120 RSAPrivateKey
* RSAPrivateKey::FindFromPublicKeyInfo(
121 const std::vector
<uint8
>& input
) {
126 RSAPrivateKey::RSAPrivateKey() : provider_(NULL
), key_(NULL
) {}
128 RSAPrivateKey::~RSAPrivateKey() {}
130 bool RSAPrivateKey::InitProvider() {
131 return FALSE
!= CryptAcquireContext(provider_
.receive(), NULL
, NULL
,
132 PROV_RSA_FULL
, CRYPT_VERIFYCONTEXT
);
135 bool RSAPrivateKey::ExportPrivateKey(std::vector
<uint8
>* output
) {
137 DWORD blob_length
= 0;
138 if (!CryptExportKey(key_
, NULL
, PRIVATEKEYBLOB
, 0, NULL
, &blob_length
)) {
143 scoped_array
<uint8
> blob(new uint8
[blob_length
]);
144 if (!CryptExportKey(key_
, NULL
, PRIVATEKEYBLOB
, 0, blob
.get(),
150 uint8
* pos
= blob
.get();
151 PUBLICKEYSTRUC
*publickey_struct
= reinterpret_cast<PUBLICKEYSTRUC
*>(pos
);
152 pos
+= sizeof(PUBLICKEYSTRUC
);
154 RSAPUBKEY
*rsa_pub_key
= reinterpret_cast<RSAPUBKEY
*>(pos
);
155 pos
+= sizeof(RSAPUBKEY
);
157 int mod_size
= rsa_pub_key
->bitlen
/ 8;
158 int primes_size
= rsa_pub_key
->bitlen
/ 16;
160 PrivateKeyInfoCodec
pki(false); // Little-Endian
162 pki
.modulus()->assign(pos
, pos
+ mod_size
);
165 pki
.prime1()->assign(pos
, pos
+ primes_size
);
167 pki
.prime2()->assign(pos
, pos
+ primes_size
);
170 pki
.exponent1()->assign(pos
, pos
+ primes_size
);
172 pki
.exponent2()->assign(pos
, pos
+ primes_size
);
175 pki
.coefficient()->assign(pos
, pos
+ primes_size
);
178 pki
.private_exponent()->assign(pos
, pos
+ mod_size
);
181 pki
.public_exponent()->assign(reinterpret_cast<uint8
*>(&rsa_pub_key
->pubexp
),
182 reinterpret_cast<uint8
*>(&rsa_pub_key
->pubexp
) + 4);
184 CHECK_EQ(pos
- blob_length
, reinterpret_cast<BYTE
*>(publickey_struct
));
186 return pki
.Export(output
);
189 bool RSAPrivateKey::ExportPublicKey(std::vector
<uint8
>* output
) {
191 if (!CryptExportPublicKeyInfo(
192 provider_
, AT_SIGNATURE
, X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
,
193 NULL
, &key_info_len
)) {
198 scoped_array
<uint8
> key_info(new uint8
[key_info_len
]);
199 if (!CryptExportPublicKeyInfo(
200 provider_
, AT_SIGNATURE
, X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
,
201 reinterpret_cast<CERT_PUBLIC_KEY_INFO
*>(key_info
.get()), &key_info_len
)) {
206 DWORD encoded_length
;
207 if (!CryptEncodeObject(
208 X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
, X509_PUBLIC_KEY_INFO
,
209 reinterpret_cast<CERT_PUBLIC_KEY_INFO
*>(key_info
.get()), NULL
,
215 scoped_array
<BYTE
> encoded(new BYTE
[encoded_length
]);
216 if (!CryptEncodeObject(
217 X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
, X509_PUBLIC_KEY_INFO
,
218 reinterpret_cast<CERT_PUBLIC_KEY_INFO
*>(key_info
.get()), encoded
.get(),
224 for (size_t i
= 0; i
< encoded_length
; ++i
)
225 output
->push_back(encoded
[i
]);