1
/*************************************************
2
* PKCS #8 Source File *
3
* (C) 1999-2007 The Botan Project *
4
*************************************************/
6
#include <botan/pkcs8.h>
7
#include <botan/der_enc.h>
8
#include <botan/ber_dec.h>
9
#include <botan/asn1_obj.h>
10
#include <botan/pk_algs.h>
11
#include <botan/config.h>
12
#include <botan/oids.h>
13
#include <botan/pem.h>
14
#include <botan/pbe.h>
23
/*************************************************
24
* Get info from an EncryptedPrivateKeyInfo *
25
*************************************************/
26
SecureVector<byte> PKCS8_extract(DataSource& source,
27
AlgorithmIdentifier& pbe_alg_id)
29
SecureVector<byte> key_data;
34
.decode(key_data, OCTET_STRING)
40
/*************************************************
41
* PEM decode and/or decrypt a private key *
42
*************************************************/
43
SecureVector<byte> PKCS8_decode(DataSource& source, const User_Interface& ui,
44
AlgorithmIdentifier& pk_alg_id)
46
AlgorithmIdentifier pbe_alg_id;
47
SecureVector<byte> key_data, key;
48
bool is_encrypted = true;
51
if(ASN1::maybe_BER(source) && !PEM_Code::matches(source))
52
key_data = PKCS8_extract(source, pbe_alg_id);
56
key_data = PEM_Code::decode(source, label);
57
if(label == "PRIVATE KEY")
59
else if(label == "ENCRYPTED PRIVATE KEY")
61
DataSource_Memory key_source(key_data);
62
key_data = PKCS8_extract(key_source, pbe_alg_id);
65
throw PKCS8_Exception("Unknown PEM label " + label);
68
if(key_data.is_empty())
69
throw PKCS8_Exception("No key data found");
73
throw Decoding_Error("PKCS #8 private key decoding failed");
79
const u32bit MAX_TRIES =
80
global_config().option_as_u32bit("base/pkcs8_tries");
86
if(MAX_TRIES && tries >= MAX_TRIES)
91
DataSource_Memory params(pbe_alg_id.parameters);
92
PBE* pbe = get_pbe(pbe_alg_id.oid, params);
94
User_Interface::UI_Result result = User_Interface::OK;
95
const std::string passphrase =
96
ui.get_passphrase("PKCS #8 private key", source.id(), result);
98
if(result == User_Interface::CANCEL_ACTION)
101
pbe->set_key(passphrase);
103
decryptor.process_msg(key_data, key_data.size());
104
key = decryptor.read_all();
110
.start_cons(SEQUENCE)
113
.decode(key, OCTET_STRING)
118
throw Decoding_Error("PKCS #8: Unknown version number");
122
catch(Decoding_Error)
129
throw Decoding_Error("PKCS #8 private key decoding failed");
135
/*************************************************
136
* DER or PEM encode a PKCS #8 private key *
137
*************************************************/
138
void encode(const Private_Key& key, Pipe& pipe, X509_Encoding encoding)
140
std::auto_ptr<PKCS8_Encoder> encoder(key.pkcs8_encoder());
142
throw Encoding_Error("PKCS8::encode: Key does not support encoding");
144
const u32bit PKCS8_VERSION = 0;
146
SecureVector<byte> contents =
148
.start_cons(SEQUENCE)
149
.encode(PKCS8_VERSION)
150
.encode(encoder->alg_id())
151
.encode(encoder->key_bits(), OCTET_STRING)
156
pipe.write(PEM_Code::encode(contents, "PRIVATE KEY"));
158
pipe.write(contents);
161
/*************************************************
162
* Encode and encrypt a PKCS #8 private key *
163
*************************************************/
164
void encrypt_key(const Private_Key& key, Pipe& pipe,
165
const std::string& pass, const std::string& pbe_algo,
166
X509_Encoding encoding)
168
const std::string DEFAULT_PBE = global_config().option("base/default_pbe");
172
encode(key, raw_key, RAW_BER);
175
PBE* pbe = get_pbe(((pbe_algo != "") ? pbe_algo : DEFAULT_PBE));
178
Pipe key_encrytor(pbe);
179
key_encrytor.process_msg(raw_key);
181
SecureVector<byte> enc_key =
183
.start_cons(SEQUENCE)
184
.encode(AlgorithmIdentifier(pbe->get_oid(), pbe->encode_params()))
185
.encode(key_encrytor.read_all(), OCTET_STRING)
190
pipe.write(PEM_Code::encode(enc_key, "ENCRYPTED PRIVATE KEY"));
195
/*************************************************
196
* PEM encode a PKCS #8 private key *
197
*************************************************/
198
std::string PEM_encode(const Private_Key& key)
202
encode(key, pem, PEM);
204
return pem.read_all_as_string();
207
/*************************************************
208
* Encrypt and PEM encode a PKCS #8 private key *
209
*************************************************/
210
std::string PEM_encode(const Private_Key& key, const std::string& pass,
211
const std::string& pbe_algo)
214
return PEM_encode(key);
218
encrypt_key(key, pem, pass, pbe_algo, PEM);
220
return pem.read_all_as_string();
223
/*************************************************
224
* Extract a private key and return it *
225
*************************************************/
226
Private_Key* load_key(DataSource& source, const User_Interface& ui)
228
AlgorithmIdentifier alg_id;
229
SecureVector<byte> pkcs8_key = PKCS8_decode(source, ui, alg_id);
231
const std::string alg_name = OIDS::lookup(alg_id.oid);
232
if(alg_name == "" || alg_name == alg_id.oid.as_string())
233
throw PKCS8_Exception("Unknown algorithm OID: " +
234
alg_id.oid.as_string());
236
std::auto_ptr<Private_Key> key(get_private_key(alg_name));
239
throw PKCS8_Exception("Unknown PK algorithm/OID: " + alg_name + ", " +
240
alg_id.oid.as_string());
242
std::auto_ptr<PKCS8_Decoder> decoder(key->pkcs8_decoder());
244
throw Decoding_Error("Key does not support PKCS #8 decoding");
246
decoder->alg_id(alg_id);
247
decoder->key_bits(pkcs8_key);
249
return key.release();
252
/*************************************************
253
* Extract a private key and return it *
254
*************************************************/
255
Private_Key* load_key(const std::string& fsname, const User_Interface& ui)
257
DataSource_Stream source(fsname, true);
258
return PKCS8::load_key(source, ui);
261
/*************************************************
262
* Extract a private key and return it *
263
*************************************************/
264
Private_Key* load_key(DataSource& source, const std::string& pass)
266
return PKCS8::load_key(source, User_Interface(pass));
269
/*************************************************
270
* Extract a private key and return it *
271
*************************************************/
272
Private_Key* load_key(const std::string& fsname, const std::string& pass)
274
return PKCS8::load_key(fsname, User_Interface(pass));
277
/*************************************************
278
* Make a copy of this private key *
279
*************************************************/
280
Private_Key* copy_key(const Private_Key& key)
285
PKCS8::encode(key, bits);
288
DataSource_Memory source(bits.read_all());
289
return PKCS8::load_key(source);