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

randombit / botan / 11087146043

28 Sep 2024 09:28PM UTC coverage: 92.003% (+0.7%) from 91.274%
11087146043

push

github

web-flow
Create terraform.yml

82959 of 90170 relevant lines covered (92.0%)

9376319.11 hits per line

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

81.08
/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 {
741✔
22
   return domain().get_p_bits();
741✔
23
}
24

25
size_t EC_PublicKey::estimated_strength() const {
388✔
26
   return ecp_work_factor(key_length());
388✔
27
}
28

29
namespace {
30

31
EC_Group_Encoding default_encoding_for(EC_Group& group) {
17,088✔
32
   if(group.get_curve_oid().empty()) {
17,026✔
33
      return EC_Group_Encoding::Explicit;
34
   } else {
35
      return EC_Group_Encoding::NamedCurve;
16,997✔
36
   }
37
}
38

39
}  // namespace
40

41
EC_PublicKey::EC_PublicKey(const EC_Group& dom_par, const EC_Point& pub_point) :
12,249✔
42
      m_domain_params(dom_par), m_public_key(pub_point), m_domain_encoding(default_encoding_for(m_domain_params)) {}
24,498✔
43

44
EC_PublicKey::EC_PublicKey(const AlgorithmIdentifier& alg_id, std::span<const uint8_t> key_bits) :
3,230✔
45
      m_domain_params{EC_Group(alg_id.parameters())},
3,202✔
46
      m_public_key{domain().OS2ECP(key_bits)},
3,202✔
47
      m_domain_encoding(default_encoding_for(m_domain_params)) {}
9,432✔
48

49
bool EC_PublicKey::check_key(RandomNumberGenerator& rng, bool /*strong*/) const {
97✔
50
   return m_domain_params.verify_group(rng) && m_domain_params.verify_public_element(public_point());
97✔
51
}
52

53
AlgorithmIdentifier EC_PublicKey::algorithm_identifier() const {
787✔
54
   return AlgorithmIdentifier(object_identifier(), DER_domain());
1,574✔
55
}
56

57
std::vector<uint8_t> EC_PublicKey::public_key_bits() const {
394✔
58
   return public_point().encode(point_encoding());
394✔
59
}
60

61
void EC_PublicKey::set_point_encoding(EC_Point_Format enc) {
3✔
62
   if(enc != EC_Point_Format::Compressed && enc != EC_Point_Format::Uncompressed && enc != EC_Point_Format::Hybrid) {
3✔
63
      throw Invalid_Argument("Invalid point encoding for EC_PublicKey");
1✔
64
   }
65

66
   m_point_encoding = enc;
2✔
67
}
2✔
68

69
void EC_PublicKey::set_parameter_encoding(EC_Group_Encoding form) {
×
70
   if(form == EC_Group_Encoding::NamedCurve && m_domain_params.get_curve_oid().empty()) {
×
71
      throw Invalid_Argument("Cannot used NamedCurve encoding for a curve without an OID");
×
72
   }
73

74
   m_domain_encoding = form;
×
75
}
×
76

77
const BigInt& EC_PrivateKey::private_value() const {
1,053✔
78
   if(m_private_key == 0) {
1,053✔
79
      throw Invalid_State("EC_PrivateKey::private_value - uninitialized");
×
80
   }
81

82
   return m_private_key;
1,053✔
83
}
84

85
/**
86
* EC_PrivateKey constructor
87
*/
88
EC_PrivateKey::EC_PrivateKey(RandomNumberGenerator& rng,
839✔
89
                             const EC_Group& ec_group,
90
                             const BigInt& x,
91
                             bool with_modular_inverse) {
839✔
92
   m_domain_params = ec_group;
839✔
93
   m_domain_encoding = default_encoding_for(m_domain_params);
839✔
94

95
   if(x == 0) {
839✔
96
      m_private_key = ec_group.random_scalar(rng);
618✔
97
   } else {
98
      BOTAN_ARG_CHECK(x > 0 && x < ec_group.get_order(), "ECC private key out of range");
530✔
99
      m_private_key = x;
530✔
100
   }
101

102
   std::vector<BigInt> ws;
839✔
103

104
   if(with_modular_inverse) {
839✔
105
      // ECKCDSA
106
      m_public_key = domain().blinded_base_point_multiply(m_domain_params.inverse_mod_order(m_private_key), rng, ws);
195✔
107
   } else {
108
      m_public_key = domain().blinded_base_point_multiply(m_private_key, rng, ws);
1,548✔
109
   }
110

111
   BOTAN_ASSERT(m_public_key.on_the_curve(), "Generated public key point was on the curve");
839✔
112
}
839✔
113

