1 /*
2 * CVC EAC1.1 tests
3 *
4 * (C) 2008 Falko Strenzke (strenzke@flexsecure.de)
5 *     2008 Jack Lloyd
6 */
7 
8 #include "validate.h"
9 #include <botan/build.h>
10 
11 #if defined(BOTAN_HAS_CARD_VERIFIABLE_CERTIFICATES)
12 
13 #include <iosfwd>
14 #include <iostream>
15 #include <iterator>
16 #include <algorithm>
17 #include <fstream>
18 #include <vector>
19 #include <memory>
20 
21 #include <botan/ecdsa.h>
22 #include <botan/rsa.h>
23 
24 #include <botan/x509cert.h>
25 #include <botan/x509self.h>
26 #include <botan/oids.h>
27 #include <botan/cvc_self.h>
28 #include <botan/cvc_cert.h>
29 #include <botan/cvc_ado.h>
30 #include <botan/time.h>
31 
32 #define TEST_DATA_DIR "checks/ecc_testdata"
33 
34 using namespace Botan;
35 
36 #define CHECK_MESSAGE(expr, print) try { if(!(expr)) std::cout << print << "\n"; } catch(std::exception& e) { std::cout << __FUNCTION__ << ": " << e.what() << "\n"; }
37 #define CHECK(expr) try { if(!(expr)) std::cout << #expr << "\n"; } catch(std::exception& e) { std::cout << __FUNCTION__ << ": " << e.what() << "\n"; }
38 
39 namespace {
40 
41 // helper functions
helper_write_file(EAC_Signed_Object const & to_write,std::string const & file_path)42 void helper_write_file(EAC_Signed_Object const& to_write, std::string const& file_path)
43    {
44    SecureVector<byte> sv = to_write.BER_encode();
45    std::ofstream cert_file(file_path.c_str(), std::ios::binary);
46    cert_file.write((char*)&sv[0], sv.size());
47    cert_file.close();
48    }
49 
helper_files_equal(std::string const & file_path1,std::string const & file_path2)50 bool helper_files_equal(std::string const& file_path1, std::string const& file_path2)
51    {
52    std::ifstream cert_1_in(file_path1.c_str());
53    std::ifstream cert_2_in(file_path2.c_str());
54    SecureVector<byte> sv1;
55    SecureVector<byte> sv2;
56    if (!cert_1_in || !cert_2_in)
57       {
58       return false;
59       }
60    while (!cert_1_in.eof())
61       {
62       char now;
63       cert_1_in.read(&now, 1);
64       sv1.push_back(now);
65       }
66    while (!cert_2_in.eof())
67       {
68       char now;
69       cert_2_in.read(&now, 1);
70       sv2.push_back(now);
71       }
72    if (sv1.size() == 0)
73       {
74       return false;
75       }
76    return sv1 == sv2;
77    }
78 
test_enc_gen_selfsigned(RandomNumberGenerator & rng)79 void test_enc_gen_selfsigned(RandomNumberGenerator& rng)
80    {
81    std::cout << '.' << std::flush;
82 
83    EAC1_1_CVC_Options opts;
84    //opts.cpi = 0;
85    opts.chr = ASN1_Chr("my_opt_chr"); // not used
86    opts.car = ASN1_Car("my_opt_car");
87    opts.cex = ASN1_Cex("2010 08 13");
88    opts.ced = ASN1_Ced("2010 07 27");
89    opts.holder_auth_templ = 0xC1;
90    opts.hash_alg = "SHA-256";
91 
92    // creating a non sense selfsigned cert w/o dom pars
93    EC_Group dom_pars(OID("1.3.36.3.3.2.8.1.1.11"));
94    ECDSA_PrivateKey key(rng, dom_pars);
95    key.set_parameter_encoding(EC_DOMPAR_ENC_IMPLICITCA);
96    EAC1_1_CVC cert = CVC_EAC::create_self_signed_cert(key, opts, rng);
97 
98    SecureVector<byte> der(cert.BER_encode());
99    std::ofstream cert_file;
100    cert_file.open(TEST_DATA_DIR "/my_cv_cert.ber", std::ios::binary);
101    //cert_file << der; // this is bad !!!
102    cert_file.write((char*)&der[0], der.size());
103    cert_file.close();
104 
105    EAC1_1_CVC cert_in(TEST_DATA_DIR "/my_cv_cert.ber");
106    CHECK(cert == cert_in);
107    // encoding it again while it has no dp
108    SecureVector<byte> der2(cert_in.BER_encode());
109    std::ofstream cert_file2(TEST_DATA_DIR "/my_cv_cert2.ber", std::ios::binary);
110    cert_file2.write((char*)&der2[0], der2.size());
111    cert_file2.close();
112    // read both and compare them
113    std::ifstream cert_1_in(TEST_DATA_DIR "/my_cv_cert.ber");
114    std::ifstream cert_2_in(TEST_DATA_DIR "/my_cv_cert2.ber");
115    SecureVector<byte> sv1;
116    SecureVector<byte> sv2;
117    if (!cert_1_in || !cert_2_in)
118       {
119       CHECK_MESSAGE(false, "could not read certificate files");
120       }
121    while (!cert_1_in.eof())
122       {
123       char now;
124 
125       cert_1_in.read(&now, 1);
126       sv1.push_back(now);
127       }
128    while (!cert_2_in.eof())
129       {
130       char now;
131       cert_2_in.read(&now, 1);
132       sv2.push_back(now);
133       }
134    CHECK(sv1.size() > 10);
135    CHECK_MESSAGE(sv1 == sv2, "reencoded file of cert without domain parameters is different from original");
136 
137    //cout << "reading cert again\n";
138    CHECK(cert_in.get_car().value() == "my_opt_car");
139    CHECK(cert_in.get_chr().value() == "my_opt_car");
140    CHECK(cert_in.get_ced().as_string() == "20100727");
141    CHECK(cert_in.get_ced().readable_string() == "2010/07/27 ");
142 
143    bool ill_date_exc = false;
144    try
145       {
146       ASN1_Ced("1999 01 01");
147       }
148    catch (...)
149       {
150       ill_date_exc = true;
151       }
152    CHECK(ill_date_exc);
153 
154    bool ill_date_exc2 = false;
155    try
156       {
157       ASN1_Ced("2100 01 01");
158       }
159    catch (...)
160       {
161       ill_date_exc2 = true;
162       }
163    CHECK(ill_date_exc2);
164    //cout << "readable = '" << cert_in.get_ced().readable_string() << "'\n";
165    std::auto_ptr<Public_Key> p_pk(cert_in.subject_public_key());
166    //auto_ptr<ECDSA_PublicKey> ecdsa_pk(dynamic_cast<auto_ptr<ECDSA_PublicKey> >(p_pk));
167    ECDSA_PublicKey* p_ecdsa_pk = dynamic_cast<ECDSA_PublicKey*>(p_pk.get());
168    // let´s see if encoding is truely implicitca, because this is what the key should have
169    // been set to when decoding (see above)(because it has no domain params):
170    //cout << "encoding = " << p_ecdsa_pk->get_parameter_encoding() << std::endl;
171    CHECK(p_ecdsa_pk->domain_format() == EC_DOMPAR_ENC_IMPLICITCA);
172    bool exc = false;
173    try
174       {
175       std::cout << "order = " << p_ecdsa_pk->domain().get_order() << std::endl;
176       }
177    catch (Invalid_State)
178       {
179       exc = true;
180       }
181    CHECK(exc);
182    // set them and try again
183    //cert_in.set_domain_parameters(dom_pars);
184    std::auto_ptr<Public_Key> p_pk2(cert_in.subject_public_key());
185    ECDSA_PublicKey* p_ecdsa_pk2 = dynamic_cast<ECDSA_PublicKey*>(p_pk2.get());
186    //p_ecdsa_pk2->set_domain_parameters(dom_pars);
187    CHECK(p_ecdsa_pk2->domain().get_order() == dom_pars.get_order());
188    bool ver_ec = cert_in.check_signature(*p_pk2);
189    CHECK_MESSAGE(ver_ec, "could not positively verify correct selfsigned cvc certificate");
190    }
191 
test_enc_gen_req(RandomNumberGenerator & rng)192 void test_enc_gen_req(RandomNumberGenerator& rng)
193    {
194    std::cout << "." << std::flush;
195 
196    EAC1_1_CVC_Options opts;
197 
198    //opts.cpi = 0;
199    opts.chr = ASN1_Chr("my_opt_chr");
200    opts.hash_alg = "SHA-160";
201 
202    // creating a non sense selfsigned cert w/o dom pars
203    EC_Group dom_pars(OID("1.3.132.0.8"));
204    ECDSA_PrivateKey key(rng, dom_pars);
205    key.set_parameter_encoding(EC_DOMPAR_ENC_IMPLICITCA);
206    EAC1_1_Req req = CVC_EAC::create_cvc_req(key, opts.chr, opts.hash_alg, rng);
207    SecureVector<byte> der(req.BER_encode());
208    std::ofstream req_file(TEST_DATA_DIR "/my_cv_req.ber", std::ios::binary);
209    req_file.write((char*)&der[0], der.size());
210    req_file.close();
211 
212    // read and check signature...
213    EAC1_1_Req req_in(TEST_DATA_DIR "/my_cv_req.ber");
214    //req_in.set_domain_parameters(dom_pars);
215    std::auto_ptr<Public_Key> p_pk(req_in.subject_public_key());
216    ECDSA_PublicKey* p_ecdsa_pk = dynamic_cast<ECDSA_PublicKey*>(p_pk.get());
217    //p_ecdsa_pk->set_domain_parameters(dom_pars);
218    CHECK(p_ecdsa_pk->domain().get_order() == dom_pars.get_order());
219    bool ver_ec = req_in.check_signature(*p_pk);
220    CHECK_MESSAGE(ver_ec, "could not positively verify correct selfsigned (created by myself) cvc request");
221    }
222 
test_cvc_req_ext(RandomNumberGenerator &)223 void test_cvc_req_ext(RandomNumberGenerator&)
224    {
225    std::cout << "." << std::flush;
226 
227    EAC1_1_Req req_in(TEST_DATA_DIR "/DE1_flen_chars_cvcRequest_ECDSA.der");
228    EC_Group dom_pars(OID("1.3.36.3.3.2.8.1.1.5")); // "german curve"
229    //req_in.set_domain_parameters(dom_pars);
230    std::auto_ptr<Public_Key> p_pk(req_in.subject_public_key());
231    ECDSA_PublicKey* p_ecdsa_pk = dynamic_cast<ECDSA_PublicKey*>(p_pk.get());
232    //p_ecdsa_pk->set_domain_parameters(dom_pars);
233    CHECK(p_ecdsa_pk->domain().get_order() == dom_pars.get_order());
234    bool ver_ec = req_in.check_signature(*p_pk);
235    CHECK_MESSAGE(ver_ec, "could not positively verify correct selfsigned (external testdata) cvc request");
236    }
237 
test_cvc_ado_ext(RandomNumberGenerator &)238 void test_cvc_ado_ext(RandomNumberGenerator&)
239    {
240    std::cout << "." << std::flush;
241 
242    EAC1_1_ADO req_in(TEST_DATA_DIR "/ado.cvcreq");
243    EC_Group dom_pars(OID("1.3.36.3.3.2.8.1.1.5")); // "german curve"
244    //cout << "car = " << req_in.get_car().value() << std::endl;
245    //req_in.set_domain_parameters(dom_pars);
246    }
247 
test_cvc_ado_creation(RandomNumberGenerator & rng)248 void test_cvc_ado_creation(RandomNumberGenerator& rng)
249    {
250    std::cout << "." << std::flush;
251 
252    EAC1_1_CVC_Options opts;
253    //opts.cpi = 0;
254    opts.chr = ASN1_Chr("my_opt_chr");
255    opts.hash_alg = "SHA-256";
256 
257    // creating a non sense selfsigned cert w/o dom pars
258    EC_Group dom_pars(OID("1.3.36.3.3.2.8.1.1.11"));
259    //cout << "mod = " << hex << dom_pars.get_curve().get_p() << std::endl;
260    ECDSA_PrivateKey req_key(rng, dom_pars);
261    req_key.set_parameter_encoding(EC_DOMPAR_ENC_IMPLICITCA);
262    //EAC1_1_Req req = CVC_EAC::create_cvc_req(req_key, opts);
263    EAC1_1_Req req = CVC_EAC::create_cvc_req(req_key, opts.chr, opts.hash_alg, rng);
264    SecureVector<byte> der(req.BER_encode());
265    std::ofstream req_file(TEST_DATA_DIR "/my_cv_req.ber", std::ios::binary);
266    req_file.write((char*)&der[0], der.size());
267    req_file.close();
268 
269    // create an ado with that req
270    ECDSA_PrivateKey ado_key(rng, dom_pars);
271    EAC1_1_CVC_Options ado_opts;
272    ado_opts.car = ASN1_Car("my_ado_car");
273    ado_opts.hash_alg = "SHA-256"; // must be equal to req´s hash alg, because ado takes his sig_algo from it´s request
274 
275    //EAC1_1_ADO ado = CVC_EAC::create_ado_req(ado_key, req, ado_opts);
276    EAC1_1_ADO ado = CVC_EAC::create_ado_req(ado_key, req, ado_opts.car, rng);
277    CHECK_MESSAGE(ado.check_signature(ado_key), "failure of ado verification after creation");
278 
279    std::ofstream ado_file(TEST_DATA_DIR "/ado", std::ios::binary);
280    SecureVector<byte> ado_der(ado.BER_encode());
281    ado_file.write((char*)&ado_der[0], ado_der.size());
282    ado_file.close();
283    // read it again and check the signature
284    EAC1_1_ADO ado2(TEST_DATA_DIR "/ado");
285    CHECK(ado == ado2);
286    //ECDSA_PublicKey* p_ado_pk = dynamic_cast<ECDSA_PublicKey*>(&ado_key);
287    //bool ver = ado2.check_signature(*p_ado_pk);
288    bool ver = ado2.check_signature(ado_key);
289    CHECK_MESSAGE(ver, "failure of ado verification after reloading");
290    }
291 
test_cvc_ado_comparison(RandomNumberGenerator & rng)292 void test_cvc_ado_comparison(RandomNumberGenerator& rng)
293    {
294    std::cout << "." << std::flush;
295 
296    EAC1_1_CVC_Options opts;
297    //opts.cpi = 0;
298    opts.chr = ASN1_Chr("my_opt_chr");
299    opts.hash_alg = "SHA-224";
300 
301    // creating a non sense selfsigned cert w/o dom pars
302    EC_Group dom_pars(OID("1.3.36.3.3.2.8.1.1.11"));
303    ECDSA_PrivateKey req_key(rng, dom_pars);
304    req_key.set_parameter_encoding(EC_DOMPAR_ENC_IMPLICITCA);
305    //EAC1_1_Req req = CVC_EAC::create_cvc_req(req_key, opts);
306    EAC1_1_Req req = CVC_EAC::create_cvc_req(req_key, opts.chr, opts.hash_alg, rng);
307 
308 
309    // create an ado with that req
310    ECDSA_PrivateKey ado_key(rng, dom_pars);
311    EAC1_1_CVC_Options ado_opts;
312    ado_opts.car = ASN1_Car("my_ado_car1");
313    ado_opts.hash_alg = "SHA-224"; // must be equal to req's hash alg, because ado takes his sig_algo from it's request
314    //EAC1_1_ADO ado = CVC_EAC::create_ado_req(ado_key, req, ado_opts);
315    EAC1_1_ADO ado = CVC_EAC::create_ado_req(ado_key, req, ado_opts.car, rng);
316    CHECK_MESSAGE(ado.check_signature(ado_key), "failure of ado verification after creation");
317    // make a second one for comparison
318    EAC1_1_CVC_Options opts2;
319    //opts2.cpi = 0;
320    opts2.chr = ASN1_Chr("my_opt_chr");
321    opts2.hash_alg = "SHA-160"; // this is the only difference
322    ECDSA_PrivateKey req_key2(rng, dom_pars);
323    req_key.set_parameter_encoding(EC_DOMPAR_ENC_IMPLICITCA);
324    //EAC1_1_Req req2 = CVC_EAC::create_cvc_req(req_key2, opts2, rng);
325    EAC1_1_Req req2 = CVC_EAC::create_cvc_req(req_key2, opts2.chr, opts2.hash_alg, rng);
326    ECDSA_PrivateKey ado_key2(rng, dom_pars);
327    EAC1_1_CVC_Options ado_opts2;
328    ado_opts2.car = ASN1_Car("my_ado_car1");
329    ado_opts2.hash_alg = "SHA-160"; // must be equal to req's hash alg, because ado takes his sig_algo from it's request
330 
331    EAC1_1_ADO ado2 = CVC_EAC::create_ado_req(ado_key2, req2, ado_opts2.car, rng);
332    CHECK_MESSAGE(ado2.check_signature(ado_key2), "failure of ado verification after creation");
333 
334    CHECK_MESSAGE(ado != ado2, "ado's found to be equal where they are not");
335    //     std::ofstream ado_file(TEST_DATA_DIR "/ado");
336    //     SecureVector<byte> ado_der(ado.BER_encode());
337    //     ado_file.write((char*)&ado_der[0], ado_der.size());
338    //     ado_file.close();
339    // read it again and check the signature
340 
341    //    EAC1_1_ADO ado2(TEST_DATA_DIR "/ado");
342    //    ECDSA_PublicKey* p_ado_pk = dynamic_cast<ECDSA_PublicKey*>(&ado_key);
343    //    //bool ver = ado2.check_signature(*p_ado_pk);
344    //    bool ver = ado2.check_signature(ado_key);
345    //    CHECK_MESSAGE(ver, "failure of ado verification after reloading");
346    }
347 
test_eac_time(RandomNumberGenerator &)348 void test_eac_time(RandomNumberGenerator&)
349    {
350    std::cout << "." << std::flush;
351 
352    const u64bit current_time = system_time();
353    EAC_Time time(current_time);
354    //     std::cout << "time as std::string = " << time.as_string() << std::endl;
355    EAC_Time sooner("", ASN1_Tag(99));
356    //X509_Time sooner("", ASN1_Tag(99));
357    sooner.set_to("2007 12 12");
358    //     std::cout << "sooner as std::string = " << sooner.as_string() << std::endl;
359    EAC_Time later("2007 12 13");
360    //X509_Time later("2007 12 13");
361    //     std::cout << "later as std::string = " << later.as_string() << std::endl;
362    CHECK(sooner <= later);
363    CHECK(sooner == sooner);
364 
365    ASN1_Cex my_cex("2007 08 01");
366    my_cex.add_months(12);
367    CHECK(my_cex.get_year() == 2008);
368    CHECK_MESSAGE(my_cex.get_month() == 8, "shoult be 8, was " << my_cex.get_month());
369 
370    my_cex.add_months(4);
371    CHECK(my_cex.get_year() == 2008);
372    CHECK(my_cex.get_month() == 12);
373 
374    my_cex.add_months(4);
375    CHECK(my_cex.get_year() == 2009);
376    CHECK(my_cex.get_month() == 4);
377 
378    my_cex.add_months(41);
379    CHECK(my_cex.get_year() == 2012);
380    CHECK(my_cex.get_month() == 9);
381 
382 
383 
384    }
385 
test_ver_cvca(RandomNumberGenerator &)386 void test_ver_cvca(RandomNumberGenerator&)
387    {
388    std::cout << "." << std::flush;
389 
390    EAC1_1_CVC req_in(TEST_DATA_DIR "/cvca01.cv.crt");
391 
392    //auto_ptr<ECDSA_PublicKey> ecdsa_pk(dynamic_cast<auto_ptr<ECDSA_PublicKey> >(p_pk));
393    //ECDSA_PublicKey* p_ecdsa_pk = dynamic_cast<ECDSA_PublicKey*>(p_pk.get());
394    bool exc = false;
395 
396    std::auto_ptr<Public_Key> p_pk2(req_in.subject_public_key());
397    ECDSA_PublicKey* p_ecdsa_pk2 = dynamic_cast<ECDSA_PublicKey*>(p_pk2.get());
398    bool ver_ec = req_in.check_signature(*p_pk2);
399    CHECK_MESSAGE(ver_ec, "could not positively verify correct selfsigned cvca certificate");
400 
401    try
402       {
403       p_ecdsa_pk2->domain().get_order();
404       }
405    catch (Invalid_State)
406       {
407       exc = true;
408       }
409    CHECK(!exc);
410    }
411 
test_copy_and_assignment(RandomNumberGenerator &)412 void test_copy_and_assignment(RandomNumberGenerator&)
413    {
414    std::cout << "." << std::flush;
415 
416    EAC1_1_CVC cert_in(TEST_DATA_DIR "/cvca01.cv.crt");
417    EAC1_1_CVC cert_cp(cert_in);
418    EAC1_1_CVC cert_ass = cert_in;
419    CHECK(cert_in == cert_cp);
420    CHECK(cert_in == cert_ass);
421 
422    EAC1_1_ADO ado_in(TEST_DATA_DIR "/ado.cvcreq");
423    //EC_Group dom_pars(OID("1.3.36.3.3.2.8.1.1.5")); // "german curve"
424    EAC1_1_ADO ado_cp(ado_in);
425    EAC1_1_ADO ado_ass = ado_in;
426    CHECK(ado_in == ado_cp);
427    CHECK(ado_in == ado_ass);
428 
429    EAC1_1_Req req_in(TEST_DATA_DIR "/DE1_flen_chars_cvcRequest_ECDSA.der");
430    //EC_Group dom_pars(OID("1.3.36.3.3.2.8.1.1.5")); // "german curve"
431    EAC1_1_Req req_cp(req_in);
432    EAC1_1_Req req_ass = req_in;
433    CHECK(req_in == req_cp);
434    CHECK(req_in == req_ass);
435    }
436 
test_eac_str_illegal_values(RandomNumberGenerator &)437 void test_eac_str_illegal_values(RandomNumberGenerator&)
438    {
439    std::cout << "." << std::flush;
440 
441    bool exc = false;
442    try
443       {
444       EAC1_1_CVC(TEST_DATA_DIR "/cvca_illegal_chars.cv.crt");
445 
446       }
447    catch (Decoding_Error)
448       {
449       exc = true;
450       }
451    CHECK(exc);
452 
453    bool exc2 = false;
454    try
455       {
456       EAC1_1_CVC(TEST_DATA_DIR "/cvca_illegal_chars2.cv.crt");
457 
458       }
459    catch (Decoding_Error)
460       {
461       exc2 = true;
462       }
463    CHECK(exc2);
464    }
465 
test_tmp_eac_str_enc(RandomNumberGenerator &)466 void test_tmp_eac_str_enc(RandomNumberGenerator&)
467    {
468    std::cout << "." << std::flush;
469 
470    bool exc = false;
471    try
472       {
473       ASN1_Car("abc!+-µ\n");
474       }
475    catch (Invalid_Argument)
476       {
477       exc = true;
478       }
479    CHECK(exc);
480    //     std::string val = car.iso_8859();
481    //     std::cout << "car 8859 = " << val << std::endl;
482    //     std::cout << hex <<(unsigned char)val[1] << std::endl;
483 
484 
485    }
486 
test_cvc_chain(RandomNumberGenerator & rng)487 void test_cvc_chain(RandomNumberGenerator& rng)
488    {
489    std::cout << "." << std::flush;
490 
491    EC_Group dom_pars(OID("1.3.36.3.3.2.8.1.1.5")); // "german curve"
492    ECDSA_PrivateKey cvca_privk(rng, dom_pars);
493    std::string hash("SHA-224");
494    ASN1_Car car("DECVCA00001");
495    EAC1_1_CVC cvca_cert = DE_EAC::create_cvca(cvca_privk, hash, car, true, true, 12, rng);
496    std::ofstream cvca_file(TEST_DATA_DIR "/cvc_chain_cvca.cer", std::ios::binary);
497    SecureVector<byte> cvca_sv = cvca_cert.BER_encode();
498    cvca_file.write((char*)&cvca_sv[0], cvca_sv.size());
499    cvca_file.close();
500 
501    ECDSA_PrivateKey cvca_privk2(rng, dom_pars);
502    ASN1_Car car2("DECVCA00002");
503    EAC1_1_CVC cvca_cert2 = DE_EAC::create_cvca(cvca_privk2, hash, car2, true, true, 12, rng);
504    EAC1_1_CVC link12 = DE_EAC::link_cvca(cvca_cert, cvca_privk, cvca_cert2, rng);
505    SecureVector<byte> link12_sv = link12.BER_encode();
506    std::ofstream link12_file(TEST_DATA_DIR "/cvc_chain_link12.cer", std::ios::binary);
507    link12_file.write((char*)&link12_sv[0], link12_sv.size());
508    link12_file.close();
509 
510    // verify the link
511    CHECK(link12.check_signature(cvca_privk));
512    EAC1_1_CVC link12_reloaded(TEST_DATA_DIR "/cvc_chain_link12.cer");
513    EAC1_1_CVC cvca1_reloaded(TEST_DATA_DIR "/cvc_chain_cvca.cer");
514    std::auto_ptr<Public_Key> cvca1_rel_pk(cvca1_reloaded.subject_public_key());
515    CHECK(link12_reloaded.check_signature(*cvca1_rel_pk));
516 
517    // create first round dvca-req
518    ECDSA_PrivateKey dvca_priv_key(rng, dom_pars);
519    EAC1_1_Req dvca_req = DE_EAC::create_cvc_req(dvca_priv_key, ASN1_Chr("DEDVCAEPASS"), hash, rng);
520    std::ofstream dvca_file(TEST_DATA_DIR "/cvc_chain_dvca_req.cer", std::ios::binary);
521    SecureVector<byte> dvca_sv = dvca_req.BER_encode();
522    dvca_file.write((char*)&dvca_sv[0], dvca_sv.size());
523    dvca_file.close();
524 
525    // sign the dvca_request
526    EAC1_1_CVC dvca_cert1 = DE_EAC::sign_request(cvca_cert, cvca_privk, dvca_req, 1, 5, true, 3, 1, rng);
527    CHECK(dvca_cert1.get_car().iso_8859() == "DECVCA00001");
528    CHECK(dvca_cert1.get_chr().iso_8859() == "DEDVCAEPASS00001");
529    helper_write_file(dvca_cert1, TEST_DATA_DIR "/cvc_chain_dvca_cert1.cer");
530 
531    // make a second round dvca ado request
532    ECDSA_PrivateKey dvca_priv_key2(rng, dom_pars);
533    EAC1_1_Req dvca_req2 = DE_EAC::create_cvc_req(dvca_priv_key2, ASN1_Chr("DEDVCAEPASS"), hash, rng);
534    std::ofstream dvca_file2(TEST_DATA_DIR "/cvc_chain_dvca_req2.cer", std::ios::binary);
535    SecureVector<byte> dvca_sv2 = dvca_req2.BER_encode();
536    dvca_file2.write((char*)&dvca_sv2[0], dvca_sv2.size());
537    dvca_file2.close();
538    EAC1_1_ADO dvca_ado2 = CVC_EAC::create_ado_req(dvca_priv_key, dvca_req2,
539                                                   ASN1_Car(dvca_cert1.get_chr().iso_8859()), rng);
540    helper_write_file(dvca_ado2, TEST_DATA_DIR "/cvc_chain_dvca_ado2.cer");
541 
542    // verify the ado and sign the request too
543 
544    std::auto_ptr<Public_Key> ap_pk(dvca_cert1.subject_public_key());
545    ECDSA_PublicKey* cert_pk = dynamic_cast<ECDSA_PublicKey*>(ap_pk.get());
546 
547    //cert_pk->set_domain_parameters(dom_pars);
548    //std::cout << "dvca_cert.public_point.size() = " << ec::EC2OSP(cert_pk->get_public_point(), ec::PointGFp::COMPRESSED).size() << std::endl;
549    EAC1_1_CVC dvca_cert1_reread(TEST_DATA_DIR "/cvc_chain_cvca.cer");
550    CHECK(dvca_ado2.check_signature(*cert_pk));
551 
552    CHECK(dvca_ado2.check_signature(dvca_priv_key)); // must also work
553 
554    EAC1_1_Req dvca_req2b = dvca_ado2.get_request();
555    helper_write_file(dvca_req2b, TEST_DATA_DIR "/cvc_chain_dvca_req2b.cer");
556    CHECK(helper_files_equal(TEST_DATA_DIR "/cvc_chain_dvca_req2b.cer", TEST_DATA_DIR "/cvc_chain_dvca_req2.cer"));
557    EAC1_1_CVC dvca_cert2 = DE_EAC::sign_request(cvca_cert, cvca_privk, dvca_req2b, 2, 5, true, 3, 1, rng);
558    CHECK(dvca_cert2.get_car().iso_8859() == "DECVCA00001");
559    CHECK_MESSAGE(dvca_cert2.get_chr().iso_8859() == "DEDVCAEPASS00002",
560                  "chr = " << dvca_cert2.get_chr().iso_8859());
561 
562    // make a first round IS request
563    ECDSA_PrivateKey is_priv_key(rng, dom_pars);
564    EAC1_1_Req is_req = DE_EAC::create_cvc_req(is_priv_key, ASN1_Chr("DEIS"), hash, rng);
565    helper_write_file(is_req, TEST_DATA_DIR "/cvc_chain_is_req.cer");
566 
567    // sign the IS request
568    //dvca_cert1.set_domain_parameters(dom_pars);
569    EAC1_1_CVC is_cert1 = DE_EAC::sign_request(dvca_cert1, dvca_priv_key, is_req, 1, 5, true, 3, 1, rng);
570    CHECK_MESSAGE(is_cert1.get_car().iso_8859() == "DEDVCAEPASS00001", "car = " << is_cert1.get_car().iso_8859());
571    CHECK(is_cert1.get_chr().iso_8859() == "DEIS00001");
572    helper_write_file(is_cert1, TEST_DATA_DIR "/cvc_chain_is_cert.cer");
573 
574    // verify the signature of the certificate
575    CHECK(is_cert1.check_signature(dvca_priv_key));
576    }
577 
578 }
579 
do_cvc_tests(Botan::RandomNumberGenerator & rng)580 u32bit do_cvc_tests(Botan::RandomNumberGenerator& rng)
581    {
582    std::cout << "Testing CVC: " << std::flush;
583 
584    test_enc_gen_selfsigned(rng);
585    test_enc_gen_req(rng);
586    test_cvc_req_ext(rng);
587    test_cvc_ado_ext(rng);
588    test_cvc_ado_creation(rng);
589    test_cvc_ado_comparison(rng);
590    test_eac_time(rng);
591    test_ver_cvca(rng);
592    test_copy_and_assignment(rng);
593    test_eac_str_illegal_values(rng);
594    test_tmp_eac_str_enc(rng);
595    test_cvc_chain(rng);
596    std::cout << std::endl;
597 
598    return 0;
599    }
600 #else
do_cvc_tests(Botan::RandomNumberGenerator &)601 u32bit do_cvc_tests(Botan::RandomNumberGenerator&) { return 0; }
602 #endif
603