aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/cert/cvc/asn1_eac_str.cpp128
-rw-r--r--src/cert/cvc/asn1_eac_tm.cpp375
-rw-r--r--src/cert/cvc/cvc_ado.cpp246
-rw-r--r--src/cert/cvc/cvc_ado.h3
-rw-r--r--src/cert/cvc/cvc_ca.cpp66
-rw-r--r--src/cert/cvc/cvc_ca.h30
-rw-r--r--src/cert/cvc/cvc_cert.cpp176
-rw-r--r--src/cert/cvc/cvc_gen_cert.h14
-rw-r--r--src/cert/cvc/cvc_req.cpp98
-rw-r--r--src/cert/cvc/cvc_self.cpp467
-rw-r--r--src/cert/cvc/cvc_self.h235
-rw-r--r--src/cert/cvc/eac_asn_obj.h128
-rw-r--r--src/cert/cvc/eac_obj.h11
-rw-r--r--src/cert/cvc/info.txt9
-rw-r--r--src/cert/cvc/signed_obj.cpp64
-rw-r--r--src/cert/cvc/signed_obj.h58
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