114
secure_vector<uint8_t> EC_PrivateKey::raw_private_key_bits() const {
×
115
   return BigInt::encode_locked(m_private_key);
×
116
}
117

118
secure_vector<uint8_t> EC_PrivateKey::private_key_bits() const {
401✔
119
   return DER_Encoder()
401✔
120
      .start_sequence()
401✔
121
      .encode(static_cast<size_t>(1))
401✔
122
      .encode(BigInt::encode_1363(m_private_key, m_private_key.bytes()), ASN1_Type::OctetString)
1,203✔
123
      .start_explicit_context_specific(1)
401✔
124
      .encode(m_public_key.encode(EC_Point_Format::Uncompressed), ASN1_Type::BitString)
802✔
125
      .end_cons()
401✔
126
      .end_cons()
401✔
127
      .get_contents();
802✔
128
}
129

130
EC_PrivateKey::EC_PrivateKey(const AlgorithmIdentifier& alg_id,
1,267✔
131
                             std::span<const uint8_t> key_bits,
132
                             bool with_modular_inverse) {
1,267✔
133
   m_domain_params = EC_Group(alg_id.parameters());
1,267✔
134
   m_domain_encoding = default_encoding_for(m_domain_params);
1,000✔
135

136
   OID key_parameters;
938✔
137
   secure_vector<uint8_t> public_key_bits;
938✔
138

139
   BER_Decoder(key_bits)
938✔
140
      .start_sequence()
1,859✔
141
      .decode_and_check<size_t>(1, "Unknown version code for ECC key")
921✔
142
      .decode_octet_string_bigint(m_private_key)
919✔
143
      .decode_optional(key_parameters, ASN1_Type(0), ASN1_Class::ExplicitContextSpecific)
1,844✔
144
      .decode_optional_string(public_key_bits, ASN1_Type::BitString, 1, ASN1_Class::ExplicitContextSpecific)
914✔
145
      .end_cons();
909✔
146

147
   if(m_private_key < 1 || m_private_key >= m_domain_params.get_order()) {
908✔
148
      throw Decoding_Error("Invalid EC private key");
61✔
149
   }
150

151
   if(public_key_bits.empty()) {
847✔
152
      if(with_modular_inverse) {
341✔
153
         // ECKCDSA
154
         m_public_key = domain().get_base_point() * m_domain_params.inverse_mod_order(m_private_key);
×
155
      } else {
156
         m_public_key = domain().get_base_point() * m_private_key;
682✔
157
      }
158

159
      BOTAN_ASSERT(m_public_key.on_the_curve(), "Public point derived from loaded key was on the curve");
341✔
160
   } else {
161
      m_public_key = domain().OS2ECP(public_key_bits);
1,025✔
162
      // OS2ECP verifies that the point is on the curve
163
   }
164
}
1,436✔
165

166
bool EC_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const {
28✔
167
   if(m_private_key < 1 || m_private_key >= m_domain_params.get_order()) {
28✔
168
      return false;
×
169
   }
170

171
   return EC_PublicKey::check_key(rng, strong);
28✔
172
}
173

174
const BigInt& EC_PublicKey::get_int_field(std::string_view field) const {
2✔
175
   if(field == "public_x") {
2✔
176
      BOTAN_ASSERT_NOMSG(this->public_point().is_affine());
×
177
      return this->public_point().get_x();
×
178
   } else if(field == "public_y") {
2✔
179
      BOTAN_ASSERT_NOMSG(this->public_point().is_affine());
×
180
      return this->public_point().get_y();
×
181
   } else if(field == "base_x") {
2✔
182
      return this->domain().get_g_x();
×
183
   } else if(field == "base_y") {
2✔
184
      return this->domain().get_g_y();
×
185
   } else if(field == "p") {
2✔
186
      return this->domain().get_p();
×
187
   } else if(field == "a") {
2✔
188
      return this->domain().get_a();
×
189
   } else if(field == "b") {
2✔
190
      return this->domain().get_b();
×
191
   } else if(field == "cofactor") {
2✔
192
      return this->domain().get_cofactor();
×
193
   } else if(field == "order") {
2✔
194
      return this->domain().get_order();
×
195
   } else {
196
      return Public_Key::get_int_field(field);
2✔
197
   }
198
}
199

200
const BigInt& EC_PrivateKey::get_int_field(std::string_view field) const {
10✔
201
   if(field == "x") {
10✔
202
      return this->private_value();
9✔
203
   } else {
204
      return EC_PublicKey::get_int_field(field);
1✔
205
   }
206
}
207

208
}  // 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