aboutsummaryrefslogtreecommitdiffstats
path: root/src/cert/cvc
diff options
context:
space:
mode:
Diffstat (limited to 'src/cert/cvc')
-rw-r--r--src/cert/cvc/cvc_ado.cpp119
-rw-r--r--src/cert/cvc/cvc_ado.h95
-rw-r--r--src/cert/cvc/cvc_ca.cpp42
-rw-r--r--src/cert/cvc/cvc_ca.h55
-rw-r--r--src/cert/cvc/cvc_cert.cpp100
-rw-r--r--src/cert/cvc/cvc_cert.h98
-rw-r--r--src/cert/cvc/cvc_gen_cert.h161
-rw-r--r--src/cert/cvc/cvc_key.h37
-rw-r--r--src/cert/cvc/cvc_req.cpp66
-rw-r--r--src/cert/cvc/cvc_req.h61
-rw-r--r--src/cert/cvc/cvc_self.cpp271
-rw-r--r--src/cert/cvc/cvc_self.h148
-rw-r--r--src/cert/cvc/eac_obj.h132
-rw-r--r--src/cert/cvc/info.txt24
14 files changed, 1409 insertions, 0 deletions
diff --git a/src/cert/cvc/cvc_ado.cpp b/src/cert/cvc/cvc_ado.cpp
new file mode 100644
index 000000000..d5083d3ab
--- /dev/null
+++ b/src/cert/cvc/cvc_ado.cpp
@@ -0,0 +1,119 @@
+#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
diff --git a/src/cert/cvc/cvc_ado.h b/src/cert/cvc/cvc_ado.h
new file mode 100644
index 000000000..e2e5395b5
--- /dev/null
+++ b/src/cert/cvc/cvc_ado.h
@@ -0,0 +1,95 @@
+/*************************************************
+* EAC1_1 CVC ADO Header File *
+* (C) 2008 Falko Strenzke *
+*************************************************/
+
+#ifndef BOTAN_EAC_CVC_ADO_H__
+#define BOTAN_EAC_CVC_ADO_H__
+
+#include <botan/x509_key.h>
+#include <botan/enums.h>
+#include <botan/pubkey.h>
+#include <botan/ecdsa.h>
+#include <botan/eac_obj.h>
+#include <botan/cvc_req.h>
+#include <string>
+
+namespace Botan {
+
+/**
+* This class represents a TR03110 (EAC) v1.1 CVC ADO request
+*/
+
+ // CRTP continuation from EAC1_1_obj
+class EAC1_1_ADO : public EAC1_1_obj<EAC1_1_ADO>
+ {
+ friend class EAC1_1_obj<EAC1_1_ADO>;
+ public:
+ /**
+ * Construct a CVC ADO request from a DER encoded CVC ADO request file.
+ * @param str the path to the DER encoded file
+ */
+ EAC1_1_ADO(const std::string& str);
+ /**
+ * Construct a CVC ADO request from a data source
+ * @param source the data source
+ */
+ EAC1_1_ADO(std::tr1::shared_ptr<DataSource> source);
+
+ /**
+ * Create a signed CVC ADO request from to be signed (TBS) data
+ * @param signer the signer used to sign the CVC ADO request
+ * @param tbs_bits the TBS data to sign
+ */
+ static MemoryVector<byte> make_signed(
+ std::auto_ptr<PK_Signer> signer,
+ const MemoryRegion<byte>& tbs_bits);
+ /**
+ * Get the CAR of this CVC ADO request
+ * @result the CAR of this CVC ADO request
+ */
+ ASN1_Car get_car() const;
+
+ /**
+ * Get the CVC request contained in this object.
+ * @result the CVC request inside this CVC ADO request
+ */
+ EAC1_1_Req get_request() const;
+
+ /**
+ * Encode this object into a pipe. Only DER is supported.
+ * @param out the pipe to encode this object into
+ * @param encoding the encoding type to use, must be DER
+ */
+ void encode(Pipe& out, X509_Encoding encoding) const;
+
+ bool operator==(EAC1_1_ADO const& rhs) const;
+
+ /**
+ * Get the TBS data of this CVC ADO request.
+ * @result the TBS data
+ */
+ SecureVector<byte> tbs_data() const;
+ virtual ~EAC1_1_ADO()
+ {}
+ private:
+ ASN1_Car m_car;
+ EAC1_1_Req m_req;
+
+ void force_decode();
+ static void decode_info(SharedPtrConverter<DataSource> source,
+ SecureVector<byte> & res_tbs_bits,
+ ECDSA_Signature & res_sig);
+ };
+
+inline bool operator!=(EAC1_1_ADO const& lhs, EAC1_1_ADO const& rhs)
+ {
+ return (!(lhs == rhs));
+ }
+
+}
+
+#endif
+
+
diff --git a/src/cert/cvc/cvc_ca.cpp b/src/cert/cvc/cvc_ca.cpp
new file mode 100644
index 000000000..19b35e074
--- /dev/null
+++ b/src/cert/cvc/cvc_ca.cpp
@@ -0,0 +1,42 @@
+#include <botan/cvc_ca.h>
+#include <botan/cvc_cert.h>
+#include <botan/der_enc.h>
+#include <botan/util.h>
+#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);
+
+ 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);
+ }
+
+}
diff --git a/src/cert/cvc/cvc_ca.h b/src/cert/cvc/cvc_ca.h
new file mode 100644
index 000000000..590cd4c91
--- /dev/null
+++ b/src/cert/cvc/cvc_ca.h
@@ -0,0 +1,55 @@
+/*************************************************
+* EAC1.1 CVC Certificate Authority Header File *
+* (C) 1999-2007 The Botan Project *
+*************************************************/
+
+#ifndef BOTAN_CVC_CA_H__
+#define BOTAN_CVC_CA_H__
+
+#include <botan/pkcs8.h>
+#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:
+
+ /**
+ * Create an arbitrary EAC 1.1 CVC.
+ * The desired key encoding must be set within the key (if applicable).
+ * @param signer the signer used to sign the certificate
+ * @param public_key the DER encoded public key to appear in
+ * the certificate
+ * @param car the CAR of the certificate
+ * @param chr the CHR of the certificate
+ * @param holder_auth_templ the holder authorization value byte to
+ * appear in the CHAT of the certificate
+ * @param ced the CED to appear in the certificate
+ * @param ced the CEX to appear in the certificate
+ */
+ 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
+ );
+
+ private:
+
+ };
+
+
+
+
+}
+
+#endif
diff --git a/src/cert/cvc/cvc_cert.cpp b/src/cert/cvc/cvc_cert.cpp
new file mode 100644
index 000000000..29b3661ba
--- /dev/null
+++ b/src/cert/cvc/cvc_cert.cpp
@@ -0,0 +1,100 @@
+#include <botan/tr1_mem_includer.h>
+#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;
+ }
+
+ 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();
+ if(enc_chat_val.size() != 1)
+ {
+ throw Decoding_Error("CertificateHolderAuthorizationValue was not of length 1");
+ }
+ if(cpi != 0)
+ {
+ throw Decoding_Error("EAC1_1 certificate´s cpi was not 0");
+ }
+ 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())
+ {
+ self_signed= true;
+ }
+
+ }
+ /*************************************************
+ * 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
+ {
+ return (tbs_data() == rhs.tbs_data()
+ && get_concat_sig() == rhs.get_concat_sig());
+ }
+
+
+}
diff --git a/src/cert/cvc/cvc_cert.h b/src/cert/cvc/cvc_cert.h
new file mode 100644
index 000000000..00bdd6679
--- /dev/null
+++ b/src/cert/cvc/cvc_cert.h
@@ -0,0 +1,98 @@
+/*************************************************
+* EAC1_1 CVC Header File *
+* (C) 2008 Falko Strenzke *
+*************************************************/
+
+#ifndef BOTAN_CVC_EAC_H__
+#define BOTAN_CVC_EAC_H__
+
+#include <botan/x509_key.h>
+#include <botan/enums.h>
+#include <botan/signed_obj.h>
+#include <string>
+#include <botan/pubkey.h>
+#include <botan/ecdsa.h>
+#include <botan/ecdsa_sig.h>
+#include <botan/eac_obj.h>
+#include <botan/cvc_gen_cert.h>
+namespace Botan
+ {
+
+
+ /**
+ * This class represents TR03110 (EAC) v1.1 CV Certificates
+ */
+ class EAC1_1_CVC : public EAC1_1_gen_CVC<EAC1_1_CVC>//Signed_Object
+ {
+ friend class EAC1_1_obj<EAC1_1_CVC>;
+
+ public:
+
+ /**
+ * Get the CAR of the certificate.
+ * @result the CAR of the certificate
+ */
+ ASN1_Car get_car() const;
+
+ /**
+ * Get the CED of this certificate.
+ * @result the CED this certificate
+ */
+ ASN1_Ced get_ced() const;
+ /**
+ * Get the CEX of this certificate.
+ * @result the CEX this certificate
+ */
+ ASN1_Cex get_cex() const;
+
+ /**
+ * Get the CHAT value.
+ * @result the CHAT value
+ */
+ u32bit get_chat_value() const;
+
+ bool operator==(const EAC1_1_CVC&) const;
+
+ /**
+ * Construct a CVC from a data source
+ * @param source the data source
+ */
+ EAC1_1_CVC(std::tr1::shared_ptr<DataSource>& source);
+ /**
+ * Construct a CVC from a file
+ * @param str the path to the certificate file
+ */
+ EAC1_1_CVC(const std::string& str);
+ virtual ~EAC1_1_CVC()
+ {}
+
+ protected:
+
+ private:
+ void force_decode();
+ friend class EAC1_1_CVC_CA;
+ EAC1_1_CVC()
+ {}
+ ASN1_Car m_car;
+ ASN1_Ced m_ced;
+ ASN1_Cex m_cex;
+ byte m_chat_val;
+ OID m_chat_oid;
+
+
+ };
+
+ /*************************************************
+ *Comparison *
+ *************************************************/
+ inline bool operator!=(EAC1_1_CVC const& lhs, EAC1_1_CVC const& rhs)
+ {
+ return !(lhs == rhs);
+ }
+
+
+}
+
+#endif
+
diff --git a/src/cert/cvc/cvc_gen_cert.h b/src/cert/cvc/cvc_gen_cert.h
new file mode 100644
index 000000000..7a9ac86fa
--- /dev/null
+++ b/src/cert/cvc/cvc_gen_cert.h
@@ -0,0 +1,161 @@
+/*************************************************
+* EAC1_1 general CVC Header File *
+* (C) 2008 Falko Strenzke *
+*************************************************/
+
+#ifndef BOTAN_EAC_CVC_GCERT_H__
+#define BOTAN_EAC_CVC_GCERT_H__
+
+#include <botan/x509_key.h>
+#include <botan/enums.h>
+#include <string>
+#include <botan/pubkey.h>
+#include <botan/ecdsa_sig.h>
+
+namespace Botan {
+
+/**
+* This class represents TR03110 (EAC) v1.1 generalized CV Certificates
+*/
+template<typename Derived>
+class EAC1_1_gen_CVC : public EAC1_1_obj<Derived> // CRTP continuation from EAC1_1_obj
+ {
+ friend class EAC1_1_obj<EAC1_1_gen_CVC>;
+ protected:
+ ECDSA_PublicKey m_pk; // public key
+ ASN1_Chr m_chr;
+ bool self_signed;
+
+ static void decode_info(SharedPtrConverter<DataSource> source, SecureVector<byte> & res_tbs_bits, ECDSA_Signature & res_sig);
+ public:
+
+ /**
+ * Get this certificates public key.
+ * @result this certificates public key
+ */
+ std::auto_ptr<Public_Key> subject_public_key() const;
+
+ /**
+ * Find out whether this object is self signed.
+ * @result true if this object is self signed
+ */
+ bool is_self_signed() const;
+
+ /**
+ * Get the CHR of the certificate.
+ * @result the CHR of the certificate
+ */
+ ASN1_Chr get_chr() const;
+
+ /**
+ * Put the DER encoded version of this object into a pipe. PEM
+ * is not supported.
+ * @param out the pipe to push the DER encoded version into
+ * @param encoding the encoding to use. Must be DER.
+ */
+ void encode(Pipe& out, X509_Encoding encoding) const;
+
+ /**
+ * Get the to-be-signed (TBS) data of this object.
+ * @result the TBS data of this object
+ */
+ SecureVector<byte> tbs_data() const;
+
+ /**
+ * Build the DER encoded certifcate body of an object
+ * @param tbs the data to be signed
+ * @result the correctly encoded body of the object
+ */
+ static SecureVector<byte> build_cert_body(MemoryRegion<byte> const& tbs);
+
+ /**
+ * Create a signed generalized CVC object.
+ * @param signer the signer used to sign this object
+ * @param tbs_bits the body the generalized CVC object to be signed
+ * @result the DER encoded signed generalized CVC object
+ */
+ static MemoryVector<byte> make_signed(
+ std::auto_ptr<PK_Signer> signer,
+ const MemoryRegion<byte>& tbs_bits);
+ virtual ~EAC1_1_gen_CVC<Derived>()
+ {}
+
+ }
+ ;
+template<typename Derived> ASN1_Chr EAC1_1_gen_CVC<Derived>::get_chr() const
+ {
+ return m_chr;
+ }
+template<typename Derived> bool EAC1_1_gen_CVC<Derived>::is_self_signed() const
+ {
+ return self_signed;
+ }
+template<typename Derived> MemoryVector<byte> EAC1_1_gen_CVC<Derived>::make_signed(
+ std::auto_ptr<PK_Signer> signer,
+ const MemoryRegion<byte>& tbs_bits) // static
+ {
+ SecureVector<byte> concat_sig = EAC1_1_obj<Derived>::make_signature(signer, tbs_bits);
+ assert(concat_sig.size() % 2 == 0);
+ return DER_Encoder()
+ .start_cons(ASN1_Tag(33), APPLICATION)
+ .raw_bytes(tbs_bits)
+ .encode(concat_sig, OCTET_STRING, ASN1_Tag(55), APPLICATION)
+ .end_cons()
+ .get_contents();
+ }
+template<typename Derived> std::auto_ptr<Public_Key> EAC1_1_gen_CVC<Derived>::subject_public_key() const
+ {
+ return std::auto_ptr<Public_Key>(new ECDSA_PublicKey(m_pk));
+ }
+template<typename Derived> SecureVector<byte> EAC1_1_gen_CVC<Derived>::build_cert_body(MemoryRegion<byte> const& tbs)
+ {
+ return DER_Encoder()
+ .start_cons(ASN1_Tag(78), APPLICATION)
+ .raw_bytes(tbs)
+ .end_cons().get_contents();
+ }
+template<typename Derived> SecureVector<byte> EAC1_1_gen_CVC<Derived>::tbs_data() const
+ {
+ return build_cert_body(EAC1_1_obj<Derived>::tbs_bits);
+ }
+template<typename Derived> void EAC1_1_gen_CVC<Derived>::encode(Pipe& out, X509_Encoding encoding) const
+ {
+ SecureVector<byte> concat_sig(EAC1_1_obj<Derived>::m_sig.get_concatenation());
+ SecureVector<byte> der = DER_Encoder()
+ .start_cons(ASN1_Tag(33), APPLICATION)
+ .start_cons(ASN1_Tag(78), APPLICATION)
+ .raw_bytes(EAC1_1_obj<Derived>::tbs_bits)
+ .end_cons()
+ .encode(concat_sig, OCTET_STRING, ASN1_Tag(55), APPLICATION)
+ .end_cons()
+ .get_contents();
+
+ if (encoding == PEM)
+ throw Invalid_Argument("EAC1_1_gen_CVC::encode() cannot PEM encode an EAC object");
+ else
+ out.write(der);
+ }
+
+template<typename Derived>
+void EAC1_1_gen_CVC<Derived>::decode_info(
+ SharedPtrConverter<DataSource> source,
+ SecureVector<byte> & res_tbs_bits,
+ ECDSA_Signature & res_sig)
+ {
+ SecureVector<byte> concat_sig;
+ BER_Decoder(source.get_shared())
+ .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);
+ }
+
+}
+
+#endif
+
+
diff --git a/src/cert/cvc/cvc_key.h b/src/cert/cvc/cvc_key.h
new file mode 100644
index 000000000..1867f04f4
--- /dev/null
+++ b/src/cert/cvc/cvc_key.h
@@ -0,0 +1,37 @@
+/*************************************************
+* EAC CVC Public Key Header File *
+* (C) 2008 FlexSecure Gmbh *
+* Falko Strenzke *
+*************************************************/
+
+#ifndef BOTAN_EAC1_1_CVC_PUBLIC_KEY_H__
+#define BOTAN_EAC1_1_CVC_PUBLIC_KEY_H__
+
+#include <botan/pipe.h>
+#include <botan/pk_keys.h>
+#include <botan/alg_id.h>
+
+namespace Botan {
+
+/*************************************************
+ * EAC CVC Public Key Encoder *
+*************************************************/
+ class EAC1_1_CVC_Encoder
+ {
+ public:
+ virtual MemoryVector<byte> public_key(AlgorithmIdentifier const&) const = 0;
+ virtual ~EAC1_1_CVC_Encoder() {}
+ };
+
+/*************************************************
+ * EAC CVC Public Key Decoder *
+*************************************************/
+ class EAC1_1_CVC_Decoder
+ {
+ public:
+ virtual AlgorithmIdentifier const public_key(const MemoryRegion<byte>&) = 0;
+ virtual ~EAC1_1_CVC_Decoder() {}
+ };
+}
+#endif
diff --git a/src/cert/cvc/cvc_req.cpp b/src/cert/cvc/cvc_req.cpp
new file mode 100644
index 000000000..2d5172917
--- /dev/null
+++ b/src/cert/cvc/cvc_req.cpp
@@ -0,0 +1,66 @@
+#include <botan/tr1_mem_includer.h>
+#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
+{
+
+
+
+ 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());
+ }
+
+ /*************************************************
+ * 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();
+ }
+
+
+}
diff --git a/src/cert/cvc/cvc_req.h b/src/cert/cvc/cvc_req.h
new file mode 100644
index 000000000..674598a20
--- /dev/null
+++ b/src/cert/cvc/cvc_req.h
@@ -0,0 +1,61 @@
+/*************************************************
+* EAC1_1 CVC Request Header File *
+* (C) 2008 Falko Strenzke *
+*************************************************/
+
+#ifndef BOTAN_EAC_CVC_REQ_H__
+#define BOTAN_EAC_CVC_REQ_H__
+
+#include <botan/x509_key.h>
+#include <botan/enums.h>
+#include <botan/cvc_gen_cert.h>
+#include <botan/cvc_req.h>
+namespace Botan
+{
+
+ /**
+ * This class represents TR03110 v1.1 EAC CV Certificate Requests.
+ */
+ class EAC1_1_Req : public EAC1_1_gen_CVC<EAC1_1_Req>
+ {
+ friend class EAC1_1_Req_CA;
+ friend class EAC1_1_ADO;
+ friend class EAC1_1_obj<EAC1_1_Req>;
+
+ public:
+ bool operator==(const EAC1_1_Req&) const;
+ /**
+ * Construct a CVC request from a data source.
+ * @param source the data source
+ */
+ EAC1_1_Req(std::tr1::shared_ptr<DataSource> source);
+ /**
+ * Construct a CVC request from a DER encoded CVC reqeust file.
+ * @param str the path to the DER encoded file
+ */
+ EAC1_1_Req(const std::string& str);
+ virtual ~EAC1_1_Req(){}
+
+ protected:
+
+ private:
+ void force_decode();
+ EAC1_1_Req()
+ {}
+
+ };
+
+ /*************************************************
+ *Comparison *
+ *************************************************/
+ inline bool operator!=(EAC1_1_Req const& lhs, EAC1_1_Req const& rhs)
+ {
+ return !(lhs == rhs);
+ }
+
+
+}
+
+#endif // h-guard
+
diff --git a/src/cert/cvc/cvc_self.cpp b/src/cert/cvc/cvc_self.cpp
new file mode 100644
index 000000000..130ac6998
--- /dev/null
+++ b/src/cert/cvc/cvc_self.cpp
@@ -0,0 +1,271 @@
+#include <botan/cvc_self.h>
+#include <botan/cvc_cert.h>
+#include <botan/cvc_ca.h>
+#include <botan/alg_id.h>
+#include <botan/cvc_key.h>
+#include <botan/oids.h>
+#include <botan/look_pk.h>
+#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 CVC_EAC
+ {
+
+ 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);
+
+ if (priv_key == 0)
+ {
+ throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type");
+ }
+
+ ASN1_Chr chr(opt.car.value());
+
+ AlgorithmIdentifier sig_algo;
+ std::string padding_and_hash(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<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);
+
+ 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);
+ 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();
+
+ 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);
+ }
+
+ EAC1_1_ADO create_ado_req(Private_Key const& key,
+ EAC1_1_Req const& req,
+ ASN1_Car const& car)
+ {
+
+ 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);
+ }
+
+ } // 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();
+
+ // 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);
+ }
+
+ } // namespace DE_EAC
+ }
diff --git a/src/cert/cvc/cvc_self.h b/src/cert/cvc/cvc_self.h
new file mode 100644
index 000000000..7caa96832
--- /dev/null
+++ b/src/cert/cvc/cvc_self.h
@@ -0,0 +1,148 @@
+/*************************************************
+* X.509 Self-Signed Certificate Header File *
+* (C) 1999-2007 The Botan Project *
+*************************************************/
+
+#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/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:
+
+ 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
+ {
+
+ /**
+ * 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);
+
+ /**
+ * 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);
+
+ /**
+ * 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_obj.h b/src/cert/cvc/eac_obj.h
new file mode 100644
index 000000000..5b1912595
--- /dev/null
+++ b/src/cert/cvc/eac_obj.h
@@ -0,0 +1,132 @@
+/*************************************************
+* EAC1_1 objects Header File *
+* (C) 2008 Falko Strenzke *
+*************************************************/
+
+#ifndef BOTAN_EAC_OBJ_H__
+#define BOTAN_EAC_OBJ_H__
+
+#include <botan/pubkey.h>
+#include <botan/x509_key.h>
+#include <botan/x509_obj.h>
+#include <botan/enums.h>
+#include <botan/pubkey.h>
+#include <botan/parsing.h>
+#include <botan/pem.h>
+#include <botan/oids.h>
+#include <botan/look_pk.h>
+#include <botan/ecdsa_sig.h>
+#include <string>
+
+namespace Botan {
+
+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:
+ {
+ // data members first:
+ protected:
+
+ ECDSA_Signature m_sig;
+
+
+ // member functions here:
+ public:
+ /**
+ * Return the signature as a concatenation of the encoded parts.
+ * @result the concatenated signature
+ */
+ SecureVector<byte> get_concat_sig() const;
+
+ /**
+ * Verify the signature of this objects.
+ * @param pub_key the public key to verify the signature with
+ * @result true if the verification succeeded
+ */
+ virtual bool check_signature(Public_Key& pub_key) const;
+
+ protected:
+ void init(SharedPtrConverter<DataSource> in);
+
+ static SecureVector<byte> make_signature(const PK_Signer* signer,
+ const MemoryRegion<byte>& tbs_bits,
+ RandomNumberGenerator& rng);
+
+ virtual ~EAC1_1_obj<Derived>(){}
+
+ };
+
+template<typename Derived> SecureVector<byte> EAC1_1_obj<Derived>::get_concat_sig() const
+ {
+ return m_sig.get_concatenation();
+ }
+template<typename Derived> SecureVector<byte> EAC1_1_obj<Derived>::make_signature(const PK_Signer* signer,
+ const MemoryRegion<byte>& tbs_bits,
+ RandomNumberGenerator& rng)
+ {
+ SecureVector<byte> seq_sig = signer->sign_message(tbs_bits, rng); // this is the signature as a der sequence
+ ECDSA_Signature sig(decode_seq(seq_sig));
+ SecureVector<byte> concat_sig(sig.get_concatenation());
+ return concat_sig;
+ }
+
+template<typename Derived> void EAC1_1_obj<Derived>::init(SharedPtrConverter<DataSource> in)
+ {
+
+ try
+ {
+ Derived::decode_info(in.get_shared(), tbs_bits, m_sig);
+ }
+ catch(Decoding_Error)
+ {
+ throw Decoding_Error(PEM_label_pref + " decoding failed");
+ }
+ }
+
+template<typename Derived> bool EAC1_1_obj<Derived>::check_signature(Public_Key& pub_key) const
+ {
+ try
+ {
+ std::vector<std::string> sig_info =
+ split_on(OIDS::lookup(sig_algo.oid), '/');
+
+ if(sig_info.size() != 2 || sig_info[0] != pub_key.algo_name())
+ {
+ return false;
+ }
+
+ std::string padding = sig_info[1];
+ Signature_Format format =
+ (pub_key.message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363;
+
+ std::auto_ptr<PK_Verifier> verifier;
+ if(dynamic_cast<PK_Verifying_wo_MR_Key*>(&pub_key))
+ {
+ PK_Verifying_wo_MR_Key& sig_key =
+ dynamic_cast<PK_Verifying_wo_MR_Key&>(pub_key);
+ verifier.reset(get_pk_verifier(sig_key, padding, format));
+ }
+ else
+ {
+ return false;
+ }
+ 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);
+
+ }
+ catch(...)
+ {
+ return false;
+ }
+ }
+
+}
+
+#endif
diff --git a/src/cert/cvc/info.txt b/src/cert/cvc/info.txt
new file mode 100644
index 000000000..6af8ff4e5
--- /dev/null
+++ b/src/cert/cvc/info.txt
@@ -0,0 +1,24 @@
+realname "Card Verifiable Certificates"
+
+define CARD_VERIFIABLE_CERTIFICATES
+
+load_on request
+
+<requires>
+</requires>
+
+<add>
+cvc_ado.cpp
+cvc_ado.h
+cvc_ca.cpp
+cvc_ca.h
+cvc_cert.cpp
+cvc_cert.h
+cvc_gen_cert.h
+cvc_key.h
+cvc_req.cpp
+cvc_req.h
+cvc_self.cpp
+cvc_self.h
+eac_obj.h
+</add>