monotone

monotone Mtn Source Tree

Root/botan/pkcs8.cpp

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

Archive Download this file

Branches

Tags

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