diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cert/cvc/asn1_eac_str.cpp | 128 | ||||
-rw-r--r-- | src/cert/cvc/asn1_eac_tm.cpp | 375 | ||||
-rw-r--r-- | src/cert/cvc/cvc_ado.cpp | 246 | ||||
-rw-r--r-- | src/cert/cvc/cvc_ado.h | 3 | ||||
-rw-r--r-- | src/cert/cvc/cvc_ca.cpp | 66 | ||||
-rw-r--r-- | src/cert/cvc/cvc_ca.h | 30 | ||||
-rw-r--r-- | src/cert/cvc/cvc_cert.cpp | 176 | ||||
-rw-r--r-- | src/cert/cvc/cvc_gen_cert.h | 14 | ||||
-rw-r--r-- | src/cert/cvc/cvc_req.cpp | 98 | ||||
-rw-r--r-- | src/cert/cvc/cvc_self.cpp | 467 | ||||
-rw-r--r-- | src/cert/cvc/cvc_self.h | 235 | ||||
-rw-r--r-- | src/cert/cvc/eac_asn_obj.h | 128 | ||||
-rw-r--r-- | src/cert/cvc/eac_obj.h | 11 | ||||
-rw-r--r-- | src/cert/cvc/info.txt | 9 | ||||
-rw-r--r-- | src/cert/cvc/signed_obj.cpp | 64 | ||||
-rw-r--r-- | src/cert/cvc/signed_obj.h | 58 |
16 files changed, 1446 insertions, 662 deletions
diff --git a/src/cert/cvc/asn1_eac_str.cpp b/src/cert/cvc/asn1_eac_str.cpp new file mode 100644 index 000000000..b367df394 --- /dev/null +++ b/src/cert/cvc/asn1_eac_str.cpp @@ -0,0 +1,128 @@ +/************************************************* +* Simple ASN.1 String Types Source File * +* (C) 2007 FlexSecure GmbH * +* 2008 Jack Lloyd * +*************************************************/ + +#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> + +namespace Botan { + +/************************************************* +* Create an ASN1_EAC_String * +*************************************************/ +ASN1_EAC_String::ASN1_EAC_String(const std::string& str, ASN1_Tag t) : tag(t) + { + iso_8859_str = Charset::transcode(str, LOCAL_CHARSET, LATIN1_CHARSET); + if (!sanity_check()) + { + throw Invalid_Argument("attempted to construct ASN1_EAC_String with illegal characters"); + } + } + +/************************************************* +* Return this string in ISO 8859-1 encoding * +*************************************************/ +std::string ASN1_EAC_String::iso_8859() const + { + return iso_8859_str; + } + +/************************************************* +* Return this string in local encoding * +*************************************************/ +std::string ASN1_EAC_String::value() const + { + return Charset::transcode(iso_8859_str, LATIN1_CHARSET, LOCAL_CHARSET); + } + +/************************************************* +* Return the type of this string object * +*************************************************/ +ASN1_Tag ASN1_EAC_String::tagging() const + { + return 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 != this->tag) + { + + std::string message("decoding type mismatch for ASN1_EAC_String, tag is "); + std::stringstream ss; + std::string str_is; + ss << std::hex << obj.type_tag; + ss >> str_is; + message.append(str_is); + message.append(", while it should be "); + std::stringstream ss2; + std::string str_should; + ss2 << std::hex << this->tag; + ss2 >> str_should; + message.append(str_should); + throw Decoding_Error(message); + } + Character_Set charset_is; + charset_is = LATIN1_CHARSET; + + try + { + *this = ASN1_EAC_String( + Charset::transcode(ASN1::to_string(obj), charset_is, LOCAL_CHARSET), + obj.type_tag); + } + catch (Invalid_Argument inv_arg) + { + throw Decoding_Error(std::string("error while decoding ASN1_EAC_String: ") + std::string(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*>(iso_8859_str.data()); + const u32bit rep_len = iso_8859_str.size(); + for (u32bit 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/cert/cvc/asn1_eac_tm.cpp b/src/cert/cvc/asn1_eac_tm.cpp new file mode 100644 index 000000000..81c99f190 --- /dev/null +++ b/src/cert/cvc/asn1_eac_tm.cpp @@ -0,0 +1,375 @@ +/************************************************* +* EAC Time Types Source File * +* (C) 2007 FlexSecure GmbH * +* 2008 Jack Lloyd * +*************************************************/ + +#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 <ctime> +#include <sstream> + +namespace Botan { + +namespace { + +/************************************************* +* Convert a time_t to a struct tm * +*************************************************/ +std::tm get_tm(u64bit timer) + { + std::time_t time_val = static_cast<std::time_t>(timer); + + std::tm* tm_p = std::gmtime(&time_val); + if (tm_p == 0) + throw Encoding_Error("EAC_Time: gmtime could not encode " + + to_string(timer)); + return (*tm_p); + } +SecureVector<byte> enc_two_digit(u32bit in) + { + SecureVector<byte> result; + in %= 100; + if (in < 10) + { + result.append(0x00); + } + else + { + u32bit y_first_pos = (in - (in%10))/10; + result.append(static_cast<byte>(y_first_pos)); + } + u32bit y_sec_pos = in%10; + result.append(static_cast<byte>(y_sec_pos)); + return result; + } +u32bit dec_two_digit(byte b1, byte b2) + { + u32bit upper = (u32bit)b1; + u32bit lower = (u32bit)b2; + if (upper > 9 || lower > 9) + { + throw Invalid_Argument("u32bit dec_two_digit(byte b1, byte b2): value too large"); + } + return upper*10 + lower; + + } +} + +/************************************************* +* Create an EAC_Time * +*************************************************/ +EAC_Time::EAC_Time(u64bit timer, ASN1_Tag t) + :tag(t) + { + std::tm time_info = get_tm(timer); + + year = time_info.tm_year + 1900; + month = time_info.tm_mon + 1; + day = time_info.tm_mday; + + } + +/************************************************* +* Create an EAC_Time * +*************************************************/ +EAC_Time::EAC_Time(const std::string& t_spec, ASN1_Tag t) + :tag(t) + { + set_to(t_spec); + } +/************************************************* +* Create an EAC_Time * +*************************************************/ +EAC_Time::EAC_Time(u32bit y, u32bit m, u32bit d, ASN1_Tag t) + : year(y), + month(m), + day(d), + tag(t) + { + } + +/************************************************* +* Set the time with a human readable string * +*************************************************/ +void EAC_Time::set_to(const std::string& time_str) + { + if (time_str == "") + { + year = month = 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); + + year = to_u32bit(params[0]); + month = to_u32bit(params[1]); + 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(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"); + + std::string asn1rep; + asn1rep = to_string(year, 2); + + asn1rep += to_string(month, 2) + to_string(day, 2); + + return asn1rep; + } + +/************************************************* +* Return if the time has been set somehow * +*************************************************/ +bool EAC_Time::time_is_set() const + { + return (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"); + + std::string readable; + readable += to_string(year, 2) + "/"; + readable += to_string(month, 2) + "/"; + readable += to_string(day, 2) + " "; + + return readable; + } + +/************************************************* +* Do a general sanity check on the time * +*************************************************/ +bool EAC_Time::passes_sanity_check() const + { + if (year < 2000 || year > 2099) + return false; + if (month == 0 || month > 12) + return false; + if (day == 0 || day > 31) + return false; + + return true; + } + +/****************************************** +* modification functions * +******************************************/ + +void EAC_Time::add_years(u32bit years) + { + year += years; + } +void EAC_Time::add_months(u32bit months) + { + year += months/12; + month += months % 12; + if(month > 12) + { + year += 1; + 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 (year < other.year) return EARLIER; + if (year > other.year) return LATER; + if (month < other.month) return EARLIER; + if (month > other.month) return LATER; + if (day < other.day) return EARLIER; + if (day > other.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); + } + +/************************************************* +* Do a validity check * +*************************************************/ +s32bit validity_check(const EAC_Time& start, const EAC_Time& end, + u64bit current_time) + { + + const s32bit NOT_YET_VALID = -1, VALID_TIME = 0, EXPIRED = 1; + + if (start.cmp(current_time) > 0) + return NOT_YET_VALID; + if (end.cmp(current_time) < 0) + return EXPIRED; + return VALID_TIME; + } + +/************************************************* +* 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 != this->tag) + { + std::string message("decoding type mismatch for EAC_Time, tag is "); + std::stringstream ss; + std::string str_is; + ss << std::hex << obj.type_tag; + ss >> str_is; + message.append(str_is); + message.append(", while it should be "); + std::stringstream ss2; + std::string str_should; + ss2 << std::hex << this->tag; + ss2 >> str_should; + message.append(str_should); + throw Decoding_Error(message); + + } + 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]); + year = tmp_year + 2000; + month = tmp_mon; + day = tmp_day; + } + catch (Invalid_Argument) + { + throw Decoding_Error("EAC_Time decoding failed"); + } + + } + +u32bit EAC_Time::get_year() const + { + return year; + } +u32bit EAC_Time::get_month() const + { + return month; + } +u32bit EAC_Time::get_day() const + { + return day; + } + +/************************************************* +* make the value an octet string for encoding * +*************************************************/ +SecureVector<byte> EAC_Time::encoded_eac_time() const + { + SecureVector<byte> result; + result.append(enc_two_digit(year)); + result.append(enc_two_digit(month)); + result.append(enc_two_digit(day)); + return result; + } + +ASN1_Ced::ASN1_Ced(std::string const& str) + : EAC_Time(str, ASN1_Tag(37)) + {} + +ASN1_Ced::ASN1_Ced(u64bit val) + : EAC_Time(val, ASN1_Tag(37)) + {} + +ASN1_Ced::ASN1_Ced(EAC_Time const& other) + : EAC_Time(other.get_year(), other.get_month(), other.get_day(), ASN1_Tag(37)) + {} + +ASN1_Cex::ASN1_Cex(std::string const& str) + : EAC_Time(str, ASN1_Tag(36)) + {} + +ASN1_Cex::ASN1_Cex(u64bit val) + : EAC_Time(val, ASN1_Tag(36)) + {} + +ASN1_Cex::ASN1_Cex(EAC_Time const& other) + : EAC_Time(other.get_year(), other.get_month(), other.get_day(), ASN1_Tag(36)) + {} + +} diff --git a/src/cert/cvc/cvc_ado.cpp b/src/cert/cvc/cvc_ado.cpp index d5083d3ab..6ea8d59c2 100644 --- a/src/cert/cvc/cvc_ado.cpp +++ b/src/cert/cvc/cvc_ado.cpp @@ -1,119 +1,133 @@ +/************************************************* +* CVC Certificate Constructor * +* (C) 2007 FlexSecure GmbH * +* 2008 Jack Lloyd * +*************************************************/ + #include <botan/cvc_ado.h> #include <fstream> #include <assert.h> -/************************************************* - * CVC Certificate Constructor * - *************************************************/ - -namespace Botan - { - EAC1_1_ADO::EAC1_1_ADO(std::tr1::shared_ptr<DataSource> in) - { - init(in); - do_decode(); - } - EAC1_1_ADO::EAC1_1_ADO(const std::string& in) - { - std::tr1::shared_ptr<DataSource> stream(new DataSource_Stream(in, true)); - init(stream); - do_decode(); - } - void EAC1_1_ADO::force_decode() - { - SecureVector<byte> inner_cert; - BER_Decoder(tbs_bits) - .start_cons(ASN1_Tag(33)) - .raw_bytes(inner_cert) - .end_cons() - .decode(m_car) - .verify_end(); - - SecureVector<byte> req_bits = DER_Encoder() - .start_cons(ASN1_Tag(33), APPLICATION) - .raw_bytes(inner_cert) - .end_cons() - .get_contents(); - - std::tr1::shared_ptr<DataSource> req_source(new DataSource_Memory(req_bits)); - m_req = EAC1_1_Req(req_source); - sig_algo = m_req.sig_algo; - } - - MemoryVector<byte> EAC1_1_ADO::make_signed( - std::auto_ptr<PK_Signer> signer, - const MemoryRegion<byte>& tbs_bits) - { - SecureVector<byte> concat_sig = EAC1_1_obj<EAC1_1_ADO>::make_signature(signer, tbs_bits); - assert(concat_sig.size() % 2 == 0); - MemoryVector<byte> result = 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(); - return result; - } - ASN1_Car EAC1_1_ADO::get_car() const - { - return m_car; - } - void EAC1_1_ADO::decode_info(SharedPtrConverter<DataSource> source, SecureVector<byte> & res_tbs_bits, ECDSA_Signature & res_sig) - { - SecureVector<byte> concat_sig; - SecureVector<byte> cert_inner_bits; - ASN1_Car car; - BER_Decoder(source.get_shared()) - .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(); - - SecureVector<byte> enc_cert = DER_Encoder() - .start_cons(ASN1_Tag(33), APPLICATION) - .raw_bytes(cert_inner_bits) - .end_cons() - .get_contents(); - SecureVector<byte> enc_car = DER_Encoder() - .encode(car) - .get_contents(); - res_tbs_bits = enc_cert; - res_tbs_bits.append(enc_car); - res_sig = decode_concatenation(concat_sig); - - - } - void EAC1_1_ADO::encode(Pipe& out, X509_Encoding encoding) const - { - SecureVector<byte> concat_sig(EAC1_1_obj<EAC1_1_ADO>::m_sig.get_concatenation()); - SecureVector<byte> der = 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(); - if(encoding == PEM) - throw Invalid_Argument("EAC1_1_ADO::encode() cannot PEM encode an EAC object"); - else - out.write(der); - } - SecureVector<byte> EAC1_1_ADO::tbs_data() const - { - return tbs_bits; - } - - bool EAC1_1_ADO::operator==(EAC1_1_ADO const& rhs) const - { - assert(((this->m_req == rhs.m_req) && (this->tbs_data() == rhs.tbs_data())) || - ((this->m_req != rhs.m_req) && (this->tbs_data() != rhs.tbs_data()))); - 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; - } -}//namespace botan + +namespace Botan { + +EAC1_1_ADO::EAC1_1_ADO(std::tr1::shared_ptr<DataSource> in) + { + init(in); + do_decode(); + } + +EAC1_1_ADO::EAC1_1_ADO(const std::string& in) + { + std::tr1::shared_ptr<DataSource> stream(new DataSource_Stream(in, true)); + init(stream); + do_decode(); + } + +void EAC1_1_ADO::force_decode() + { + SecureVector<byte> inner_cert; + BER_Decoder(tbs_bits) + .start_cons(ASN1_Tag(33)) + .raw_bytes(inner_cert) + .end_cons() + .decode(m_car) + .verify_end(); + + SecureVector<byte> req_bits = DER_Encoder() + .start_cons(ASN1_Tag(33), APPLICATION) + .raw_bytes(inner_cert) + .end_cons() + .get_contents(); + + std::tr1::shared_ptr<DataSource> req_source(new DataSource_Memory(req_bits)); + m_req = EAC1_1_Req(req_source); + sig_algo = m_req.sig_algo; + } + +MemoryVector<byte> EAC1_1_ADO::make_signed( + std::auto_ptr<PK_Signer> signer, + const MemoryRegion<byte>& tbs_bits, + RandomNumberGenerator& rng) + { + SecureVector<byte> concat_sig = + EAC1_1_obj<EAC1_1_ADO>::make_signature(signer.get(), tbs_bits, rng); + assert(concat_sig.size() % 2 == 0); + MemoryVector<byte> result = 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(); + return result; + } + +ASN1_Car EAC1_1_ADO::get_car() const + { + return m_car; + } + +void EAC1_1_ADO::decode_info(SharedPtrConverter<DataSource> source, + SecureVector<byte> & res_tbs_bits, + ECDSA_Signature & res_sig) + { + SecureVector<byte> concat_sig; + SecureVector<byte> cert_inner_bits; + ASN1_Car car; + BER_Decoder(*source.get_ptr().get()) + .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(); + + SecureVector<byte> enc_cert = DER_Encoder() + .start_cons(ASN1_Tag(33), APPLICATION) + .raw_bytes(cert_inner_bits) + .end_cons() + .get_contents(); + SecureVector<byte> enc_car = DER_Encoder() + .encode(car) + .get_contents(); + res_tbs_bits = enc_cert; + res_tbs_bits.append(enc_car); + res_sig = decode_concatenation(concat_sig); + + + } +void EAC1_1_ADO::encode(Pipe& out, X509_Encoding encoding) const + { + SecureVector<byte> concat_sig(EAC1_1_obj<EAC1_1_ADO>::m_sig.get_concatenation()); + SecureVector<byte> der = 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(); + if(encoding == PEM) + throw Invalid_Argument("EAC1_1_ADO::encode() cannot PEM encode an EAC object"); + else + out.write(der); + } + +SecureVector<byte> EAC1_1_ADO::tbs_data() const + { + return tbs_bits; + } + +bool EAC1_1_ADO::operator==(EAC1_1_ADO const& rhs) const + { + assert(((this->m_req == rhs.m_req) && (this->tbs_data() == rhs.tbs_data())) || + ((this->m_req != rhs.m_req) && (this->tbs_data() != rhs.tbs_data()))); + 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/cert/cvc/cvc_ado.h b/src/cert/cvc/cvc_ado.h index e2e5395b5..de0fc7c13 100644 --- a/src/cert/cvc/cvc_ado.h +++ b/src/cert/cvc/cvc_ado.h @@ -44,7 +44,8 @@ class EAC1_1_ADO : public EAC1_1_obj<EAC1_1_ADO> */ static MemoryVector<byte> make_signed( std::auto_ptr<PK_Signer> signer, - const MemoryRegion<byte>& tbs_bits); + const MemoryRegion<byte>& tbs_bits, + RandomNumberGenerator& rng); /** * Get the CAR of this CVC ADO request * @result the CAR of this CVC ADO request diff --git a/src/cert/cvc/cvc_ca.cpp b/src/cert/cvc/cvc_ca.cpp index 19b35e074..638d3f984 100644 --- a/src/cert/cvc/cvc_ca.cpp +++ b/src/cert/cvc/cvc_ca.cpp @@ -5,38 +5,42 @@ #include <botan/oids.h> namespace Botan { - EAC1_1_CVC EAC1_1_CVC_CA::make_cert( - std::auto_ptr<PK_Signer> signer, - MemoryRegion<byte> const& public_key, - ASN1_Car const& car, - ASN1_Chr const& chr, - byte holder_auth_templ, - ASN1_Ced ced, - ASN1_Cex cex - ) - { - OID chat_oid(OIDS::lookup("CertificateHolderAuthorizationTemplate")); - MemoryVector<byte> enc_chat_val; - enc_chat_val.append(holder_auth_templ); +EAC1_1_CVC EAC1_1_CVC_CA::make_cert(std::auto_ptr<PK_Signer> signer, + MemoryRegion<byte> const& public_key, + ASN1_Car const& car, + ASN1_Chr const& chr, + byte holder_auth_templ, + ASN1_Ced ced, + ASN1_Cex cex, + RandomNumberGenerator& rng) + { + OID chat_oid(OIDS::lookup("CertificateHolderAuthorizationTemplate")); + MemoryVector<byte> enc_chat_val; + enc_chat_val.append(holder_auth_templ); - MemoryVector<byte> enc_cpi; - enc_cpi.append(0x00); - MemoryVector<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(); + MemoryVector<byte> enc_cpi; + enc_cpi.append(0x00); + MemoryVector<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(); - MemoryVector<byte> signed_cert = EAC1_1_CVC::make_signed(signer, EAC1_1_CVC::build_cert_body(tbs)); - std::tr1::shared_ptr<DataSource> source(new DataSource_Memory(signed_cert)); - return EAC1_1_CVC(source); - } + MemoryVector<byte> signed_cert = + EAC1_1_CVC::make_signed(signer, + EAC1_1_CVC::build_cert_body(tbs), + rng); + + std::tr1::shared_ptr<DataSource> source(new DataSource_Memory(signed_cert)); + + return EAC1_1_CVC(source); + } } diff --git a/src/cert/cvc/cvc_ca.h b/src/cert/cvc/cvc_ca.h index 590cd4c91..ec70aab42 100644 --- a/src/cert/cvc/cvc_ca.h +++ b/src/cert/cvc/cvc_ca.h @@ -1,6 +1,7 @@ /************************************************* * EAC1.1 CVC Certificate Authority Header File * -* (C) 1999-2007 The Botan Project * +* (C) 2007 FlexSecure GmbH * +* 2008 Jack Lloyd * *************************************************/ #ifndef BOTAN_CVC_CA_H__ @@ -10,15 +11,15 @@ #include <botan/pkcs10.h> #include <botan/pubkey.h> #include <botan/cvc_cert.h> -namespace Botan - { - /** - * This class represents a CVC CA. - */ - class EAC1_1_CVC_CA - { - public: +namespace Botan { + +/** +* This class represents a CVC CA. +*/ +class EAC1_1_CVC_CA + { + public: /** * Create an arbitrary EAC 1.1 CVC. @@ -33,19 +34,18 @@ namespace Botan * @param ced the CED to appear in the certificate * @param ced the CEX to appear in the certificate */ - static EAC1_1_CVC make_cert( - std::auto_ptr<PK_Signer> signer, + static EAC1_1_CVC make_cert(std::auto_ptr<PK_Signer> signer, MemoryRegion<byte> const& public_key, ASN1_Car const& car, ASN1_Chr const& chr, byte holder_auth_templ, ASN1_Ced ced, - ASN1_Cex cex - ); + ASN1_Cex cex, + RandomNumberGenerator& rng); - private: + private: - }; + }; diff --git a/src/cert/cvc/cvc_cert.cpp b/src/cert/cvc/cvc_cert.cpp index 29b3661ba..11539ef1e 100644 --- a/src/cert/cvc/cvc_cert.cpp +++ b/src/cert/cvc/cvc_cert.cpp @@ -1,100 +1,100 @@ -#include <botan/tr1_mem_includer.h> +/* + (C) 2007 FlexSecure GmbH + 2008 Jack Lloyd +*/ + #include <botan/cvc_cert.h> -#include <botan/der_enc.h> -#include <botan/ber_dec.h> -#include <botan/pem.h> -#include <botan/parsing.h> -#include <ios> -#include <assert.h> -#include <botan/ec.h> #include <botan/cvc_key.h> -#include <botan/oids.h> -#include <botan/look_pk.h> -namespace Botan - { - ASN1_Car EAC1_1_CVC::get_car() const - { - return m_car; - } +#include <botan/ecdsa.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() + { + SecureVector<byte> enc_pk; + SecureVector<byte> enc_chat_val; + u32bit cpi; + BER_Decoder tbs_cert(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(); - 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; - } + if(enc_chat_val.size() != 1) + throw Decoding_Error("CertificateHolderAuthorizationValue was not of length 1"); - /************************************************* - * Decode the TBSCertificate data * - *************************************************/ - void EAC1_1_CVC::force_decode() - { - SecureVector<byte> enc_pk; - SecureVector<byte> enc_chat_val; - u32bit cpi; - BER_Decoder tbs_cert(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) + if(cpi != 0) + throw Decoding_Error("EAC1_1 certificate´s cpi was not 0"); + + // XXX: PK algos have no notion of EAC encoder/decoder currently +#if 0 + ECDSA_PublicKey tmp_pk; + std::auto_ptr<EAC1_1_CVC_Decoder> dec = tmp_pk.cvc_eac1_1_decoder(); + sig_algo = dec->public_key(enc_pk); + + + m_pk = tmp_pk; + m_chat_val = enc_chat_val[0]; + self_signed = false; + if(m_car.iso_8859() == m_chr.iso_8859()) { - throw Decoding_Error("CertificateHolderAuthorizationValue was not of length 1"); + self_signed= true; } - if(cpi != 0) - { - throw Decoding_Error("EAC1_1 certificate´s cpi was not 0"); - } - ECDSA_PublicKey tmp_pk; - std::auto_ptr<EAC1_1_CVC_Decoder> dec = tmp_pk.cvc_eac1_1_decoder(); - sig_algo = dec->public_key(enc_pk); +#endif + } +/************************************************* +* CVC Certificate Constructor * +*************************************************/ +EAC1_1_CVC::EAC1_1_CVC(std::tr1::shared_ptr<DataSource>& in) + { + init(in); + self_signed = false; + do_decode(); + } - m_pk = tmp_pk; - m_chat_val = enc_chat_val[0]; - self_signed = false; - if(m_car.iso_8859() == m_chr.iso_8859()) - { - self_signed= true; - } +EAC1_1_CVC::EAC1_1_CVC(const std::string& in) + { + std::tr1::shared_ptr<DataSource> stream(new DataSource_Stream(in, true)); + init(stream); + self_signed = false; + do_decode(); + } - } - /************************************************* - * CVC Certificate Constructor * - *************************************************/ - EAC1_1_CVC::EAC1_1_CVC(std::tr1::shared_ptr<DataSource>& in) - { - init(in); - self_signed = false; - do_decode(); - } - EAC1_1_CVC::EAC1_1_CVC(const std::string& in) - { - std::tr1::shared_ptr<DataSource> stream(new DataSource_Stream(in, true)); - init(stream); - self_signed = false; - do_decode(); - } - bool EAC1_1_CVC::operator==(EAC1_1_CVC const& rhs) const - { +bool EAC1_1_CVC::operator==(EAC1_1_CVC const& rhs) const + { return (tbs_data() == rhs.tbs_data() - && get_concat_sig() == rhs.get_concat_sig()); - } - + && get_concat_sig() == rhs.get_concat_sig()); + } } diff --git a/src/cert/cvc/cvc_gen_cert.h b/src/cert/cvc/cvc_gen_cert.h index 7a9ac86fa..7da99f197 100644 --- a/src/cert/cvc/cvc_gen_cert.h +++ b/src/cert/cvc/cvc_gen_cert.h @@ -8,10 +8,12 @@ #define BOTAN_EAC_CVC_GCERT_H__ #include <botan/x509_key.h> +#include <botan/eac_asn_obj.h> #include <botan/enums.h> #include <string> #include <botan/pubkey.h> #include <botan/ecdsa_sig.h> +#include <assert.h> namespace Botan { @@ -77,7 +79,8 @@ class EAC1_1_gen_CVC : public EAC1_1_obj<Derived> // CRTP continuation from EAC1 */ static MemoryVector<byte> make_signed( std::auto_ptr<PK_Signer> signer, - const MemoryRegion<byte>& tbs_bits); + const MemoryRegion<byte>& tbs_bits, + RandomNumberGenerator& rng); virtual ~EAC1_1_gen_CVC<Derived>() {} @@ -93,9 +96,10 @@ template<typename Derived> bool EAC1_1_gen_CVC<Derived>::is_self_signed() const } template<typename Derived> MemoryVector<byte> EAC1_1_gen_CVC<Derived>::make_signed( std::auto_ptr<PK_Signer> signer, - const MemoryRegion<byte>& tbs_bits) // static + const MemoryRegion<byte>& tbs_bits, + RandomNumberGenerator& rng) // static { - SecureVector<byte> concat_sig = EAC1_1_obj<Derived>::make_signature(signer, tbs_bits); + SecureVector<byte> concat_sig = EAC1_1_obj<Derived>::make_signature(signer.get(), tbs_bits, rng); assert(concat_sig.size() % 2 == 0); return DER_Encoder() .start_cons(ASN1_Tag(33), APPLICATION) @@ -144,14 +148,14 @@ void EAC1_1_gen_CVC<Derived>::decode_info( ECDSA_Signature & res_sig) { SecureVector<byte> concat_sig; - BER_Decoder(source.get_shared()) + BER_Decoder(*source.get_shared().get()) .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 = ecdsa::decode_concatenation(concat_sig); + res_sig = decode_concatenation(concat_sig); } } diff --git a/src/cert/cvc/cvc_req.cpp b/src/cert/cvc/cvc_req.cpp index 2d5172917..84ea3ba8a 100644 --- a/src/cert/cvc/cvc_req.cpp +++ b/src/cert/cvc/cvc_req.cpp @@ -1,66 +1,66 @@ -#include <botan/tr1_mem_includer.h> +/* + (C) 2007 FlexSecure GmbH + 2008 Jack Lloyd +*/ + #include <botan/cvc_cert.h> #include <botan/der_enc.h> #include <botan/ber_dec.h> #include <botan/pem.h> #include <botan/parsing.h> -#include <ios> #include <assert.h> -#include <botan/ec.h> #include <botan/cvc_key.h> #include <botan/oids.h> #include <botan/look_pk.h> #include <botan/cvc_req.h> -namespace Botan -{ +#include <botan/freestore.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() + { + SecureVector<byte> enc_pk; + BER_Decoder tbs_cert(tbs_bits); + u32bit 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 request´s cpi was not 0"); + } - 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()); - } + // XXX: No EAC support in ECDSA +#if 0 + ECDSA_PublicKey tmp_pk; + std::auto_ptr<EAC1_1_CVC_Decoder> dec = tmp_pk.cvc_eac1_1_decoder(); + sig_algo = dec->public_key(enc_pk); + m_pk = tmp_pk; +#endif + } - /************************************************* - * Decode the TBSCertificate data * - *************************************************/ - void EAC1_1_Req::force_decode() - { - SecureVector<byte> enc_pk; - BER_Decoder tbs_cert(tbs_bits); - u32bit 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 request´s cpi was not 0"); - } - ECDSA_PublicKey tmp_pk; - std::auto_ptr<EAC1_1_CVC_Decoder> dec = tmp_pk.cvc_eac1_1_decoder(); - sig_algo = dec->public_key(enc_pk); - m_pk = tmp_pk; - } - /************************************************* - * X509_Certificate Constructor * - *************************************************/ - EAC1_1_Req::EAC1_1_Req(std::tr1::shared_ptr<DataSource> in) - { - init(in); - self_signed = true; - do_decode(); - } - EAC1_1_Req::EAC1_1_Req(const std::string& in) - { - std::tr1::shared_ptr<DataSource> stream(new DataSource_Stream(in, true)); - init(stream); - self_signed = true; - do_decode(); - } +EAC1_1_Req::EAC1_1_Req(std::tr1::shared_ptr<DataSource> in) + { + init(in); + self_signed = true; + do_decode(); + } +EAC1_1_Req::EAC1_1_Req(const std::string& in) + { + std::tr1::shared_ptr<DataSource> stream(new DataSource_Stream(in, true)); + init(stream); + self_signed = true; + do_decode(); + } } diff --git a/src/cert/cvc/cvc_self.cpp b/src/cert/cvc/cvc_self.cpp index 130ac6998..9ea561366 100644 --- a/src/cert/cvc/cvc_self.cpp +++ b/src/cert/cvc/cvc_self.cpp @@ -1,3 +1,8 @@ +/* + (C) 2007 FlexSecure GmbH + 2008 Jack Lloyd +*/ + #include <botan/cvc_self.h> #include <botan/cvc_cert.h> #include <botan/cvc_ca.h> @@ -8,264 +13,262 @@ #include <botan/cvc_req.h> #include <botan/cvc_ado.h> #include <botan/util.h> -#include <botan/config.h> -#include <botan/ec.h> #include <sstream> -using namespace Botan; -namespace Botan - { - namespace - { - std::string padding_and_hash_from_oid(OID const& oid) - { - std::string padding_and_hash = OIDS::lookup(oid); // use the hash - assert(padding_and_hash.substr(0,6) == "ECDSA/"); // can only be ECDSA for now - assert(padding_and_hash.find("/",0) == 5); - padding_and_hash.erase(0, padding_and_hash.find("/",0) + 1); - return padding_and_hash; - } - std::string fixed_len_seqnr(u32bit seqnr, u32bit len) - { - std::stringstream ss; - std::string result; - ss << seqnr; - ss >> result; - if (result.size() > len) - { - throw Invalid_Argument("fixed_len_seqnr(): number too high to be encoded in provided length"); - } - while (result.size() < len) - { - result.insert(0,"0"); - } - return result; - } +namespace Botan { +namespace { + +std::string padding_and_hash_from_oid(OID const& oid) + { + std::string padding_and_hash = OIDS::lookup(oid); // use the hash + assert(padding_and_hash.substr(0,6) == "ECDSA/"); // can only be ECDSA for now + assert(padding_and_hash.find("/",0) == 5); + padding_and_hash.erase(0, padding_and_hash.find("/",0) + 1); + return padding_and_hash; + } +std::string fixed_len_seqnr(u32bit seqnr, u32bit len) + { + std::stringstream ss; + std::string result; + ss << seqnr; + ss >> result; + if (result.size() > len) + { + throw Invalid_Argument("fixed_len_seqnr(): number too high to be encoded in provided length"); } - namespace CVC_EAC + while (result.size() < len) { + result.insert(0,"0"); + } + return result; + } - EAC1_1_CVC create_self_signed_cert(Private_Key const& key, - EAC1_1_CVC_Options const& opt) - { - // NOTE: we ignore - // the value - // of opt.chr - ECDSA_PrivateKey const* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&key); +} +namespace CVC_EAC +{ - if (priv_key == 0) - { - throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type"); - } +EAC1_1_CVC create_self_signed_cert(Private_Key const& key, + EAC1_1_CVC_Options const& opt) + { + // NOTE: we ignore + // the value + // of opt.chr + ECDSA_PrivateKey const* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&key); - ASN1_Chr chr(opt.car.value()); + if (priv_key == 0) + { + throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type"); + } - AlgorithmIdentifier sig_algo; - std::string padding_and_hash(eac_cvc_emsa + "(" + opt.hash_alg + ")"); - sig_algo.oid = OIDS::lookup_bsi(priv_key->algo_name() + "/" + padding_and_hash); - sig_algo = AlgorithmIdentifier(sig_algo.oid, AlgorithmIdentifier::USE_NULL_PARAM); + ASN1_Chr chr(opt.car.value()); - std::auto_ptr<Botan::PK_Signer> signer = get_pk_signer(*priv_key, padding_and_hash); + AlgorithmIdentifier sig_algo; + std::string padding_and_hash(eac_cvc_emsa + "(" + opt.hash_alg + ")"); + sig_algo.oid = OIDS::lookup_bsi(priv_key->algo_name() + "/" + padding_and_hash); + sig_algo = AlgorithmIdentifier(sig_algo.oid, AlgorithmIdentifier::USE_NULL_PARAM); - std::auto_ptr<EAC1_1_CVC_Encoder> enc(priv_key->cvc_eac1_1_encoder()); - MemoryVector<byte> enc_public_key = enc->public_key(sig_algo); - return EAC1_1_CVC_CA::make_cert(signer, enc_public_key, opt.car, chr, opt.holder_auth_templ, opt.ced, opt.cex); + std::auto_ptr<Botan::PK_Signer> signer(get_pk_signer(*priv_key, padding_and_hash)); - } + std::auto_ptr<EAC1_1_CVC_Encoder> enc(priv_key->cvc_eac1_1_encoder()); + MemoryVector<byte> enc_public_key = enc->public_key(sig_algo); + return EAC1_1_CVC_CA::make_cert(signer, enc_public_key, opt.car, chr, opt.holder_auth_templ, opt.ced, opt.cex); - EAC1_1_Req create_cvc_req(Private_Key const& key, - ASN1_Chr const& chr, - std::string const& hash_alg) - { + } - 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(eac_cvc_emsa + "(" + hash_alg + ")"); - sig_algo.oid = OIDS::lookup_bsi(priv_key->algo_name() + "/" + padding_and_hash); - sig_algo = AlgorithmIdentifier(sig_algo.oid, AlgorithmIdentifier::USE_NULL_PARAM); +EAC1_1_Req create_cvc_req(Private_Key const& key, + ASN1_Chr const& chr, + std::string const& hash_alg) + { - std::auto_ptr<Botan::PK_Signer> signer = get_pk_signer(*priv_key, padding_and_hash); + 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(eac_cvc_emsa + "(" + hash_alg + ")"); + sig_algo.oid = OIDS::lookup_bsi(priv_key->algo_name() + "/" + padding_and_hash); + sig_algo = AlgorithmIdentifier(sig_algo.oid, AlgorithmIdentifier::USE_NULL_PARAM); - std::auto_ptr<EAC1_1_CVC_Encoder> enc(priv_key->cvc_eac1_1_encoder()); - MemoryVector<byte> enc_public_key = enc->public_key(sig_algo); - MemoryVector<byte> enc_cpi; - enc_cpi.append(0x00); - MemoryVector<byte> tbs = DER_Encoder() - .encode(enc_cpi, OCTET_STRING, ASN1_Tag(41), APPLICATION) - .raw_bytes(enc_public_key) - .encode(chr) - .get_contents(); + std::auto_ptr<Botan::PK_Signer> signer = get_pk_signer(*priv_key, padding_and_hash); - MemoryVector<byte> signed_cert = EAC1_1_gen_CVC<EAC1_1_Req>::make_signed(signer, EAC1_1_gen_CVC<EAC1_1_Req>::build_cert_body(tbs)); - std::tr1::shared_ptr<DataSource> source(new DataSource_Memory(signed_cert)); - return EAC1_1_Req(source); - } + std::auto_ptr<EAC1_1_CVC_Encoder> enc(priv_key->cvc_eac1_1_encoder()); + MemoryVector<byte> enc_public_key = enc->public_key(sig_algo); + MemoryVector<byte> enc_cpi; + enc_cpi.append(0x00); + MemoryVector<byte> tbs = DER_Encoder() + .encode(enc_cpi, OCTET_STRING, ASN1_Tag(41), APPLICATION) + .raw_bytes(enc_public_key) + .encode(chr) + .get_contents(); - EAC1_1_ADO create_ado_req(Private_Key const& key, - EAC1_1_Req const& req, - ASN1_Car const& car) - { + MemoryVector<byte> signed_cert = EAC1_1_gen_CVC<EAC1_1_Req>::make_signed(signer, EAC1_1_gen_CVC<EAC1_1_Req>::build_cert_body(tbs)); + std::tr1::shared_ptr<DataSource> source(new DataSource_Memory(signed_cert)); + return EAC1_1_Req(source); + } - 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); - std::auto_ptr<Botan::PK_Signer> signer = get_pk_signer(*priv_key, padding_and_hash); - SecureVector<byte> tbs_bits = req.BER_encode(); - tbs_bits.append(DER_Encoder().encode(car).get_contents()); - MemoryVector<byte> signed_cert = EAC1_1_ADO::make_signed(signer, tbs_bits); - std::tr1::shared_ptr<DataSource> source(new DataSource_Memory(signed_cert)); - return EAC1_1_ADO(source); - } +EAC1_1_ADO create_ado_req(Private_Key const& key, + EAC1_1_Req const& req, + ASN1_Car const& car) + { - } // namespace CVC_EAC - namespace DE_EAC + ECDSA_PrivateKey const* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&key); + if (priv_key == 0) { - EAC1_1_CVC create_cvca(Private_Key const& key, std::string const& hash, ASN1_Car const& car, bool iris, bool fingerpr) - { - 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; - const u64bit current_time = system_time(); + 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); + std::auto_ptr<Botan::PK_Signer> signer(get_pk_signer(*priv_key, padding_and_hash)); + SecureVector<byte> tbs_bits = req.BER_encode(); + tbs_bits.append(DER_Encoder().encode(car).get_contents()); + MemoryVector<byte> signed_cert = EAC1_1_ADO::make_signed(signer, tbs_bits); + std::tr1::shared_ptr<DataSource> source(new DataSource_Memory(signed_cert)); + return EAC1_1_ADO(source); + } - opts.ced = ASN1_Ced(current_time); - opts.cex = ASN1_Cex(opts.ced); - opts.cex.add_months(global_config().option_as_u32bit("eac/ca/cvca_validity_months")); - opts.holder_auth_templ = (CVCA | (iris * IRIS) | (fingerpr * FINGERPRINT)); - opts.hash_alg = hash; - return Botan::CVC_EAC::create_self_signed_cert(*priv_key, opts); - } +} // 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) + { + 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; + const u64bit current_time = system_time(); + opts.ced = ASN1_Ced(current_time); + opts.cex = ASN1_Cex(opts.ced); + opts.cex.add_months(global_config().option_as_u32bit("eac/ca/cvca_validity_months")); + opts.holder_auth_templ = (CVCA | (iris * IRIS) | (fingerpr * FINGERPRINT)); + opts.hash_alg = hash; + return Botan::CVC_EAC::create_self_signed_cert(*priv_key, opts); + } - EAC1_1_CVC link_cvca(EAC1_1_CVC const& signer, - Private_Key const& key, - EAC1_1_CVC const& signee) - { - 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"); - } - ASN1_Ced ced(system_time()); - 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); - std::auto_ptr<Botan::PK_Signer> pk_signer = get_pk_signer(*priv_key, padding_and_hash); - std::auto_ptr<Public_Key> pk = signee.subject_public_key(); - ECDSA_PublicKey* subj_pk = dynamic_cast<ECDSA_PublicKey*>(pk.get()); - subj_pk->set_parameter_encoding(ENC_EXPLICIT); - std::auto_ptr<EAC1_1_CVC_Encoder> enc(subj_pk->cvc_eac1_1_encoder()); - MemoryVector<byte> enc_public_key = enc->public_key(sig_algo); - return EAC1_1_CVC_CA::make_cert(pk_signer, enc_public_key, - signer.get_car(), - signee.get_chr(), - signer.get_chat_value(), - ced, - cex); - } - 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) - { - 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(); - chr_str.append(fixed_len_seqnr(seqnr, seqnr_len)); - ASN1_Chr chr(chr_str); - std::string padding_and_hash = padding_and_hash_from_oid(signee.signature_algorithm().oid); - std::auto_ptr<Botan::PK_Signer> pk_signer = get_pk_signer(*priv_key, padding_and_hash); - std::auto_ptr<Public_Key> pk = signee.subject_public_key(); - ECDSA_PublicKey* subj_pk = dynamic_cast<ECDSA_PublicKey*>(pk.get()); - std::auto_ptr<Public_Key> signer_pk = signer_cert.subject_public_key(); +EAC1_1_CVC link_cvca(EAC1_1_CVC const& signer, + Private_Key const& key, + EAC1_1_CVC const& signee) + { + 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"); + } + ASN1_Ced ced(system_time()); + 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); + std::auto_ptr<Botan::PK_Signer> pk_signer = get_pk_signer(*priv_key, padding_and_hash); + std::auto_ptr<Public_Key> pk = signee.subject_public_key(); + ECDSA_PublicKey* subj_pk = dynamic_cast<ECDSA_PublicKey*>(pk.get()); + subj_pk->set_parameter_encoding(ENC_EXPLICIT); + std::auto_ptr<EAC1_1_CVC_Encoder> enc(subj_pk->cvc_eac1_1_encoder()); + MemoryVector<byte> enc_public_key = enc->public_key(sig_algo); + return EAC1_1_CVC_CA::make_cert(pk_signer, enc_public_key, + signer.get_car(), + signee.get_chr(), + signer.get_chat_value(), + ced, + cex); + } + +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) + { + 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(); + chr_str.append(fixed_len_seqnr(seqnr, seqnr_len)); + ASN1_Chr chr(chr_str); + std::string padding_and_hash = padding_and_hash_from_oid(signee.signature_algorithm().oid); + std::auto_ptr<Botan::PK_Signer> pk_signer = get_pk_signer(*priv_key, padding_and_hash); + std::auto_ptr<Public_Key> pk = signee.subject_public_key(); + ECDSA_PublicKey* subj_pk = dynamic_cast<ECDSA_PublicKey*>(pk.get()); + std::auto_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->get_domain_parameters()); - // 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->get_domain_parameters()); + subj_pk->set_parameter_encoding(ENC_IMPLICITCA); + std::auto_ptr<EAC1_1_CVC_Encoder> enc(subj_pk->cvc_eac1_1_encoder()); + AlgorithmIdentifier sig_algo(signer_cert.signature_algorithm()); + MemoryVector<byte> enc_public_key = enc->public_key(sig_algo); + const u64bit current_time = system_time(); + ASN1_Ced ced(current_time); + 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(global_config().option_as_u32bit("eac/ca/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(global_config().option_as_u32bit("eac/ca/is_validity_months")); + chat_val = IS | chat_low; + } + else + { + throw Invalid_Argument("sign_request(): encountered illegal value for CHAT"); + // (IS cannot sign certificates) + } + return EAC1_1_CVC_CA::make_cert(pk_signer, enc_public_key, + ASN1_Car(signer_cert.get_chr().iso_8859()), + chr, + chat_val, + ced, + cex); + } +EAC1_1_Req create_cvc_req(Private_Key const& prkey, + ASN1_Chr const& chr, + std::string const& hash_alg) + { + 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(ENC_IMPLICITCA); + return Botan::CVC_EAC::create_cvc_req(key, chr, hash_alg); + } - subj_pk->set_parameter_encoding(ENC_IMPLICITCA); - std::auto_ptr<EAC1_1_CVC_Encoder> enc(subj_pk->cvc_eac1_1_encoder()); - AlgorithmIdentifier sig_algo(signer_cert.signature_algorithm()); - MemoryVector<byte> enc_public_key = enc->public_key(sig_algo); - const u64bit current_time = system_time(); - ASN1_Ced ced(current_time); - 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(global_config().option_as_u32bit("eac/ca/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(global_config().option_as_u32bit("eac/ca/is_validity_months")); - chat_val = IS | chat_low; - } - else - { - throw Invalid_Argument("sign_request(): encountered illegal value for CHAT"); - // (IS cannot sign certificates) - } - return EAC1_1_CVC_CA::make_cert(pk_signer, enc_public_key, - ASN1_Car(signer_cert.get_chr().iso_8859()), - chr, - chat_val, - ced, - cex); - } - EAC1_1_Req create_cvc_req(Private_Key const& prkey, - ASN1_Chr const& chr, - std::string const& hash_alg) - { - 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(ENC_IMPLICITCA); - return Botan::CVC_EAC::create_cvc_req(key, chr, hash_alg); - } +} // namespace DE_EAC - } // namespace DE_EAC - } +} diff --git a/src/cert/cvc/cvc_self.h b/src/cert/cvc/cvc_self.h index 7caa96832..c2eaf9737 100644 --- a/src/cert/cvc/cvc_self.h +++ b/src/cert/cvc/cvc_self.h @@ -1,148 +1,147 @@ /************************************************* -* X.509 Self-Signed Certificate Header File * -* (C) 1999-2007 The Botan Project * +* CVC Self-Signed Certificate Header File * +* (C) 2007 FlexSecure GmbH * +* 2008 Jack Lloyd * *************************************************/ #ifndef BOTAN_CVC_EAC_SELF_H__ #define BOTAN_CVC_EAC_SELF_H__ -#include <botan/x509cert.h> #include <botan/pkcs8.h> #include <botan/pkcs10.h> #include <botan/cvc_cert.h> -#include <botan/ec.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 EAC1_1_CVC_Options - { - public: +namespace Botan { - ASN1_Car car; - ASN1_Chr chr; - byte holder_auth_templ; - ASN1_Ced ced; - ASN1_Cex cex; - std::string hash_alg; - }; +/** +* This class represents a set of options used for the creation of CVC certificates +*/ +class EAC1_1_CVC_Options + { + public: + + ASN1_Car car; + ASN1_Chr chr; + byte holder_auth_templ; + ASN1_Ced ced; + ASN1_Cex cex; + std::string hash_alg; + }; /** * This namespace represents general EAC 1.1 convenience functions. */ - namespace CVC_EAC - { +namespace CVC_EAC +{ - /** - * Create a selfsigned CVCA - * @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 - */ +/** +* Create a selfsigned CVCA +* @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 create_self_signed_cert(Private_Key const& key, - EAC1_1_CVC_Options const& opts); - /** - * 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 - * @result the new request - */ - EAC1_1_Req create_cvc_req(Private_Key const& priv_key, - ASN1_Chr const& chr, - std::string const& hash_alg); + EAC1_1_CVC_Options const& opts); +/** +* 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 +* @result the new request +*/ +EAC1_1_Req create_cvc_req(Private_Key const& priv_key, + ASN1_Chr const& chr, + std::string const& hash_alg); - /** - * 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 - */ - EAC1_1_ADO create_ado_req(Private_Key const& priv_key, - EAC1_1_Req const& req, - ASN1_Car const& car); - } +/** +* 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 +*/ +EAC1_1_ADO create_ado_req(Private_Key const& priv_key, + EAC1_1_Req const& req, + ASN1_Car const& car); +} /** * 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 - * @result the CVCA certificate created - */ - EAC1_1_CVC create_cvca(Private_Key const& priv_key, - std::string const& hash, - ASN1_Car const& car, - bool iris, - bool fingerpr); - - /** - * 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 - */ - EAC1_1_CVC link_cvca(EAC1_1_CVC const& signer, - Private_Key const& priv_key, - EAC1_1_CVC const& to_be_signed); +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 +* @result the CVCA certificate created +*/ +EAC1_1_CVC create_cvca(Private_Key const& priv_key, + std::string const& hash, + ASN1_Car const& car, + bool iris, + bool fingerpr); - /** - * 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 - * @result the new request - */ - EAC1_1_Req create_cvc_req(Private_Key const& priv_key, - ASN1_Chr const& chr, - std::string const& hash_alg); - /** - * 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 - * @result the new certificate - * - **/ - EAC1_1_CVC 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); - } +/** +* 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 +*/ +EAC1_1_CVC link_cvca(EAC1_1_CVC const& signer, + Private_Key const& priv_key, + EAC1_1_CVC const& to_be_signed); +/** +* 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 +* @result the new request +*/ +EAC1_1_Req create_cvc_req(Private_Key const& priv_key, + ASN1_Chr const& chr, + std::string const& hash_alg); +/** +* 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 +* @result the new certificate +* +**/ +EAC1_1_CVC 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); +} - } +} #endif diff --git a/src/cert/cvc/eac_asn_obj.h b/src/cert/cvc/eac_asn_obj.h new file mode 100644 index 000000000..6bb77cf7f --- /dev/null +++ b/src/cert/cvc/eac_asn_obj.h @@ -0,0 +1,128 @@ +/************************************************* +* Common ASN.1 Objects Header File * +* (C) 1999-2007 The Botan Project * +*************************************************/ + +#ifndef BOTAN_EAC_ASN1_OBJ_H__ +#define BOTAN_EAC_ASN1_OBJ_H__ + +#include <botan/asn1_obj.h> +#include <vector> +#include <map> + +namespace Botan { + +/************************************************* +* CVC EAC Time * +*************************************************/ +class EAC_Time : public ASN1_Object + { + public: + void encode_into(class DER_Encoder&) const; + void decode_from(class BER_Decoder&); + + std::string as_string() const; + std::string readable_string() const; + bool time_is_set() const; + + s32bit cmp(const EAC_Time&) const; + + void set_to(const std::string&); + //void set_to(const std::string&, ASN1_Tag); + void add_years(u32bit years); + void add_months(u32bit months); + + u32bit get_year() const; + u32bit get_month() const; + u32bit get_day() const; + + EAC_Time(u64bit, ASN1_Tag t = ASN1_Tag(0)); + //EAC_Time(const std::string& = ""); + EAC_Time(const std::string&, ASN1_Tag = ASN1_Tag(0)); + EAC_Time(u32bit year, u32bit month, u32bit day, ASN1_Tag = ASN1_Tag(0)); + virtual ~EAC_Time(){}; + private: + SecureVector<byte> encoded_eac_time() const; + bool passes_sanity_check() const; + u32bit year, month, day; + ASN1_Tag tag; + }; + +// function definitions in asn_eac_tm.cpp +class ASN1_Ced : public EAC_Time + { + public: + ASN1_Ced(std::string const& str=""); + ASN1_Ced(u64bit); + ASN1_Ced(EAC_Time const& other); + //ASN1_Ced(ASN1_Cex const& cex); + }; + +// function definitions in asn_eac_tm.cpp +class ASN1_Cex : public EAC_Time + { + public: + ASN1_Cex(std::string const& str=""); + ASN1_Cex(u64bit); + ASN1_Cex(EAC_Time const& other); + //ASN1_Cex(ASN1_Ced const& ced); + }; + +/************************************************* +* String for car/chr of cv certificates * +*************************************************/ +class ASN1_EAC_String: public ASN1_Object + { + public: + void encode_into(class DER_Encoder&) const; + void decode_from(class BER_Decoder&); + + std::string value() const; + 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 iso_8859_str; + ASN1_Tag tag; + }; + +// String tagged with 2 +// function definitions in asn1_eac_str.cpp +class ASN1_Car : public ASN1_EAC_String + { + public: + ASN1_Car(std::string const& str = ""); + }; + +// String tagged with 32 +// function definitions in asn1_eac_str.cpp +class ASN1_Chr : public ASN1_EAC_String + { + public: + ASN1_Chr(std::string const& str = ""); + }; + +/************************************************* +* Comparison Operations * +*************************************************/ +bool operator==(const EAC_Time&, const EAC_Time&); +bool operator!=(const EAC_Time&, const EAC_Time&); +bool operator<=(const EAC_Time&, const EAC_Time&); +bool operator>=(const EAC_Time&, const EAC_Time&); +bool operator>(const EAC_Time&, const EAC_Time&); +bool operator<(const EAC_Time&, const EAC_Time&); + +bool 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/cert/cvc/eac_obj.h b/src/cert/cvc/eac_obj.h index 5b1912595..baf811d9d 100644 --- a/src/cert/cvc/eac_obj.h +++ b/src/cert/cvc/eac_obj.h @@ -9,7 +9,7 @@ #include <botan/pubkey.h> #include <botan/x509_key.h> -#include <botan/x509_obj.h> +#include <botan/signed_obj.h> #include <botan/enums.h> #include <botan/pubkey.h> #include <botan/parsing.h> @@ -27,14 +27,13 @@ const std::string eac_cvc_emsa("EMSA1_BSI"); * TR03110 v1.1 EAC CV Certificate * *************************************************/ template<typename Derived> -class EAC1_1_obj : public X509_Object // CRTP is used enable the call sequence: +class EAC1_1_obj : public EAC_Signed_Object // CRTP is used enable the call sequence: { // data members first: protected: ECDSA_Signature m_sig; - // member functions here: public: /** @@ -53,7 +52,7 @@ class EAC1_1_obj : public X509_Object // CRTP is used enable the call sequence: protected: void init(SharedPtrConverter<DataSource> in); - static SecureVector<byte> make_signature(const PK_Signer* signer, + static SecureVector<byte> make_signature(PK_Signer* signer, const MemoryRegion<byte>& tbs_bits, RandomNumberGenerator& rng); @@ -65,7 +64,7 @@ template<typename Derived> SecureVector<byte> EAC1_1_obj<Derived>::get_concat_si { return m_sig.get_concatenation(); } -template<typename Derived> SecureVector<byte> EAC1_1_obj<Derived>::make_signature(const PK_Signer* signer, +template<typename Derived> SecureVector<byte> EAC1_1_obj<Derived>::make_signature(PK_Signer* signer, const MemoryRegion<byte>& tbs_bits, RandomNumberGenerator& rng) { @@ -115,7 +114,7 @@ template<typename Derived> bool EAC1_1_obj<Derived>::check_signature(Public_Key& { return false; } - std::auto_ptr<ECDSA_Signature_Encoder> enc = m_sig.x509_encoder(); + std::auto_ptr<ECDSA_Signature_Encoder> enc(m_sig.x509_encoder()); SecureVector<byte> seq_sig = enc->signature_bits(); SecureVector<byte> to_sign = tbs_data(); return verifier->verify_message(to_sign, seq_sig); diff --git a/src/cert/cvc/info.txt b/src/cert/cvc/info.txt index 6af8ff4e5..50483dc91 100644 --- a/src/cert/cvc/info.txt +++ b/src/cert/cvc/info.txt @@ -2,12 +2,16 @@ realname "Card Verifiable Certificates" define CARD_VERIFIABLE_CERTIFICATES -load_on request +load_on auto <requires> +asn1 +ecdsa </requires> <add> +asn1_eac_str.cpp +asn1_eac_tm.cpp cvc_ado.cpp cvc_ado.h cvc_ca.cpp @@ -20,5 +24,8 @@ cvc_req.cpp cvc_req.h cvc_self.cpp cvc_self.h +eac_asn_obj.h eac_obj.h +signed_obj.cpp +signed_obj.h </add> diff --git a/src/cert/cvc/signed_obj.cpp b/src/cert/cvc/signed_obj.cpp new file mode 100644 index 000000000..6a5952812 --- /dev/null +++ b/src/cert/cvc/signed_obj.cpp @@ -0,0 +1,64 @@ +/************************************************* +* X.509 SIGNED Object Source File * +* (C) 1999-2007 The Botan Project * +*************************************************/ + +#include <botan/signed_obj.h> + +namespace Botan { + +/************************************************* +* Return a BER encoded X.509 object * +*************************************************/ +SecureVector<byte> EAC_Signed_Object::BER_encode() const + { + Pipe ber; + ber.start_msg(); + encode(ber, RAW_BER); + ber.end_msg(); + return 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 sig_algo; + } + +/************************************************* +* 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(PEM_label_pref + " decoding failed (" + + what.substr(23, std::string::npos) + ")"); + } + catch(Invalid_Argument& e) + { + const std::string what = e.what(); + throw Decoding_Error(PEM_label_pref + " decoding failed (" + + what.substr(7, std::string::npos) + ")"); + } + } + +} diff --git a/src/cert/cvc/signed_obj.h b/src/cert/cvc/signed_obj.h new file mode 100644 index 000000000..9116b783e --- /dev/null +++ b/src/cert/cvc/signed_obj.h @@ -0,0 +1,58 @@ +/************************************************* +* EAC SIGNED Object Header File * +* (C) 2007 FlexSecure GmbH * +* 2008 Jack Lloyd * +*************************************************/ + +#ifndef BOTAN_EAC_SIGNED_OBJECT_H__ +#define BOTAN_EAC_SIGNED_OBJECT_H__ + +#include <botan/asn1_obj.h> +#include <botan/enums.h> +#include <botan/freestore.h> +#include <botan/pipe.h> +#include <vector> + +namespace Botan { + +/************************************************* +* EAC SIGNED Object * +*************************************************/ +class EAC_Signed_Object + { + public: + virtual SecureVector<byte> tbs_data() const = 0; + virtual SecureVector<byte> get_concat_sig() const = 0; // NOTE: this is here + // only because abstract + // signature objects have + // not yet been introduced + /** + * Get the signature algorithm identifier used to sign this object. + * @result the signature algorithm identifier + */ + AlgorithmIdentifier signature_algorithm() const; + + virtual bool check_signature(class Public_Key&) const = 0; + virtual void encode(Pipe&, X509_Encoding = PEM) const = 0; + SecureVector<byte> BER_encode() const; + std::string PEM_encode() const; + + EAC_Signed_Object(SharedPtrConverter<DataSource>, const std::string&); + EAC_Signed_Object(const std::string&, const std::string&); + virtual ~EAC_Signed_Object() {} + protected: + void do_decode(); + EAC_Signed_Object() {} + AlgorithmIdentifier sig_algo; + SecureVector<byte> tbs_bits; + std::string PEM_label_pref; + std::vector<std::string> PEM_labels_allowed; + private: + + virtual void force_decode() = 0; + + }; + +} + +#endif |