00001
00002
00003
00004
00005
00006
00007
00008 #include <botan/cvc_self.h>
00009 #include <botan/ecc_key.h>
00010 #include <botan/point_gfp.h>
00011 #include <botan/time.h>
00012 #include <botan/oids.h>
00013 #include <sstream>
00014
00015 namespace Botan {
00016
00017 namespace {
00018
00019
00020
00021
00022 enum CHAT_values{
00023 CVCA = 0xC0,
00024 DVCA_domestic = 0x80,
00025 DVCA_foreign = 0x40,
00026 IS = 0x00,
00027
00028 IRIS = 0x02,
00029 FINGERPRINT = 0x01
00030 };
00031
00032 void encode_eac_bigint(DER_Encoder& der, const BigInt& x, ASN1_Tag tag)
00033 {
00034 der.encode(BigInt::encode_1363(x, x.bytes()), OCTET_STRING, tag);
00035 }
00036
00037 MemoryVector<byte> eac_1_1_encoding(const EC_PublicKey* key,
00038 const OID& sig_algo)
00039 {
00040 if(key->domain_format() == EC_DOMPAR_ENC_OID)
00041 throw Encoding_Error("CVC encoder: cannot encode parameters by OID");
00042
00043 const EC_Domain_Params& domain = key->domain();
00044
00045
00046
00047 DER_Encoder enc;
00048 enc.start_cons(ASN1_Tag(73), APPLICATION)
00049 .encode(sig_algo);
00050
00051 if(key->domain_format() == EC_DOMPAR_ENC_EXPLICIT)
00052 {
00053 encode_eac_bigint(enc, domain.get_curve().get_p(), ASN1_Tag(1));
00054 encode_eac_bigint(enc, domain.get_curve().get_a(), ASN1_Tag(2));
00055 encode_eac_bigint(enc, domain.get_curve().get_b(), ASN1_Tag(3));
00056
00057 enc.encode(EC2OSP(domain.get_base_point(), PointGFp::UNCOMPRESSED),
00058 OCTET_STRING, ASN1_Tag(4));
00059
00060 encode_eac_bigint(enc, domain.get_order(), ASN1_Tag(4));
00061 }
00062
00063 enc.encode(EC2OSP(key->public_point(), PointGFp::UNCOMPRESSED),
00064 OCTET_STRING, ASN1_Tag(6));
00065
00066 if(key->domain_format() == EC_DOMPAR_ENC_EXPLICIT)
00067 encode_eac_bigint(enc, domain.get_cofactor(), ASN1_Tag(7));
00068
00069 enc.end_cons();
00070
00071 return enc.get_contents();
00072 }
00073
00074 std::string padding_and_hash_from_oid(OID const& oid)
00075 {
00076 std::string padding_and_hash = OIDS::lookup(oid);
00077
00078 if(padding_and_hash.substr(0,6) != "ECDSA/")
00079 throw Invalid_State("CVC: Can only use ECDSA, not " + padding_and_hash);
00080
00081 padding_and_hash.erase(0, padding_and_hash.find("/") + 1);
00082 return padding_and_hash;
00083 }
00084
00085 }
00086
00087 namespace CVC_EAC {
00088
00089 EAC1_1_CVC create_self_signed_cert(Private_Key const& key,
00090 EAC1_1_CVC_Options const& opt,
00091 RandomNumberGenerator& rng)
00092 {
00093
00094
00095 const ECDSA_PrivateKey* priv_key = dynamic_cast<const ECDSA_PrivateKey*>(&key);
00096
00097 if(priv_key == 0)
00098 throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type");
00099
00100 ASN1_Chr chr(opt.car.value());
00101
00102 AlgorithmIdentifier sig_algo;
00103 std::string padding_and_hash("EMSA1_BSI(" + opt.hash_alg + ")");
00104 sig_algo.oid = OIDS::lookup(priv_key->algo_name() + "/" + padding_and_hash);
00105 sig_algo = AlgorithmIdentifier(sig_algo.oid, AlgorithmIdentifier::USE_NULL_PARAM);
00106
00107 PK_Signer signer(*priv_key, padding_and_hash);
00108
00109 MemoryVector<byte> enc_public_key = eac_1_1_encoding(priv_key, sig_algo.oid);
00110
00111 return make_cvc_cert(signer,
00112 enc_public_key,
00113 opt.car, chr,
00114 opt.holder_auth_templ,
00115 opt.ced, opt.cex, rng);
00116 }
00117
00118 EAC1_1_Req create_cvc_req(Private_Key const& key,
00119 ASN1_Chr const& chr,
00120 std::string const& hash_alg,
00121 RandomNumberGenerator& rng)
00122 {
00123
00124 ECDSA_PrivateKey const* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&key);
00125 if (priv_key == 0)
00126 {
00127 throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type");
00128 }
00129 AlgorithmIdentifier sig_algo;
00130 std::string padding_and_hash("EMSA1_BSI(" + hash_alg + ")");
00131 sig_algo.oid = OIDS::lookup(priv_key->algo_name() + "/" + padding_and_hash);
00132 sig_algo = AlgorithmIdentifier(sig_algo.oid, AlgorithmIdentifier::USE_NULL_PARAM);
00133
00134 PK_Signer signer(*priv_key, padding_and_hash);
00135
00136 MemoryVector<byte> enc_public_key = eac_1_1_encoding(priv_key, sig_algo.oid);
00137
00138 MemoryVector<byte> enc_cpi;
00139 enc_cpi.append(0x00);
00140 MemoryVector<byte> tbs = DER_Encoder()
00141 .encode(enc_cpi, OCTET_STRING, ASN1_Tag(41), APPLICATION)
00142 .raw_bytes(enc_public_key)
00143 .encode(chr)
00144 .get_contents();
00145
00146 MemoryVector<byte> signed_cert =
00147 EAC1_1_gen_CVC<EAC1_1_Req>::make_signed(signer,
00148 EAC1_1_gen_CVC<EAC1_1_Req>::build_cert_body(tbs),
00149 rng);
00150
00151 DataSource_Memory source(signed_cert);
00152 return EAC1_1_Req(source);
00153 }
00154
00155 EAC1_1_ADO create_ado_req(Private_Key const& key,
00156 EAC1_1_Req const& req,
00157 ASN1_Car const& car,
00158 RandomNumberGenerator& rng)
00159 {
00160
00161 ECDSA_PrivateKey const* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&key);
00162 if (priv_key == 0)
00163 {
00164 throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type");
00165 }
00166 std::string padding_and_hash = padding_and_hash_from_oid(req.signature_algorithm().oid);
00167 PK_Signer signer(*priv_key, padding_and_hash);
00168 SecureVector<byte> tbs_bits = req.BER_encode();
00169 tbs_bits.append(DER_Encoder().encode(car).get_contents());
00170 MemoryVector<byte> signed_cert = EAC1_1_ADO::make_signed(signer, tbs_bits, rng);
00171
00172 DataSource_Memory source(signed_cert);
00173 return EAC1_1_ADO(source);
00174 }
00175
00176 }
00177 namespace DE_EAC
00178 {
00179
00180 EAC1_1_CVC create_cvca(Private_Key const& key,
00181 std::string const& hash,
00182 ASN1_Car const& car, bool iris, bool fingerpr,
00183 u32bit cvca_validity_months,
00184 RandomNumberGenerator& rng)
00185 {
00186 ECDSA_PrivateKey const* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&key);
00187 if (priv_key == 0)
00188 {
00189 throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type");
00190 }
00191 EAC1_1_CVC_Options opts;
00192 opts.car = car;
00193 const u64bit current_time = system_time();
00194
00195 opts.ced = ASN1_Ced(current_time);
00196 opts.cex = ASN1_Cex(opts.ced);
00197 opts.cex.add_months(cvca_validity_months);
00198 opts.holder_auth_templ = (CVCA | (iris * IRIS) | (fingerpr * FINGERPRINT));
00199 opts.hash_alg = hash;
00200 return CVC_EAC::create_self_signed_cert(*priv_key, opts, rng);
00201 }
00202
00203
00204
00205 EAC1_1_CVC link_cvca(EAC1_1_CVC const& signer,
00206 Private_Key const& key,
00207 EAC1_1_CVC const& signee,
00208 RandomNumberGenerator& rng)
00209 {
00210 ECDSA_PrivateKey const* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&key);
00211 if (priv_key == 0)
00212 {
00213 throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type");
00214 }
00215 ASN1_Ced ced(system_time());
00216 ASN1_Cex cex(signee.get_cex());
00217 if (*static_cast<EAC_Time*>(&ced) > *static_cast<EAC_Time*>(&cex))
00218 {
00219 std::string detail("link_cvca(): validity periods of provided certificates don't overlap: currend time = ced = ");
00220 detail += ced.as_string();
00221 detail += ", signee.cex = ";
00222 detail += cex.as_string();
00223 throw Invalid_Argument(detail);
00224 }
00225 if (signer.signature_algorithm() != signee.signature_algorithm())
00226 {
00227 throw Invalid_Argument("link_cvca(): signature algorithms of signer and signee don't match");
00228 }
00229 AlgorithmIdentifier sig_algo = signer.signature_algorithm();
00230 std::string padding_and_hash = padding_and_hash_from_oid(sig_algo.oid);
00231 PK_Signer pk_signer(*priv_key, padding_and_hash);
00232 std::auto_ptr<Public_Key> pk = signee.subject_public_key();
00233 ECDSA_PublicKey* subj_pk = dynamic_cast<ECDSA_PublicKey*>(pk.get());
00234 subj_pk->set_parameter_encoding(EC_DOMPAR_ENC_EXPLICIT);
00235
00236 MemoryVector<byte> enc_public_key = eac_1_1_encoding(priv_key, sig_algo.oid);
00237
00238 return make_cvc_cert(pk_signer, enc_public_key,
00239 signer.get_car(),
00240 signee.get_chr(),
00241 signer.get_chat_value(),
00242 ced, cex,
00243 rng);
00244 }
00245
00246 EAC1_1_CVC sign_request(EAC1_1_CVC const& signer_cert,
00247 Private_Key const& key,
00248 EAC1_1_Req const& signee,
00249 u32bit seqnr,
00250 u32bit seqnr_len,
00251 bool domestic,
00252 u32bit dvca_validity_months,
00253 u32bit ca_is_validity_months,
00254 RandomNumberGenerator& rng)
00255 {
00256 ECDSA_PrivateKey const* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&key);
00257 if (priv_key == 0)
00258 {
00259 throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type");
00260 }
00261 std::string chr_str = signee.get_chr().value();
00262 chr_str += to_string(seqnr, seqnr_len);
00263 ASN1_Chr chr(chr_str);
00264 std::string padding_and_hash = padding_and_hash_from_oid(signee.signature_algorithm().oid);
00265 PK_Signer pk_signer(*priv_key, padding_and_hash);
00266 std::auto_ptr<Public_Key> pk = signee.subject_public_key();
00267 ECDSA_PublicKey* subj_pk = dynamic_cast<ECDSA_PublicKey*>(pk.get());
00268 std::auto_ptr<Public_Key> signer_pk = signer_cert.subject_public_key();
00269
00270
00271
00272
00273
00274 subj_pk->set_parameter_encoding(EC_DOMPAR_ENC_IMPLICITCA);
00275
00276 AlgorithmIdentifier sig_algo(signer_cert.signature_algorithm());
00277 const u64bit current_time = system_time();
00278 ASN1_Ced ced(current_time);
00279 u32bit chat_val;
00280 u32bit chat_low = signer_cert.get_chat_value() & 0x3;
00281 ASN1_Cex cex(ced);
00282 if ((signer_cert.get_chat_value() & CVCA) == CVCA)
00283 {
00284
00285 cex.add_months(dvca_validity_months);
00286 if (domestic)
00287 chat_val = DVCA_domestic | chat_low;
00288 else
00289 chat_val = DVCA_foreign | chat_low;
00290 }
00291 else if ((signer_cert.get_chat_value() & DVCA_domestic) == DVCA_domestic ||
00292 (signer_cert.get_chat_value() & DVCA_foreign) == DVCA_foreign)
00293 {
00294 cex.add_months(ca_is_validity_months);
00295 chat_val = IS | chat_low;
00296 }
00297 else
00298 {
00299 throw Invalid_Argument("sign_request(): encountered illegal value for CHAT");
00300
00301 }
00302
00303 MemoryVector<byte> enc_public_key = eac_1_1_encoding(priv_key, sig_algo.oid);
00304
00305 return make_cvc_cert(pk_signer, enc_public_key,
00306 ASN1_Car(signer_cert.get_chr().iso_8859()),
00307 chr,
00308 chat_val,
00309 ced,
00310 cex,
00311 rng);
00312 }
00313
00314 EAC1_1_Req create_cvc_req(Private_Key const& prkey,
00315 ASN1_Chr const& chr,
00316 std::string const& hash_alg,
00317 RandomNumberGenerator& rng)
00318 {
00319 ECDSA_PrivateKey const* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&prkey);
00320 if (priv_key == 0)
00321 {
00322 throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type");
00323 }
00324 ECDSA_PrivateKey key(*priv_key);
00325 key.set_parameter_encoding(EC_DOMPAR_ENC_IMPLICITCA);
00326 return CVC_EAC::create_cvc_req(key, chr, hash_alg, rng);
00327 }
00328
00329 }
00330
00331 }