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