3
* (C) 1999-2008 Jack Lloyd
5
* Distributed under the terms of the Botan license
8
#include <botan/pkcs8.h>
9
#include <botan/get_pbe.h>
10
#include <botan/der_enc.h>
11
#include <botan/ber_dec.h>
12
#include <botan/asn1_obj.h>
13
#include <botan/pk_algs.h>
14
#include <botan/oids.h>
15
#include <botan/pem.h>
25
* Get info from an EncryptedPrivateKeyInfo
27
SecureVector<byte> PKCS8_extract(DataSource& source,
28
AlgorithmIdentifier& pbe_alg_id)
30
SecureVector<byte> key_data;
35
.decode(key_data, OCTET_STRING)
42
* PEM decode and/or decrypt a private key
44
SecureVector<byte> PKCS8_decode(DataSource& source, const User_Interface& ui,
45
AlgorithmIdentifier& pk_alg_id)
47
AlgorithmIdentifier pbe_alg_id;
48
SecureVector<byte> key_data, key;
49
bool is_encrypted = true;
52
if(ASN1::maybe_BER(source) && !PEM_Code::matches(source))
53
key_data = PKCS8_extract(source, pbe_alg_id);
57
key_data = PEM_Code::decode(source, label);
58
if(label == "PRIVATE KEY")
60
else if(label == "ENCRYPTED PRIVATE KEY")
62
DataSource_Memory key_source(key_data);
63
key_data = PKCS8_extract(key_source, pbe_alg_id);
66
throw PKCS8_Exception("Unknown PEM label " + label);
69
if(key_data.is_empty())
70
throw PKCS8_Exception("No key data found");
74
throw Decoding_Error("PKCS #8 private key decoding failed");
80
const u32bit MAX_TRIES = 3;
86
if(MAX_TRIES && tries >= MAX_TRIES)
91
DataSource_Memory params(pbe_alg_id.parameters);
92
std::auto_ptr<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);
102
Pipe decryptor(pbe.release());
104
decryptor.process_msg(key_data, key_data.size());
105
key = decryptor.read_all();
111
.start_cons(SEQUENCE)
114
.decode(key, OCTET_STRING)
119
throw Decoding_Error("PKCS #8: Unknown version number");
123
catch(Decoding_Error)
130
throw Decoding_Error("PKCS #8 private key decoding failed");
137
* DER or PEM encode a PKCS #8 private key
139
void encode(const Private_Key& key, Pipe& pipe, X509_Encoding encoding)
141
std::auto_ptr<PKCS8_Encoder> encoder(key.pkcs8_encoder());
143
throw Encoding_Error("PKCS8::encode: Key does not support encoding");
145
const u32bit PKCS8_VERSION = 0;
147
SecureVector<byte> contents =
149
.start_cons(SEQUENCE)
150
.encode(PKCS8_VERSION)
151
.encode(encoder->alg_id())
152
.encode(encoder->key_bits(), OCTET_STRING)
157
pipe.write(PEM_Code::encode(contents, "PRIVATE KEY"));
159
pipe.write(contents);
163
* Encode and encrypt a PKCS #8 private key
165
void encrypt_key(const Private_Key& key,
167
RandomNumberGenerator& rng,
168
const std::string& pass, const std::string& pbe_algo,
169
X509_Encoding encoding)
171
const std::string DEFAULT_PBE = "PBE-PKCS5v20(SHA-1,TripleDES/CBC)";
175
encode(key, raw_key, RAW_BER);
178
std::auto_ptr<PBE> pbe(get_pbe(((pbe_algo != "") ? pbe_algo : DEFAULT_PBE)));
180
pbe->new_params(rng);
183
AlgorithmIdentifier pbe_algid(pbe->get_oid(), pbe->encode_params());
185
Pipe key_encrytor(pbe.release());
186
key_encrytor.process_msg(raw_key);
188
SecureVector<byte> enc_key =
190
.start_cons(SEQUENCE)
192
.encode(key_encrytor.read_all(), OCTET_STRING)
197
pipe.write(PEM_Code::encode(enc_key, "ENCRYPTED PRIVATE KEY"));
203
* PEM encode a PKCS #8 private key
205
std::string PEM_encode(const Private_Key& key)
209
encode(key, pem, PEM);
211
return pem.read_all_as_string();
215
* Encrypt and PEM encode a PKCS #8 private key
217
std::string PEM_encode(const Private_Key& key,
218
RandomNumberGenerator& rng,
219
const std::string& pass,
220
const std::string& pbe_algo)
223
return PEM_encode(key);
227
encrypt_key(key, pem, rng, pass, pbe_algo, PEM);
229
return pem.read_all_as_string();
233
* Extract a private key and return it
235
Private_Key* load_key(DataSource& source,
236
RandomNumberGenerator& rng,
237
const User_Interface& ui)
239
AlgorithmIdentifier alg_id;
240
SecureVector<byte> pkcs8_key = PKCS8_decode(source, ui, alg_id);
242
const std::string alg_name = OIDS::lookup(alg_id.oid);
243
if(alg_name == "" || alg_name == alg_id.oid.as_string())
244
throw PKCS8_Exception("Unknown algorithm OID: " +
245
alg_id.oid.as_string());
247
std::auto_ptr<Private_Key> key(get_private_key(alg_name));
250
throw PKCS8_Exception("Unknown PK algorithm/OID: " + alg_name + ", " +
251
alg_id.oid.as_string());
253
std::auto_ptr<PKCS8_Decoder> decoder(key->pkcs8_decoder(rng));
256
throw Decoding_Error("Key does not support PKCS #8 decoding");
258
decoder->alg_id(alg_id);
259
decoder->key_bits(pkcs8_key);
261
return key.release();
265
* Extract a private key and return it
267
Private_Key* load_key(const std::string& fsname,
268
RandomNumberGenerator& rng,
269
const User_Interface& ui)
271
DataSource_Stream source(fsname, true);
272
return PKCS8::load_key(source, rng, ui);
276
* Extract a private key and return it
278
Private_Key* load_key(DataSource& source,
279
RandomNumberGenerator& rng,
280
const std::string& pass)
282
return PKCS8::load_key(source, rng, User_Interface(pass));
286
* Extract a private key and return it
288
Private_Key* load_key(const std::string& fsname,
289
RandomNumberGenerator& rng,
290
const std::string& pass)
292
return PKCS8::load_key(fsname, rng, User_Interface(pass));
296
* Make a copy of this private key
298
Private_Key* copy_key(const Private_Key& key,
299
RandomNumberGenerator& rng)
304
PKCS8::encode(key, bits);
307
DataSource_Memory source(bits.read_all());
308
return PKCS8::load_key(source, rng);