~ubuntu-branches/debian/sid/botan/sid

« back to all changes in this revision

Viewing changes to src/pkcs8.cpp

  • Committer: Package Import Robot
  • Author(s): Laszlo Boszormenyi (GCS)
  • Date: 2018-03-01 22:23:25 UTC
  • mfrom: (1.2.2)
  • Revision ID: package-import@ubuntu.com-20180301222325-7p7vc45gu3hta34d
Tags: 2.4.0-2
* Don't remove .doctrees from the manual if it doesn't exist.
* Don't specify parallel to debhelper.

Show diffs side-by-side

added added

removed removed

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