Botan  2.4.0
Crypto and TLS for C++11
ec_group.cpp
Go to the documentation of this file.
1 /*
2 * ECC Domain Parameters
3 *
4 * (C) 2007 Falko Strenzke, FlexSecure GmbH
5 * 2008 Jack Lloyd
6 *
7 * Botan is released under the Simplified BSD License (see license.txt)
8 */
9 
10 #include <botan/ec_group.h>
11 #include <botan/ber_dec.h>
12 #include <botan/der_enc.h>
13 #include <botan/oids.h>
14 #include <botan/pem.h>
15 #include <botan/reducer.h>
16 
17 namespace Botan {
18 
19 EC_Group::EC_Group(const OID& domain_oid)
20  {
21  const std::string pem = PEM_for_named_group(OIDS::lookup(domain_oid));
22 
23  if(pem == "")
24  {
25  throw Lookup_Error("No ECC domain data for '" + domain_oid.as_string() + "'");
26  }
27 
28  *this = EC_Group(pem);
29  m_oid = domain_oid.as_string();
30  }
31 
32 EC_Group::EC_Group(const std::string& str)
33  {
34  if(str == "")
35  return; // no initialization / uninitialized
36 
37  try
38  {
39  std::vector<uint8_t> ber =
40  unlock(PEM_Code::decode_check_label(str, "EC PARAMETERS"));
41 
42  *this = EC_Group(ber);
43  }
44  catch(Decoding_Error) // hmm, not PEM?
45  {
46  *this = EC_Group(OIDS::lookup(str));
47  }
48  }
49 
50 EC_Group::EC_Group(const std::vector<uint8_t>& ber_data)
51  {
52  BER_Decoder ber(ber_data);
53  BER_Object obj = ber.get_next_object();
54 
55  if(obj.type_tag == NULL_TAG)
56  throw Decoding_Error("Cannot handle ImplicitCA ECDSA parameters");
57  else if(obj.type_tag == OBJECT_ID)
58  {
59  OID dom_par_oid;
60  BER_Decoder(ber_data).decode(dom_par_oid);
61  *this = EC_Group(dom_par_oid);
62  }
63  else if(obj.type_tag == SEQUENCE)
64  {
65  BigInt p, a, b;
66  std::vector<uint8_t> sv_base_point;
67 
68  BER_Decoder(ber_data)
70  .decode_and_check<size_t>(1, "Unknown ECC param version code")
71  .start_cons(SEQUENCE)
72  .decode_and_check(OID("1.2.840.10045.1.1"),
73  "Only prime ECC fields supported")
74  .decode(p)
75  .end_cons()
79  .end_cons()
80  .decode(sv_base_point, OCTET_STRING)
81  .decode(m_order)
82  .decode(m_cofactor)
83  .end_cons()
84  .verify_end();
85 
86  m_curve = CurveGFp(p, a, b);
87  m_base_point = OS2ECP(sv_base_point, m_curve);
88  }
89  else
90  throw Decoding_Error("Unexpected tag while decoding ECC domain params");
91  }
92 
93 std::vector<uint8_t>
95  {
96  if(form == EC_DOMPAR_ENC_EXPLICIT)
97  {
98  const size_t ecpVers1 = 1;
99  OID curve_type("1.2.840.10045.1.1");
100 
101  const size_t p_bytes = m_curve.get_p().bytes();
102 
103  return DER_Encoder()
105  .encode(ecpVers1)
107  .encode(curve_type)
108  .encode(m_curve.get_p())
109  .end_cons()
111  .encode(BigInt::encode_1363(m_curve.get_a(), p_bytes),
112  OCTET_STRING)
113  .encode(BigInt::encode_1363(m_curve.get_b(), p_bytes),
114  OCTET_STRING)
115  .end_cons()
117  .encode(m_order)
118  .encode(m_cofactor)
119  .end_cons()
121  }
122  else if(form == EC_DOMPAR_ENC_OID)
123  {
124  if(get_oid().empty())
125  {
126  throw Encoding_Error("Cannot encode EC_Group as OID because OID not set");
127  }
129  }
130  else if(form == EC_DOMPAR_ENC_IMPLICITCA)
132  else
133  throw Internal_Error("EC_Group::DER_encode: Unknown encoding");
134  }
135 
136 std::string EC_Group::PEM_encode() const
137  {
138  const std::vector<uint8_t> der = DER_encode(EC_DOMPAR_ENC_EXPLICIT);
139  return PEM_Code::encode(der, "EC PARAMETERS");
140  }
141 
143  bool) const
144  {
145  //compute the discriminant
146  Modular_Reducer p(m_curve.get_p());
147  BigInt discriminant = p.multiply(4, m_curve.get_a());
148  discriminant += p.multiply(27, m_curve.get_b());
149  discriminant = p.reduce(discriminant);
150  //check the discriminant
151  if(discriminant == 0)
152  {
153  return false;
154  }
155  //check for valid cofactor
156  if(m_cofactor < 1)
157  {
158  return false;
159  }
160  //check if the base point is on the curve
161  if(!m_base_point.on_the_curve())
162  {
163  return false;
164  }
165  if((m_base_point * m_cofactor).is_zero())
166  {
167  return false;
168  }
169  //check if order is prime
170  if(!is_prime(m_order, rng, 128))
171  {
172  return false;
173  }
174  //check if order of the base point is correct
175  if(!(m_base_point * m_order).is_zero())
176  {
177  return false;
178  }
179  return true;
180  }
181 
182 }
std::vector< uint8_t > get_contents_unlocked()
Definition: der_enc.h:27
BER_Decoder & decode_and_check(const T &expected, const std::string &error_msg)
Definition: ber_dec.h:163
std::string as_string() const
Definition: asn1_oid.cpp:50
bool is_prime(const BigInt &n, RandomNumberGenerator &rng, size_t prob, bool is_random)
Definition: numthry.cpp:455
BER_Decoder & decode(bool &v)
Definition: ber_dec.cpp:355
BER_Decoder & decode_octet_string_bigint(class BigInt &b)
Definition: ber_dec.cpp:376
DER_Encoder & end_cons()
Definition: der_enc.cpp:146
static std::string PEM_for_named_group(const std::string &name)
Definition: ec_named.cpp:13
DER_Encoder & encode(bool b)
Definition: der_enc.cpp:202
secure_vector< uint8_t > decode_check_label(DataSource &source, const std::string &label_want)
Definition: pem.cpp:54
std::string encode(const uint8_t der[], size_t length, const std::string &label, size_t width)
Definition: pem.cpp:43
std::string PEM_encode() const
Definition: ec_group.cpp:136
BER_Decoder & end_cons()
Definition: ber_dec.cpp:265
DER_Encoder & encode_null()
Definition: der_enc.cpp:194
secure_vector< uint8_t > EC2OSP(const PointGFp &point, uint8_t format)
Definition: point_gfp.cpp:469
BER_Decoder start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Definition: ber_dec.cpp:251
EC_Group(const CurveGFp &curve, const PointGFp &base_point, const BigInt &order, const BigInt &cofactor)
Definition: ec_group.h:43
Definition: alg_id.cpp:13
size_t bytes() const
Definition: bigint.cpp:175
const BigInt & get_b() const
Definition: curve_gfp.h:85
BER_Object get_next_object()
Definition: ber_dec.cpp:197
bool on_the_curve() const
Definition: point_gfp.cpp:413
std::vector< T > unlock(const secure_vector< T > &in)
Definition: secmem.h:95
EC_Group_Encoding
Definition: ec_group.h:23
const BigInt & get_a() const
Definition: curve_gfp.h:80
ASN1_Tag type_tag
Definition: asn1_obj.h:94
BER_Decoder & verify_end()
Definition: ber_dec.cpp:176
DER_Encoder & start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Definition: der_enc.cpp:136
static secure_vector< uint8_t > encode_1363(const BigInt &n, size_t bytes)
Definition: big_code.cpp:82
const BigInt & get_p() const
Definition: curve_gfp.h:91
std::string lookup(const OID &oid)
Definition: oids.cpp:18
bool verify_group(RandomNumberGenerator &rng, bool strong=false) const
Definition: ec_group.cpp:142
std::string get_oid() const
Definition: ec_group.h:116
std::vector< uint8_t > DER_encode(EC_Group_Encoding form) const
Definition: ec_group.cpp:94
PointGFp OS2ECP(const uint8_t data[], size_t data_len, const CurveGFp &curve)
Definition: point_gfp.cpp:543