diff options
author | lloyd <[email protected]> | 2008-10-08 20:40:40 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2008-10-08 20:40:40 +0000 |
commit | 0ffb4257258df236dc469ef086b1871fe7b5afba (patch) | |
tree | 8cad23bb8bdf1db1f4d7e6a19eb23d6c1ef2e4ae /src/cert/cvc | |
parent | fa7aa7f8dc857bae547fe6981fa6fc2b065b2004 (diff) |
Many improvements towards getting the CVC implementation from InSiTo
compiling against mainline. Add several missing classes extracted from
other files inside InSiTo. Add dependency note for ecdsa and asn1
Diffstat (limited to 'src/cert/cvc')
-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 |