Botan  2.4.0
Crypto and TLS for C++11
ecgdsa.cpp
Go to the documentation of this file.
1 /*
2 * ECGDSA (BSI-TR-03111, version 2.0)
3 * (C) 2016 RenĂ© Korthaus
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/ecgdsa.h>
9 #include <botan/keypair.h>
10 #include <botan/reducer.h>
11 #include <botan/internal/pk_ops_impl.h>
12 
13 namespace Botan {
14 
16  bool strong) const
17  {
18  if(!public_point().on_the_curve())
19  return false;
20 
21  if(!strong)
22  return true;
23 
24  return KeyPair::signature_consistency_check(rng, *this, "EMSA1(SHA-256)");
25  }
26 
27 namespace {
28 
29 /**
30 * ECGDSA signature operation
31 */
32 class ECGDSA_Signature_Operation final : public PK_Ops::Signature_with_EMSA
33  {
34  public:
35 
36  ECGDSA_Signature_Operation(const ECGDSA_PrivateKey& ecgdsa,
37  const std::string& emsa) :
39  m_order(ecgdsa.domain().get_order()),
40  m_base_point(ecgdsa.domain().get_base_point(), m_order),
41  m_x(ecgdsa.private_value()),
42  m_mod_order(m_order)
43  {
44  }
45 
46  secure_vector<uint8_t> raw_sign(const uint8_t msg[], size_t msg_len,
47  RandomNumberGenerator& rng) override;
48 
49  size_t max_input_bits() const override { return m_order.bits(); }
50 
51  private:
52  const BigInt& m_order;
53  Blinded_Point_Multiply m_base_point;
54  const BigInt& m_x;
55  Modular_Reducer m_mod_order;
56  };
57 
59 ECGDSA_Signature_Operation::raw_sign(const uint8_t msg[], size_t msg_len,
61  {
62  const BigInt m(msg, msg_len);
63 
64  BigInt k = BigInt::random_integer(rng, 1, m_order);
65 
66  const PointGFp k_times_P = m_base_point.blinded_multiply(k, rng);
67  const BigInt r = m_mod_order.reduce(k_times_P.get_affine_x());
68  const BigInt s = m_mod_order.multiply(m_x, mul_sub(k, r, m));
69 
70  // With overwhelming probability, a bug rather than actual zero r/s
71  BOTAN_ASSERT(s != 0, "invalid s");
72  BOTAN_ASSERT(r != 0, "invalid r");
73 
74  return BigInt::encode_fixed_length_int_pair(r, s, m_order.bytes());
75  }
76 
77 /**
78 * ECGDSA verification operation
79 */
80 class ECGDSA_Verification_Operation final : public PK_Ops::Verification_with_EMSA
81  {
82  public:
83 
84  ECGDSA_Verification_Operation(const ECGDSA_PublicKey& ecgdsa,
85  const std::string& emsa) :
87  m_base_point(ecgdsa.domain().get_base_point()),
88  m_public_point(ecgdsa.public_point()),
89  m_order(ecgdsa.domain().get_order()),
90  m_mod_order(m_order)
91  {
92  }
93 
94  size_t max_input_bits() const override { return m_order.bits(); }
95 
96  bool with_recovery() const override { return false; }
97 
98  bool verify(const uint8_t msg[], size_t msg_len,
99  const uint8_t sig[], size_t sig_len) override;
100  private:
101  const PointGFp& m_base_point;
102  const PointGFp& m_public_point;
103  const BigInt& m_order;
104  // FIXME: should be offered by curve
105  Modular_Reducer m_mod_order;
106  };
107 
108 bool ECGDSA_Verification_Operation::verify(const uint8_t msg[], size_t msg_len,
109  const uint8_t sig[], size_t sig_len)
110  {
111  if(sig_len != m_order.bytes()*2)
112  return false;
113 
114  BigInt e(msg, msg_len);
115 
116  BigInt r(sig, sig_len / 2);
117  BigInt s(sig + sig_len / 2, sig_len / 2);
118 
119  if(r <= 0 || r >= m_order || s <= 0 || s >= m_order)
120  return false;
121 
122  BigInt w = inverse_mod(r, m_order);
123 
124  const BigInt u1 = m_mod_order.reduce(e * w);
125  const BigInt u2 = m_mod_order.reduce(s * w);
126  const PointGFp R = multi_exponentiate(m_base_point, u1, m_public_point, u2);
127 
128  if(R.is_zero())
129  return false;
130 
131  const BigInt v = m_mod_order.reduce(R.get_affine_x());
132  return (v == r);
133  }
134 
135 }
136 
137 std::unique_ptr<PK_Ops::Verification>
139  const std::string& provider) const
140  {
141  if(provider == "base" || provider.empty())
142  return std::unique_ptr<PK_Ops::Verification>(new ECGDSA_Verification_Operation(*this, params));
143  throw Provider_Not_Found(algo_name(), provider);
144  }
145 
146 std::unique_ptr<PK_Ops::Signature>
148  const std::string& params,
149  const std::string& provider) const
150  {
151  if(provider == "base" || provider.empty())
152  return std::unique_ptr<PK_Ops::Signature>(new ECGDSA_Signature_Operation(*this, params));
153  throw Provider_Not_Found(algo_name(), provider);
154  }
155 
156 }
std::string algo_name() const override
Definition: ecgdsa.h:44
const BigInt & private_value() const
Definition: ecc_key.cpp:112
const PointGFp & get_base_point() const
Definition: ec_group.h:96
std::unique_ptr< PK_Ops::Signature > create_signature_op(RandomNumberGenerator &rng, const std::string &params, const std::string &provider) const override
Definition: ecgdsa.cpp:147
BigInt mul_sub(const BigInt &a, const BigInt &b, const BigInt &c)
Definition: mp_numth.cpp:71
const PointGFp & public_point() const
Definition: ecc_key.h:57
static BigInt random_integer(RandomNumberGenerator &rng, const BigInt &min, const BigInt &max)
Definition: big_rand.cpp:45
std::unique_ptr< PK_Ops::Verification > create_verification_op(const std::string &params, const std::string &provider) const override
Definition: ecgdsa.cpp:138
BigInt get_affine_x() const
Definition: point_gfp.cpp:389
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:29
bool signature_consistency_check(RandomNumberGenerator &rng, const Private_Key &private_key, const Public_Key &public_key, const std::string &padding)
Definition: keypair.cpp:49
const EC_Group & domain() const
Definition: ecc_key.h:72
BigInt inverse_mod(const BigInt &n, const BigInt &mod)
Definition: numthry.cpp:277
Definition: alg_id.cpp:13
const BigInt & get_order() const
Definition: ec_group.h:102
bool check_key(RandomNumberGenerator &rng, bool) const override
Definition: ecgdsa.cpp:15
bool is_zero() const
Definition: point_gfp.h:179
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:88
static secure_vector< uint8_t > encode_fixed_length_int_pair(const BigInt &n1, const BigInt &n2, size_t bytes)
Definition: big_code.cpp:103
PointGFp multi_exponentiate(const PointGFp &p1, const BigInt &z1, const PointGFp &p2, const BigInt &z2)
Definition: point_gfp.cpp:247