diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/cert/cvc/asn1_eac_str.cpp | 127 | ||||
-rw-r--r-- | src/lib/cert/cvc/asn1_eac_tm.cpp | 297 | ||||
-rw-r--r-- | src/lib/cert/cvc/cvc_ado.cpp | 127 | ||||
-rw-r--r-- | src/lib/cert/cvc/cvc_ado.h | 98 | ||||
-rw-r--r-- | src/lib/cert/cvc/cvc_cert.cpp | 135 | ||||
-rw-r--r-- | src/lib/cert/cvc/cvc_cert.h | 116 | ||||
-rw-r--r-- | src/lib/cert/cvc/cvc_gen_cert.h | 180 | ||||
-rw-r--r-- | src/lib/cert/cvc/cvc_req.cpp | 53 | ||||
-rw-r--r-- | src/lib/cert/cvc/cvc_req.h | 59 | ||||
-rw-r--r-- | src/lib/cert/cvc/cvc_self.cpp | 339 | ||||
-rw-r--r-- | src/lib/cert/cvc/cvc_self.h | 180 | ||||
-rw-r--r-- | src/lib/cert/cvc/eac_asn_obj.h | 239 | ||||
-rw-r--r-- | src/lib/cert/cvc/eac_obj.h | 55 | ||||
-rw-r--r-- | src/lib/cert/cvc/ecdsa_sig.cpp | 59 | ||||
-rw-r--r-- | src/lib/cert/cvc/ecdsa_sig.h | 61 | ||||
-rw-r--r-- | src/lib/cert/cvc/info.txt | 35 | ||||
-rw-r--r-- | src/lib/cert/cvc/signed_obj.cpp | 95 | ||||
-rw-r--r-- | src/lib/cert/cvc/signed_obj.h | 95 | ||||
-rw-r--r-- | src/tests/test_cvc.cpp | 611 |
19 files changed, 0 insertions, 2961 deletions
diff --git a/src/lib/cert/cvc/asn1_eac_str.cpp b/src/lib/cert/cvc/asn1_eac_str.cpp deleted file mode 100644 index 72ad24926..000000000 --- a/src/lib/cert/cvc/asn1_eac_str.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/* -* Simple ASN.1 String Types -* (C) 2007 FlexSecure GmbH -* 2008-2011 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include <botan/eac_asn_obj.h> -#include <botan/der_enc.h> -#include <botan/ber_dec.h> -#include <botan/charset.h> -#include <botan/parsing.h> -#include <sstream> -#include <ios> - -namespace Botan { - -/* -* Create an ASN1_EAC_String -*/ -ASN1_EAC_String::ASN1_EAC_String(const std::string& str, ASN1_Tag t) : m_tag(t) - { - m_iso_8859_str = Charset::transcode(str, LOCAL_CHARSET, LATIN1_CHARSET); - - if(!sanity_check()) - throw Invalid_Argument("ASN1_EAC_String contains illegal characters"); - } - -/* -* Return this string in ISO 8859-1 encoding -*/ -std::string ASN1_EAC_String::iso_8859() const - { - return m_iso_8859_str; - } - -/* -* Return this string in local encoding -*/ -std::string ASN1_EAC_String::value() const - { - return Charset::transcode(m_iso_8859_str, LATIN1_CHARSET, LOCAL_CHARSET); - } - -/* -* Return the type of this string object -*/ -ASN1_Tag ASN1_EAC_String::tagging() const - { - return m_tag; - } - -/* -* DER encode an ASN1_EAC_String -*/ -void ASN1_EAC_String::encode_into(DER_Encoder& encoder) const - { - std::string value = iso_8859(); - encoder.add_object(tagging(), APPLICATION, value); - } - -/* -* Decode a BER encoded ASN1_EAC_String -*/ -void ASN1_EAC_String::decode_from(BER_Decoder& source) - { - BER_Object obj = source.get_next_object(); - - if(obj.type_tag != m_tag) - { - std::stringstream ss; - - ss << "ASN1_EAC_String tag mismatch, tag was " - << std::hex << obj.type_tag - << " expected " - << std::hex << m_tag; - - throw Decoding_Error(ss.str()); - } - - Character_Set charset_is; - charset_is = LATIN1_CHARSET; - - try - { - *this = ASN1_EAC_String( - Charset::transcode(ASN1::to_string(obj), LOCAL_CHARSET, charset_is), - obj.type_tag); - } - catch(Invalid_Argument& inv_arg) - { - throw Decoding_Error(std::string("ASN1_EAC_String decoding failed: ") + - inv_arg.what()); - } - } - -// checks for compliance to the alphabet defined in TR-03110 v1.10, 2007-08-20 -// p. 43 -bool ASN1_EAC_String::sanity_check() const - { - const byte* rep = reinterpret_cast<const byte*>(m_iso_8859_str.data()); - const size_t rep_len = m_iso_8859_str.size(); - - for(size_t i = 0; i != rep_len; ++i) - { - if((rep[i] < 0x20) || ((rep[i] >= 0x7F) && (rep[i] < 0xA0))) - return false; - } - - return true; - } - -bool operator==(const ASN1_EAC_String& lhs, const ASN1_EAC_String& rhs) - { - return (lhs.iso_8859() == rhs.iso_8859()); - } - -ASN1_Car::ASN1_Car(std::string const& str) - : ASN1_EAC_String(str, ASN1_Tag(2)) - {} - -ASN1_Chr::ASN1_Chr(std::string const& str) - : ASN1_EAC_String(str, ASN1_Tag(32)) - {} - -} diff --git a/src/lib/cert/cvc/asn1_eac_tm.cpp b/src/lib/cert/cvc/asn1_eac_tm.cpp deleted file mode 100644 index 9c65fcf6a..000000000 --- a/src/lib/cert/cvc/asn1_eac_tm.cpp +++ /dev/null @@ -1,297 +0,0 @@ -/* -* EAC Time Types -* (C) 2007 FlexSecure GmbH -* 2008-2009 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include <botan/eac_asn_obj.h> -#include <botan/der_enc.h> -#include <botan/ber_dec.h> -#include <botan/charset.h> -#include <botan/parsing.h> -#include <botan/internal/rounding.h> -#include <botan/calendar.h> -#include <sstream> -#include <iomanip> - -namespace Botan { - -namespace { - -std::vector<byte> enc_two_digit(u32bit in) - { - std::vector<byte> result; - in %= 100; - if(in < 10) - result.push_back(0x00); - else - { - u32bit y_first_pos = round_down<u32bit>(in, 10) / 10; - result.push_back(static_cast<byte>(y_first_pos)); - } - - u32bit y_sec_pos = in % 10; - result.push_back(static_cast<byte>(y_sec_pos)); - return result; - } - -u32bit dec_two_digit(byte b1, byte b2) - { - u32bit upper = b1; - u32bit lower = b2; - - if(upper > 9 || lower > 9) - throw Invalid_Argument("CVC dec_two_digit value too large"); - - return upper*10 + lower; - } - -} - -/* -* Create an EAC_Time -*/ -EAC_Time::EAC_Time(const std::chrono::system_clock::time_point& time, - ASN1_Tag t) : m_tag(t) - { - calendar_point cal = calendar_value(time); - - m_year = cal.year; - m_month = cal.month; - m_day = cal.day; - } - -/* -* Create an EAC_Time -*/ -EAC_Time::EAC_Time(const std::string& t_spec, ASN1_Tag t) : m_tag(t) - { - set_to(t_spec); - } - -/* -* Create an EAC_Time -*/ -EAC_Time::EAC_Time(u32bit y, u32bit m, u32bit d, ASN1_Tag t) : - m_year(y), m_month(m), m_day(d), m_tag(t) - { - } - -/* -* Set the time with a human readable string -*/ -void EAC_Time::set_to(const std::string& time_str) - { - if(time_str == "") - { - m_year = m_month = m_day = 0; - return; - } - - std::vector<std::string> params; - std::string current; - - for(u32bit j = 0; j != time_str.size(); ++j) - { - if(Charset::is_digit(time_str[j])) - current += time_str[j]; - else - { - if(current != "") - params.push_back(current); - current.clear(); - } - } - if(current != "") - params.push_back(current); - - if(params.size() != 3) - throw Invalid_Argument("Invalid time specification " + time_str); - - m_year = to_u32bit(params[0]); - m_month = to_u32bit(params[1]); - m_day = to_u32bit(params[2]); - - if(!passes_sanity_check()) - throw Invalid_Argument("Invalid time specification " + time_str); - } - - -/* -* DER encode a EAC_Time -*/ -void EAC_Time::encode_into(DER_Encoder& der) const - { - der.add_object(m_tag, APPLICATION, - encoded_eac_time()); - } - -/* -* Return a string representation of the time -*/ -std::string EAC_Time::as_string() const - { - if(time_is_set() == false) - throw Invalid_State("EAC_Time::as_string: No time set"); - - return std::to_string(m_year * 10000 + m_month * 100 + m_day); - } - -/* -* Return if the time has been set somehow -*/ -bool EAC_Time::time_is_set() const - { - return (m_year != 0); - } - -/* -* Return a human readable string representation -*/ -std::string EAC_Time::readable_string() const - { - if(time_is_set() == false) - throw Invalid_State("EAC_Time::readable_string: No time set"); - - // desired format: "%04d/%02d/%02d" - std::stringstream output; - output << std::setfill('0') - << std::setw(4) << m_year << "/" - << std::setw(2) << m_month << "/" - << std::setw(2) << m_day; - return output.str(); - } - -/* -* Do a general sanity check on the time -*/ -bool EAC_Time::passes_sanity_check() const - { - if(m_year < 2000 || m_year > 2099) - return false; - if(m_month == 0 || m_month > 12) - return false; - if(m_day == 0 || m_day > 31) - return false; - - return true; - } - -/* -* modification functions -*/ -void EAC_Time::add_years(u32bit years) - { - m_year += years; - } - -void EAC_Time::add_months(u32bit months) - { - m_year += months/12; - m_month += months % 12; - if(m_month > 12) - { - m_year += 1; - m_month -= 12; - } - } - -/* -* Compare this time against another -*/ -s32bit EAC_Time::cmp(const EAC_Time& other) const - { - if(time_is_set() == false) - throw Invalid_State("EAC_Time::cmp: No time set"); - - const s32bit EARLIER = -1, LATER = 1, SAME_TIME = 0; - - if(m_year < other.m_year) return EARLIER; - if(m_year > other.m_year) return LATER; - if(m_month < other.m_month) return EARLIER; - if(m_month > other.m_month) return LATER; - if(m_day < other.m_day) return EARLIER; - if(m_day > other.m_day) return LATER; - - return SAME_TIME; - } - -/* -* Compare two EAC_Times for in various ways -*/ -bool operator==(const EAC_Time& t1, const EAC_Time& t2) - { - return (t1.cmp(t2) == 0); - } - -bool operator!=(const EAC_Time& t1, const EAC_Time& t2) - { - return (t1.cmp(t2) != 0); - } - -bool operator<=(const EAC_Time& t1, const EAC_Time& t2) - { - return (t1.cmp(t2) <= 0); - } - -bool operator>=(const EAC_Time& t1, const EAC_Time& t2) - { - return (t1.cmp(t2) >= 0); - } - -bool operator>(const EAC_Time& t1, const EAC_Time& t2) - { - return (t1.cmp(t2) > 0); - } - -bool operator<(const EAC_Time& t1, const EAC_Time& t2) - { - return (t1.cmp(t2) < 0); - } - -/* -* Decode a BER encoded EAC_Time -*/ -void EAC_Time::decode_from(BER_Decoder& source) - { - BER_Object obj = source.get_next_object(); - - if(obj.type_tag != m_tag) - throw BER_Decoding_Error("Tag mismatch when decoding"); - - if(obj.value.size() != 6) - { - throw Decoding_Error("EAC_Time decoding failed"); - } - - try - { - u32bit tmp_year = dec_two_digit(obj.value[0], obj.value[1]); - u32bit tmp_mon = dec_two_digit(obj.value[2], obj.value[3]); - u32bit tmp_day = dec_two_digit(obj.value[4], obj.value[5]); - m_year = tmp_year + 2000; - m_month = tmp_mon; - m_day = tmp_day; - } - catch (Invalid_Argument) - { - throw Decoding_Error("EAC_Time decoding failed"); - } - - } - -/* -* make the value an octet string for encoding -*/ -std::vector<byte> EAC_Time::encoded_eac_time() const - { - std::vector<byte> result; - result += enc_two_digit(m_year); - result += enc_two_digit(m_month); - result += enc_two_digit(m_day); - return result; - } - -} diff --git a/src/lib/cert/cvc/cvc_ado.cpp b/src/lib/cert/cvc/cvc_ado.cpp deleted file mode 100644 index f803c6bf3..000000000 --- a/src/lib/cert/cvc/cvc_ado.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/* -* CVC Certificate Constructor -* (C) 2007 FlexSecure GmbH -* 2008 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include <botan/cvc_ado.h> -#include <fstream> - -namespace Botan { - -EAC1_1_ADO::EAC1_1_ADO(DataSource& in) - { - init(in); - do_decode(); - } - -EAC1_1_ADO::EAC1_1_ADO(const std::string& in) - { - DataSource_Stream stream(in, true); - init(stream); - do_decode(); - } - -void EAC1_1_ADO::force_decode() - { - std::vector<byte> inner_cert; - BER_Decoder(m_tbs_bits) - .start_cons(ASN1_Tag(33)) - .raw_bytes(inner_cert) - .end_cons() - .decode(m_car) - .verify_end(); - - std::vector<byte> req_bits = DER_Encoder() - .start_cons(ASN1_Tag(33), APPLICATION) - .raw_bytes(inner_cert) - .end_cons() - .get_contents_unlocked(); - - DataSource_Memory req_source(req_bits); - m_req = EAC1_1_Req(req_source); - m_sig_algo = m_req.m_sig_algo; - } - -std::vector<byte> EAC1_1_ADO::make_signed(PK_Signer& signer, - const std::vector<byte>& tbs_bits, - RandomNumberGenerator& rng) - { - const std::vector<byte> concat_sig = signer.sign_message(tbs_bits, rng); - - return DER_Encoder() - .start_cons(ASN1_Tag(7), APPLICATION) - .raw_bytes(tbs_bits) - .encode(concat_sig, OCTET_STRING, ASN1_Tag(55), APPLICATION) - .end_cons() - .get_contents_unlocked(); - } - -ASN1_Car EAC1_1_ADO::get_car() const - { - return m_car; - } - -void EAC1_1_ADO::decode_info(DataSource& source, - std::vector<byte> & res_tbs_bits, - ECDSA_Signature & res_sig) - { - std::vector<byte> concat_sig; - std::vector<byte> cert_inner_bits; - ASN1_Car car; - - BER_Decoder(source) - .start_cons(ASN1_Tag(7)) - .start_cons(ASN1_Tag(33)) - .raw_bytes(cert_inner_bits) - .end_cons() - .decode(car) - .decode(concat_sig, OCTET_STRING, ASN1_Tag(55), APPLICATION) - .end_cons(); - - std::vector<byte> enc_cert = DER_Encoder() - .start_cons(ASN1_Tag(33), APPLICATION) - .raw_bytes(cert_inner_bits) - .end_cons() - .get_contents_unlocked(); - - res_tbs_bits = enc_cert; - res_tbs_bits += DER_Encoder().encode(car).get_contents(); - res_sig = decode_concatenation(concat_sig); - } - -void EAC1_1_ADO::encode(Pipe& out, X509_Encoding encoding) const - { - if(encoding == PEM) - throw Invalid_Argument("EAC1_1_ADO::encode() cannot PEM encode an EAC object"); - - auto concat_sig = EAC1_1_obj<EAC1_1_ADO>::m_sig.get_concatenation(); - - out.write(DER_Encoder() - .start_cons(ASN1_Tag(7), APPLICATION) - .raw_bytes(m_tbs_bits) - .encode(concat_sig, OCTET_STRING, ASN1_Tag(55), APPLICATION) - .end_cons() - .get_contents()); - } - -std::vector<byte> EAC1_1_ADO::tbs_data() const - { - return m_tbs_bits; - } - -bool EAC1_1_ADO::operator==(EAC1_1_ADO const& rhs) const - { - return (this->get_concat_sig() == rhs.get_concat_sig() - && this->tbs_data() == rhs.tbs_data() - && this->get_car() == rhs.get_car()); - } - -EAC1_1_Req EAC1_1_ADO::get_request() const - { - return m_req; - } - -} diff --git a/src/lib/cert/cvc/cvc_ado.h b/src/lib/cert/cvc/cvc_ado.h deleted file mode 100644 index 4b861ec81..000000000 --- a/src/lib/cert/cvc/cvc_ado.h +++ /dev/null @@ -1,98 +0,0 @@ -/* -* EAC1_1 CVC ADO -* (C) 2008 Falko Strenzke -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_EAC_CVC_ADO_H__ -#define BOTAN_EAC_CVC_ADO_H__ - -#include <botan/eac_obj.h> -#include <botan/eac_asn_obj.h> -#include <botan/cvc_req.h> -#include <string> - -namespace Botan { - -/** -* This class represents a TR03110 (EAC) v1.1 CVC ADO request -*/ - - // CRTP continuation from EAC1_1_obj -class BOTAN_DLL EAC1_1_ADO : public EAC1_1_obj<EAC1_1_ADO> - { - public: - friend class EAC1_1_obj<EAC1_1_ADO>; - - /** - * Construct a CVC ADO request from a DER encoded CVC ADO request file. - * @param str the path to the DER encoded file - */ - EAC1_1_ADO(const std::string& str); - - /** - * Construct a CVC ADO request from a data source - * @param source the data source - */ - EAC1_1_ADO(DataSource& source); - - /** - * Create a signed CVC ADO request from to be signed (TBS) data - * @param signer the signer used to sign the CVC ADO request - * @param tbs_bits the TBS data to sign - * @param rng a random number generator - */ - static std::vector<byte> make_signed( - PK_Signer& signer, - const std::vector<byte>& tbs_bits, - RandomNumberGenerator& rng); - - /** - * Get the CAR of this CVC ADO request - * @result the CAR of this CVC ADO request - */ - ASN1_Car get_car() const; - - /** - * Get the CVC request contained in this object. - * @result the CVC request inside this CVC ADO request - */ - EAC1_1_Req get_request() const; - - /** - * Encode this object into a pipe. Only DER is supported. - * @param out the pipe to encode this object into - * @param encoding the encoding type to use, must be DER - */ - void encode(Pipe& out, X509_Encoding encoding) const; - - bool operator==(EAC1_1_ADO const& rhs) const; - - /** - * Get the TBS data of this CVC ADO request. - * @result the TBS data - */ - std::vector<byte> tbs_data() const; - - virtual ~EAC1_1_ADO() {} - private: - ASN1_Car m_car; - EAC1_1_Req m_req; - - void force_decode(); - static void decode_info(DataSource& source, - std::vector<byte> & res_tbs_bits, - ECDSA_Signature & res_sig); - }; - -inline bool operator!=(EAC1_1_ADO const& lhs, EAC1_1_ADO const& rhs) - { - return (!(lhs == rhs)); - } - -} - -#endif - - diff --git a/src/lib/cert/cvc/cvc_cert.cpp b/src/lib/cert/cvc/cvc_cert.cpp deleted file mode 100644 index 280a8acda..000000000 --- a/src/lib/cert/cvc/cvc_cert.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/* -* (C) 2007 FlexSecure GmbH -* 2008-2010 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include <botan/cvc_cert.h> -#include <botan/oids.h> - -namespace Botan { - -ASN1_Car EAC1_1_CVC::get_car() const - { - return m_car; - } - -ASN1_Ced EAC1_1_CVC::get_ced() const - { - return m_ced; - } -ASN1_Cex EAC1_1_CVC::get_cex() const - { - return m_cex; - } -u32bit EAC1_1_CVC::get_chat_value() const - { - return m_chat_val; - } - -/* -* Decode the TBSCertificate data -*/ -void EAC1_1_CVC::force_decode() - { - std::vector<byte> enc_pk; - std::vector<byte> enc_chat_val; - size_t cpi; - BER_Decoder tbs_cert(m_tbs_bits); - tbs_cert.decode(cpi, ASN1_Tag(41), APPLICATION) - .decode(m_car) - .start_cons(ASN1_Tag(73)) - .raw_bytes(enc_pk) - .end_cons() - .decode(m_chr) - .start_cons(ASN1_Tag(76)) - .decode(m_chat_oid) - .decode(enc_chat_val, OCTET_STRING, ASN1_Tag(19), APPLICATION) - .end_cons() - .decode(m_ced) - .decode(m_cex) - .verify_end(); - - if(enc_chat_val.size() != 1) - throw Decoding_Error("CertificateHolderAuthorizationValue was not of length 1"); - - if(cpi != 0) - throw Decoding_Error("EAC1_1 certificate's cpi was not 0"); - - m_pk = decode_eac1_1_key(enc_pk, m_sig_algo); - - m_chat_val = enc_chat_val[0]; - - m_self_signed = (m_car.iso_8859() == m_chr.iso_8859()); - } - -/* -* CVC Certificate Constructor -*/ -EAC1_1_CVC::EAC1_1_CVC(DataSource& in) - { - init(in); - m_self_signed = false; - do_decode(); - } - -EAC1_1_CVC::EAC1_1_CVC(const std::string& in) - { - DataSource_Stream stream(in, true); - init(stream); - m_self_signed = false; - do_decode(); - } - -bool EAC1_1_CVC::operator==(EAC1_1_CVC const& rhs) const - { - return (tbs_data() == rhs.tbs_data() - && get_concat_sig() == rhs.get_concat_sig()); - } - -ECDSA_PublicKey* decode_eac1_1_key(const std::vector<byte>&, - AlgorithmIdentifier&) - { - throw Internal_Error("decode_eac1_1_key: Unimplemented"); - return 0; - } - -EAC1_1_CVC make_cvc_cert(PK_Signer& signer, - const std::vector<byte>& public_key, - ASN1_Car const& car, - ASN1_Chr const& chr, - byte holder_auth_templ, - ASN1_Ced ced, - ASN1_Cex cex, - RandomNumberGenerator& rng) - { - OID chat_oid(OIDS::lookup("CertificateHolderAuthorizationTemplate")); - std::vector<byte> enc_chat_val; - enc_chat_val.push_back(holder_auth_templ); - - std::vector<byte> enc_cpi; - enc_cpi.push_back(0x00); - std::vector<byte> tbs = DER_Encoder() - .encode(enc_cpi, OCTET_STRING, ASN1_Tag(41), APPLICATION) // cpi - .encode(car) - .raw_bytes(public_key) - .encode(chr) - .start_cons(ASN1_Tag(76), APPLICATION) - .encode(chat_oid) - .encode(enc_chat_val, OCTET_STRING, ASN1_Tag(19), APPLICATION) - .end_cons() - .encode(ced) - .encode(cex) - .get_contents_unlocked(); - - std::vector<byte> signed_cert = - EAC1_1_CVC::make_signed(signer, - EAC1_1_CVC::build_cert_body(tbs), - rng); - - DataSource_Memory source(signed_cert); - return EAC1_1_CVC(source); - } - -} diff --git a/src/lib/cert/cvc/cvc_cert.h b/src/lib/cert/cvc/cvc_cert.h deleted file mode 100644 index a45388550..000000000 --- a/src/lib/cert/cvc/cvc_cert.h +++ /dev/null @@ -1,116 +0,0 @@ -/* -* EAC1_1 CVC -* (C) 2008 Falko Strenzke -* 2008 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_CVC_EAC_H__ -#define BOTAN_CVC_EAC_H__ - -#include <botan/cvc_gen_cert.h> -#include <botan/ecdsa.h> -#include <string> - -namespace Botan { - -/** -* This class represents TR03110 (EAC) v1.1 CV Certificates -*/ -class BOTAN_DLL EAC1_1_CVC : public EAC1_1_gen_CVC<EAC1_1_CVC>//Signed_Object - { - public: - friend class EAC1_1_obj<EAC1_1_CVC>; - - /** - * Get the CAR of the certificate. - * @result the CAR of the certificate - */ - ASN1_Car get_car() const; - - /** - * Get the CED of this certificate. - * @result the CED this certificate - */ - ASN1_Ced get_ced() const; - - /** - * Get the CEX of this certificate. - * @result the CEX this certificate - */ - ASN1_Cex get_cex() const; - - /** - * Get the CHAT value. - * @result the CHAT value - */ - u32bit get_chat_value() const; - - bool operator==(const EAC1_1_CVC&) const; - - /** - * Construct a CVC from a data source - * @param source the data source - */ - EAC1_1_CVC(DataSource& source); - - /** - * Construct a CVC from a file - * @param str the path to the certificate file - */ - EAC1_1_CVC(const std::string& str); - - virtual ~EAC1_1_CVC() {} - private: - void force_decode(); - EAC1_1_CVC() {} - - ASN1_Car m_car; - ASN1_Ced m_ced; - ASN1_Cex m_cex; - byte m_chat_val; - OID m_chat_oid; - }; - -/* -* Comparison -*/ -inline bool operator!=(EAC1_1_CVC const& lhs, EAC1_1_CVC const& rhs) - { - return !(lhs == rhs); - } - -/** -* Create an arbitrary EAC 1.1 CVC. -* The desired key encoding must be set within the key (if applicable). -* @param signer the signer used to sign the certificate -* @param public_key the DER encoded public key to appear in -* the certificate -* @param car the CAR of the certificate -* @param chr the CHR of the certificate -* @param holder_auth_templ the holder authorization value byte to -* appear in the CHAT of the certificate -* @param ced the CED to appear in the certificate -* @param cex the CEX to appear in the certificate -* @param rng a random number generator -*/ -EAC1_1_CVC BOTAN_DLL make_cvc_cert(PK_Signer& signer, - const std::vector<byte>& public_key, - ASN1_Car const& car, - ASN1_Chr const& chr, - byte holder_auth_templ, - ASN1_Ced ced, - ASN1_Cex cex, - RandomNumberGenerator& rng); - -/** -* Decode an EAC encoding ECDSA key -*/ -BOTAN_DLL ECDSA_PublicKey* decode_eac1_1_key(const std::vector<byte>& enc_key, - AlgorithmIdentifier& sig_algo); - -} - -#endif - diff --git a/src/lib/cert/cvc/cvc_gen_cert.h b/src/lib/cert/cvc/cvc_gen_cert.h deleted file mode 100644 index 2c3bca73d..000000000 --- a/src/lib/cert/cvc/cvc_gen_cert.h +++ /dev/null @@ -1,180 +0,0 @@ -/* -* EAC1_1 general CVC -* (C) 2008 Falko Strenzke -* 2008-2010 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_EAC_CVC_GEN_CERT_H__ -#define BOTAN_EAC_CVC_GEN_CERT_H__ - -#include <botan/eac_obj.h> -#include <botan/eac_asn_obj.h> -#include <botan/ecdsa.h> -#include <botan/pubkey.h> - -namespace Botan { - -/** -* This class represents TR03110 (EAC) v1.1 generalized CV Certificates -*/ -template<typename Derived> -class EAC1_1_gen_CVC : public EAC1_1_obj<Derived> // CRTP continuation from EAC1_1_obj - { - friend class EAC1_1_obj<EAC1_1_gen_CVC>; - - public: - - /** - * Get this certificates public key. - * @result this certificates public key - */ - Public_Key* subject_public_key() const; - - /** - * Find out whether this object is self signed. - * @result true if this object is self signed - */ - bool is_self_signed() const; - - /** - * Get the CHR of the certificate. - * @result the CHR of the certificate - */ - ASN1_Chr get_chr() const; - - /** - * Put the DER encoded version of this object into a pipe. PEM - * is not supported. - * @param out the pipe to push the DER encoded version into - * @param encoding the encoding to use. Must be DER. - */ - void encode(Pipe& out, X509_Encoding encoding) const; - - /** - * Get the to-be-signed (TBS) data of this object. - * @result the TBS data of this object - */ - std::vector<byte> tbs_data() const; - - /** - * Build the DER encoded certifcate body of an object - * @param tbs the data to be signed - * @result the correctly encoded body of the object - */ - static std::vector<byte> build_cert_body(const std::vector<byte>& tbs); - - /** - * Create a signed generalized CVC object. - * @param signer the signer used to sign this object - * @param tbs_bits the body the generalized CVC object to be signed - * @param rng a random number generator - * @result the DER encoded signed generalized CVC object - */ - static std::vector<byte> make_signed( - PK_Signer& signer, - const std::vector<byte>& tbs_bits, - RandomNumberGenerator& rng); - - EAC1_1_gen_CVC() { m_pk = nullptr; } - - virtual ~EAC1_1_gen_CVC<Derived>() - { delete m_pk; } - - protected: - ECDSA_PublicKey* m_pk; - ASN1_Chr m_chr; - bool m_self_signed; - - static void decode_info(DataSource& source, - std::vector<byte> & res_tbs_bits, - ECDSA_Signature & res_sig); - - }; - -template<typename Derived> ASN1_Chr EAC1_1_gen_CVC<Derived>::get_chr() const - { - return m_chr; - } - -template<typename Derived> bool EAC1_1_gen_CVC<Derived>::is_self_signed() const - { - return m_self_signed; - } - -template<typename Derived> -std::vector<byte> EAC1_1_gen_CVC<Derived>::make_signed( - PK_Signer& signer, - const std::vector<byte>& tbs_bits, - RandomNumberGenerator& rng) // static - { - const auto concat_sig = signer.sign_message(tbs_bits, rng); - - return DER_Encoder() - .start_cons(ASN1_Tag(33), APPLICATION) - .raw_bytes(tbs_bits) - .encode(concat_sig, OCTET_STRING, ASN1_Tag(55), APPLICATION) - .end_cons() - .get_contents_unlocked(); - } - -template<typename Derived> -Public_Key* EAC1_1_gen_CVC<Derived>::subject_public_key() const - { - return new ECDSA_PublicKey(*m_pk); - } - -template<typename Derived> std::vector<byte> EAC1_1_gen_CVC<Derived>::build_cert_body(const std::vector<byte>& tbs) - { - return DER_Encoder() - .start_cons(ASN1_Tag(78), APPLICATION) - .raw_bytes(tbs) - .end_cons().get_contents_unlocked(); - } - -template<typename Derived> std::vector<byte> EAC1_1_gen_CVC<Derived>::tbs_data() const - { - return build_cert_body(EAC1_1_obj<Derived>::m_tbs_bits); - } - -template<typename Derived> void EAC1_1_gen_CVC<Derived>::encode(Pipe& out, X509_Encoding encoding) const - { - std::vector<byte> concat_sig(EAC1_1_obj<Derived>::m_sig.get_concatenation()); - std::vector<byte> der = DER_Encoder() - .start_cons(ASN1_Tag(33), APPLICATION) - .start_cons(ASN1_Tag(78), APPLICATION) - .raw_bytes(EAC1_1_obj<Derived>::m_tbs_bits) - .end_cons() - .encode(concat_sig, OCTET_STRING, ASN1_Tag(55), APPLICATION) - .end_cons() - .get_contents_unlocked(); - - if (encoding == PEM) - throw Invalid_Argument("EAC1_1_gen_CVC::encode() cannot PEM encode an EAC object"); - else - out.write(der); - } - -template<typename Derived> -void EAC1_1_gen_CVC<Derived>::decode_info( - DataSource& source, - std::vector<byte> & res_tbs_bits, - ECDSA_Signature & res_sig) - { - std::vector<byte> concat_sig; - BER_Decoder(source) - .start_cons(ASN1_Tag(33)) - .start_cons(ASN1_Tag(78)) - .raw_bytes(res_tbs_bits) - .end_cons() - .decode(concat_sig, OCTET_STRING, ASN1_Tag(55), APPLICATION) - .end_cons(); - res_sig = decode_concatenation(concat_sig); - } - -} - -#endif - - diff --git a/src/lib/cert/cvc/cvc_req.cpp b/src/lib/cert/cvc/cvc_req.cpp deleted file mode 100644 index 1cb6b50ac..000000000 --- a/src/lib/cert/cvc/cvc_req.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* -* (C) 2007 FlexSecure GmbH -* 2008-2010 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include <botan/cvc_req.h> -#include <botan/cvc_cert.h> -#include <botan/ber_dec.h> - -namespace Botan { - -bool EAC1_1_Req::operator==(EAC1_1_Req const& rhs) const - { - return (this->tbs_data() == rhs.tbs_data() && - this->get_concat_sig() == rhs.get_concat_sig()); - } - -void EAC1_1_Req::force_decode() - { - std::vector<byte> enc_pk; - BER_Decoder tbs_cert(m_tbs_bits); - size_t cpi; - tbs_cert.decode(cpi, ASN1_Tag(41), APPLICATION) - .start_cons(ASN1_Tag(73)) - .raw_bytes(enc_pk) - .end_cons() - .decode(m_chr) - .verify_end(); - - if(cpi != 0) - throw Decoding_Error("EAC1_1 requests cpi was not 0"); - - m_pk = decode_eac1_1_key(enc_pk, m_sig_algo); - } - -EAC1_1_Req::EAC1_1_Req(DataSource& in) - { - init(in); - m_self_signed = true; - do_decode(); - } - -EAC1_1_Req::EAC1_1_Req(const std::string& in) - { - DataSource_Stream stream(in, true); - init(stream); - m_self_signed = true; - do_decode(); - } - -} diff --git a/src/lib/cert/cvc/cvc_req.h b/src/lib/cert/cvc/cvc_req.h deleted file mode 100644 index b71a8e764..000000000 --- a/src/lib/cert/cvc/cvc_req.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -* EAC1_1 CVC Request -* (C) 2008 Falko Strenzke -* 2010 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_EAC_CVC_REQ_H__ -#define BOTAN_EAC_CVC_REQ_H__ - -#include <botan/cvc_gen_cert.h> - -namespace Botan { - -/** -* This class represents TR03110 v1.1 EAC CV Certificate Requests. -*/ -class BOTAN_DLL EAC1_1_Req : public EAC1_1_gen_CVC<EAC1_1_Req> - { - public: - friend class EAC1_1_ADO; - friend class EAC1_1_obj<EAC1_1_Req>; - - /** - * Compare for equality with other - * @param other compare for equality with this object - */ - bool operator==(const EAC1_1_Req& other) const; - - /** - * Construct a CVC request from a data source. - * @param source the data source - */ - EAC1_1_Req(DataSource& source); - - /** - * Construct a CVC request from a DER encoded CVC request file. - * @param str the path to the DER encoded file - */ - EAC1_1_Req(const std::string& str); - - virtual ~EAC1_1_Req(){} - private: - void force_decode(); - EAC1_1_Req() {} - }; - -/* -* Comparison Operator -*/ -inline bool operator!=(EAC1_1_Req const& lhs, EAC1_1_Req const& rhs) - { - return !(lhs == rhs); - } - -} - -#endif diff --git a/src/lib/cert/cvc/cvc_self.cpp b/src/lib/cert/cvc/cvc_self.cpp deleted file mode 100644 index fa59f4c6d..000000000 --- a/src/lib/cert/cvc/cvc_self.cpp +++ /dev/null @@ -1,339 +0,0 @@ -/* -* (C) 2007 FlexSecure GmbH -* 2008-2010 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include <botan/cvc_self.h> -#include <botan/ecc_key.h> -#include <botan/point_gfp.h> -#include <botan/oids.h> -#include <sstream> - -namespace Botan { - -namespace { - -/* -* cvc CHAT values -*/ -enum CHAT_values{ - CVCA = 0xC0, - DVCA_domestic = 0x80, - DVCA_foreign = 0x40, - IS = 0x00, - - IRIS = 0x02, - FINGERPRINT = 0x01 -}; - -void encode_eac_bigint(DER_Encoder& der, const BigInt& x, ASN1_Tag tag) - { - der.encode(BigInt::encode_1363(x, x.bytes()), OCTET_STRING, tag); - } - -std::vector<byte> eac_1_1_encoding(const EC_PublicKey* key, - const OID& sig_algo) - { - if(key->domain_format() == EC_DOMPAR_ENC_OID) - throw Encoding_Error("CVC encoder: cannot encode parameters by OID"); - - const EC_Group& domain = key->domain(); - - // This is why we can't have nice things - - DER_Encoder enc; - enc.start_cons(ASN1_Tag(73), APPLICATION) - .encode(sig_algo); - - if(key->domain_format() == EC_DOMPAR_ENC_EXPLICIT) - { - encode_eac_bigint(enc, domain.get_curve().get_p(), ASN1_Tag(1)); - encode_eac_bigint(enc, domain.get_curve().get_a(), ASN1_Tag(2)); - encode_eac_bigint(enc, domain.get_curve().get_b(), ASN1_Tag(3)); - - enc.encode(EC2OSP(domain.get_base_point(), PointGFp::UNCOMPRESSED), - OCTET_STRING, ASN1_Tag(4)); - - encode_eac_bigint(enc, domain.get_order(), ASN1_Tag(4)); - } - - enc.encode(EC2OSP(key->public_point(), PointGFp::UNCOMPRESSED), - OCTET_STRING, ASN1_Tag(6)); - - if(key->domain_format() == EC_DOMPAR_ENC_EXPLICIT) - encode_eac_bigint(enc, domain.get_cofactor(), ASN1_Tag(7)); - - enc.end_cons(); - - return enc.get_contents_unlocked(); - } - -std::string padding_and_hash_from_oid(OID const& oid) - { - std::string padding_and_hash = OIDS::lookup(oid); // use the hash - - if(padding_and_hash.substr(0,6) != "ECDSA/") - throw Invalid_State("CVC: Can only use ECDSA, not " + padding_and_hash); - - padding_and_hash.erase(0, padding_and_hash.find("/") + 1); - return padding_and_hash; - } - -} - -namespace CVC_EAC { - -EAC1_1_CVC create_self_signed_cert(Private_Key const& key, - EAC1_1_CVC_Options const& opt, - RandomNumberGenerator& rng) - { - // NOTE: we ignore the value of opt.chr - - const ECDSA_PrivateKey* priv_key = dynamic_cast<const ECDSA_PrivateKey*>(&key); - - if(priv_key == 0) - throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type"); - - ASN1_Chr chr(opt.car.value()); - - AlgorithmIdentifier sig_algo; - std::string padding_and_hash("EMSA1(" + opt.hash_alg + ")"); - sig_algo.oid = OIDS::lookup(priv_key->algo_name() + "/" + padding_and_hash); - sig_algo = AlgorithmIdentifier(sig_algo.oid, AlgorithmIdentifier::USE_NULL_PARAM); - - PK_Signer signer(*priv_key, padding_and_hash); - - std::vector<byte> enc_public_key = eac_1_1_encoding(priv_key, sig_algo.oid); - - return make_cvc_cert(signer, - enc_public_key, - opt.car, chr, - opt.holder_auth_templ, - opt.ced, opt.cex, rng); - } - -EAC1_1_Req create_cvc_req(Private_Key const& key, - ASN1_Chr const& chr, - std::string const& hash_alg, - RandomNumberGenerator& rng) - { - - ECDSA_PrivateKey const* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&key); - if (priv_key == 0) - { - throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type"); - } - AlgorithmIdentifier sig_algo; - std::string padding_and_hash("EMSA1(" + hash_alg + ")"); - sig_algo.oid = OIDS::lookup(priv_key->algo_name() + "/" + padding_and_hash); - sig_algo = AlgorithmIdentifier(sig_algo.oid, AlgorithmIdentifier::USE_NULL_PARAM); - - PK_Signer signer(*priv_key, padding_and_hash); - - std::vector<byte> enc_public_key = eac_1_1_encoding(priv_key, sig_algo.oid); - - std::vector<byte> enc_cpi; - enc_cpi.push_back(0x00); - std::vector<byte> tbs = DER_Encoder() - .encode(enc_cpi, OCTET_STRING, ASN1_Tag(41), APPLICATION) - .raw_bytes(enc_public_key) - .encode(chr) - .get_contents_unlocked(); - - std::vector<byte> signed_cert = - EAC1_1_gen_CVC<EAC1_1_Req>::make_signed(signer, - EAC1_1_gen_CVC<EAC1_1_Req>::build_cert_body(tbs), - rng); - - DataSource_Memory source(signed_cert); - return EAC1_1_Req(source); - } - -EAC1_1_ADO create_ado_req(Private_Key const& key, - EAC1_1_Req const& req, - ASN1_Car const& car, - RandomNumberGenerator& rng) - { - - ECDSA_PrivateKey const* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&key); - if (priv_key == 0) - { - throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type"); - } - - std::string padding_and_hash = padding_and_hash_from_oid(req.signature_algorithm().oid); - PK_Signer signer(*priv_key, padding_and_hash); - std::vector<byte> tbs_bits = req.BER_encode(); - tbs_bits += DER_Encoder().encode(car).get_contents(); - - std::vector<byte> signed_cert = - EAC1_1_ADO::make_signed(signer, tbs_bits, rng); - - DataSource_Memory source(signed_cert); - return EAC1_1_ADO(source); - } - -} // namespace CVC_EAC -namespace DE_EAC -{ - -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) - { - ECDSA_PrivateKey const* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&key); - if (priv_key == 0) - { - throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type"); - } - EAC1_1_CVC_Options opts; - opts.car = car; - - opts.ced = ASN1_Ced(std::chrono::system_clock::now()); - opts.cex = ASN1_Cex(opts.ced); - opts.cex.add_months(cvca_validity_months); - opts.holder_auth_templ = (CVCA | (iris * IRIS) | (fingerpr * FINGERPRINT)); - opts.hash_alg = hash; - return CVC_EAC::create_self_signed_cert(*priv_key, opts, rng); - } - - - -EAC1_1_CVC link_cvca(EAC1_1_CVC const& signer, - Private_Key const& key, - EAC1_1_CVC const& signee, - RandomNumberGenerator& rng) - { - const ECDSA_PrivateKey* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&key); - - if (priv_key == 0) - throw Invalid_Argument("link_cvca(): unsupported key type"); - - ASN1_Ced ced(std::chrono::system_clock::now()); - ASN1_Cex cex(signee.get_cex()); - if (*static_cast<EAC_Time*>(&ced) > *static_cast<EAC_Time*>(&cex)) - { - std::string detail("link_cvca(): validity periods of provided certificates don't overlap: currend time = ced = "); - detail += ced.as_string(); - detail += ", signee.cex = "; - detail += cex.as_string(); - throw Invalid_Argument(detail); - } - if (signer.signature_algorithm() != signee.signature_algorithm()) - { - throw Invalid_Argument("link_cvca(): signature algorithms of signer and signee don't match"); - } - AlgorithmIdentifier sig_algo = signer.signature_algorithm(); - std::string padding_and_hash = padding_and_hash_from_oid(sig_algo.oid); - PK_Signer pk_signer(*priv_key, padding_and_hash); - std::unique_ptr<Public_Key> pk(signee.subject_public_key()); - ECDSA_PublicKey* subj_pk = dynamic_cast<ECDSA_PublicKey*>(pk.get()); - subj_pk->set_parameter_encoding(EC_DOMPAR_ENC_EXPLICIT); - - std::vector<byte> enc_public_key = eac_1_1_encoding(priv_key, sig_algo.oid); - - return make_cvc_cert(pk_signer, enc_public_key, - signer.get_car(), - signee.get_chr(), - signer.get_chat_value(), - ced, cex, - rng); - } - -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) - { - ECDSA_PrivateKey const* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&key); - if (priv_key == 0) - { - throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type"); - } - std::string chr_str = signee.get_chr().value(); - - std::string seqnr_string = std::to_string(seqnr); - - while(seqnr_string.size() < seqnr_len) - seqnr_string = '0' + seqnr_string; - - chr_str += seqnr_string; - ASN1_Chr chr(chr_str); - std::string padding_and_hash = padding_and_hash_from_oid(signee.signature_algorithm().oid); - PK_Signer pk_signer(*priv_key, padding_and_hash); - std::unique_ptr<Public_Key> pk(signee.subject_public_key()); - ECDSA_PublicKey* subj_pk = dynamic_cast<ECDSA_PublicKey*>(pk.get()); - std::unique_ptr<Public_Key> signer_pk(signer_cert.subject_public_key()); - - // for the case that the domain parameters are not set... - // (we use those from the signer because they must fit) - //subj_pk->set_domain_parameters(priv_key->domain_parameters()); - - subj_pk->set_parameter_encoding(EC_DOMPAR_ENC_IMPLICITCA); - - AlgorithmIdentifier sig_algo(signer_cert.signature_algorithm()); - - ASN1_Ced ced(std::chrono::system_clock::now()); - - u32bit chat_val; - u32bit chat_low = signer_cert.get_chat_value() & 0x3; // take the chat rights from signer - ASN1_Cex cex(ced); - if ((signer_cert.get_chat_value() & CVCA) == CVCA) - { - // we sign a dvca - cex.add_months(dvca_validity_months); - if (domestic) - chat_val = DVCA_domestic | chat_low; - else - chat_val = DVCA_foreign | chat_low; - } - else if ((signer_cert.get_chat_value() & DVCA_domestic) == DVCA_domestic || - (signer_cert.get_chat_value() & DVCA_foreign) == DVCA_foreign) - { - cex.add_months(ca_is_validity_months); - chat_val = IS | chat_low; - } - else - { - throw Invalid_Argument("sign_request(): encountered illegal value for CHAT"); - // (IS cannot sign certificates) - } - - std::vector<byte> enc_public_key = eac_1_1_encoding(priv_key, sig_algo.oid); - - return make_cvc_cert(pk_signer, enc_public_key, - ASN1_Car(signer_cert.get_chr().iso_8859()), - chr, - chat_val, - ced, - cex, - rng); - } - -EAC1_1_Req create_cvc_req(Private_Key const& prkey, - ASN1_Chr const& chr, - std::string const& hash_alg, - RandomNumberGenerator& rng) - { - ECDSA_PrivateKey const* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&prkey); - if (priv_key == 0) - { - throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type"); - } - ECDSA_PrivateKey key(*priv_key); - key.set_parameter_encoding(EC_DOMPAR_ENC_IMPLICITCA); - return CVC_EAC::create_cvc_req(key, chr, hash_alg, rng); - } - -} // namespace DE_EAC - -} diff --git a/src/lib/cert/cvc/cvc_self.h b/src/lib/cert/cvc/cvc_self.h deleted file mode 100644 index d56e96c40..000000000 --- a/src/lib/cert/cvc/cvc_self.h +++ /dev/null @@ -1,180 +0,0 @@ -/* -* CVC Self-Signed Certificate -* (C) 2007 FlexSecure GmbH -* 2008 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_CVC_EAC_SELF_H__ -#define BOTAN_CVC_EAC_SELF_H__ - -#include <botan/cvc_cert.h> -#include <botan/ecdsa.h> -#include <botan/asn1_obj.h> -#include <botan/cvc_req.h> -#include <botan/cvc_ado.h> - -namespace Botan { - -/** -* This class represents a set of options used for the creation of CVC certificates -*/ -class BOTAN_DLL EAC1_1_CVC_Options - { - public: - - // public member variable: - ASN1_Car car; - - // public member variable: - ASN1_Chr chr; - - // public member variable: - byte holder_auth_templ; - - // public member variable: - ASN1_Ced ced; - - // public member variable: - ASN1_Cex cex; - - // public member variable: - std::string hash_alg; - }; - -/** -* This namespace represents general EAC 1.1 convenience functions. -*/ -namespace CVC_EAC { - -/** -* Create a selfsigned CVCA -* @param rng the rng to use -* @param key the ECDSA private key to be used to sign the certificate -* @param opts used to set several parameters. Necessary are: -* car, holder_auth_templ, hash_alg, ced, cex and hash_alg -* @result the self signed certificate -*/ - -EAC1_1_CVC BOTAN_DLL create_self_signed_cert(Private_Key const& key, - EAC1_1_CVC_Options const& opts, - RandomNumberGenerator& rng); -/** -* Create a CVC request. The key encoding will be according to the provided private key. -* @param priv_key the private key associated with the requesting entity -* @param chr the chr to appear in the certificate (to be provided without -* sequence number) -* @param hash_alg the string defining the hash algorithm to be used for the creation -* of the signature -* @param rng the rng to use -* @result the new request -*/ -EAC1_1_Req BOTAN_DLL create_cvc_req(Private_Key const& priv_key, - ASN1_Chr const& chr, - std::string const& hash_alg, - RandomNumberGenerator& rng); - -/** -* Create an ADO from a request object. -* @param priv_key the private key used to sign the ADO -* @param req the request forming the body of the ADO -* @param car the CAR forming the body of the ADO, i.e. the -* CHR of the entity associated with the provided private key -* @param rng the rng to use -*/ -EAC1_1_ADO BOTAN_DLL create_ado_req(Private_Key const& priv_key, - EAC1_1_Req const& req, - ASN1_Car const& car, - RandomNumberGenerator& rng); -} -/** -* This namespace represents EAC 1.1 CVC convenience functions -* following the specific german requirements. -*/ - -namespace DE_EAC { - -/** -* Create a CVCA certificate. -* @param priv_key the private key associated with the CVCA certificate -* to be created -* @param hash the string identifying the hash algorithm to be used -* for signing the certificate to be created -* @param car the CAR of the certificate to be created -* @param iris indicates whether the entity associated with the certificate -* shall be entitled to read the biometrical iris image -* @param fingerpr indicates whether the entity associated with the certificate -* shall be entitled to read the biometrical fingerprint image -* @param cvca_validity_months length of time in months this will be valid -* @param rng a random number generator -* @result the CVCA certificate created -*/ -EAC1_1_CVC BOTAN_DLL create_cvca(Private_Key const& priv_key, - std::string const& hash, - ASN1_Car const& car, - bool iris, - bool fingerpr, - u32bit cvca_validity_months, - RandomNumberGenerator& rng); - -/** -* Create a link certificate between two CVCA certificates. The key -* encoding will be implicitCA. -* @param signer the cvca certificate associated with the signing -* entity -* @param priv_key the private key associated with the signer -* @param to_be_signed the certificate which whose CAR/CHR will be -* the holder of the link certificate -* @param rng a random number generator -*/ -EAC1_1_CVC BOTAN_DLL link_cvca(EAC1_1_CVC const& signer, - Private_Key const& priv_key, - EAC1_1_CVC const& to_be_signed, - RandomNumberGenerator& rng); - -/** -* Create a CVC request. The key encoding will be implicitCA. -* @param priv_key the private key associated with the requesting entity -* @param chr the chr to appear in the certificate (to be provided without -* sequence number) -* @param hash_alg the string defining the hash algorithm to be used for the creation -* of the signature -* @param rng a random number generator -* @result the new request -*/ -EAC1_1_Req BOTAN_DLL create_cvc_req(Private_Key const& priv_key, - ASN1_Chr const& chr, - std::string const& hash_alg, - RandomNumberGenerator& rng); - -/** -* Sign a CVC request. -* @param signer_cert the certificate of the signing entity -* @param priv_key the private key of the signing entity -* @param req the request to be signed -* @param seqnr the sequence number of the certificate to be created -* @param seqnr_len the number of digits the sequence number will be -* encoded in -* @param domestic indicates whether to sign a domestic or a foreign -* certificate: set to true for domestic -* @param dvca_validity_months validity period in months -* @param ca_is_validity_months validity period in months -* @param rng a random number generator -* @result the new certificate -* -**/ -EAC1_1_CVC BOTAN_DLL sign_request(EAC1_1_CVC const& signer_cert, - Private_Key const& priv_key, - EAC1_1_Req const& req, - u32bit seqnr, - u32bit seqnr_len, - bool domestic, - u32bit dvca_validity_months, - u32bit ca_is_validity_months, - RandomNumberGenerator& rng); -} - -} - -#endif diff --git a/src/lib/cert/cvc/eac_asn_obj.h b/src/lib/cert/cvc/eac_asn_obj.h deleted file mode 100644 index b4dcb6342..000000000 --- a/src/lib/cert/cvc/eac_asn_obj.h +++ /dev/null @@ -1,239 +0,0 @@ -/* -* EAC ASN.1 Objects -* (C) 2007-2008 FlexSecure GmbH -* 2008-2010 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_EAC_ASN1_OBJ_H__ -#define BOTAN_EAC_ASN1_OBJ_H__ - -#include <botan/asn1_obj.h> -#include <chrono> - -namespace Botan { - -/** -* This class represents CVC EAC Time objects. -* It only models year, month and day. Only limited sanity checks of -* the inputted date value are performed. -*/ -class BOTAN_DLL EAC_Time : public ASN1_Object - { - public: - void encode_into(class DER_Encoder&) const; - void decode_from(class BER_Decoder&); - - /** - * Get a this objects value as a string. - * @return date string - */ - std::string as_string() const; - - /** - * Get a this objects value as a readable formatted string. - * @return date string - */ - std::string readable_string() const; - - /** - * Find out whether this object's values have been set. - * @return true if this object's internal values are set - */ - bool time_is_set() const; - - /** - * Compare this to another EAC_Time object. - * @return -1 if this object's date is earlier than - * other, +1 in the opposite case, and 0 if both dates are - * equal. - */ - s32bit cmp(const EAC_Time& other) const; - - /** - * Set this' value by a string value. - * @param str a string in the format "yyyy mm dd", - * e.g. "2007 08 01" - */ - void set_to(const std::string& str); - - /** - * Add the specified number of years to this. - * @param years the number of years to add - */ - void add_years(u32bit years); - - /** - * Add the specified number of months to this. - * @param months the number of months to add - */ - void add_months(u32bit months); - - /** - * Get the year value of this objects. - * @return year value - */ - u32bit get_year() const { return m_year; } - - /** - * Get the month value of this objects. - * @return month value - */ - u32bit get_month() const { return m_month; } - - /** - * Get the day value of this objects. - * @return day value - */ - u32bit get_day() const { return m_day; } - - EAC_Time(const std::chrono::system_clock::time_point& time, - ASN1_Tag tag = ASN1_Tag(0)); - - EAC_Time(const std::string& yyyy_mm_dd, - ASN1_Tag tag = ASN1_Tag(0)); - - EAC_Time(u32bit year, u32bit month, u32bit day, - ASN1_Tag tag = ASN1_Tag(0)); - - virtual ~EAC_Time() {} - private: - std::vector<byte> encoded_eac_time() const; - bool passes_sanity_check() const; - u32bit m_year, m_month, m_day; - ASN1_Tag m_tag; - }; - -/** -* This class represents CVC CEDs. Only limited sanity checks of -* the inputted date value are performed. -*/ -class BOTAN_DLL ASN1_Ced : public EAC_Time - { - public: - /** - * Construct a CED from a string value. - * @param str a string in the format "yyyy mm dd", - * e.g. "2007 08 01" - */ - ASN1_Ced(const std::string& str = "") : - EAC_Time(str, ASN1_Tag(37)) {} - - /** - * Construct a CED from a time point - */ - ASN1_Ced(const std::chrono::system_clock::time_point& time) : - EAC_Time(time, ASN1_Tag(37)) {} - - /** - * Copy constructor (for general EAC_Time objects). - * @param other the object to copy from - */ - ASN1_Ced(const EAC_Time& other) : - EAC_Time(other.get_year(), other.get_month(), other.get_day(), - ASN1_Tag(37)) - {} - }; - -/** -* This class represents CVC CEXs. Only limited sanity checks of -* the inputted date value are performed. -*/ -class BOTAN_DLL ASN1_Cex : public EAC_Time - { - public: - /** - * Construct a CEX from a string value. - * @param str a string in the format "yyyy mm dd", - * e.g. "2007 08 01" - */ - ASN1_Cex(const std::string& str = "") : - EAC_Time(str, ASN1_Tag(36)) {} - - ASN1_Cex(const std::chrono::system_clock::time_point& time) : - EAC_Time(time, ASN1_Tag(36)) {} - - ASN1_Cex(const EAC_Time& other) : - EAC_Time(other.get_year(), other.get_month(), other.get_day(), - ASN1_Tag(36)) - {} - }; - -/** -* Base class for car/chr of cv certificates. -*/ -class BOTAN_DLL ASN1_EAC_String: public ASN1_Object - { - public: - void encode_into(class DER_Encoder&) const; - void decode_from(class BER_Decoder&); - - /** - * Get this objects string value. - * @return string value - */ - std::string value() const; - - /** - * Get this objects string value. - * @return string value in iso8859 encoding - */ - std::string iso_8859() const; - - ASN1_Tag tagging() const; - ASN1_EAC_String(const std::string& str, ASN1_Tag the_tag); - - virtual ~ASN1_EAC_String() {} - protected: - bool sanity_check() const; - private: - std::string m_iso_8859_str; - ASN1_Tag m_tag; - }; - -/** -* This class represents CARs of CVCs. (String tagged with 2) -*/ -class BOTAN_DLL ASN1_Car : public ASN1_EAC_String - { - public: - /** - * Create a CAR with the specified content. - * @param str the CAR value - */ - ASN1_Car(std::string const& str = ""); - }; - -/** -* This class represents CHRs of CVCs (tag 32) -*/ -class BOTAN_DLL ASN1_Chr : public ASN1_EAC_String - { - public: - /** - * Create a CHR with the specified content. - * @param str the CHR value - */ - ASN1_Chr(std::string const& str = ""); - }; - -/* -* Comparison Operations -*/ -bool BOTAN_DLL operator==(const EAC_Time&, const EAC_Time&); -bool BOTAN_DLL operator!=(const EAC_Time&, const EAC_Time&); -bool BOTAN_DLL operator<=(const EAC_Time&, const EAC_Time&); -bool BOTAN_DLL operator>=(const EAC_Time&, const EAC_Time&); -bool BOTAN_DLL operator>(const EAC_Time&, const EAC_Time&); -bool BOTAN_DLL operator<(const EAC_Time&, const EAC_Time&); - -bool BOTAN_DLL operator==(const ASN1_EAC_String&, const ASN1_EAC_String&); -inline bool operator!=(const ASN1_EAC_String& lhs, const ASN1_EAC_String& rhs) - { - return !(lhs == rhs); - } - -} - -#endif diff --git a/src/lib/cert/cvc/eac_obj.h b/src/lib/cert/cvc/eac_obj.h deleted file mode 100644 index a6e676076..000000000 --- a/src/lib/cert/cvc/eac_obj.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -* EAC1_1 objects -* (C) 2008 Falko Strenzke -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_EAC_OBJ_H__ -#define BOTAN_EAC_OBJ_H__ - -#include <botan/signed_obj.h> -#include <botan/ecdsa_sig.h> - -namespace Botan { - -/** -* TR03110 v1.1 EAC CV Certificate -*/ -template<typename Derived> // CRTP is used enable the call sequence: -class EAC1_1_obj : public EAC_Signed_Object - { - public: - /** - * Return the signature as a concatenation of the encoded parts. - * @result the concatenated signature - */ - std::vector<byte> get_concat_sig() const - { return m_sig.get_concatenation(); } - - bool check_signature(class Public_Key& key) const - { - return EAC_Signed_Object::check_signature(key, m_sig.DER_encode()); - } - - protected: - ECDSA_Signature m_sig; - - void init(DataSource& in) - { - try - { - Derived::decode_info(in, m_tbs_bits, m_sig); - } - catch(Decoding_Error) - { - throw Decoding_Error(m_PEM_label_pref + " decoding failed"); - } - } - - virtual ~EAC1_1_obj<Derived>(){} - }; - -} - -#endif diff --git a/src/lib/cert/cvc/ecdsa_sig.cpp b/src/lib/cert/cvc/ecdsa_sig.cpp deleted file mode 100644 index 5e85d7932..000000000 --- a/src/lib/cert/cvc/ecdsa_sig.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* -* ECDSA Signature -* (C) 2007 Falko Strenzke, FlexSecure GmbH -* (C) 2008-2010 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include <botan/ecdsa_sig.h> - -namespace Botan { - -ECDSA_Signature::ECDSA_Signature(const std::vector<byte>& ber) - { - BER_Decoder(ber) - .start_cons(SEQUENCE) - .decode(m_r) - .decode(m_s) - .end_cons() - .verify_end(); - } - -std::vector<byte> ECDSA_Signature::DER_encode() const - { - return DER_Encoder() - .start_cons(SEQUENCE) - .encode(get_r()) - .encode(get_s()) - .end_cons() - .get_contents_unlocked(); - } - -std::vector<byte> ECDSA_Signature::get_concatenation() const - { - // use the larger - const size_t enc_len = m_r > m_s ? m_r.bytes() : m_s.bytes(); - - const auto sv_r = BigInt::encode_1363(m_r, enc_len); - const auto sv_s = BigInt::encode_1363(m_s, enc_len); - - secure_vector<byte> result(sv_r); - result += sv_s; - return unlock(result); - } - -ECDSA_Signature decode_concatenation(const std::vector<byte>& concat) - { - if(concat.size() % 2 != 0) - throw Invalid_Argument("Erroneous length of signature"); - - const size_t rs_len = concat.size() / 2; - - BigInt r = BigInt::decode(&concat[0], rs_len); - BigInt s = BigInt::decode(&concat[rs_len], rs_len); - - return ECDSA_Signature(r, s); - } - -} diff --git a/src/lib/cert/cvc/ecdsa_sig.h b/src/lib/cert/cvc/ecdsa_sig.h deleted file mode 100644 index 2845cbec9..000000000 --- a/src/lib/cert/cvc/ecdsa_sig.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -* ECDSA Signature -* (C) 2007 Falko Strenzke, FlexSecure GmbH -* (C) 2008-2010 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_ECDSA_SIGNATURE_H__ -#define BOTAN_ECDSA_SIGNATURE_H__ - -#include <botan/bigint.h> -#include <botan/der_enc.h> -#include <botan/ber_dec.h> - -namespace Botan { - -/** -* Class representing an ECDSA signature -*/ -class BOTAN_DLL ECDSA_Signature - { - public: - friend class ECDSA_Signature_Decoder; - - ECDSA_Signature() {} - ECDSA_Signature(const BigInt& r, const BigInt& s) : - m_r(r), m_s(s) {} - - ECDSA_Signature(const std::vector<byte>& ber); - - const BigInt& get_r() const { return m_r; } - const BigInt& get_s() const { return m_s; } - - /** - * return the r||s - */ - std::vector<byte> get_concatenation() const; - - std::vector<byte> DER_encode() const; - - bool operator==(const ECDSA_Signature& other) const - { - return (get_r() == other.get_r() && get_s() == other.get_s()); - } - - private: - BigInt m_r; - BigInt m_s; - }; - -inline bool operator!=(const ECDSA_Signature& lhs, const ECDSA_Signature& rhs) - { - return !(lhs == rhs); - } - -ECDSA_Signature decode_concatenation(const std::vector<byte>& concatenation); - -} - -#endif diff --git a/src/lib/cert/cvc/info.txt b/src/lib/cert/cvc/info.txt deleted file mode 100644 index e3da5435e..000000000 --- a/src/lib/cert/cvc/info.txt +++ /dev/null @@ -1,35 +0,0 @@ -define CARD_VERIFIABLE_CERTIFICATES 20131128 -load_on request - -<header:public> -cvc_ado.h -cvc_cert.h -cvc_gen_cert.h -cvc_req.h -cvc_self.h -eac_asn_obj.h -eac_obj.h -ecdsa_sig.h -signed_obj.h -</header:public> - -<source> -asn1_eac_str.cpp -asn1_eac_tm.cpp -ecdsa_sig.cpp -cvc_ado.cpp -cvc_cert.cpp -cvc_req.cpp -cvc_self.cpp -signed_obj.cpp -</source> - -<requires> -asn1 -bigint -ecdsa -filters -oid_lookup -pem -pubkey -</requires> diff --git a/src/lib/cert/cvc/signed_obj.cpp b/src/lib/cert/cvc/signed_obj.cpp deleted file mode 100644 index 1e3849663..000000000 --- a/src/lib/cert/cvc/signed_obj.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* -* EAC SIGNED Object -* (C) 1999-2010 Jack Lloyd -* 2007 FlexSecure GmbH -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include <botan/signed_obj.h> -#include <botan/pubkey.h> -#include <botan/oids.h> - -namespace Botan { - -/* -* Return a BER encoded X.509 object -*/ -std::vector<byte> EAC_Signed_Object::BER_encode() const - { - Pipe ber; - ber.start_msg(); - encode(ber, RAW_BER); - ber.end_msg(); - return unlock(ber.read_all()); - } - -/* -* Return a PEM encoded X.509 object -*/ -std::string EAC_Signed_Object::PEM_encode() const - { - Pipe pem; - pem.start_msg(); - encode(pem, PEM); - pem.end_msg(); - return pem.read_all_as_string(); - } - -/* -* Return the algorithm used to sign this object -*/ -AlgorithmIdentifier EAC_Signed_Object::signature_algorithm() const - { - return m_sig_algo; - } - -bool EAC_Signed_Object::check_signature(Public_Key& pub_key, - const std::vector<byte>& sig) const - { - try - { - std::vector<std::string> sig_info = - split_on(OIDS::lookup(m_sig_algo.oid), '/'); - - if(sig_info.size() != 2 || sig_info[0] != pub_key.algo_name()) - { - return false; - } - - std::string padding = sig_info[1]; - Signature_Format format = - (pub_key.message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363; - - std::vector<byte> to_sign = tbs_data(); - - PK_Verifier verifier(pub_key, padding, format); - return verifier.verify_message(to_sign, sig); - } - catch(...) - { - return false; - } - } - -/* -* Try to decode the actual information -*/ -void EAC_Signed_Object::do_decode() - { - try { - force_decode(); - } - catch(Decoding_Error& e) - { - const std::string what = e.what(); - throw Decoding_Error(m_PEM_label_pref + " decoding failed (" + what + ")"); - } - catch(Invalid_Argument& e) - { - const std::string what = e.what(); - throw Decoding_Error(m_PEM_label_pref + " decoding failed (" + what + ")"); - } - } - -} diff --git a/src/lib/cert/cvc/signed_obj.h b/src/lib/cert/cvc/signed_obj.h deleted file mode 100644 index b3fe20f31..000000000 --- a/src/lib/cert/cvc/signed_obj.h +++ /dev/null @@ -1,95 +0,0 @@ -/* -* EAC SIGNED Object -* (C) 2007 FlexSecure GmbH -* 2008 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_EAC_SIGNED_OBJECT_H__ -#define BOTAN_EAC_SIGNED_OBJECT_H__ - -#include <botan/asn1_obj.h> -#include <botan/x509_key.h> -#include <botan/pipe.h> -#include <vector> - -namespace Botan { - -/** -* This class represents abstract signed EAC object -*/ -class BOTAN_DLL EAC_Signed_Object - { - public: - /** - * Get the TBS (to-be-signed) data in this object. - * @return DER encoded TBS data of this object - */ - virtual std::vector<byte> tbs_data() const = 0; - - /** - * Get the signature of this object as a concatenation, i.e. if the - * signature consists of multiple parts (like in the case of ECDSA) - * these will be concatenated. - * @return signature as a concatenation of its parts - */ - - /* - NOTE: this is here only because abstract signature objects have - not yet been introduced - */ - virtual std::vector<byte> get_concat_sig() const = 0; - - /** - * Get the signature algorithm identifier used to sign this object. - * @result the signature algorithm identifier - */ - AlgorithmIdentifier signature_algorithm() const; - - /** - * Check the signature of this object. - * @param key the public key associated with this signed object - * @param sig the signature we are checking - * @return true if the signature was created by the private key - * associated with this public key - */ - bool check_signature(class Public_Key& key, - const std::vector<byte>& sig) const; - - /** - * Write this object DER encoded into a specified pipe. - * @param pipe the pipe to write the encoded object to - * @param encoding the encoding type to use - */ - virtual void encode(Pipe& pipe, - X509_Encoding encoding = PEM) const = 0; - - /** - * BER encode this object. - * @return result containing the BER representation of this object. - */ - std::vector<byte> BER_encode() const; - - /** - * PEM encode this object. - * @return result containing the PEM representation of this object. - */ - std::string PEM_encode() const; - - virtual ~EAC_Signed_Object() {} - protected: - void do_decode(); - EAC_Signed_Object() {} - - AlgorithmIdentifier m_sig_algo; - std::vector<byte> m_tbs_bits; - std::string m_PEM_label_pref; - std::vector<std::string> m_PEM_labels_allowed; - private: - virtual void force_decode() = 0; - }; - -} - -#endif diff --git a/src/tests/test_cvc.cpp b/src/tests/test_cvc.cpp deleted file mode 100644 index dc4b50ebd..000000000 --- a/src/tests/test_cvc.cpp +++ /dev/null @@ -1,611 +0,0 @@ -/* -* CVC EAC1.1 tests -* -* (C) 2008 Falko Strenzke ([email protected]) -* 2008,2015 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include "tests.h" - -#if defined(BOTAN_HAS_CARD_VERIFIABLE_CERTIFICATES) - -#include <botan/ecdsa.h> -#include <botan/x509cert.h> -#include <botan/x509self.h> -#include <botan/oids.h> -#include <botan/cvc_self.h> -#include <botan/cvc_cert.h> -#include <botan/cvc_ado.h> - -#endif - -namespace Botan_Tests { - -namespace { - -#if defined(BOTAN_HAS_CARD_VERIFIABLE_CERTIFICATES) - -using namespace Botan; - -// helper functions -void helper_write_file(EAC_Signed_Object const& to_write, const std::string& file_path) - { - std::vector<byte> sv = to_write.BER_encode(); - std::ofstream cert_file(file_path, std::ios::binary); - cert_file.write((char*)sv.data(), sv.size()); - cert_file.close(); - } - -bool helper_files_equal(const std::string& file_path1, const std::string& file_path2) - { - std::ifstream cert_1_in(file_path1); - std::ifstream cert_2_in(file_path2); - std::vector<byte> sv1; - std::vector<byte> sv2; - if (!cert_1_in || !cert_2_in) - { - return false; - } - while (!cert_1_in.eof()) - { - char now; - cert_1_in.read(&now, 1); - sv1.push_back(now); - } - while (!cert_2_in.eof()) - { - char now; - cert_2_in.read(&now, 1); - sv2.push_back(now); - } - if (sv1.size() == 0) - { - return false; - } - return sv1 == sv2; - } - -Test::Result test_cvc_times() - { - Test::Result result("CVC"); - - auto time1 = Botan::EAC_Time("2008-02-01"); - auto time2 = Botan::EAC_Time("2008/02/28"); - auto time3 = Botan::EAC_Time("2004-06-14"); - - result.confirm("time1 set", time1.time_is_set()); - result.confirm("time2 set", time2.time_is_set()); - result.confirm("time3 set", time3.time_is_set()); - - result.test_eq("time1 readable_string", time1.readable_string(), "2008/02/01"); - result.test_eq("time2 readable_string", time2.readable_string(), "2008/02/28"); - result.test_eq("time3 readable_string", time3.readable_string(), "2004/06/14"); - - result.test_eq("not set", Botan::EAC_Time("").time_is_set(), false); - - const std::vector<std::string> invalid = { - " ", - "2008`02-01", - "9999-02-01", - "2000-02-01 17", - "999921" - }; - - for(auto&& v : invalid) - { - result.test_throws("invalid time " + v, [v]() { Botan::EAC_Time w(v); }); - } - - return result; - } - -Test::Result test_enc_gen_selfsigned() - { - Test::Result result("CVC"); - - EAC1_1_CVC_Options opts; - //opts.cpi = 0; - opts.chr = ASN1_Chr("my_opt_chr"); // not used - opts.car = ASN1_Car("my_opt_car"); - opts.cex = ASN1_Cex("2010 08 13"); - opts.ced = ASN1_Ced("2010 07 27"); - opts.holder_auth_templ = 0xC1; - opts.hash_alg = "SHA-256"; - - // creating a non sense selfsigned cert w/o dom pars - EC_Group dom_pars(OID("1.3.36.3.3.2.8.1.1.11")); - ECDSA_PrivateKey key(Test::rng(), dom_pars); - key.set_parameter_encoding(EC_DOMPAR_ENC_IMPLICITCA); - EAC1_1_CVC cert = CVC_EAC::create_self_signed_cert(key, opts, Test::rng()); - - std::vector<byte> der(cert.BER_encode()); - std::ofstream cert_file; - cert_file.open(Test::data_file("ecc/my_cv_cert.ber"), std::ios::binary); - cert_file.write((char*)der.data(), der.size()); - cert_file.close(); - - EAC1_1_CVC cert_in(Test::data_file("ecc/my_cv_cert.ber")); - result.confirm("reloaded cert matches", cert_in == cert); - - // encoding it again while it has no dp - std::vector<byte> der2(cert_in.BER_encode()); - std::ofstream cert_file2(Test::data_file("ecc/my_cv_cert2.ber"), std::ios::binary); - cert_file2.write((char*)der2.data(), der2.size()); - cert_file2.close(); - - // read both and compare them - std::ifstream cert_1_in(Test::data_file("ecc/my_cv_cert.ber")); - std::ifstream cert_2_in(Test::data_file("ecc/my_cv_cert2.ber")); - std::vector<byte> sv1; - std::vector<byte> sv2; - if (!cert_1_in || cert_2_in) - { - result.test_failure("Unable to reread cert files"); - } - while (!cert_1_in.eof()) - { - char now; - cert_1_in.read(&now, 1); - sv1.push_back(now); - } - while (!cert_2_in.eof()) - { - char now; - cert_2_in.read(&now, 1); - sv2.push_back(now); - } - - result.test_gte("size", sv1.size(), 10); - result.test_ne("reencoded file of cert without domain parameters is different from original", sv1, sv2); - - result.test_eq("car", cert_in.get_car().value(), "my_opt_car"); - result.test_eq("chr", cert_in.get_chr().value(), "my_opt_car"); - result.test_eq("ced", cert_in.get_ced().as_string(), "20100727"); - result.test_eq("ced", cert_in.get_ced().readable_string(), "2010/07/27"); - - try - { - ASN1_Ced invalid("1999 01 01"); - result.test_failure("Allowed creation of invalid 1999 ASN1_Ced"); - } - catch(...) {} - - try - { - ASN1_Ced("2100 01 01"); - result.test_failure("Allowed creation of invalid 2100 ASN1_Ced"); - } - catch(...) {} - - std::unique_ptr<Public_Key> p_pk(cert_in.subject_public_key()); - ECDSA_PublicKey* p_ecdsa_pk = dynamic_cast<ECDSA_PublicKey*>(p_pk.get()); - - // let's see if encoding is truely implicitca, because this is what the key should have - // been set to when decoding (see above)(because it has no domain params): - - result.confirm("implicit CA", p_ecdsa_pk->domain_format() == EC_DOMPAR_ENC_IMPLICITCA); - - try - { - const BigInt order = p_ecdsa_pk->domain().get_order(); - result.test_failure("Expected accessing domain to fail"); - } - catch (Invalid_State) {} - { - } - - // set them and try again - //cert_in.set_domain_parameters(dom_pars); - std::unique_ptr<Public_Key> p_pk2(cert_in.subject_public_key()); - ECDSA_PublicKey* p_ecdsa_pk2 = dynamic_cast<ECDSA_PublicKey*>(p_pk2.get()); - //p_ecdsa_pk2->set_domain_parameters(dom_pars); - result.test_eq("order", p_ecdsa_pk2->domain().get_order(), dom_pars.get_order()); - result.confirm("verified signature", cert_in.check_signature(*p_pk2)); - - return result; - } - -Test::Result test_enc_gen_req() - { - Test::Result result("CVC"); - - EAC1_1_CVC_Options opts; - - //opts.cpi = 0; - opts.chr = ASN1_Chr("my_opt_chr"); - opts.hash_alg = "SHA-160"; - - // creating a non sense selfsigned cert w/o dom pars - EC_Group dom_pars(OID("1.3.132.0.8")); - ECDSA_PrivateKey key(Test::rng(), dom_pars); - key.set_parameter_encoding(EC_DOMPAR_ENC_IMPLICITCA); - EAC1_1_Req req = CVC_EAC::create_cvc_req(key, opts.chr, opts.hash_alg, Test::rng()); - std::vector<byte> der(req.BER_encode()); - std::ofstream req_file(Test::data_file("ecc/my_cv_req.ber"), std::ios::binary); - req_file.write((char*)der.data(), der.size()); - req_file.close(); - - // read and check signature... - EAC1_1_Req req_in(Test::data_file("ecc/my_cv_req.ber")); - //req_in.set_domain_parameters(dom_pars); - std::unique_ptr<Public_Key> p_pk(req_in.subject_public_key()); - ECDSA_PublicKey* p_ecdsa_pk = dynamic_cast<ECDSA_PublicKey*>(p_pk.get()); - //p_ecdsa_pk->set_domain_parameters(dom_pars); - result.test_eq("order", p_ecdsa_pk->domain().get_order(), dom_pars.get_order()); - result.confirm("signature valid on CVC request", req_in.check_signature(*p_pk)); - - return result; - } - -Test::Result test_cvc_req_ext() - { - EAC1_1_Req req_in(Test::data_file("ecc/DE1_flen_chars_cvcRequest_ECDSA.der")); - EC_Group dom_pars(OID("1.3.36.3.3.2.8.1.1.5")); // "german curve" - //req_in.set_domain_parameters(dom_pars); - std::unique_ptr<Public_Key> p_pk(req_in.subject_public_key()); - ECDSA_PublicKey* p_ecdsa_pk = dynamic_cast<ECDSA_PublicKey*>(p_pk.get()); - - Test::Result result("CVC"); - result.test_eq("order", p_ecdsa_pk->domain().get_order(), dom_pars.get_order()); - result.confirm("signature valid on CVC request", req_in.check_signature(*p_pk)); - return result; - } - -Test::Result test_cvc_ado_creation() - { - Test::Result result("CVC"); - - EAC1_1_CVC_Options opts; - //opts.cpi = 0; - opts.chr = ASN1_Chr("my_opt_chr"); - opts.hash_alg = "SHA-256"; - - // creating a non sense selfsigned cert w/o dom pars - EC_Group dom_pars(OID("1.3.36.3.3.2.8.1.1.11")); - ECDSA_PrivateKey req_key(Test::rng(), dom_pars); - req_key.set_parameter_encoding(EC_DOMPAR_ENC_IMPLICITCA); - //EAC1_1_Req req = CVC_EAC::create_cvc_req(req_key, opts); - EAC1_1_Req req = CVC_EAC::create_cvc_req(req_key, opts.chr, opts.hash_alg, Test::rng()); - std::vector<byte> der(req.BER_encode()); - std::ofstream req_file(Test::data_file("ecc/my_cv_req.ber"), std::ios::binary); - req_file.write((char*)der.data(), der.size()); - req_file.close(); - - // create an ado with that req - ECDSA_PrivateKey ado_key(Test::rng(), dom_pars); - EAC1_1_CVC_Options ado_opts; - ado_opts.car = ASN1_Car("my_ado_car"); - ado_opts.hash_alg = "SHA-256"; // must be equal to req's hash alg, because ado takes his sig_algo from it's request - - //EAC1_1_ADO ado = CVC_EAC::create_ado_req(ado_key, req, ado_opts); - EAC1_1_ADO ado = CVC_EAC::create_ado_req(ado_key, req, ado_opts.car, Test::rng()); - result.confirm("ADO signature verifies", ado.check_signature(ado_key)); - - std::ofstream ado_file(Test::data_file("ecc/ado"), std::ios::binary); - std::vector<byte> ado_der(ado.BER_encode()); - ado_file.write((char*)ado_der.data(), ado_der.size()); - ado_file.close(); - // read it again and check the signature - EAC1_1_ADO ado2(Test::data_file("ecc/ado")); - result.confirm("ADOs match", ado == ado2); - - result.confirm("ADO signature valid", ado2.check_signature(ado_key)); - - return result; - } - -Test::Result test_cvc_ado_comparison() - { - Test::Result result("CVC"); - - EAC1_1_CVC_Options opts; - //opts.cpi = 0; - opts.chr = ASN1_Chr("my_opt_chr"); - opts.hash_alg = "SHA-224"; - - // creating a non sense selfsigned cert w/o dom pars - EC_Group dom_pars(OID("1.3.36.3.3.2.8.1.1.11")); - ECDSA_PrivateKey req_key(Test::rng(), dom_pars); - req_key.set_parameter_encoding(EC_DOMPAR_ENC_IMPLICITCA); - //EAC1_1_Req req = CVC_EAC::create_cvc_req(req_key, opts); - EAC1_1_Req req = CVC_EAC::create_cvc_req(req_key, opts.chr, opts.hash_alg, Test::rng()); - - - // create an ado with that req - ECDSA_PrivateKey ado_key(Test::rng(), dom_pars); - EAC1_1_CVC_Options ado_opts; - ado_opts.car = ASN1_Car("my_ado_car1"); - ado_opts.hash_alg = "SHA-224"; // must be equal to req's hash alg, because ado takes his sig_algo from it's request - //EAC1_1_ADO ado = CVC_EAC::create_ado_req(ado_key, req, ado_opts); - EAC1_1_ADO ado = CVC_EAC::create_ado_req(ado_key, req, ado_opts.car, Test::rng()); - result.confirm("ADO signature valid", ado.check_signature(ado_key)); - // make a second one for comparison - EAC1_1_CVC_Options opts2; - //opts2.cpi = 0; - opts2.chr = ASN1_Chr("my_opt_chr"); - opts2.hash_alg = "SHA-160"; // this is the only difference - ECDSA_PrivateKey req_key2(Test::rng(), dom_pars); - req_key.set_parameter_encoding(EC_DOMPAR_ENC_IMPLICITCA); - //EAC1_1_Req req2 = CVC_EAC::create_cvc_req(req_key2, opts2, Test::rng()); - EAC1_1_Req req2 = CVC_EAC::create_cvc_req(req_key2, opts2.chr, opts2.hash_alg, Test::rng()); - ECDSA_PrivateKey ado_key2(Test::rng(), dom_pars); - EAC1_1_CVC_Options ado_opts2; - ado_opts2.car = ASN1_Car("my_ado_car1"); - ado_opts2.hash_alg = "SHA-160"; // must be equal to req's hash alg, because ado takes his sig_algo from it's request - - EAC1_1_ADO ado2 = CVC_EAC::create_ado_req(ado_key2, req2, ado_opts2.car, Test::rng()); - result.confirm("ADO signature after creation", ado2.check_signature(ado_key2)); - - result.confirm("ADOs should not be equal", ado != ado2); - // std::ofstream ado_file(Test::data_file("ecc/ado")); - // std::vector<byte> ado_der(ado.BER_encode()); - // ado_file.write((char*)ado_der.data(), ado_der.size()); - // ado_file.close(); - // read it again and check the signature - - // EAC1_1_ADO ado2(Test::data_file("ecc/ado")); - // ECDSA_PublicKey* p_ado_pk = dynamic_cast<ECDSA_PublicKey*>(&ado_key); - // //bool ver = ado2.check_signature(*p_ado_pk); - // bool ver = ado2.check_signature(ado_key); - // CHECK_MESSAGE(ver, "failure of ado verification after reloading"); - - return result; - } - -void confirm_cex_time(Test::Result& result, - const ASN1_Cex& cex, - size_t exp_year, - size_t exp_month) - { - result.test_eq("year", cex.get_year(), exp_year); - result.test_eq("month", cex.get_month(), exp_month); - } - -Test::Result test_eac_time() - { - Test::Result result("CVC"); - - EAC_Time sooner("", ASN1_Tag(99)); - sooner.set_to("2007 12 12"); - EAC_Time later("2007 12 13"); - - result.confirm("sooner < later", sooner < later); - result.confirm("self-equal", sooner == sooner); - - ASN1_Cex my_cex("2007 08 01"); - my_cex.add_months(12); - confirm_cex_time(result, my_cex, 2008, 8); - - my_cex.add_months(4); - confirm_cex_time(result, my_cex, 2008, 12); - - my_cex.add_months(4); - confirm_cex_time(result, my_cex, 2009, 4); - - my_cex.add_months(41); - confirm_cex_time(result, my_cex, 2012, 9); - - return result; - } - -Test::Result test_ver_cvca() - { - Test::Result result("CVC"); - - EAC1_1_CVC cvc(Test::data_file("ecc/cvca01.cv.crt")); - - std::unique_ptr<Public_Key> p_pk2(cvc.subject_public_key()); - result.confirm("verified CVCA cert", cvc.check_signature(*p_pk2)); - - try - { - ECDSA_PublicKey* p_ecdsa_pk2 = dynamic_cast<ECDSA_PublicKey*>(p_pk2.get()); - p_ecdsa_pk2->domain().get_order(); - result.test_failure("Expected failure"); - } - catch(Invalid_State) - { - result.test_note("Accessing order failed"); - } - - return result; - } - -Test::Result test_copy_and_assignment() - { - Test::Result result("CVC"); - - EAC1_1_CVC cert_in(Test::data_file("ecc/cvca01.cv.crt")); - EAC1_1_CVC cert_cp(cert_in); - EAC1_1_CVC cert_ass = cert_in; - - result.confirm("same cert", cert_in == cert_cp); - result.confirm("same cert", cert_in == cert_ass); - - EAC1_1_ADO ado_in(Test::data_file("ecc/ado.cvcreq")); - EAC1_1_ADO ado_cp(ado_in); - EAC1_1_ADO ado_ass = ado_in; - result.confirm("same", ado_in == ado_cp); - result.confirm("same", ado_in == ado_ass); - - EAC1_1_Req req_in(Test::data_file("ecc/DE1_flen_chars_cvcRequest_ECDSA.der")); - EAC1_1_Req req_cp(req_in); - EAC1_1_Req req_ass = req_in; - result.confirm("same", req_in == req_cp); - result.confirm("same", req_in == req_ass); - - return result; - } - -Test::Result test_eac_str_illegal_values() - { - Test::Result result("CVC"); - - try - { - EAC1_1_CVC(Test::data_file("ecc/cvca_illegal_chars.cv.crt")); - result.test_failure("Accepted invalid EAC 1.1 CVC"); - } - catch (Decoding_Error) {} - - try - { - EAC1_1_CVC(Test::data_file("ecc/cvca_illegal_chars2.cv.crt")); - result.test_failure("Accepted invalid EAC 1.1 CVC #2"); - } - catch (Decoding_Error) {} - - return result; - } - -Test::Result test_tmp_eac_str_enc() - { - Test::Result result("CVC"); - try - { - ASN1_Car("abc!+-ยต\n"); - result.test_failure("Accepted invalid EAC string"); - } - catch(Invalid_Argument) {} - - return result; - } - -Test::Result test_cvc_chain() - { - Test::Result result("CVC"); - - EC_Group dom_pars(OID("1.3.36.3.3.2.8.1.1.5")); // "german curve" - ECDSA_PrivateKey cvca_privk(Test::rng(), dom_pars); - std::string hash("SHA-224"); - ASN1_Car car("DECVCA00001"); - EAC1_1_CVC cvca_cert = DE_EAC::create_cvca(cvca_privk, hash, car, true, true, 12, Test::rng()); - std::ofstream cvca_file(Test::data_file("ecc/cvc_chain_cvca.cer"), std::ios::binary); - std::vector<byte> cvca_sv = cvca_cert.BER_encode(); - cvca_file.write((char*)cvca_sv.data(), cvca_sv.size()); - cvca_file.close(); - - ECDSA_PrivateKey cvca_privk2(Test::rng(), dom_pars); - ASN1_Car car2("DECVCA00002"); - EAC1_1_CVC cvca_cert2 = DE_EAC::create_cvca(cvca_privk2, hash, car2, true, true, 12, Test::rng()); - EAC1_1_CVC link12 = DE_EAC::link_cvca(cvca_cert, cvca_privk, cvca_cert2, Test::rng()); - std::vector<byte> link12_sv = link12.BER_encode(); - std::ofstream link12_file(Test::data_file("ecc/cvc_chain_link12.cer"), std::ios::binary); - link12_file.write((char*)link12_sv.data(), link12_sv.size()); - link12_file.close(); - - // verify the link - result.confirm("signature valid", link12.check_signature(cvca_privk)); - EAC1_1_CVC link12_reloaded(Test::data_file("ecc/cvc_chain_link12.cer")); - EAC1_1_CVC cvca1_reloaded(Test::data_file("ecc/cvc_chain_cvca.cer")); - std::unique_ptr<Public_Key> cvca1_rel_pk(cvca1_reloaded.subject_public_key()); - result.confirm("signature valid", link12_reloaded.check_signature(*cvca1_rel_pk)); - - // create first round dvca-req - ECDSA_PrivateKey dvca_priv_key(Test::rng(), dom_pars); - EAC1_1_Req dvca_req = DE_EAC::create_cvc_req(dvca_priv_key, ASN1_Chr("DEDVCAEPASS"), hash, Test::rng()); - std::ofstream dvca_file(Test::data_file("ecc/cvc_chain_dvca_req.cer"), std::ios::binary); - std::vector<byte> dvca_sv = dvca_req.BER_encode(); - dvca_file.write((char*)dvca_sv.data(), dvca_sv.size()); - dvca_file.close(); - - // sign the dvca_request - EAC1_1_CVC dvca_cert1 = DE_EAC::sign_request(cvca_cert, cvca_privk, dvca_req, 1, 5, true, 3, 1, Test::rng()); - result.test_eq("DVCA car", dvca_cert1.get_car().iso_8859(), "DECVCA00001"); - result.test_eq("DVCA chr", dvca_cert1.get_chr().iso_8859(), "DEDVCAEPASS00001"); - helper_write_file(dvca_cert1, Test::data_file("ecc/cvc_chain_dvca_cert1.cer")); - - // make a second round dvca ado request - ECDSA_PrivateKey dvca_priv_key2(Test::rng(), dom_pars); - EAC1_1_Req dvca_req2 = DE_EAC::create_cvc_req(dvca_priv_key2, ASN1_Chr("DEDVCAEPASS"), hash, Test::rng()); - std::ofstream dvca_file2(Test::data_file("ecc/cvc_chain_dvca_req2.cer"), std::ios::binary); - std::vector<byte> dvca_sv2 = dvca_req2.BER_encode(); - dvca_file2.write((char*)dvca_sv2.data(), dvca_sv2.size()); - dvca_file2.close(); - EAC1_1_ADO dvca_ado2 = CVC_EAC::create_ado_req(dvca_priv_key, dvca_req2, - ASN1_Car(dvca_cert1.get_chr().iso_8859()), Test::rng()); - helper_write_file(dvca_ado2, Test::data_file("ecc/cvc_chain_dvca_ado2.cer")); - - // verify the ado and sign the request too - - std::unique_ptr<Public_Key> ap_pk(dvca_cert1.subject_public_key()); - ECDSA_PublicKey* cert_pk = dynamic_cast<ECDSA_PublicKey*>(ap_pk.get()); - - //cert_pk->set_domain_parameters(dom_pars); - EAC1_1_CVC dvca_cert1_reread(Test::data_file("ecc/cvc_chain_cvca.cer")); - result.confirm("signature valid", dvca_ado2.check_signature(*cert_pk)); - result.confirm("signature valid", dvca_ado2.check_signature(dvca_priv_key)); // must also work - - EAC1_1_Req dvca_req2b = dvca_ado2.get_request(); - helper_write_file(dvca_req2b, Test::data_file("ecc/cvc_chain_dvca_req2b.cer")); - result.confirm("files match", helper_files_equal(Test::data_file("ecc/cvc_chain_dvca_req2b.cer"), Test::data_file("ecc/cvc_chain_dvca_req2.cer"))); - EAC1_1_CVC dvca_cert2 = DE_EAC::sign_request(cvca_cert, cvca_privk, dvca_req2b, 2, 5, true, 3, 1, Test::rng()); - result.test_eq("DVCA car", dvca_cert2.get_car().iso_8859(), "DECVCA00001"); - result.test_eq("DVCA chr", dvca_cert2.get_chr().iso_8859(), "DEDVCAEPASS00002"); - - // make a first round IS request - ECDSA_PrivateKey is_priv_key(Test::rng(), dom_pars); - EAC1_1_Req is_req = DE_EAC::create_cvc_req(is_priv_key, ASN1_Chr("DEIS"), hash, Test::rng()); - helper_write_file(is_req, Test::data_file("ecc/cvc_chain_is_req.cer")); - - // sign the IS request - //dvca_cert1.set_domain_parameters(dom_pars); - EAC1_1_CVC is_cert1 = DE_EAC::sign_request(dvca_cert1, dvca_priv_key, is_req, 1, 5, true, 3, 1, Test::rng()); - result.test_eq("EAC 1.1 CVC car", is_cert1.get_car().iso_8859(), "DEDVCAEPASS00001"); - result.test_eq("EAC 1.1 CVC chr", is_cert1.get_chr().iso_8859(), "DEIS00001"); - helper_write_file(is_cert1, Test::data_file("ecc/cvc_chain_is_cert.cer")); - - // verify the signature of the certificate - result.confirm("valid signature", is_cert1.check_signature(dvca_priv_key)); - - return result; - } - -class CVC_Unit_Tests : public Test - { - public: - std::vector<Test::Result> run() override - { - std::vector<Test::Result> results; - - std::vector<std::function<Test::Result()>> fns = { - test_cvc_times, - test_enc_gen_selfsigned, - test_enc_gen_req, - test_cvc_req_ext, - test_cvc_ado_creation, - test_cvc_ado_comparison, - test_eac_time, - test_ver_cvca, - test_copy_and_assignment, - test_eac_str_illegal_values, - test_tmp_eac_str_enc, - test_cvc_chain - }; - - for(size_t i = 0; i != fns.size(); ++i) - { - try - { - results.push_back(fns[i]()); - } - catch(std::exception& e) - { - results.push_back(Test::Result::Failure("CVC test " + std::to_string(i), e.what())); - } - } - - return results; - } - - }; - -BOTAN_REGISTER_TEST("cvc", CVC_Unit_Tests); - -#endif - -} - -} |