monotone

monotone Mtn Source Tree

Root/botan/pkcs8.cpp

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

Archive Download this file

Branches

Tags

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