Botan  2.8.0
Crypto and TLS for C++11
bearssl_ec.cpp
Go to the documentation of this file.
1 /*
2 * ECDSA via BearSSL
3 * (C) 2015,2016 Jack Lloyd
4 * (C) 2017 Patrick Wildt
5 *
6 * Botan is released under the Simplified BSD License (see license.txt)
7 */
8 
9 #include <botan/exceptn.h>
10 #include <botan/hash.h>
11 #include <botan/scan_name.h>
12 #include <botan/internal/bearssl.h>
13 
14 #if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
15  #include <botan/der_enc.h>
16  #include <botan/pkcs8.h>
17  #include <botan/oids.h>
18  #include <botan/internal/pk_ops_impl.h>
19 #endif
20 
21 #if defined(BOTAN_HAS_ECDSA)
22  #include <botan/ecdsa.h>
23 #endif
24 
25 extern "C" {
26  #include <bearssl_hash.h>
27  #include <bearssl_ec.h>
28 }
29 
30 namespace Botan {
31 
32 #if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
33 
34 namespace {
35 
36 int BearSSL_EC_curve_for(const OID& oid)
37  {
38  if(oid.empty())
39  return -1;
40 
41  const std::string name = OIDS::lookup(oid);
42 
43  if(name == "secp256r1")
44  return BR_EC_secp256r1;
45  if(name == "secp384r1")
46  return BR_EC_secp384r1;
47  if(name == "secp521r1")
48  return BR_EC_secp521r1;
49 
50  return -1;
51  }
52 
53 const br_hash_class *BearSSL_hash_class_for(const std::string& emsa)
54  {
55  if (emsa == "EMSA1(SHA-1)")
56  return &br_sha1_vtable;
57  if (emsa == "EMSA1(SHA-224)")
58  return &br_sha224_vtable;
59  if (emsa == "EMSA1(SHA-256)")
60  return &br_sha256_vtable;
61  if (emsa == "EMSA1(SHA-384)")
62  return &br_sha384_vtable;
63  if (emsa == "EMSA1(SHA-512)")
64  return &br_sha512_vtable;
65 
66  return nullptr;
67  }
68 }
69 
70 #endif
71 
72 #if defined(BOTAN_HAS_ECDSA)
73 
74 namespace {
75 
76 class BearSSL_ECDSA_Verification_Operation final : public PK_Ops::Verification
77  {
78  public:
79  BearSSL_ECDSA_Verification_Operation(const ECDSA_PublicKey& ecdsa, const std::string& emsa) :
80  m_order_bits(ecdsa.domain().get_order_bits())
81  {
82  const int curve = BearSSL_EC_curve_for(ecdsa.domain().get_oid());
83  if (curve < 0)
84  throw Lookup_Error("BearSSL ECDSA does not support this curve");
85 
86  m_hash = BearSSL_hash_class_for(emsa);
87  if (m_hash == nullptr)
88  throw Lookup_Error("BearSSL ECDSA does not support EMSA " + emsa);
89 
90  const SCAN_Name req(emsa);
91  m_hf = make_bearssl_hash(req.arg(0));
92  if (m_hf == nullptr)
93  throw Lookup_Error("BearSSL ECDSA does not support hash " + req.arg(0));
94 
95  m_q_buf = ecdsa.public_point().encode(PointGFp::UNCOMPRESSED);
96 
97  m_key.qlen = m_q_buf.size();
98  m_key.q = m_q_buf.data();
99  m_key.curve = curve;
100  }
101 
102  void update(const uint8_t msg[], size_t msg_len) override
103  {
104  m_hf->update(msg, msg_len);
105  }
106 
107  bool is_valid_signature(const uint8_t sig[], size_t sig_len) override
108  {
109  const size_t order_bytes = (m_order_bits + 7) / 8;
110  if (sig_len != 2 * order_bytes)
111  return false;
112  secure_vector<uint8_t> msg = m_hf->final();
113 
114  br_ecdsa_vrfy engine = br_ecdsa_vrfy_raw_get_default();
115  if (!engine(&br_ec_prime_i31, msg.data(), msg.size(), &m_key, sig, sig_len))
116  return false;
117 
118  return true;
119  }
120 
121  size_t max_input_bits() const { return m_order_bits; }
122 
123  private:
124  br_ec_public_key m_key;
125  std::unique_ptr<HashFunction> m_hf;
126  std::vector<uint8_t> m_q_buf;
127  const br_hash_class *m_hash;
128  size_t m_order_bits;
129  };
130 
131 class BearSSL_ECDSA_Signing_Operation final : public PK_Ops::Signature
132  {
133  public:
134  BearSSL_ECDSA_Signing_Operation(const ECDSA_PrivateKey& ecdsa, const std::string& emsa) :
135  m_order_bits(ecdsa.domain().get_order_bits()),
136  m_order_bytes(ecdsa.domain().get_order_bytes())
137  {
138  const int curve = BearSSL_EC_curve_for(ecdsa.domain().get_oid());
139  if(curve < 0)
140  throw Lookup_Error("BearSSL ECDSA does not support this curve");
141 
142  m_hash = BearSSL_hash_class_for(emsa);
143  if (m_hash == nullptr)
144  throw Lookup_Error("BearSSL ECDSA does not support EMSA " + emsa);
145 
146  const SCAN_Name req(emsa);
147  m_hf = make_bearssl_hash(req.arg(0));
148  if (m_hf == nullptr)
149  throw Lookup_Error("BearSSL ECDSA does not support hash " + req.arg(0));
150 
151  m_x_buf = BigInt::encode_locked(ecdsa.private_value());
152 
153  m_key.xlen = m_x_buf.size();
154  m_key.x = m_x_buf.data();
155  m_key.curve = curve;
156  }
157 
158  void update(const uint8_t msg[], size_t msg_len) override
159  {
160  m_hf->update(msg, msg_len);
161  }
162 
163  secure_vector<uint8_t> sign(RandomNumberGenerator&) override
164  {
165  const size_t order_bytes = (m_order_bits + 7) / 8;
166  secure_vector<uint8_t> sigval(2*order_bytes);
167 
168  br_ecdsa_sign engine = br_ecdsa_sign_raw_get_default();
169  size_t sign_len = engine(&br_ec_prime_i31, m_hash, m_hf->final().data(), &m_key, sigval.data());
170  if (sign_len == 0)
171  throw BearSSL_Error("br_ecdsa_sign");
172 
173  sigval.resize(sign_len);
174  return sigval;
175  }
176 
177  size_t max_input_bits() const { return m_order_bits; }
178 
179  size_t signature_length() const override { return 2*m_order_bytes; }
180 
181  private:
182  br_ec_private_key m_key;
183  std::unique_ptr<HashFunction> m_hf;
184  secure_vector<uint8_t> m_x_buf;
185  const br_hash_class *m_hash;
186  size_t m_order_bits;
187  size_t m_order_bytes;
188  };
189 
190 }
191 
192 std::unique_ptr<PK_Ops::Verification>
193 make_bearssl_ecdsa_ver_op(const ECDSA_PublicKey& key, const std::string& params)
194  {
195  return std::unique_ptr<PK_Ops::Verification>(new BearSSL_ECDSA_Verification_Operation(key, params));
196  }
197 
198 std::unique_ptr<PK_Ops::Signature>
199 make_bearssl_ecdsa_sig_op(const ECDSA_PrivateKey& key, const std::string& params)
200  {
201  return std::unique_ptr<PK_Ops::Signature>(new BearSSL_ECDSA_Signing_Operation(key, params));
202  }
203 
204 #endif
205 
206 }
int(* final)(unsigned char *, CTX *)
std::unique_ptr< HashFunction > make_bearssl_hash(const std::string &name)
static secure_vector< uint8_t > encode_locked(const BigInt &n)
Definition: bigint.h:690
std::string name
Definition: alg_id.cpp:13
int(* update)(CTX *, const void *, CC_LONG len)
std::string lookup(const OID &oid)
Definition: oids.cpp:113
const RSA_PrivateKey & m_key
Definition: rsa.cpp:277