Botan
1.11.15
|
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 }