1 /*
2 * ECGDSA (BSI-TR-03111, version 2.0)
3 * (C) 2016 René Korthaus
4 * (C) 2018 Jack Lloyd
5 *
6 * Botan is released under the Simplified BSD License (see license.txt)
7 */
8 
9 #include <botan/ecgdsa.h>
10 #include <botan/keypair.h>
11 #include <botan/reducer.h>
12 #include <botan/internal/pk_ops_impl.h>
13 #include <botan/internal/point_mul.h>
14 
15 namespace Botan {
16 
check_key(RandomNumberGenerator & rng,bool strong) const17 bool ECGDSA_PrivateKey::check_key(RandomNumberGenerator& rng,
18                                  bool strong) const
19    {
20    if(!public_point().on_the_curve())
21       return false;
22 
23    if(!strong)
24       return true;
25 
26    return KeyPair::signature_consistency_check(rng, *this, "EMSA1(SHA-256)");
27    }
28 
29 namespace {
30 
31 /**
32 * ECGDSA signature operation
33 */
34 class ECGDSA_Signature_Operation final : public PK_Ops::Signature_with_EMSA
35    {
36    public:
37 
ECGDSA_Signature_Operation(const ECGDSA_PrivateKey & ecgdsa,const std::string & emsa)38       ECGDSA_Signature_Operation(const ECGDSA_PrivateKey& ecgdsa,
39                                 const std::string& emsa) :
40          PK_Ops::Signature_with_EMSA(emsa),
41          m_group(ecgdsa.domain()),
42          m_x(ecgdsa.private_value())
43          {
44          }
45 
46       secure_vector<uint8_t> raw_sign(const uint8_t msg[], size_t msg_len,
47                                       RandomNumberGenerator& rng) override;
48 
signature_length() const49       size_t signature_length() const override { return 2*m_group.get_order_bytes(); }
50 
max_input_bits() const51       size_t max_input_bits() const override { return m_group.get_order_bits(); }
52 
53    private:
54       const EC_Group m_group;
55       const BigInt& m_x;
56       std::vector<BigInt> m_ws;
57    };
58 
59 secure_vector<uint8_t>
raw_sign(const uint8_t msg[],size_t msg_len,RandomNumberGenerator & rng)60 ECGDSA_Signature_Operation::raw_sign(const uint8_t msg[], size_t msg_len,
61                                      RandomNumberGenerator& rng)
62    {
63    const BigInt m(msg, msg_len, m_group.get_order_bits());
64 
65    const BigInt k = m_group.random_scalar(rng);
66 
67    const BigInt r = m_group.mod_order(
68       m_group.blinded_base_point_multiply_x(k, rng, m_ws));
69 
70    const BigInt kr = m_group.multiply_mod_order(k, r);
71 
72    const BigInt s = m_group.multiply_mod_order(m_x, kr - m);
73 
74    // With overwhelming probability, a bug rather than actual zero r/s
75    if(r.is_zero() || s.is_zero())
76       throw Internal_Error("During ECGDSA signature generated zero r/s");
77 
78    return BigInt::encode_fixed_length_int_pair(r, s, m_group.get_order_bytes());
79    }
80 
81 /**
82 * ECGDSA verification operation
83 */
84 class ECGDSA_Verification_Operation final : public PK_Ops::Verification_with_EMSA
85    {
86    public:
87 
ECGDSA_Verification_Operation(const ECGDSA_PublicKey & ecgdsa,const std::string & emsa)88       ECGDSA_Verification_Operation(const ECGDSA_PublicKey& ecgdsa,
89                                    const std::string& emsa) :
90          PK_Ops::Verification_with_EMSA(emsa),
91          m_group(ecgdsa.domain()),
92          m_gy_mul(m_group.get_base_point(), ecgdsa.public_point())
93          {
94          }
95 
max_input_bits() const96       size_t max_input_bits() const override { return m_group.get_order_bits(); }
97 
with_recovery() const98       bool with_recovery() const override { return false; }
99 
100       bool verify(const uint8_t msg[], size_t msg_len,
101                   const uint8_t sig[], size_t sig_len) override;
102    private:
103       const EC_Group m_group;
104       const PointGFp_Multi_Point_Precompute m_gy_mul;
105    };
106 
verify(const uint8_t msg[],size_t msg_len,const uint8_t sig[],size_t sig_len)107 bool ECGDSA_Verification_Operation::verify(const uint8_t msg[], size_t msg_len,
108                                            const uint8_t sig[], size_t sig_len)
109    {
110    if(sig_len != m_group.get_order_bytes() * 2)
111       return false;
112 
113    const BigInt e(msg, msg_len, m_group.get_order_bits());
114 
115    const BigInt r(sig, sig_len / 2);
116    const BigInt s(sig + sig_len / 2, sig_len / 2);
117 
118    if(r <= 0 || r >= m_group.get_order() || s <= 0 || s >= m_group.get_order())
119       return false;
120 
121    const BigInt w = m_group.inverse_mod_order(r);
122 
123    const BigInt u1 = m_group.multiply_mod_order(e, w);
124    const BigInt u2 = m_group.multiply_mod_order(s, w);
125    const PointGFp R = m_gy_mul.multi_exp(u1, u2);
126 
127    if(R.is_zero())
128       return false;
129 
130    const BigInt v = m_group.mod_order(R.get_affine_x());
131    return (v == r);
132    }
133 
134 }
135 
136 std::unique_ptr<PK_Ops::Verification>
create_verification_op(const std::string & params,const std::string & provider) const137 ECGDSA_PublicKey::create_verification_op(const std::string& params,
138                                          const std::string& provider) const
139    {
140    if(provider == "base" || provider.empty())
141       return std::unique_ptr<PK_Ops::Verification>(new ECGDSA_Verification_Operation(*this, params));
142    throw Provider_Not_Found(algo_name(), provider);
143    }
144 
145 std::unique_ptr<PK_Ops::Signature>
create_signature_op(RandomNumberGenerator &,const std::string & params,const std::string & provider) const146 ECGDSA_PrivateKey::create_signature_op(RandomNumberGenerator& /*rng*/,
147                                        const std::string& params,
148                                        const std::string& provider) const
149    {
150    if(provider == "base" || provider.empty())
151       return std::unique_ptr<PK_Ops::Signature>(new ECGDSA_Signature_Operation(*this, params));
152    throw Provider_Not_Found(algo_name(), provider);
153    }
154 
155 }
156