monotone

monotone Mtn Source Tree

Root/botan/pkcs8.cpp

1/*************************************************
2* PKCS #8 Source File *
3* (C) 1999-2006 The Botan Project *
4*************************************************/
5
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>
15#include <memory>
16
17namespace Botan {
18
19namespace PKCS8 {
20
21namespace {
22
23/*************************************************
24* Get info from an EncryptedPrivateKeyInfo *
25*************************************************/
26SecureVector<byte> PKCS8_extract(DataSource& source,
27 AlgorithmIdentifier& alg_id)
28 {
29 SecureVector<byte> enc_pkcs8_key;
30
31 try {
32 BER_Decoder decoder(source);
33 BER_Decoder sequence = decoder.start_cons(SEQUENCE);
34 sequence.decode(alg_id);
35 sequence.decode(enc_pkcs8_key, OCTET_STRING);
36 sequence.verify_end();
37 }
38 catch(Decoding_Error)
39 {
40 throw PKCS8_Exception("Private key decoding failed");
41 }
42
43 return enc_pkcs8_key;
44 }
45
46/*************************************************
47* PEM decode and/or decrypt a private key *
48*************************************************/
49SecureVector<byte> PKCS8_decode(DataSource& source, const User_Interface& ui,
50 AlgorithmIdentifier& pk_alg_id)
51 {
52 AlgorithmIdentifier pbe_alg_id;
53 SecureVector<byte> key_data, key;
54 bool is_encrypted = true;
55
56 try {
57 if(ASN1::maybe_BER(source) && !PEM_Code::matches(source))
58 key_data = PKCS8_extract(source, pbe_alg_id);
59 else
60 {
61 std::string label;
62 key_data = PEM_Code::decode(source, label);
63 if(label == "PRIVATE KEY")
64 is_encrypted = false;
65 else if(label == "ENCRYPTED PRIVATE KEY")
66 {
67 DataSource_Memory key_source(key_data);
68 key_data = PKCS8_extract(key_source, pbe_alg_id);
69 }
70 else
71 throw PKCS8_Exception("Unknown PEM label " + label);
72 }
73
74 if(key_data.is_empty())
75 throw PKCS8_Exception("No key data found");
76 }
77 catch(Decoding_Error)
78 {
79 throw Decoding_Error("PKCS #8 private key decoding failed");
80 }
81
82 if(!is_encrypted)
83 key = key_data;
84
85 const u32bit MAX_TRIES =
86 global_config().option_as_u32bit("base/pkcs8_tries");
87
88 u32bit tries = 0;
89 while(true)
90 {
91 try {
92 if(MAX_TRIES && tries >= MAX_TRIES)
93 break;
94
95 if(is_encrypted)
96 {
97 DataSource_Memory params(pbe_alg_id.parameters);
98 PBE* pbe = get_pbe(pbe_alg_id.oid, params);
99
100 User_Interface::UI_Result result = User_Interface::OK;
101 const std::string passphrase =
102 ui.get_passphrase("PKCS #8 private key", source.id(), result);
103
104 if(result == User_Interface::CANCEL_ACTION)
105 break;
106
107 pbe->set_key(passphrase);
108 Pipe decryptor(pbe);
109 decryptor.process_msg(key_data, key_data.size());
110 key = decryptor.read_all();
111 }
112
113 u32bit version;
114
115 BER_Decoder(key)
116 .start_cons(SEQUENCE)
117 .decode(version)
118 .decode(pk_alg_id)
119 .decode(key, OCTET_STRING)
120 .discard_remaining()
121 .end_cons();
122
123 if(version != 0)
124 throw Decoding_Error("PKCS #8: Unknown version number");
125
126 break;
127 }
128 catch(Decoding_Error)
129 {
130 ++tries;
131 }
132 }
133
134 if(key.is_empty())
135 throw Decoding_Error("PKCS #8 private key decoding failed");
136 return key;
137 }
138
139}
140
141/*************************************************
142* DER or PEM encode a PKCS #8 private key *
143*************************************************/
144void encode(const Private_Key& key, Pipe& pipe, X509_Encoding encoding)
145 {
146 std::auto_ptr<PKCS8_Encoder> encoder(key.pkcs8_encoder());
147 if(!encoder.get())
148 throw Encoding_Error("PKCS8::encode: Key does not support encoding");
149
150 const u32bit PKCS8_VERSION = 0;
151
152 SecureVector<byte> contents =
153 DER_Encoder()
154 .start_cons(SEQUENCE)
155 .encode(PKCS8_VERSION)
156 .encode(encoder->alg_id())
157 .encode(encoder->key_bits(), OCTET_STRING)
158 .end_cons()
159 .get_contents();
160
161 if(encoding == PEM)
162 pipe.write(PEM_Code::encode(contents, "PRIVATE KEY"));
163 else
164 pipe.write(contents);
165 }
166
167/*************************************************
168* Encode and encrypt a PKCS #8 private key *
169*************************************************/
170void encrypt_key(const Private_Key& key, Pipe& pipe,
171 const std::string& pass, const std::string& pbe_algo,
172 X509_Encoding encoding)
173 {
174 const std::string DEFAULT_PBE = global_config().option("base/default_pbe");
175
176 Pipe raw_key;
177 raw_key.start_msg();
178 encode(key, raw_key, RAW_BER);
179 raw_key.end_msg();
180
181 PBE* pbe = get_pbe(((pbe_algo != "") ? pbe_algo : DEFAULT_PBE));
182 pbe->set_key(pass);
183
184 Pipe key_encrytor(pbe);
185 key_encrytor.process_msg(raw_key);
186
187 SecureVector<byte> enc_key =
188 DER_Encoder()
189 .start_cons(SEQUENCE)
190 .encode(AlgorithmIdentifier(pbe->get_oid(), pbe->encode_params()))
191 .encode(key_encrytor.read_all(), OCTET_STRING)
192 .end_cons()
193 .get_contents();
194
195 if(encoding == PEM)
196 pipe.write(PEM_Code::encode(enc_key, "ENCRYPTED PRIVATE KEY"));
197 else
198 pipe.write(enc_key);
199 }
200
201/*************************************************
202* PEM encode a PKCS #8 private key *
203*************************************************/
204std::string PEM_encode(const Private_Key& key)
205 {
206 Pipe pem;
207 pem.start_msg();
208 encode(key, pem, PEM);
209 pem.end_msg();
210 return pem.read_all_as_string();
211 }
212
213/*************************************************
214* Encrypt and PEM encode a PKCS #8 private key *
215*************************************************/
216std::string PEM_encode(const Private_Key& key, const std::string& pass,
217 const std::string& pbe_algo)
218 {
219 if(pass == "")
220 return PEM_encode(key);
221
222 Pipe pem;
223 pem.start_msg();
224 encrypt_key(key, pem, pass, pbe_algo, PEM);
225 pem.end_msg();
226 return pem.read_all_as_string();
227 }
228
229/*************************************************
230* Extract a private key and return it *
231*************************************************/
232Private_Key* load_key(DataSource& source, const User_Interface& ui)
233 {
234 AlgorithmIdentifier alg_id;
235 SecureVector<byte> pkcs8_key = PKCS8_decode(source, ui, alg_id);
236
237 const std::string alg_name = OIDS::lookup(alg_id.oid);
238 if(alg_name == "" || alg_name == alg_id.oid.as_string())
239 throw PKCS8_Exception("Unknown algorithm OID: " +
240 alg_id.oid.as_string());
241
242 std::auto_ptr<Private_Key> key(get_private_key(alg_name));
243
244 if(!key.get())
245 throw PKCS8_Exception("Unknown PK algorithm/OID: " + alg_name + ", " +
246 alg_id.oid.as_string());
247
248 std::auto_ptr<PKCS8_Decoder> decoder(key->pkcs8_decoder());
249 if(!decoder.get())
250 throw Decoding_Error("Key does not support PKCS #8 decoding");
251
252 decoder->alg_id(alg_id);
253 decoder->key_bits(pkcs8_key);
254
255 return key.release();
256 }
257
258/*************************************************
259* Extract a private key and return it *
260*************************************************/
261Private_Key* load_key(const std::string& fsname, const User_Interface& ui)
262 {
263 DataSource_Stream source(fsname, true);
264 return PKCS8::load_key(source, ui);
265 }
266
267/*************************************************
268* Extract a private key and return it *
269*************************************************/
270Private_Key* load_key(DataSource& source, const std::string& pass)
271 {
272 return PKCS8::load_key(source, User_Interface(pass));
273 }
274
275/*************************************************
276* Extract a private key and return it *
277*************************************************/
278Private_Key* load_key(const std::string& fsname, const std::string& pass)
279 {
280 return PKCS8::load_key(fsname, User_Interface(pass));
281 }
282
283/*************************************************
284* Make a copy of this private key *
285*************************************************/
286Private_Key* copy_key(const Private_Key& key)
287 {
288 Pipe bits;
289
290 bits.start_msg();
291 PKCS8::encode(key, bits);
292 bits.end_msg();
293
294 DataSource_Memory source(bits.read_all());
295 return PKCS8::load_key(source);
296 }
297
298}
299
300}

Archive Download this file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status