Botan  2.4.0
Crypto and TLS for C++11
pk_algs.cpp
Go to the documentation of this file.
1 /*
2 * PK Key
3 * (C) 1999-2010,2016 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/pk_algs.h>
9 #include <botan/oids.h>
10 #include <botan/parsing.h>
11 
12 #if defined(BOTAN_HAS_RSA)
13  #include <botan/rsa.h>
14 #endif
15 
16 #if defined(BOTAN_HAS_DSA)
17  #include <botan/dsa.h>
18 #endif
19 
20 #if defined(BOTAN_HAS_DL_GROUP)
21  #include <botan/dl_group.h>
22 #endif
23 
24 #if defined(BOTAN_HAS_DIFFIE_HELLMAN)
25  #include <botan/dh.h>
26 #endif
27 
28 #if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
29  #include <botan/ecc_key.h>
30 #endif
31 
32 #if defined(BOTAN_HAS_ECDSA)
33  #include <botan/ecdsa.h>
34 #endif
35 
36 #if defined(BOTAN_HAS_ECGDSA)
37  #include <botan/ecgdsa.h>
38 #endif
39 
40 #if defined(BOTAN_HAS_ECKCDSA)
41  #include <botan/eckcdsa.h>
42 #endif
43 
44 #if defined(BOTAN_HAS_ED25519)
45  #include <botan/ed25519.h>
46 #endif
47 
48 #if defined(BOTAN_HAS_GOST_34_10_2001)
49  #include <botan/gost_3410.h>
50 #endif
51 
52 #if defined(BOTAN_HAS_ELGAMAL)
53  #include <botan/elgamal.h>
54 #endif
55 
56 #if defined(BOTAN_HAS_ECDH)
57  #include <botan/ecdh.h>
58 #endif
59 
60 #if defined(BOTAN_HAS_CURVE_25519)
61  #include <botan/curve25519.h>
62 #endif
63 
64 #if defined(BOTAN_HAS_MCELIECE)
65  #include <botan/mceliece.h>
66 #endif
67 
68 #if defined(BOTAN_HAS_XMSS)
69  #include <botan/xmss.h>
70 #endif
71 
72 #if defined(BOTAN_HAS_SM2)
73  #include <botan/sm2.h>
74  #include <botan/sm2_enc.h>
75 #endif
76 
77 #if defined(BOTAN_HAS_OPENSSL)
78  #include <botan/internal/openssl.h>
79 #endif
80 
81 namespace Botan {
82 
83 std::unique_ptr<Public_Key>
85  const std::vector<uint8_t>& key_bits)
86  {
87  const std::vector<std::string> alg_info = split_on(OIDS::lookup(alg_id.get_oid()), '/');
88 
89  if(alg_info.empty())
90  throw Decoding_Error("Unknown algorithm OID: " + alg_id.get_oid().as_string());
91 
92  const std::string alg_name = alg_info[0];
93 
94 #if defined(BOTAN_HAS_RSA)
95  if(alg_name == "RSA")
96  return std::unique_ptr<Public_Key>(new RSA_PublicKey(alg_id, key_bits));
97 #endif
98 
99 #if defined(BOTAN_HAS_CURVE_25519)
100  if(alg_name == "Curve25519")
101  return std::unique_ptr<Public_Key>(new Curve25519_PublicKey(alg_id, key_bits));
102 #endif
103 
104 #if defined(BOTAN_HAS_MCELIECE)
105  if(alg_name == "McEliece")
106  return std::unique_ptr<Public_Key>(new McEliece_PublicKey(key_bits));
107 #endif
108 
109 #if defined(BOTAN_HAS_ECDSA)
110  if(alg_name == "ECDSA")
111  return std::unique_ptr<Public_Key>(new ECDSA_PublicKey(alg_id, key_bits));
112 #endif
113 
114 #if defined(BOTAN_HAS_ECDH)
115  if(alg_name == "ECDH")
116  return std::unique_ptr<Public_Key>(new ECDH_PublicKey(alg_id, key_bits));
117 #endif
118 
119 #if defined(BOTAN_HAS_DIFFIE_HELLMAN)
120  if(alg_name == "DH")
121  return std::unique_ptr<Public_Key>(new DH_PublicKey(alg_id, key_bits));
122 #endif
123 
124 #if defined(BOTAN_HAS_DSA)
125  if(alg_name == "DSA")
126  return std::unique_ptr<Public_Key>(new DSA_PublicKey(alg_id, key_bits));
127 #endif
128 
129 #if defined(BOTAN_HAS_ELGAMAL)
130  if(alg_name == "ElGamal")
131  return std::unique_ptr<Public_Key>(new ElGamal_PublicKey(alg_id, key_bits));
132 #endif
133 
134 #if defined(BOTAN_HAS_ECGDSA)
135  if(alg_name == "ECGDSA")
136  return std::unique_ptr<Public_Key>(new ECGDSA_PublicKey(alg_id, key_bits));
137 #endif
138 
139 #if defined(BOTAN_HAS_ECKCDSA)
140  if(alg_name == "ECKCDSA")
141  return std::unique_ptr<Public_Key>(new ECKCDSA_PublicKey(alg_id, key_bits));
142 #endif
143 
144 #if defined(BOTAN_HAS_ED25519)
145  if(alg_name == "Ed25519")
146  return std::unique_ptr<Public_Key>(new Ed25519_PublicKey(alg_id, key_bits));
147 #endif
148 
149 #if defined(BOTAN_HAS_GOST_34_10_2001)
150  if(alg_name == "GOST-34.10")
151  return std::unique_ptr<Public_Key>(new GOST_3410_PublicKey(alg_id, key_bits));
152 #endif
153 
154 #if defined(BOTAN_HAS_SM2)
155  if(alg_name == "SM2_Sig")
156  return std::unique_ptr<Public_Key>(new SM2_Signature_PublicKey(alg_id, key_bits));
157  if(alg_name == "SM2_Enc")
158  return std::unique_ptr<Public_Key>(new SM2_Encryption_PublicKey(alg_id, key_bits));
159 #endif
160 
161 #if defined(BOTAN_HAS_XMSS)
162  if(alg_name == "XMSS")
163  return std::unique_ptr<Public_Key>(new XMSS_PublicKey(key_bits));
164 #endif
165 
166  throw Decoding_Error("Unhandled PK algorithm " + alg_name);
167  }
168 
169 std::unique_ptr<Private_Key>
171  const secure_vector<uint8_t>& key_bits)
172  {
173  const std::string alg_name = OIDS::lookup(alg_id.get_oid());
174  if(alg_name == "")
175  throw Decoding_Error("Unknown algorithm OID: " + alg_id.get_oid().as_string());
176 
177 #if defined(BOTAN_HAS_RSA)
178  if(alg_name == "RSA")
179  return std::unique_ptr<Private_Key>(new RSA_PrivateKey(alg_id, key_bits));
180 #endif
181 
182 #if defined(BOTAN_HAS_CURVE_25519)
183  if(alg_name == "Curve25519")
184  return std::unique_ptr<Private_Key>(new Curve25519_PrivateKey(alg_id, key_bits));
185 #endif
186 
187 #if defined(BOTAN_HAS_ECDSA)
188  if(alg_name == "ECDSA")
189  return std::unique_ptr<Private_Key>(new ECDSA_PrivateKey(alg_id, key_bits));
190 #endif
191 
192 #if defined(BOTAN_HAS_ECDH)
193  if(alg_name == "ECDH")
194  return std::unique_ptr<Private_Key>(new ECDH_PrivateKey(alg_id, key_bits));
195 #endif
196 
197 #if defined(BOTAN_HAS_DIFFIE_HELLMAN)
198  if(alg_name == "DH")
199  return std::unique_ptr<Private_Key>(new DH_PrivateKey(alg_id, key_bits));
200 #endif
201 
202 #if defined(BOTAN_HAS_DSA)
203  if(alg_name == "DSA")
204  return std::unique_ptr<Private_Key>(new DSA_PrivateKey(alg_id, key_bits));
205 #endif
206 
207 #if defined(BOTAN_HAS_MCELIECE)
208  if(alg_name == "McEliece")
209  return std::unique_ptr<Private_Key>(new McEliece_PrivateKey(key_bits));
210 #endif
211 
212 #if defined(BOTAN_HAS_ECGDSA)
213  if(alg_name == "ECGDSA")
214  return std::unique_ptr<Private_Key>(new ECGDSA_PrivateKey(alg_id, key_bits));
215 #endif
216 
217 #if defined(BOTAN_HAS_ECKCDSA)
218  if(alg_name == "ECKCDSA")
219  return std::unique_ptr<Private_Key>(new ECKCDSA_PrivateKey(alg_id, key_bits));
220 #endif
221 
222 #if defined(BOTAN_HAS_ED25519)
223  if(alg_name == "Ed25519")
224  return std::unique_ptr<Private_Key>(new Ed25519_PrivateKey(alg_id, key_bits));
225 #endif
226 
227 #if defined(BOTAN_HAS_GOST_34_10_2001)
228  if(alg_name == "GOST-34.10")
229  return std::unique_ptr<Private_Key>(new GOST_3410_PrivateKey(alg_id, key_bits));
230 #endif
231 
232 #if defined(BOTAN_HAS_SM2)
233  if(alg_name == "SM2_Sig")
234  return std::unique_ptr<Private_Key>(new SM2_Signature_PrivateKey(alg_id, key_bits));
235  if(alg_name == "SM2_Enc")
236  return std::unique_ptr<Private_Key>(new SM2_Encryption_PrivateKey(alg_id, key_bits));
237 #endif
238 
239 #if defined(BOTAN_HAS_ELGAMAL)
240  if(alg_name == "ElGamal")
241  return std::unique_ptr<Private_Key>(new ElGamal_PrivateKey(alg_id, key_bits));
242 #endif
243 
244 #if defined(BOTAN_HAS_XMSS)
245  if(alg_name == "XMSS")
246  return std::unique_ptr<Private_Key>(new XMSS_PrivateKey(key_bits));
247 #endif
248 
249  throw Decoding_Error("Unhandled PK algorithm " + alg_name);
250  }
251 
252 #if defined(BOTAN_HAS_ECC_GROUP)
253 
254 namespace {
255 
256 std::string default_ec_group_for(const std::string& alg_name)
257  {
258  if(alg_name == "SM2_Enc" || alg_name == "SM2_Sig")
259  return "sm2p256v1";
260  if(alg_name == "GOST-34.10")
261  return "gost_256A";
262  if(alg_name == "ECGDSA")
263  return "brainpool256r1";
264  return "secp256r1";
265 
266  }
267 
268 }
269 
270 #endif
271 
272 std::unique_ptr<Private_Key>
273 create_private_key(const std::string& alg_name,
275  const std::string& params,
276  const std::string& provider)
277  {
278  /*
279  * Default paramaters are chosen for work factor > 2**128 where possible
280  */
281 
282 #if defined(BOTAN_HAS_CURVE_25519)
283  if(alg_name == "Curve25519")
284  return std::unique_ptr<Private_Key>(new Curve25519_PrivateKey(rng));
285 #endif
286 
287 #if defined(BOTAN_HAS_RSA)
288  if(alg_name == "RSA")
289  {
290  const size_t rsa_bits = (params.empty() ? 3072 : to_u32bit(params));
291 #if defined(BOTAN_HAS_OPENSSL)
292  if(provider.empty() || provider == "openssl")
293  {
294  std::unique_ptr<Botan::Private_Key> pk;
295  if((pk = make_openssl_rsa_private_key(rng, rsa_bits)))
296  return pk;
297 
298  if(!provider.empty())
299  return nullptr;
300  }
301 #endif
302  return std::unique_ptr<Private_Key>(new RSA_PrivateKey(rng, rsa_bits));
303  }
304 #endif
305 
306 #if defined(BOTAN_HAS_MCELIECE)
307  if(alg_name == "McEliece")
308  {
309  std::vector<std::string> mce_param =
310  Botan::split_on(params.empty() ? "2960,57" : params, ',');
311 
312  if(mce_param.size() != 2)
313  throw Invalid_Argument("create_private_key bad McEliece parameters " + params);
314 
315  size_t mce_n = Botan::to_u32bit(mce_param[0]);
316  size_t mce_t = Botan::to_u32bit(mce_param[1]);
317 
318  return std::unique_ptr<Botan::Private_Key>(new Botan::McEliece_PrivateKey(rng, mce_n, mce_t));
319  }
320 #endif
321 
322 #if defined(BOTAN_HAS_XMSS)
323  if(alg_name == "XMSS")
324  {
325  return std::unique_ptr<Private_Key>(
326  new XMSS_PrivateKey(XMSS_Parameters(params.empty() ? "XMSS_SHA2-512_W16_H10" : params).oid(), rng));
327  }
328 #endif
329 
330 #if defined(BOTAN_HAS_ED25519)
331  if(alg_name == "Ed25519")
332  {
333  return std::unique_ptr<Private_Key>(new Ed25519_PrivateKey(rng));
334  }
335 #endif
336 
337  // ECC crypto
338 #if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
339 
340  if(alg_name == "ECDSA" ||
341  alg_name == "ECDH" ||
342  alg_name == "ECKCDSA" ||
343  alg_name == "ECGDSA" ||
344  alg_name == "SM2_Sig" ||
345  alg_name == "SM2_Enc" ||
346  alg_name == "GOST-34.10")
347  {
348  const EC_Group ec_group(params.empty() ? default_ec_group_for(alg_name) : params);
349 
350 #if defined(BOTAN_HAS_ECDSA)
351  if(alg_name == "ECDSA")
352  return std::unique_ptr<Private_Key>(new ECDSA_PrivateKey(rng, ec_group));
353 #endif
354 
355 #if defined(BOTAN_HAS_ECDH)
356  if(alg_name == "ECDH")
357  return std::unique_ptr<Private_Key>(new ECDH_PrivateKey(rng, ec_group));
358 #endif
359 
360 #if defined(BOTAN_HAS_ECKCDSA)
361  if(alg_name == "ECKCDSA")
362  return std::unique_ptr<Private_Key>(new ECKCDSA_PrivateKey(rng, ec_group));
363 #endif
364 
365 #if defined(BOTAN_HAS_GOST_34_10_2001)
366  if(alg_name == "GOST-34.10")
367  return std::unique_ptr<Private_Key>(new GOST_3410_PrivateKey(rng, ec_group));
368 #endif
369 
370 #if defined(BOTAN_HAS_SM2)
371  if(alg_name == "SM2_Sig")
372  return std::unique_ptr<Private_Key>(new SM2_Signature_PrivateKey(rng, ec_group));
373  if(alg_name == "SM2_Enc")
374  return std::unique_ptr<Private_Key>(new SM2_Encryption_PrivateKey(rng, ec_group));
375 #endif
376 
377 #if defined(BOTAN_HAS_ECGDSA)
378  if(alg_name == "ECGDSA")
379  return std::unique_ptr<Private_Key>(new ECGDSA_PrivateKey(rng, ec_group));
380 #endif
381  }
382 #endif
383 
384  // DL crypto
385 #if defined(BOTAN_HAS_DL_GROUP)
386  if(alg_name == "DH" || alg_name == "DSA" || alg_name == "ElGamal")
387  {
388  std::string default_group = (alg_name == "DSA") ? "dsa/botan/2048" : "modp/ietf/2048";
389  DL_Group modp_group(params.empty() ? default_group : params);
390 
391 #if defined(BOTAN_HAS_DIFFIE_HELLMAN)
392  if(alg_name == "DH")
393  return std::unique_ptr<Private_Key>(new DH_PrivateKey(rng, modp_group));
394 #endif
395 
396 #if defined(BOTAN_HAS_DSA)
397  if(alg_name == "DSA")
398  return std::unique_ptr<Private_Key>(new DSA_PrivateKey(rng, modp_group));
399 #endif
400 
401 #if defined(BOTAN_HAS_ELGAMAL)
402  if(alg_name == "ElGamal")
403  return std::unique_ptr<Private_Key>(new ElGamal_PrivateKey(rng, modp_group));
404 #endif
405  }
406 #endif
407 
408  BOTAN_UNUSED(alg_name, rng, params, provider);
409 
410  return std::unique_ptr<Private_Key>();
411  }
412 
413 std::vector<std::string>
414 probe_provider_private_key(const std::string& alg_name,
415  const std::vector<std::string> possible)
416  {
417  std::vector<std::string> providers;
418  for(auto&& prov : possible)
419  {
420  if(prov == "base" ||
421 #if defined(BOTAN_HAS_OPENSSL)
422  (prov == "openssl" && alg_name == "RSA") ||
423 #endif
424  0)
425  {
426  providers.push_back(prov); // available
427  }
428  }
429 
430  BOTAN_UNUSED(alg_name);
431 
432  return providers;
433  }
434 }
std::unique_ptr< Private_Key > load_private_key(const AlgorithmIdentifier &alg_id, const secure_vector< uint8_t > &key_bits)
Definition: pk_algs.cpp:170
std::vector< std::string > split_on(const std::string &str, char delim)
Definition: parsing.cpp:142
std::string as_string() const
Definition: asn1_oid.cpp:50
std::unique_ptr< Private_Key > create_private_key(const std::string &alg_name, RandomNumberGenerator &rng, const std::string &params, const std::string &provider)
Definition: pk_algs.cpp:273
std::unique_ptr< Public_Key > load_public_key(const AlgorithmIdentifier &alg_id, const std::vector< uint8_t > &key_bits)
Definition: pk_algs.cpp:84
uint32_t to_u32bit(const std::string &str)
Definition: parsing.cpp:29
Definition: alg_id.cpp:13
#define BOTAN_UNUSED(...)
Definition: assert.h:106
std::vector< std::string > probe_provider_private_key(const std::string &alg_name, const std::vector< std::string > possible)
Definition: pk_algs.cpp:414
const OID & get_oid() const
Definition: alg_id.h:37
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:88
std::string lookup(const OID &oid)
Definition: oids.cpp:18