Botan: src/cert/cvc/cvc_self.cpp Source File

Botan 1.10.17

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),
59 OCTET_STRING, ASN1_Tag(4));
60
61 encode_eac_bigint(enc, domain.get_order(), ASN1_Tag(4));
62 }
63
64 enc.encode(EC2OSP(key->public_point(), PointGFp::UNCOMPRESSED),
65 OCTET_STRING, ASN1_Tag(6));
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
90 EAC1_1_CVC create_self_signed_cert(Private_Key const& key,
91 EAC1_1_CVC_Options const& opt,
92 RandomNumberGenerator& rng)
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);
106 sig_algo = AlgorithmIdentifier(sig_algo.oid, AlgorithmIdentifier::USE_NULL_PARAM);
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
119 EAC1_1_Req create_cvc_req(Private_Key const& key,
120 ASN1_Chr const& chr,
121 std::string const& hash_alg,
122 RandomNumberGenerator& rng)
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);
133 sig_algo = AlgorithmIdentifier(sig_algo.oid, AlgorithmIdentifier::USE_NULL_PARAM);
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);
141 MemoryVector<byte> tbs = DER_Encoder()
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 =
148 EAC1_1_gen_CVC<EAC1_1_Req>::make_signed(signer,
149 EAC1_1_gen_CVC<EAC1_1_Req>::build_cert_body(tbs),
150 rng);
151
152 DataSource_Memory source(signed_cert);
153 return EAC1_1_Req(source);
154 }
155
156 EAC1_1_ADO create_ado_req(Private_Key const& key,
157 EAC1_1_Req const& req,
158 ASN1_Car const& car,
159 RandomNumberGenerator& rng)
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
183 EAC1_1_CVC create_cvca(Private_Key const& key,
184 std::string const& hash,
185 ASN1_Car const& car, bool iris, bool fingerpr,
186 u32bit cvca_validity_months,
187 RandomNumberGenerator& rng)
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
208 EAC1_1_CVC link_cvca(EAC1_1_CVC const& signer,
209 Private_Key const& key,
210 EAC1_1_CVC const& signee,
211 RandomNumberGenerator& rng)
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());
237 subj_pk->set_parameter_encoding(EC_DOMPAR_ENC_EXPLICIT);
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,
257 RandomNumberGenerator& rng)
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
277 subj_pk->set_parameter_encoding(EC_DOMPAR_ENC_IMPLICITCA);
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
317 EAC1_1_Req create_cvc_req(Private_Key const& prkey,
318 ASN1_Chr const& chr,
319 std::string const& hash_alg,
320 RandomNumberGenerator& rng)
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);
328 key.set_parameter_encoding(EC_DOMPAR_ENC_IMPLICITCA);
329 return CVC_EAC::create_cvc_req(key, chr, hash_alg, rng);
330 }
331
332 } // namespace DE_EAC
333
334 }
Botan::EAC1_1_Req
Definition: cvc_req.h:19
Botan::DER_Encoder::get_contents
SecureVector< byte > get_contents()
Definition: der_enc.cpp:122
Botan::EAC1_1_gen_CVC::subject_public_key
Public_Key * subject_public_key() const
Definition: cvc_gen_cert.h:123
Botan::EAC1_1_CVC_Options
Definition: cvc_self.h:24
Botan::EAC1_1_ADO::make_signed
static MemoryVector< byte > make_signed(PK_Signer &signer, const MemoryRegion< byte > &tbs_bits, RandomNumberGenerator &rng)
Definition: cvc_ado.cpp:48
Botan::EAC1_1_CVC
Definition: cvc_cert.h:21
Botan::PointGFp::UNCOMPRESSED
Definition: point_gfp.h:45
Botan::BigInt
Definition: bigint.h:22
Botan::EC_DOMPAR_ENC_EXPLICIT
Definition: ec_group.h:23
Botan::EAC1_1_CVC_Options::cex
ASN1_Cex cex
Definition: cvc_self.h:32
Botan::DER_Encoder::raw_bytes
DER_Encoder & raw_bytes(const byte val[], size_t len)
Definition: der_enc.cpp:188
Botan::RandomNumberGenerator
Definition: rng.h:20
Botan::ASN1_Cex
Definition: eac_asn_obj.h:139
Botan::Private_Key
Definition: pk_keys.h:86
Botan::EC_PublicKey::set_parameter_encoding
void set_parameter_encoding(EC_Group_Encoding enc)
Definition: ecc_key.cpp:55
Botan::CVC_EAC::create_ado_req
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
Botan::EAC1_1_CVC_Options::car
ASN1_Car car
Definition: cvc_self.h:28
Botan::MemoryRegion::push_back
void push_back(T x)
Definition: secmem.h:149
Botan::Invalid_Argument
std::invalid_argument Invalid_Argument
Definition: exceptn.h:20
Botan::DE_EAC::link_cvca
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
Botan::DE_EAC::sign_request
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
Botan::DER_Encoder::end_cons
DER_Encoder & end_cons()
Definition: der_enc.cpp:145
Botan::EAC1_1_CVC::get_chat_value
u32bit get_chat_value() const
Definition: cvc_cert.cpp:26
Botan::make_cvc_cert
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
Botan::EAC_Time
Definition: eac_asn_obj.h:21
Botan::EC2OSP
SecureVector< byte > EC2OSP(const PointGFp &point, byte format)
Definition: point_gfp.cpp:490
Botan::EAC1_1_CVC_Options::hash_alg
std::string hash_alg
Definition: cvc_self.h:33
Botan::EAC1_1_gen_CVC::get_chr
ASN1_Chr get_chr() const
Definition: cvc_gen_cert.h:96
Botan::u64bit
unsigned long long u64bit
Definition: types.h:49
Botan::DER_Encoder::encode
DER_Encoder & encode(bool b)
Definition: der_enc.cpp:209
Botan::OCTET_STRING
Definition: asn1_int.h:31
Botan::DER_Encoder
Definition: der_enc.h:22
Botan::EAC_Time::add_months
void add_months(u32bit months)
Definition: asn1_eac_tm.cpp:190
Botan::EC_DOMPAR_ENC_IMPLICITCA
Definition: ec_group.h:24
Botan::OIDS::lookup
std::string lookup(const OID &oid)
Definition: oids.cpp:31
Botan::EAC1_1_gen_CVC::make_signed
static MemoryVector< byte > make_signed(PK_Signer &signer, const MemoryRegion< byte > &tbs_bits, RandomNumberGenerator &rng)
Definition: cvc_gen_cert.h:107
Botan::ASN1_Tag
ASN1_Tag
Definition: asn1_int.h:19
Botan::ECDSA_PublicKey
Definition: ecdsa.h:22
Botan::AlgorithmIdentifier::oid
OID oid
Definition: alg_id.h:35
Botan::EAC1_1_CVC::get_car
ASN1_Car get_car() const
Definition: cvc_cert.cpp:13
Botan::@121::CHAT_values
CHAT_values
Definition: cvc_self.cpp:23
Botan::ASN1_EAC_String::value
std::string value() const
Definition: asn1_eac_str.cpp:41
Botan
Definition: algo_base.h:14
Botan::MemoryVector< byte >
Botan::ASN1_Car
Definition: eac_asn_obj.h:201
Botan::BigInt::bytes
size_t bytes() const
Definition: bigint.cpp:246
Botan::CVC_EAC::create_self_signed_cert
EAC1_1_CVC create_self_signed_cert(Private_Key const &key, EAC1_1_CVC_Options const &opt, RandomNumberGenerator &rng)
Definition: cvc_self.cpp:90
Botan::EC_DOMPAR_ENC_OID
Definition: ec_group.h:25
Botan::ASN1_EAC_String::iso_8859
std::string iso_8859() const
Definition: asn1_eac_str.cpp:33
Botan::APPLICATION
Definition: asn1_int.h:21
Botan::DE_EAC::create_cvca
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
Botan::DataSource_Memory
Definition: data_src.h:94
Botan::EAC1_1_CVC::get_cex
ASN1_Cex get_cex() const
Definition: cvc_cert.cpp:22
Botan::AlgorithmIdentifier
Definition: alg_id.h:20
Botan::DER_Encoder::start_cons
DER_Encoder & start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Definition: der_enc.cpp:135
Botan::CVC_EAC::create_cvc_req
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
Botan::EAC1_1_CVC_Options::ced
ASN1_Ced ced
Definition: cvc_self.h:31
Botan::ECDSA_PrivateKey
Definition: ecdsa.h:64
Botan::EAC_Signed_Object::signature_algorithm
AlgorithmIdentifier signature_algorithm() const
Definition: signed_obj.cpp:43
Botan::to_string
std::string to_string(u64bit n, size_t min_len)
Definition: parsing.cpp:42
Botan::EAC1_1_CVC_Options::holder_auth_templ
byte holder_auth_templ
Definition: cvc_self.h:30
Botan::SecureVector< byte >
Botan::AlgorithmIdentifier::USE_NULL_PARAM
Definition: alg_id.h:23
Botan::PK_Signer
Definition: pubkey.h:123
Botan::EAC1_1_ADO
Definition: cvc_ado.h:23
Botan::ASN1_Chr
Definition: eac_asn_obj.h:214
Botan::ASN1_Ced
Definition: eac_asn_obj.h:108
Botan::BigInt::encode_1363
static SecureVector< byte > encode_1363(const BigInt &n, size_t bytes)
Definition: big_code.cpp:78
Botan::EAC_Time::as_string
std::string as_string() const
Definition: asn1_eac_tm.cpp:130
Botan::ECDSA_PublicKey::algo_name
std::string algo_name() const
Definition: ecdsa.h:43
Botan::system_time
u64bit system_time()
Definition: time.cpp:73
Botan::u32bit
unsigned int u32bit
Definition: types.h:32
Botan::DE_EAC::create_cvc_req
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 oid
Definition: x509_ext.cpp:446
Botan::EAC_Signed_Object::BER_encode
SecureVector< byte > BER_encode() const
Definition: signed_obj.cpp:19
Botan::EAC1_1_gen_CVC
Definition: cvc_gen_cert.h:23