• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 5111374265

29 May 2023 11:19AM UTC coverage: 92.227% (+0.5%) from 91.723%
5111374265

push

github

randombit
Next release will be 3.1.0. Update release notes

75588 of 81959 relevant lines covered (92.23%)

11886470.91 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

81.0
/src/lib/pubkey/ecc_key/ecc_key.cpp
1
/*
2
* ECC Key implemenation
3
* (C) 2007 Manuel Hartl, FlexSecure GmbH
4
*          Falko Strenzke, FlexSecure GmbH
5
*     2008-2010 Jack Lloyd
6
*
7
* Botan is released under the Simplified BSD License (see license.txt)
8
*/
9

10
#include <botan/ecc_key.h>
11

12
#include <botan/ber_dec.h>
13
#include <botan/der_enc.h>
14
#include <botan/ec_point.h>
15
#include <botan/numthry.h>
16
#include <botan/secmem.h>
17
#include <botan/internal/workfactor.h>
18

19
namespace Botan {
20

21
size_t EC_PublicKey::key_length() const { return domain().get_p_bits(); }
800✔
22

23
size_t EC_PublicKey::estimated_strength() const { return ecp_work_factor(key_length()); }
300✔
24

25
namespace {
26

27
EC_Group_Encoding default_encoding_for(EC_Group& group) {
16,193✔
28
   if(group.get_curve_oid().empty())
16,132✔
29
      return EC_Group_Encoding::Explicit;
30
   else
31
      return EC_Group_Encoding::NamedCurve;
16,103✔
32
}
33

34
}  // namespace
35

36
EC_PublicKey::EC_PublicKey(const EC_Group& dom_par, const EC_Point& pub_point) :
12,394✔
37
      m_domain_params(dom_par), m_public_key(pub_point), m_domain_encoding(default_encoding_for(m_domain_params)) {}
24,788✔
38

39
EC_PublicKey::EC_PublicKey(const AlgorithmIdentifier& alg_id, std::span<const uint8_t> key_bits) :
2,465✔
40
      m_domain_params{EC_Group(alg_id.parameters())},
2,437✔
41
      m_public_key{domain().OS2ECP(key_bits)},
2,437✔
42
      m_domain_encoding(default_encoding_for(m_domain_params)) {}
7,137✔
43

44
bool EC_PublicKey::check_key(RandomNumberGenerator& rng, bool /*strong*/) const {
79✔
45
   return m_domain_params.verify_group(rng) && m_domain_params.verify_public_element(public_point());
79✔
46
}
47

48
AlgorithmIdentifier EC_PublicKey::algorithm_identifier() const {
700✔
49
   return AlgorithmIdentifier(object_identifier(), DER_domain());
1,400✔
50
}
51

52
std::vector<uint8_t> EC_PublicKey::public_key_bits() const { return public_point().encode(point_encoding()); }
371✔
53

54
void EC_PublicKey::set_point_encoding(EC_Point_Format enc) {
3✔
55
   if(enc != EC_Point_Format::Compressed && enc != EC_Point_Format::Uncompressed && enc != EC_Point_Format::Hybrid)
3✔
56
      throw Invalid_Argument("Invalid point encoding for EC_PublicKey");
1✔
57

58
   m_point_encoding = enc;
2✔
59
}
2✔
60

61
void EC_PublicKey::set_parameter_encoding(EC_Group_Encoding form) {
×
62
   if(form == EC_Group_Encoding::NamedCurve && m_domain_params.get_curve_oid().empty())
×
63
      throw Invalid_Argument("Cannot used NamedCurve encoding for a curve without an OID");
×
64

65
   m_domain_encoding = form;
×
66
}
×
67

68
const BigInt& EC_PrivateKey::private_value() const {
1,215✔
69
   if(m_private_key == 0)
1,215✔
70
      throw Invalid_State("EC_PrivateKey::private_value - uninitialized");
×
71

72
   return m_private_key;
1,215✔
73
}
74

75
/**
76
* EC_PrivateKey constructor
77
*/
78
EC_PrivateKey::EC_PrivateKey(RandomNumberGenerator& rng,
1,030✔
79
                             const EC_Group& ec_group,
80
                             const BigInt& x,
81
                             bool with_modular_inverse) {
1,030✔
82
   m_domain_params = ec_group;
1,030✔
83
   m_domain_encoding = default_encoding_for(m_domain_params);
1,030✔
84

85
   if(x == 0) {
1,030✔
86
      m_private_key = ec_group.random_scalar(rng);
1,000✔
87
   } else {
88
      m_private_key = x;
530✔
89
   }
90

91
   std::vector<BigInt> ws;
1,030✔
92

93
   if(with_modular_inverse) {
1,030✔
94
      // ECKCDSA
95
      m_public_key = domain().blinded_base_point_multiply(m_domain_params.inverse_mod_order(m_private_key), rng, ws);
171✔
96
   } else {
97
      m_public_key = domain().blinded_base_point_multiply(m_private_key, rng, ws);
1,946✔
98
   }
99

100
   BOTAN_ASSERT(m_public_key.on_the_curve(), "Generated public key point was on the curve");
1,030✔
101
}
1,030✔
102

103
secure_vector<uint8_t> EC_PrivateKey::raw_private_key_bits() const { return BigInt::encode_locked(m_private_key); }
×
104

105
secure_vector<uint8_t> EC_PrivateKey::private_key_bits() const {
344✔
106
   return DER_Encoder()
344✔
107
      .start_sequence()
344✔
108
      .encode(static_cast<size_t>(1))
344✔
109
      .encode(BigInt::encode_1363(m_private_key, m_private_key.bytes()), ASN1_Type::OctetString)
1,032✔
110
      .start_explicit_context_specific(1)
344✔
111
      .encode(m_public_key.encode(EC_Point_Format::Uncompressed), ASN1_Type::BitString)
688✔
112
      .end_cons()
344✔
113
      .end_cons()
344✔
114
      .get_contents();
688✔
115
}
116

117
EC_PrivateKey::EC_PrivateKey(const AlgorithmIdentifier& alg_id,
800✔
118
                             std::span<const uint8_t> key_bits,
119
                             bool with_modular_inverse) {
800✔
120
   m_domain_params = EC_Group(alg_id.parameters());
800✔
121
   m_domain_encoding = default_encoding_for(m_domain_params);
534✔
122

123
   OID key_parameters;
473✔
124
   secure_vector<uint8_t> public_key_bits;
473✔
125

126
   BER_Decoder(key_bits)
473✔
127
      .start_sequence()
929✔
128
      .decode_and_check<size_t>(1, "Unknown version code for ECC key")
456✔
129
      .decode_octet_string_bigint(m_private_key)
455✔
130
      .decode_optional(key_parameters, ASN1_Type(0), ASN1_Class::ExplicitContextSpecific)
889✔
131
      .decode_optional_string(public_key_bits, ASN1_Type::BitString, 1, ASN1_Class::ExplicitContextSpecific)
423✔
132
      .end_cons();
423✔
133

134
   if(public_key_bits.empty()) {
422✔
135
      if(with_modular_inverse) {
98✔
136
         // ECKCDSA
137
         m_public_key = domain().get_base_point() * m_domain_params.inverse_mod_order(m_private_key);
×
138
      } else {
139
         m_public_key = domain().get_base_point() * m_private_key;
196✔
140
      }
141

142
      BOTAN_ASSERT(m_public_key.on_the_curve(), "Public point derived from loaded key was on the curve");
98✔
143
   } else {
144
      m_public_key = domain().OS2ECP(public_key_bits);
679✔
145
      // OS2ECP verifies that the point is on the curve
146
   }
147
}
871✔
148

149
const BigInt& EC_PublicKey::get_int_field(std::string_view field) const {
2✔
150
   if(field == "public_x") {
2✔
151
      BOTAN_ASSERT_NOMSG(this->public_point().is_affine());
×
152
      return this->public_point().get_x();
×
153
   } else if(field == "public_y") {
2✔
154
      BOTAN_ASSERT_NOMSG(this->public_point().is_affine());
×
155
      return this->public_point().get_y();
×
156
   } else if(field == "base_x")
2✔
157
      return this->domain().get_g_x();
×
158
   else if(field == "base_y")
2✔
159
      return this->domain().get_g_y();
×
160
   else if(field == "p")
2✔
161
      return this->domain().get_p();
×
162
   else if(field == "a")
2✔
163
      return this->domain().get_a();
×
164
   else if(field == "b")
2✔
165
      return this->domain().get_b();
×
166
   else if(field == "cofactor")
2✔
167
      return this->domain().get_cofactor();
×
168
   else if(field == "order")
2✔
169
      return this->domain().get_order();
×
170
   else
171
      return Public_Key::get_int_field(field);
2✔
172
}
173

174
const BigInt& EC_PrivateKey::get_int_field(std::string_view field) const {
10✔
175
   if(field == "x")
10✔
176
      return this->private_value();
9✔
177
   else
178
      return EC_PublicKey::get_int_field(field);
1✔
179
}
180

181
}  // namespace Botan
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc