Botan  2.9.0
Crypto and TLS for C++11
openssl_ec.cpp
Go to the documentation of this file.
1 /*
2 * ECDSA and ECDH via OpenSSL
3 * (C) 2015,2016 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/internal/openssl.h>
9 
10 #if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
11  #include <botan/der_enc.h>
12  #include <botan/pkcs8.h>
13  #include <botan/oids.h>
14  #include <botan/internal/pk_ops_impl.h>
15 #endif
16 
17 #if defined(BOTAN_HAS_ECDSA)
18  #include <botan/ecdsa.h>
19 #endif
20 
21 #if defined(BOTAN_HAS_ECDH)
22  #include <botan/ecdh.h>
23 #endif
24 
25 #include <openssl/x509.h>
26 #include <openssl/objects.h>
27 
28 #if !defined(OPENSSL_NO_EC)
29  #include <openssl/ec.h>
30 #endif
31 
32 #if !defined(OPENSSL_NO_ECDSA)
33  #include <openssl/ecdsa.h>
34 #endif
35 
36 #if !defined(OPENSSL_NO_ECDH)
37  #include <openssl/ecdh.h>
38 #endif
39 
40 namespace Botan {
41 
42 #if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
43 
44 namespace {
45 
46 secure_vector<uint8_t> PKCS8_for_openssl(const EC_PrivateKey& ec)
47  {
48  const PointGFp& pub_key = ec.public_point();
49  const BigInt& priv_key = ec.private_value();
50 
51  return DER_Encoder()
52  .start_cons(SEQUENCE)
53  .encode(static_cast<size_t>(1))
54  .encode(BigInt::encode_1363(priv_key, priv_key.bytes()), OCTET_STRING)
55  .start_cons(ASN1_Tag(0), PRIVATE)
56  .raw_bytes(ec.domain().DER_encode(EC_DOMPAR_ENC_OID))
57  .end_cons()
58  .start_cons(ASN1_Tag(1), PRIVATE)
59  .encode(pub_key.encode(PointGFp::UNCOMPRESSED), BIT_STRING)
60  .end_cons()
61  .end_cons()
62  .get_contents();
63  }
64 
65 int OpenSSL_EC_curve_builtin(int nid)
66  {
67  // the NID macro is still defined even though the curve may not be
68  // supported, so we need to check the list of builtin curves at runtime
69  EC_builtin_curve builtin_curves[100];
70  size_t num = 0;
71 
72  if (!(num = EC_get_builtin_curves(builtin_curves, sizeof(builtin_curves))))
73  {
74  return -1;
75  }
76 
77  for(size_t i = 0; i < num; ++i)
78  {
79  if(builtin_curves[i].nid == nid)
80  {
81  return nid;
82  }
83  }
84 
85  return -1;
86  }
87 
88 int OpenSSL_EC_nid_for(const OID& oid)
89  {
90  if(oid.empty())
91  return -1;
92 
93  const std::string name = OIDS::lookup(oid);
94 
95  if(name == "secp192r1")
96  return OpenSSL_EC_curve_builtin(NID_X9_62_prime192v1);
97  if(name == "secp224r1")
98  return OpenSSL_EC_curve_builtin(NID_secp224r1);
99  if(name == "secp256r1")
100  return OpenSSL_EC_curve_builtin(NID_X9_62_prime256v1);
101  if(name == "secp384r1")
102  return OpenSSL_EC_curve_builtin(NID_secp384r1);
103  if(name == "secp521r1")
104  return OpenSSL_EC_curve_builtin(NID_secp521r1);
105 
106  // OpenSSL 1.0.2 added brainpool curves
107 #if OPENSSL_VERSION_NUMBER >= 0x1000200fL
108  if(name == "brainpool160r1")
109  return OpenSSL_EC_curve_builtin(NID_brainpoolP160r1);
110  if(name == "brainpool192r1")
111  return OpenSSL_EC_curve_builtin(NID_brainpoolP192r1);
112  if(name == "brainpool224r1")
113  return OpenSSL_EC_curve_builtin(NID_brainpoolP224r1);
114  if(name == "brainpool256r1")
115  return OpenSSL_EC_curve_builtin(NID_brainpoolP256r1);
116  if(name == "brainpool320r1")
117  return OpenSSL_EC_curve_builtin(NID_brainpoolP320r1);
118  if(name == "brainpool384r1")
119  return OpenSSL_EC_curve_builtin(NID_brainpoolP384r1);
120  if(name == "brainpool512r1")
121  return OpenSSL_EC_curve_builtin(NID_brainpoolP512r1);
122 #endif
123 
124  return -1;
125  }
126 
127 }
128 
129 #endif
130 
131 #if defined(BOTAN_HAS_ECDSA) && !defined(OPENSSL_NO_ECDSA)
132 
133 namespace {
134 
135 class OpenSSL_ECDSA_Verification_Operation final : public PK_Ops::Verification_with_EMSA
136  {
137  public:
138  OpenSSL_ECDSA_Verification_Operation(const ECDSA_PublicKey& ecdsa, const std::string& emsa, int nid) :
139  PK_Ops::Verification_with_EMSA(emsa), m_ossl_ec(::EC_KEY_new(), ::EC_KEY_free)
140  {
141  std::unique_ptr<::EC_GROUP, std::function<void (::EC_GROUP*)>> grp(::EC_GROUP_new_by_curve_name(nid),
142  ::EC_GROUP_free);
143 
144  if(!grp)
145  throw OpenSSL_Error("EC_GROUP_new_by_curve_name", ERR_get_error());
146 
147  if(!::EC_KEY_set_group(m_ossl_ec.get(), grp.get()))
148  throw OpenSSL_Error("EC_KEY_set_group", ERR_get_error());
149 
150  const std::vector<uint8_t> enc = ecdsa.public_point().encode(PointGFp::UNCOMPRESSED);
151  const uint8_t* enc_ptr = enc.data();
152  EC_KEY* key_ptr = m_ossl_ec.get();
153  if(!::o2i_ECPublicKey(&key_ptr, &enc_ptr, enc.size()))
154  throw OpenSSL_Error("o2i_ECPublicKey", ERR_get_error());
155 
156  const EC_GROUP* group = ::EC_KEY_get0_group(m_ossl_ec.get());
157  m_order_bits = ::EC_GROUP_get_degree(group);
158  }
159 
160  size_t max_input_bits() const override { return m_order_bits; }
161 
162  bool with_recovery() const override { return false; }
163 
164  bool verify(const uint8_t msg[], size_t msg_len,
165  const uint8_t sig_bytes[], size_t sig_len) override
166  {
167  const size_t order_bytes = (m_order_bits + 7) / 8;
168  if(sig_len != 2 * order_bytes)
169  return false;
170 
171  std::unique_ptr<ECDSA_SIG, std::function<void (ECDSA_SIG*)>> sig(nullptr, ECDSA_SIG_free);
172  sig.reset(::ECDSA_SIG_new());
173 
174 #if OPENSSL_VERSION_NUMBER < 0x10100000L
175  sig->r = BN_bin2bn(sig_bytes , sig_len / 2, sig->r);
176  sig->s = BN_bin2bn(sig_bytes + sig_len / 2, sig_len / 2, sig->s);
177 #else
178  BIGNUM* r = BN_bin2bn(sig_bytes , sig_len / 2, nullptr);
179  BIGNUM* s = BN_bin2bn(sig_bytes + sig_len / 2, sig_len / 2, nullptr);
180  if(r == nullptr || s == nullptr)
181  throw OpenSSL_Error("BN_bin2bn sig s", ERR_get_error());
182 
183  ECDSA_SIG_set0(sig.get(), r, s);
184 #endif
185 
186  const int res = ECDSA_do_verify(msg, msg_len, sig.get(), m_ossl_ec.get());
187  if(res < 0)
188  {
189  int err = ERR_get_error();
190 
191  bool hard_error = true;
192 
193 #if defined(EC_R_BAD_SIGNATURE)
194  if(ERR_GET_REASON(err) == EC_R_BAD_SIGNATURE)
195  hard_error = false;
196 #endif
197 #if defined(EC_R_POINT_AT_INFINITY)
198  if(ERR_GET_REASON(err) == EC_R_POINT_AT_INFINITY)
199  hard_error = false;
200 #endif
201 #if defined(ECDSA_R_BAD_SIGNATURE)
202  if(ERR_GET_REASON(err) == ECDSA_R_BAD_SIGNATURE)
203  hard_error = false;
204 #endif
205 
206  if(hard_error)
207  throw OpenSSL_Error("ECDSA_do_verify", err);
208  }
209  return (res == 1);
210  }
211 
212  private:
213  std::unique_ptr<EC_KEY, std::function<void (EC_KEY*)>> m_ossl_ec;
214  size_t m_order_bits = 0;
215  };
216 
217 class OpenSSL_ECDSA_Signing_Operation final : public PK_Ops::Signature_with_EMSA
218  {
219  public:
220  OpenSSL_ECDSA_Signing_Operation(const ECDSA_PrivateKey& ecdsa, const std::string& emsa) :
221  PK_Ops::Signature_with_EMSA(emsa),
222  m_ossl_ec(nullptr, ::EC_KEY_free)
223  {
224  const secure_vector<uint8_t> der = PKCS8_for_openssl(ecdsa);
225  const uint8_t* der_ptr = der.data();
226  m_ossl_ec.reset(d2i_ECPrivateKey(nullptr, &der_ptr, der.size()));
227  if(!m_ossl_ec)
228  throw OpenSSL_Error("d2i_ECPrivateKey", ERR_get_error());
229 
230  const EC_GROUP* group = ::EC_KEY_get0_group(m_ossl_ec.get());
231  m_order_bits = ::EC_GROUP_get_degree(group);
232  m_order_bytes = (m_order_bits + 7) / 8;
233  }
234 
235  size_t signature_length() const override { return 2*m_order_bytes; }
236 
237  secure_vector<uint8_t> raw_sign(const uint8_t msg[], size_t msg_len,
238  RandomNumberGenerator&) override
239  {
240  std::unique_ptr<ECDSA_SIG, std::function<void (ECDSA_SIG*)>> sig(nullptr, ECDSA_SIG_free);
241  sig.reset(::ECDSA_do_sign(msg, msg_len, m_ossl_ec.get()));
242 
243  if(!sig)
244  throw OpenSSL_Error("ECDSA_do_sign", ERR_get_error());
245 
246 #if OPENSSL_VERSION_NUMBER < 0x10100000L
247  const BIGNUM* r = sig->r;
248  const BIGNUM* s = sig->s;
249 #else
250  const BIGNUM* r;
251  const BIGNUM* s;
252  ECDSA_SIG_get0(sig.get(), &r, &s);
253 #endif
254 
255  const size_t r_bytes = BN_num_bytes(r);
256  const size_t s_bytes = BN_num_bytes(s);
257  secure_vector<uint8_t> sigval(2*m_order_bytes);
258  BN_bn2bin(r, &sigval[m_order_bytes - r_bytes]);
259  BN_bn2bin(s, &sigval[2*m_order_bytes - s_bytes]);
260  return sigval;
261  }
262 
263  size_t max_input_bits() const override { return m_order_bits; }
264 
265  private:
266  std::unique_ptr<EC_KEY, std::function<void (EC_KEY*)>> m_ossl_ec;
267  size_t m_order_bits;
268  size_t m_order_bytes;
269  };
270 
271 }
272 
273 std::unique_ptr<PK_Ops::Verification>
274 make_openssl_ecdsa_ver_op(const ECDSA_PublicKey& key, const std::string& params)
275  {
276  const int nid = OpenSSL_EC_nid_for(key.domain().get_curve_oid());
277  if(nid < 0)
278  {
279  throw Lookup_Error("OpenSSL ECDSA does not support this curve");
280  }
281 
282  try
283  {
284  return std::unique_ptr<PK_Ops::Verification>(new OpenSSL_ECDSA_Verification_Operation(key, params, nid));
285  }
286  catch(OpenSSL_Error&)
287  {
288  throw Lookup_Error("OpenSSL ECDSA does not support this key");
289  }
290  }
291 
292 std::unique_ptr<PK_Ops::Signature>
293 make_openssl_ecdsa_sig_op(const ECDSA_PrivateKey& key, const std::string& params)
294  {
295  const int nid = OpenSSL_EC_nid_for(key.domain().get_curve_oid());
296  if(nid < 0)
297  {
298  throw Lookup_Error("OpenSSL ECDSA does not support this curve");
299  }
300  return std::unique_ptr<PK_Ops::Signature>(new OpenSSL_ECDSA_Signing_Operation(key, params));
301  }
302 
303 #endif
304 
305 #if defined(BOTAN_HAS_ECDH) && !defined(OPENSSL_NO_ECDH)
306 
307 namespace {
308 
309 class OpenSSL_ECDH_KA_Operation final : public PK_Ops::Key_Agreement_with_KDF
310  {
311  public:
312 
313  OpenSSL_ECDH_KA_Operation(const ECDH_PrivateKey& ecdh, const std::string& kdf) :
314  PK_Ops::Key_Agreement_with_KDF(kdf), m_ossl_ec(::EC_KEY_new(), ::EC_KEY_free)
315  {
316  m_value_size = ecdh.domain().get_p_bytes();
317  const secure_vector<uint8_t> der = PKCS8_for_openssl(ecdh);
318  const uint8_t* der_ptr = der.data();
319  m_ossl_ec.reset(d2i_ECPrivateKey(nullptr, &der_ptr, der.size()));
320  if(!m_ossl_ec)
321  throw OpenSSL_Error("d2i_ECPrivateKey", ERR_get_error());
322  }
323 
324  size_t agreed_value_size() const override { return m_value_size; }
325 
326  secure_vector<uint8_t> raw_agree(const uint8_t w[], size_t w_len) override
327  {
328  const EC_GROUP* group = ::EC_KEY_get0_group(m_ossl_ec.get());
329  const size_t out_len = (::EC_GROUP_get_degree(group) + 7) / 8;
330  secure_vector<uint8_t> out(out_len);
331 
332  std::unique_ptr<EC_POINT, std::function<void (EC_POINT*)>> pub_key(
333  ::EC_POINT_new(group), ::EC_POINT_free);
334 
335  if(!pub_key)
336  throw OpenSSL_Error("EC_POINT_new", ERR_get_error());
337 
338  const int os2ecp_rc =
339  ::EC_POINT_oct2point(group, pub_key.get(), w, w_len, nullptr);
340 
341  if(os2ecp_rc != 1)
342  throw OpenSSL_Error("EC_POINT_oct2point", ERR_get_error());
343 
344  const int ecdh_rc = ::ECDH_compute_key(out.data(),
345  out.size(),
346  pub_key.get(),
347  m_ossl_ec.get(),
348  /*KDF*/nullptr);
349 
350  if(ecdh_rc <= 0)
351  throw OpenSSL_Error("ECDH_compute_key", ERR_get_error());
352 
353  const size_t ecdh_sz = static_cast<size_t>(ecdh_rc);
354 
355  if(ecdh_sz > out.size())
356  throw Internal_Error("OpenSSL ECDH returned more than requested");
357 
358  out.resize(ecdh_sz);
359  return out;
360  }
361 
362  private:
363  std::unique_ptr<EC_KEY, std::function<void (EC_KEY*)>> m_ossl_ec;
364  size_t m_value_size;
365  };
366 
367 }
368 
369 std::unique_ptr<PK_Ops::Key_Agreement>
370 make_openssl_ecdh_ka_op(const ECDH_PrivateKey& key, const std::string& params)
371  {
372  const int nid = OpenSSL_EC_nid_for(key.domain().get_curve_oid());
373  if(nid < 0)
374  {
375  throw Lookup_Error("OpenSSL ECDH does not support this curve");
376  }
377 
378  return std::unique_ptr<PK_Ops::Key_Agreement>(new OpenSSL_ECDH_KA_Operation(key, params));
379  }
380 
381 #endif
382 
383 }
384 
int(* final)(unsigned char *, CTX *)
ASN1_Tag
Definition: asn1_obj.h:22
std::string name
Definition: alg_id.cpp:13
static secure_vector< uint8_t > encode_1363(const BigInt &n, size_t bytes)
Definition: big_code.cpp:123
std::string lookup(const OID &oid)
Definition: oids.cpp:113