8#include <botan/internal/openssl.h>
10#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
11 #include <botan/der_enc.h>
12 #include <botan/pkcs8.h>
13 #include <botan/internal/pk_ops_impl.h>
16#if defined(BOTAN_HAS_ECDSA)
17 #include <botan/ecdsa.h>
20#if defined(BOTAN_HAS_ECDH)
21 #include <botan/ecdh.h>
24#include <openssl/x509.h>
25#include <openssl/objects.h>
27#if !defined(OPENSSL_NO_EC)
28 #include <openssl/ec.h>
31#if !defined(OPENSSL_NO_ECDSA)
32 #include <openssl/ecdsa.h>
35#if !defined(OPENSSL_NO_ECDH)
36 #include <openssl/ecdh.h>
41#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
45secure_vector<uint8_t> PKCS8_for_openssl(
const EC_PrivateKey& ec)
47 const PointGFp& pub_key = ec.public_point();
48 const BigInt& priv_key = ec.private_value();
52 .encode(
static_cast<size_t>(1))
64int OpenSSL_EC_curve_builtin(
int nid)
68 EC_builtin_curve builtin_curves[100];
71 if (!(num = EC_get_builtin_curves(builtin_curves,
sizeof(builtin_curves))))
76 for(
size_t i = 0; i < num; ++i)
78 if(builtin_curves[i].nid == nid)
87int OpenSSL_EC_nid_for(
const OID& oid)
92 const std::string
name = oid.to_formatted_string();
94 if(
name ==
"secp192r1")
95 return OpenSSL_EC_curve_builtin(NID_X9_62_prime192v1);
96 if(
name ==
"secp224r1")
97 return OpenSSL_EC_curve_builtin(NID_secp224r1);
98 if(
name ==
"secp256r1")
99 return OpenSSL_EC_curve_builtin(NID_X9_62_prime256v1);
100 if(
name ==
"secp384r1")
101 return OpenSSL_EC_curve_builtin(NID_secp384r1);
102 if(
name ==
"secp521r1")
103 return OpenSSL_EC_curve_builtin(NID_secp521r1);
106#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
107 if(
name ==
"brainpool160r1")
108 return OpenSSL_EC_curve_builtin(NID_brainpoolP160r1);
109 if(
name ==
"brainpool192r1")
110 return OpenSSL_EC_curve_builtin(NID_brainpoolP192r1);
111 if(
name ==
"brainpool224r1")
112 return OpenSSL_EC_curve_builtin(NID_brainpoolP224r1);
113 if(
name ==
"brainpool256r1")
114 return OpenSSL_EC_curve_builtin(NID_brainpoolP256r1);
115 if(
name ==
"brainpool320r1")
116 return OpenSSL_EC_curve_builtin(NID_brainpoolP320r1);
117 if(
name ==
"brainpool384r1")
118 return OpenSSL_EC_curve_builtin(NID_brainpoolP384r1);
119 if(
name ==
"brainpool512r1")
120 return OpenSSL_EC_curve_builtin(NID_brainpoolP512r1);
130#if defined(BOTAN_HAS_ECDSA) && !defined(OPENSSL_NO_ECDSA)
134class OpenSSL_ECDSA_Verification_Operation
final :
public PK_Ops::Verification_with_EMSA
137 OpenSSL_ECDSA_Verification_Operation(
const ECDSA_PublicKey& ecdsa,
const std::string& emsa,
int nid) :
138 PK_Ops::Verification_with_EMSA(emsa), m_ossl_ec(::EC_KEY_new(), ::EC_KEY_free)
140 std::unique_ptr<::EC_GROUP, std::function<void (::EC_GROUP*)>> grp(::EC_GROUP_new_by_curve_name(nid),
144 throw OpenSSL_Error(
"EC_GROUP_new_by_curve_name", ERR_get_error());
146 if(!::EC_KEY_set_group(m_ossl_ec.get(), grp.get()))
147 throw OpenSSL_Error(
"EC_KEY_set_group", ERR_get_error());
150 const uint8_t* enc_ptr = enc.data();
151 EC_KEY* key_ptr = m_ossl_ec.get();
152 if(!::o2i_ECPublicKey(&key_ptr, &enc_ptr, enc.size()))
153 throw OpenSSL_Error(
"o2i_ECPublicKey", ERR_get_error());
155 const EC_GROUP* group = ::EC_KEY_get0_group(m_ossl_ec.get());
156 m_order_bits = ::EC_GROUP_get_degree(group);
159 size_t max_input_bits()
const override {
return m_order_bits; }
161 bool with_recovery()
const override {
return false; }
163 bool verify(
const uint8_t msg[],
size_t msg_len,
164 const uint8_t sig_bytes[],
size_t sig_len)
override
166 const size_t order_bytes = (m_order_bits + 7) / 8;
167 if(sig_len != 2 * order_bytes)
170 std::unique_ptr<ECDSA_SIG, std::function<void (ECDSA_SIG*)>> sig(
nullptr, ECDSA_SIG_free);
171 sig.reset(::ECDSA_SIG_new());
173#if OPENSSL_VERSION_NUMBER < 0x10100000L
174 sig->r = BN_bin2bn(sig_bytes , sig_len / 2, sig->r);
175 sig->s = BN_bin2bn(sig_bytes + sig_len / 2, sig_len / 2, sig->s);
177 BIGNUM* r = BN_bin2bn(sig_bytes , sig_len / 2,
nullptr);
178 BIGNUM* s = BN_bin2bn(sig_bytes + sig_len / 2, sig_len / 2,
nullptr);
179 if(r ==
nullptr || s ==
nullptr)
180 throw OpenSSL_Error(
"BN_bin2bn sig s", ERR_get_error());
182 ECDSA_SIG_set0(sig.get(), r, s);
185 const int res = ECDSA_do_verify(msg, msg_len, sig.get(), m_ossl_ec.get());
188 int err = ERR_get_error();
190 bool hard_error =
true;
192#if defined(EC_R_BAD_SIGNATURE)
193 if(ERR_GET_REASON(err) == EC_R_BAD_SIGNATURE)
196#if defined(EC_R_POINT_AT_INFINITY)
197 if(ERR_GET_REASON(err) == EC_R_POINT_AT_INFINITY)
200#if defined(ECDSA_R_BAD_SIGNATURE)
201 if(ERR_GET_REASON(err) == ECDSA_R_BAD_SIGNATURE)
206 throw OpenSSL_Error(
"ECDSA_do_verify", err);
212 std::unique_ptr<EC_KEY, std::function<void (EC_KEY*)>> m_ossl_ec;
213 size_t m_order_bits = 0;
216class OpenSSL_ECDSA_Signing_Operation
final :
public PK_Ops::Signature_with_EMSA
219 OpenSSL_ECDSA_Signing_Operation(
const ECDSA_PrivateKey& ecdsa,
const std::string& emsa) :
220 PK_Ops::Signature_with_EMSA(emsa),
221 m_ossl_ec(nullptr, ::EC_KEY_free)
223 const secure_vector<uint8_t> der = PKCS8_for_openssl(ecdsa);
224 const uint8_t* der_ptr = der.data();
225 m_ossl_ec.reset(d2i_ECPrivateKey(
nullptr, &der_ptr, der.size()));
227 throw OpenSSL_Error(
"d2i_ECPrivateKey", ERR_get_error());
229 const EC_GROUP* group = ::EC_KEY_get0_group(m_ossl_ec.get());
230 m_order_bits = ::EC_GROUP_get_degree(group);
231 m_order_bytes = (m_order_bits + 7) / 8;
234 size_t signature_length()
const override {
return 2*m_order_bytes; }
236 secure_vector<uint8_t> raw_sign(
const uint8_t msg[],
size_t msg_len,
237 RandomNumberGenerator&)
override
239 std::unique_ptr<ECDSA_SIG, std::function<void (ECDSA_SIG*)>> sig(
nullptr, ECDSA_SIG_free);
240 sig.reset(::ECDSA_do_sign(msg, msg_len, m_ossl_ec.get()));
243 throw OpenSSL_Error(
"ECDSA_do_sign", ERR_get_error());
245#if OPENSSL_VERSION_NUMBER < 0x10100000L
246 const BIGNUM* r = sig->r;
247 const BIGNUM* s = sig->s;
251 ECDSA_SIG_get0(sig.get(), &r, &s);
254 const size_t r_bytes = BN_num_bytes(r);
255 const size_t s_bytes = BN_num_bytes(s);
256 secure_vector<uint8_t> sigval(2*m_order_bytes);
257 BN_bn2bin(r, &sigval[m_order_bytes - r_bytes]);
258 BN_bn2bin(s, &sigval[2*m_order_bytes - s_bytes]);
262 size_t max_input_bits()
const override {
return m_order_bits; }
265 std::unique_ptr<EC_KEY, std::function<void (EC_KEY*)>> m_ossl_ec;
267 size_t m_order_bytes;
272std::unique_ptr<PK_Ops::Verification>
273make_openssl_ecdsa_ver_op(
const ECDSA_PublicKey& key,
const std::string& params)
275 const int nid = OpenSSL_EC_nid_for(key.domain().get_curve_oid());
278 throw Lookup_Error(
"OpenSSL ECDSA does not support this curve");
283 return std::unique_ptr<PK_Ops::Verification>(
new OpenSSL_ECDSA_Verification_Operation(key, params, nid));
285 catch(OpenSSL_Error&)
287 throw Lookup_Error(
"OpenSSL ECDSA does not support this key");
291std::unique_ptr<PK_Ops::Signature>
292make_openssl_ecdsa_sig_op(
const ECDSA_PrivateKey& key,
const std::string& params)
294 const int nid = OpenSSL_EC_nid_for(key.domain().get_curve_oid());
297 throw Lookup_Error(
"OpenSSL ECDSA does not support this curve");
299 return std::unique_ptr<PK_Ops::Signature>(
new OpenSSL_ECDSA_Signing_Operation(key, params));
304#if defined(BOTAN_HAS_ECDH) && !defined(OPENSSL_NO_ECDH)
308class OpenSSL_ECDH_KA_Operation
final :
public PK_Ops::Key_Agreement_with_KDF
312 OpenSSL_ECDH_KA_Operation(
const ECDH_PrivateKey& ecdh,
const std::string& kdf) :
313 PK_Ops::Key_Agreement_with_KDF(kdf), m_ossl_ec(::EC_KEY_new(), ::EC_KEY_free)
315 m_value_size = ecdh.domain().get_p_bytes();
316 const secure_vector<uint8_t> der = PKCS8_for_openssl(ecdh);
317 const uint8_t* der_ptr = der.data();
318 m_ossl_ec.reset(d2i_ECPrivateKey(
nullptr, &der_ptr, der.size()));
320 throw OpenSSL_Error(
"d2i_ECPrivateKey", ERR_get_error());
323 size_t agreed_value_size()
const override {
return m_value_size; }
325 secure_vector<uint8_t> raw_agree(
const uint8_t w[],
size_t w_len)
override
327 const EC_GROUP* group = ::EC_KEY_get0_group(m_ossl_ec.get());
328 const size_t out_len = (::EC_GROUP_get_degree(group) + 7) / 8;
329 secure_vector<uint8_t> out(out_len);
331 std::unique_ptr<EC_POINT, std::function<void (EC_POINT*)>> pub_key(
332 ::EC_POINT_new(group), ::EC_POINT_free);
335 throw OpenSSL_Error(
"EC_POINT_new", ERR_get_error());
337 const int os2ecp_rc =
338 ::EC_POINT_oct2point(group, pub_key.get(), w, w_len,
nullptr);
341 throw OpenSSL_Error(
"EC_POINT_oct2point", ERR_get_error());
343 const int ecdh_rc = ::ECDH_compute_key(out.data(),
350 throw OpenSSL_Error(
"ECDH_compute_key", ERR_get_error());
352 const size_t ecdh_sz =
static_cast<size_t>(ecdh_rc);
354 if(ecdh_sz > out.size())
355 throw Internal_Error(
"OpenSSL ECDH returned more than requested");
362 std::unique_ptr<EC_KEY, std::function<void (EC_KEY*)>> m_ossl_ec;
368std::unique_ptr<PK_Ops::Key_Agreement>
369make_openssl_ecdh_ka_op(
const ECDH_PrivateKey& key,
const std::string& params)
371 const int nid = OpenSSL_EC_nid_for(key.domain().get_curve_oid());
374 throw Lookup_Error(
"OpenSSL ECDH does not support this curve");
377 return std::unique_ptr<PK_Ops::Key_Agreement>(
new OpenSSL_ECDH_KA_Operation(key, params));
static secure_vector< uint8_t > encode_1363(const BigInt &n, size_t bytes)
int(* final)(unsigned char *, CTX *)