Botan  1.10.9
cvc_self.cpp
Go to the documentation of this file.
1 /*
2  (C) 2007 FlexSecure GmbH
3  2008-2010 Jack Lloyd
4 *
5 * Distributed under the terms of the Botan license
6 */
7 
8 #include <botan/cvc_self.h>
9 #include <botan/ecc_key.h>
10 #include <botan/point_gfp.h>
11 #include <botan/time.h>
12 #include <botan/oids.h>
13 #include <sstream>
14 #include <memory>
15 
16 namespace Botan {
17 
18 namespace {
19 
20 /*
21 * cvc CHAT values
22 */
23 enum CHAT_values{
24  CVCA = 0xC0,
25  DVCA_domestic = 0x80,
26  DVCA_foreign = 0x40,
27  IS = 0x00,
28 
29  IRIS = 0x02,
30  FINGERPRINT = 0x01
31 };
32 
33 void encode_eac_bigint(DER_Encoder& der, const BigInt& x, ASN1_Tag tag)
34  {
35  der.encode(BigInt::encode_1363(x, x.bytes()), OCTET_STRING, tag);
36  }
37 
38 MemoryVector<byte> eac_1_1_encoding(const EC_PublicKey* key,
39  const OID& sig_algo)
40  {
41  if(key->domain_format() == EC_DOMPAR_ENC_OID)
42  throw Encoding_Error("CVC encoder: cannot encode parameters by OID");
43 
44  const EC_Group& domain = key->domain();
45 
46  // This is why we can't have nice things
47 
48  DER_Encoder enc;
49  enc.start_cons(ASN1_Tag(73), APPLICATION)
50  .encode(sig_algo);
51 
52  if(key->domain_format() == EC_DOMPAR_ENC_EXPLICIT)
53  {
54  encode_eac_bigint(enc, domain.get_curve().get_p(), ASN1_Tag(1));
55  encode_eac_bigint(enc, domain.get_curve().get_a(), ASN1_Tag(2));
56  encode_eac_bigint(enc, domain.get_curve().get_b(), ASN1_Tag(3));
57 
58  enc.encode(EC2OSP(domain.get_base_point(), PointGFp::UNCOMPRESSED),
60 
61  encode_eac_bigint(enc, domain.get_order(), ASN1_Tag(4));
62  }
63 
64  enc.encode(EC2OSP(key->public_point(), PointGFp::UNCOMPRESSED),
66 
67  if(key->domain_format() == EC_DOMPAR_ENC_EXPLICIT)
68  encode_eac_bigint(enc, domain.get_cofactor(), ASN1_Tag(7));
69 
70  enc.end_cons();
71 
72  return enc.get_contents();
73  }
74 
75 std::string padding_and_hash_from_oid(OID const& oid)
76  {
77  std::string padding_and_hash = OIDS::lookup(oid); // use the hash
78 
79  if(padding_and_hash.substr(0,6) != "ECDSA/")
80  throw Invalid_State("CVC: Can only use ECDSA, not " + padding_and_hash);
81 
82  padding_and_hash.erase(0, padding_and_hash.find("/") + 1);
83  return padding_and_hash;
84  }
85 
86 }
87 
88 namespace CVC_EAC {
89 
91  EAC1_1_CVC_Options const& opt,
93  {
94  // NOTE: we ignore the value of opt.chr
95 
96  const ECDSA_PrivateKey* priv_key = dynamic_cast<const ECDSA_PrivateKey*>(&key);
97 
98  if(priv_key == 0)
99  throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type");
100 
101  ASN1_Chr chr(opt.car.value());
102 
103  AlgorithmIdentifier sig_algo;
104  std::string padding_and_hash("EMSA1_BSI(" + opt.hash_alg + ")");
105  sig_algo.oid = OIDS::lookup(priv_key->algo_name() + "/" + padding_and_hash);
107 
108  PK_Signer signer(*priv_key, padding_and_hash);
109 
110  MemoryVector<byte> enc_public_key = eac_1_1_encoding(priv_key, sig_algo.oid);
111 
112  return make_cvc_cert(signer,
113  enc_public_key,
114  opt.car, chr,
115  opt.holder_auth_templ,
116  opt.ced, opt.cex, rng);
117  }
118 
120  ASN1_Chr const& chr,
121  std::string const& hash_alg,
123  {
124 
125  ECDSA_PrivateKey const* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&key);
126  if (priv_key == 0)
127  {
128  throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type");
129  }
130  AlgorithmIdentifier sig_algo;
131  std::string padding_and_hash("EMSA1_BSI(" + hash_alg + ")");
132  sig_algo.oid = OIDS::lookup(priv_key->algo_name() + "/" + padding_and_hash);
134 
135  PK_Signer signer(*priv_key, padding_and_hash);
136 
137  MemoryVector<byte> enc_public_key = eac_1_1_encoding(priv_key, sig_algo.oid);
138 
139  MemoryVector<byte> enc_cpi;
140  enc_cpi.push_back(0x00);
142  .encode(enc_cpi, OCTET_STRING, ASN1_Tag(41), APPLICATION)
143  .raw_bytes(enc_public_key)
144  .encode(chr)
145  .get_contents();
146 
147  MemoryVector<byte> signed_cert =
150  rng);
151 
152  DataSource_Memory source(signed_cert);
153  return EAC1_1_Req(source);
154  }
155 
157  EAC1_1_Req const& req,
158  ASN1_Car const& car,
160  {
161 
162  ECDSA_PrivateKey const* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&key);
163  if (priv_key == 0)
164  {
165  throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type");
166  }
167  std::string padding_and_hash = padding_and_hash_from_oid(req.signature_algorithm().oid);
168  PK_Signer signer(*priv_key, padding_and_hash);
169  SecureVector<byte> tbs_bits = req.BER_encode();
170  tbs_bits += DER_Encoder().encode(car).get_contents();
171 
172  MemoryVector<byte> signed_cert =
173  EAC1_1_ADO::make_signed(signer, tbs_bits, rng);
174 
175  DataSource_Memory source(signed_cert);
176  return EAC1_1_ADO(source);
177  }
178 
179 } // namespace CVC_EAC
180 namespace DE_EAC
181 {
182 
184  std::string const& hash,
185  ASN1_Car const& car, bool iris, bool fingerpr,
186  u32bit cvca_validity_months,
188  {
189  ECDSA_PrivateKey const* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&key);
190  if (priv_key == 0)
191  {
192  throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type");
193  }
194  EAC1_1_CVC_Options opts;
195  opts.car = car;
196  const u64bit current_time = system_time();
197 
198  opts.ced = ASN1_Ced(current_time);
199  opts.cex = ASN1_Cex(opts.ced);
200  opts.cex.add_months(cvca_validity_months);
201  opts.holder_auth_templ = (CVCA | (iris * IRIS) | (fingerpr * FINGERPRINT));
202  opts.hash_alg = hash;
203  return CVC_EAC::create_self_signed_cert(*priv_key, opts, rng);
204  }
205 
206 
207 
209  Private_Key const& key,
210  EAC1_1_CVC const& signee,
212  {
213  ECDSA_PrivateKey const* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&key);
214  if (priv_key == 0)
215  {
216  throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type");
217  }
218  ASN1_Ced ced(system_time());
219  ASN1_Cex cex(signee.get_cex());
220  if (*static_cast<EAC_Time*>(&ced) > *static_cast<EAC_Time*>(&cex))
221  {
222  std::string detail("link_cvca(): validity periods of provided certificates don't overlap: currend time = ced = ");
223  detail += ced.as_string();
224  detail += ", signee.cex = ";
225  detail += cex.as_string();
226  throw Invalid_Argument(detail);
227  }
228  if (signer.signature_algorithm() != signee.signature_algorithm())
229  {
230  throw Invalid_Argument("link_cvca(): signature algorithms of signer and signee don't match");
231  }
232  AlgorithmIdentifier sig_algo = signer.signature_algorithm();
233  std::string padding_and_hash = padding_and_hash_from_oid(sig_algo.oid);
234  PK_Signer pk_signer(*priv_key, padding_and_hash);
235  std::auto_ptr<Public_Key> pk(signee.subject_public_key());
236  ECDSA_PublicKey* subj_pk = dynamic_cast<ECDSA_PublicKey*>(pk.get());
238 
239  MemoryVector<byte> enc_public_key = eac_1_1_encoding(priv_key, sig_algo.oid);
240 
241  return make_cvc_cert(pk_signer, enc_public_key,
242  signer.get_car(),
243  signee.get_chr(),
244  signer.get_chat_value(),
245  ced, cex,
246  rng);
247  }
248 
249 EAC1_1_CVC sign_request(EAC1_1_CVC const& signer_cert,
250  Private_Key const& key,
251  EAC1_1_Req const& signee,
252  u32bit seqnr,
253  u32bit seqnr_len,
254  bool domestic,
255  u32bit dvca_validity_months,
256  u32bit ca_is_validity_months,
258  {
259  ECDSA_PrivateKey const* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&key);
260  if (priv_key == 0)
261  {
262  throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type");
263  }
264  std::string chr_str = signee.get_chr().value();
265  chr_str += to_string(seqnr, seqnr_len);
266  ASN1_Chr chr(chr_str);
267  std::string padding_and_hash = padding_and_hash_from_oid(signee.signature_algorithm().oid);
268  PK_Signer pk_signer(*priv_key, padding_and_hash);
269  std::auto_ptr<Public_Key> pk(signee.subject_public_key());
270  ECDSA_PublicKey* subj_pk = dynamic_cast<ECDSA_PublicKey*>(pk.get());
271  std::auto_ptr<Public_Key> signer_pk(signer_cert.subject_public_key());
272 
273  // for the case that the domain parameters are not set...
274  // (we use those from the signer because they must fit)
275  //subj_pk->set_domain_parameters(priv_key->domain_parameters());
276 
278 
279  AlgorithmIdentifier sig_algo(signer_cert.signature_algorithm());
280  const u64bit current_time = system_time();
281  ASN1_Ced ced(current_time);
282  u32bit chat_val;
283  u32bit chat_low = signer_cert.get_chat_value() & 0x3; // take the chat rights from signer
284  ASN1_Cex cex(ced);
285  if ((signer_cert.get_chat_value() & CVCA) == CVCA)
286  {
287  // we sign a dvca
288  cex.add_months(dvca_validity_months);
289  if (domestic)
290  chat_val = DVCA_domestic | chat_low;
291  else
292  chat_val = DVCA_foreign | chat_low;
293  }
294  else if ((signer_cert.get_chat_value() & DVCA_domestic) == DVCA_domestic ||
295  (signer_cert.get_chat_value() & DVCA_foreign) == DVCA_foreign)
296  {
297  cex.add_months(ca_is_validity_months);
298  chat_val = IS | chat_low;
299  }
300  else
301  {
302  throw Invalid_Argument("sign_request(): encountered illegal value for CHAT");
303  // (IS cannot sign certificates)
304  }
305 
306  MemoryVector<byte> enc_public_key = eac_1_1_encoding(priv_key, sig_algo.oid);
307 
308  return make_cvc_cert(pk_signer, enc_public_key,
309  ASN1_Car(signer_cert.get_chr().iso_8859()),
310  chr,
311  chat_val,
312  ced,
313  cex,
314  rng);
315  }
316 
318  ASN1_Chr const& chr,
319  std::string const& hash_alg,
321  {
322  ECDSA_PrivateKey const* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&prkey);
323  if (priv_key == 0)
324  {
325  throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type");
326  }
327  ECDSA_PrivateKey key(*priv_key);
329  return CVC_EAC::create_cvc_req(key, chr, hash_alg, rng);
330  }
331 
332 } // namespace DE_EAC
333 
334 }
SecureVector< byte > get_contents()
Definition: der_enc.cpp:122
static MemoryVector< byte > make_signed(PK_Signer &signer, const MemoryRegion< byte > &tbs_bits, RandomNumberGenerator &rng)
Definition: cvc_ado.cpp:48
ASN1_Car get_car() const
Definition: cvc_cert.cpp:13
DER_Encoder & raw_bytes(const byte val[], size_t len)
Definition: der_enc.cpp:188
void set_parameter_encoding(EC_Group_Encoding enc)
Definition: ecc_key.cpp:55
EAC1_1_ADO create_ado_req(Private_Key const &key, EAC1_1_Req const &req, ASN1_Car const &car, RandomNumberGenerator &rng)
Definition: cvc_self.cpp:156
void push_back(T x)
Definition: secmem.h:143
std::invalid_argument Invalid_Argument
Definition: exceptn.h:20
EAC1_1_CVC link_cvca(EAC1_1_CVC const &signer, Private_Key const &key, EAC1_1_CVC const &signee, RandomNumberGenerator &rng)
Definition: cvc_self.cpp:208
EAC1_1_CVC sign_request(EAC1_1_CVC const &signer_cert, Private_Key const &key, EAC1_1_Req const &signee, u32bit seqnr, u32bit seqnr_len, bool domestic, u32bit dvca_validity_months, u32bit ca_is_validity_months, RandomNumberGenerator &rng)
Definition: cvc_self.cpp:249
SecureVector< byte > BER_encode() const
Definition: signed_obj.cpp:19
EAC1_1_CVC make_cvc_cert(PK_Signer &signer, MemoryRegion< byte > const &public_key, ASN1_Car const &car, ASN1_Chr const &chr, byte holder_auth_templ, ASN1_Ced ced, ASN1_Cex cex, RandomNumberGenerator &rng)
Definition: cvc_cert.cpp:98
SecureVector< byte > EC2OSP(const PointGFp &point, byte format)
Definition: point_gfp.cpp:482
std::string hash_alg
Definition: cvc_self.h:33
unsigned long long u64bit
Definition: types.h:49
DER_Encoder & encode(bool b)
Definition: der_enc.cpp:209
ASN1_Cex get_cex() const
Definition: cvc_cert.cpp:22
RandomNumberGenerator * rng
Definition: global_rng.cpp:165
void add_months(u32bit months)
std::string lookup(const OID &oid)
Definition: oids.cpp:31
static MemoryVector< byte > make_signed(PK_Signer &signer, const MemoryRegion< byte > &tbs_bits, RandomNumberGenerator &rng)
Definition: cvc_gen_cert.h:107
ASN1_Tag
Definition: asn1_int.h:19
ASN1_Chr get_chr() const
Definition: cvc_gen_cert.h:96
std::string as_string() const
std::string value() const
EAC1_1_CVC create_self_signed_cert(Private_Key const &key, EAC1_1_CVC_Options const &opt, RandomNumberGenerator &rng)
Definition: cvc_self.cpp:90
u32bit get_chat_value() const
Definition: cvc_cert.cpp:26
EAC1_1_CVC create_cvca(Private_Key const &key, std::string const &hash, ASN1_Car const &car, bool iris, bool fingerpr, u32bit cvca_validity_months, RandomNumberGenerator &rng)
Definition: cvc_self.cpp:183
std::string algo_name() const
Definition: ecdsa.h:43
Public_Key * subject_public_key() const
Definition: cvc_gen_cert.h:123
EAC1_1_Req create_cvc_req(Private_Key const &key, ASN1_Chr const &chr, std::string const &hash_alg, RandomNumberGenerator &rng)
Definition: cvc_self.cpp:119
std::string to_string(u64bit n, size_t min_len)
Definition: parsing.cpp:42
std::string iso_8859() const
AlgorithmIdentifier signature_algorithm() const
Definition: signed_obj.cpp:43
static SecureVector< byte > encode_1363(const BigInt &n, size_t bytes)
Definition: big_code.cpp:78
u64bit system_time()
Definition: time.cpp:73
unsigned int u32bit
Definition: types.h:32
EAC1_1_Req create_cvc_req(Private_Key const &prkey, ASN1_Chr const &chr, std::string const &hash_alg, RandomNumberGenerator &rng)
Definition: cvc_self.cpp:317
OID oid
Definition: x509_ext.cpp:446