Botan
1.11.15
|
00001 /* 00002 * X.509 Certificates 00003 * (C) 1999-2010 Jack Lloyd 00004 * 00005 * Botan is released under the Simplified BSD License (see license.txt) 00006 */ 00007 00008 #include <botan/x509cert.h> 00009 #include <botan/x509_ext.h> 00010 #include <botan/der_enc.h> 00011 #include <botan/ber_dec.h> 00012 #include <botan/internal/stl_util.h> 00013 #include <botan/parsing.h> 00014 #include <botan/bigint.h> 00015 #include <botan/lookup.h> 00016 #include <botan/oids.h> 00017 #include <botan/pem.h> 00018 #include <botan/hash.h> 00019 #include <botan/hex.h> 00020 #include <algorithm> 00021 #include <iterator> 00022 #include <sstream> 00023 00024 namespace Botan { 00025 00026 namespace { 00027 00028 /* 00029 * Lookup each OID in the vector 00030 */ 00031 std::vector<std::string> lookup_oids(const std::vector<std::string>& in) 00032 { 00033 std::vector<std::string> out; 00034 00035 for(auto i = in.begin(); i != in.end(); ++i) 00036 out.push_back(OIDS::lookup(OID(*i))); 00037 return out; 00038 } 00039 00040 } 00041 00042 /* 00043 * X509_Certificate Constructor 00044 */ 00045 X509_Certificate::X509_Certificate(DataSource& in) : 00046 X509_Object(in, "CERTIFICATE/X509 CERTIFICATE") 00047 { 00048 self_signed = false; 00049 do_decode(); 00050 } 00051 00052 /* 00053 * X509_Certificate Constructor 00054 */ 00055 X509_Certificate::X509_Certificate(const std::string& in) : 00056 X509_Object(in, "CERTIFICATE/X509 CERTIFICATE") 00057 { 00058 self_signed = false; 00059 do_decode(); 00060 } 00061 00062 /* 00063 * X509_Certificate Constructor 00064 */ 00065 X509_Certificate::X509_Certificate(const std::vector<byte>& in) : 00066 X509_Object(in, "CERTIFICATE/X509 CERTIFICATE") 00067 { 00068 self_signed = false; 00069 do_decode(); 00070 } 00071 00072 /* 00073 * Decode the TBSCertificate data 00074 */ 00075 void X509_Certificate::force_decode() 00076 { 00077 size_t version; 00078 BigInt serial_bn; 00079 AlgorithmIdentifier sig_algo_inner; 00080 X509_DN dn_issuer, dn_subject; 00081 X509_Time start, end; 00082 00083 BER_Decoder tbs_cert(tbs_bits); 00084 00085 tbs_cert.decode_optional(version, ASN1_Tag(0), 00086 ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)) 00087 .decode(serial_bn) 00088 .decode(sig_algo_inner) 00089 .decode(dn_issuer) 00090 .start_cons(SEQUENCE) 00091 .decode(start) 00092 .decode(end) 00093 .verify_end() 00094 .end_cons() 00095 .decode(dn_subject); 00096 00097 if(version > 2) 00098 throw Decoding_Error("Unknown X.509 cert version " + std::to_string(version)); 00099 if(sig_algo != sig_algo_inner) 00100 throw Decoding_Error("Algorithm identifier mismatch"); 00101 00102 self_signed = (dn_subject == dn_issuer); 00103 00104 subject.add(dn_subject.contents()); 00105 issuer.add(dn_issuer.contents()); 00106 00107 subject.add("X509.Certificate.dn_bits", ASN1::put_in_sequence(dn_subject.get_bits())); 00108 issuer.add("X509.Certificate.dn_bits", ASN1::put_in_sequence(dn_issuer.get_bits())); 00109 00110 BER_Object public_key = tbs_cert.get_next_object(); 00111 if(public_key.type_tag != SEQUENCE || public_key.class_tag != CONSTRUCTED) 00112 throw BER_Bad_Tag("X509_Certificate: Unexpected tag for public key", 00113 public_key.type_tag, public_key.class_tag); 00114 00115 std::vector<byte> v2_issuer_key_id, v2_subject_key_id; 00116 00117 tbs_cert.decode_optional_string(v2_issuer_key_id, BIT_STRING, 1); 00118 tbs_cert.decode_optional_string(v2_subject_key_id, BIT_STRING, 2); 00119 00120 BER_Object v3_exts_data = tbs_cert.get_next_object(); 00121 if(v3_exts_data.type_tag == 3 && 00122 v3_exts_data.class_tag == ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)) 00123 { 00124 Extensions extensions; 00125 00126 BER_Decoder(v3_exts_data.value).decode(extensions).verify_end(); 00127 00128 extensions.contents_to(subject, issuer); 00129 } 00130 else if(v3_exts_data.type_tag != NO_OBJECT) 00131 throw BER_Bad_Tag("Unknown tag in X.509 cert", 00132 v3_exts_data.type_tag, v3_exts_data.class_tag); 00133 00134 if(tbs_cert.more_items()) 00135 throw Decoding_Error("TBSCertificate has more items that expected"); 00136 00137 subject.add("X509.Certificate.version", version); 00138 subject.add("X509.Certificate.serial", BigInt::encode(serial_bn)); 00139 subject.add("X509.Certificate.start", start.readable_string()); 00140 subject.add("X509.Certificate.end", end.readable_string()); 00141 00142 issuer.add("X509.Certificate.v2.key_id", v2_issuer_key_id); 00143 subject.add("X509.Certificate.v2.key_id", v2_subject_key_id); 00144 00145 subject.add("X509.Certificate.public_key", 00146 hex_encode(public_key.value)); 00147 00148 if(self_signed && version == 0) 00149 { 00150 subject.add("X509v3.BasicConstraints.is_ca", 1); 00151 subject.add("X509v3.BasicConstraints.path_constraint", Cert_Extension::NO_CERT_PATH_LIMIT); 00152 } 00153 00154 if(is_CA_cert() && 00155 !subject.has_value("X509v3.BasicConstraints.path_constraint")) 00156 { 00157 const size_t limit = (x509_version() < 3) ? 00158 Cert_Extension::NO_CERT_PATH_LIMIT : 0; 00159 00160 subject.add("X509v3.BasicConstraints.path_constraint", limit); 00161 } 00162 } 00163 00164 /* 00165 * Return the X.509 version in use 00166 */ 00167 u32bit X509_Certificate::x509_version() const 00168 { 00169 return (subject.get1_u32bit("X509.Certificate.version") + 1); 00170 } 00171 00172 /* 00173 * Return the time this cert becomes valid 00174 */ 00175 std::string X509_Certificate::start_time() const 00176 { 00177 return subject.get1("X509.Certificate.start"); 00178 } 00179 00180 /* 00181 * Return the time this cert becomes invalid 00182 */ 00183 std::string X509_Certificate::end_time() const 00184 { 00185 return subject.get1("X509.Certificate.end"); 00186 } 00187 00188 /* 00189 * Return information about the subject 00190 */ 00191 std::vector<std::string> 00192 X509_Certificate::subject_info(const std::string& what) const 00193 { 00194 return subject.get(X509_DN::deref_info_field(what)); 00195 } 00196 00197 /* 00198 * Return information about the issuer 00199 */ 00200 std::vector<std::string> 00201 X509_Certificate::issuer_info(const std::string& what) const 00202 { 00203 return issuer.get(X509_DN::deref_info_field(what)); 00204 } 00205 00206 /* 00207 * Return the public key in this certificate 00208 */ 00209 Public_Key* X509_Certificate::subject_public_key() const 00210 { 00211 return X509::load_key( 00212 ASN1::put_in_sequence(this->subject_public_key_bits())); 00213 } 00214 00215 std::vector<byte> X509_Certificate::subject_public_key_bits() const 00216 { 00217 return hex_decode(subject.get1("X509.Certificate.public_key")); 00218 } 00219 00220 /* 00221 * Check if the certificate is for a CA 00222 */ 00223 bool X509_Certificate::is_CA_cert() const 00224 { 00225 if(!subject.get1_u32bit("X509v3.BasicConstraints.is_ca")) 00226 return false; 00227 00228 return allowed_usage(KEY_CERT_SIGN); 00229 } 00230 00231 bool X509_Certificate::allowed_usage(Key_Constraints usage) const 00232 { 00233 if(constraints() == NO_CONSTRAINTS) 00234 return true; 00235 return (constraints() & usage); 00236 } 00237 00238 bool X509_Certificate::allowed_usage(const std::string& usage) const 00239 { 00240 for(auto constraint : ex_constraints()) 00241 if(constraint == usage) 00242 return true; 00243 00244 return false; 00245 } 00246 00247 /* 00248 * Return the path length constraint 00249 */ 00250 u32bit X509_Certificate::path_limit() const 00251 { 00252 return subject.get1_u32bit("X509v3.BasicConstraints.path_constraint", 0); 00253 } 00254 00255 /* 00256 * Return the key usage constraints 00257 */ 00258 Key_Constraints X509_Certificate::constraints() const 00259 { 00260 return Key_Constraints(subject.get1_u32bit("X509v3.KeyUsage", 00261 NO_CONSTRAINTS)); 00262 } 00263 00264 /* 00265 * Return the list of extended key usage OIDs 00266 */ 00267 std::vector<std::string> X509_Certificate::ex_constraints() const 00268 { 00269 return lookup_oids(subject.get("X509v3.ExtendedKeyUsage")); 00270 } 00271 00272 /* 00273 * Return the list of certificate policies 00274 */ 00275 std::vector<std::string> X509_Certificate::policies() const 00276 { 00277 return lookup_oids(subject.get("X509v3.CertificatePolicies")); 00278 } 00279 00280 std::string X509_Certificate::ocsp_responder() const 00281 { 00282 return subject.get1("OCSP.responder", ""); 00283 } 00284 00285 std::string X509_Certificate::crl_distribution_point() const 00286 { 00287 return subject.get1("CRL.DistributionPoint", ""); 00288 } 00289 00290 /* 00291 * Return the authority key id 00292 */ 00293 std::vector<byte> X509_Certificate::authority_key_id() const 00294 { 00295 return issuer.get1_memvec("X509v3.AuthorityKeyIdentifier"); 00296 } 00297 00298 /* 00299 * Return the subject key id 00300 */ 00301 std::vector<byte> X509_Certificate::subject_key_id() const 00302 { 00303 return subject.get1_memvec("X509v3.SubjectKeyIdentifier"); 00304 } 00305 00306 /* 00307 * Return the certificate serial number 00308 */ 00309 std::vector<byte> X509_Certificate::serial_number() const 00310 { 00311 return subject.get1_memvec("X509.Certificate.serial"); 00312 } 00313 00314 /* 00315 * Return the distinguished name of the issuer 00316 */ 00317 X509_DN X509_Certificate::issuer_dn() const 00318 { 00319 return create_dn(issuer); 00320 } 00321 00322 std::vector<byte> X509_Certificate::raw_issuer_dn() const 00323 { 00324 return issuer.get1_memvec("X509.Certificate.dn_bits"); 00325 } 00326 00327 /* 00328 * Return the distinguished name of the subject 00329 */ 00330 X509_DN X509_Certificate::subject_dn() const 00331 { 00332 return create_dn(subject); 00333 } 00334 00335 std::vector<byte> X509_Certificate::raw_subject_dn() const 00336 { 00337 return subject.get1_memvec("X509.Certificate.dn_bits"); 00338 } 00339 00340 namespace { 00341 00342 bool cert_subject_dns_match(const std::string& name, 00343 const std::vector<std::string>& cert_names) 00344 { 00345 for(size_t i = 0; i != cert_names.size(); ++i) 00346 { 00347 const std::string cn = cert_names[i]; 00348 00349 if(cn == name) 00350 return true; 00351 00352 /* 00353 * Possible wildcard match. We only support the most basic form of 00354 * cert wildcarding ala RFC 2595 00355 */ 00356 if(cn.size() > 2 && cn[0] == '*' && cn[1] == '.' && name.size() > cn.size()) 00357 { 00358 const std::string base = cn.substr(1, std::string::npos); 00359 00360 if(name.compare(name.size() - base.size(), base.size(), base) == 0) 00361 return true; 00362 } 00363 } 00364 00365 return false; 00366 } 00367 00368 } 00369 00370 std::string X509_Certificate::fingerprint(const std::string& hash_name) const 00371 { 00372 std::unique_ptr<HashFunction> hash(get_hash(hash_name)); 00373 hash->update(this->BER_encode()); 00374 const auto hex_print = hex_encode(hash->final()); 00375 00376 std::string formatted_print; 00377 00378 for(size_t i = 0; i != hex_print.size(); i += 2) 00379 { 00380 formatted_print.push_back(hex_print[i]); 00381 formatted_print.push_back(hex_print[i+1]); 00382 00383 if(i != hex_print.size() - 2) 00384 formatted_print.push_back(':'); 00385 } 00386 00387 return formatted_print; 00388 } 00389 00390 bool X509_Certificate::matches_dns_name(const std::string& name) const 00391 { 00392 if(name == "") 00393 return false; 00394 00395 if(cert_subject_dns_match(name, subject_info("DNS"))) 00396 return true; 00397 00398 if(cert_subject_dns_match(name, subject_info("Name"))) 00399 return true; 00400 00401 return false; 00402 } 00403 00404 /* 00405 * Compare two certificates for equality 00406 */ 00407 bool X509_Certificate::operator==(const X509_Certificate& other) const 00408 { 00409 return (sig == other.sig && 00410 sig_algo == other.sig_algo && 00411 self_signed == other.self_signed && 00412 issuer == other.issuer && 00413 subject == other.subject); 00414 } 00415 00416 bool X509_Certificate::operator<(const X509_Certificate& other) const 00417 { 00418 /* If signature values are not equal, sort by lexicographic ordering of that */ 00419 if(sig != other.sig) 00420 { 00421 if(sig < other.sig) 00422 return true; 00423 return false; 00424 } 00425 00426 // Then compare the signed contents 00427 return tbs_bits < other.tbs_bits; 00428 } 00429 00430 /* 00431 * X.509 Certificate Comparison 00432 */ 00433 bool operator!=(const X509_Certificate& cert1, const X509_Certificate& cert2) 00434 { 00435 return !(cert1 == cert2); 00436 } 00437 00438 std::string X509_Certificate::to_string() const 00439 { 00440 const char* dn_fields[] = { "Name", 00441 "Email", 00442 "Organization", 00443 "Organizational Unit", 00444 "Locality", 00445 "State", 00446 "Country", 00447 "IP", 00448 "DNS", 00449 "URI", 00450 "PKIX.XMPPAddr", 00451 nullptr }; 00452 00453 std::ostringstream out; 00454 00455 for(size_t i = 0; dn_fields[i]; ++i) 00456 { 00457 const std::vector<std::string> vals = this->subject_info(dn_fields[i]); 00458 00459 if(vals.empty()) 00460 continue; 00461 00462 out << "Subject " << dn_fields[i] << ":"; 00463 for(size_t j = 0; j != vals.size(); ++j) 00464 out << " " << vals[j]; 00465 out << "\n"; 00466 } 00467 00468 for(size_t i = 0; dn_fields[i]; ++i) 00469 { 00470 const std::vector<std::string> vals = this->issuer_info(dn_fields[i]); 00471 00472 if(vals.empty()) 00473 continue; 00474 00475 out << "Issuer " << dn_fields[i] << ":"; 00476 for(size_t j = 0; j != vals.size(); ++j) 00477 out << " " << vals[j]; 00478 out << "\n"; 00479 } 00480 00481 out << "Version: " << this->x509_version() << "\n"; 00482 00483 out << "Not valid before: " << this->start_time() << "\n"; 00484 out << "Not valid after: " << this->end_time() << "\n"; 00485 00486 out << "Constraints:\n"; 00487 Key_Constraints constraints = this->constraints(); 00488 if(constraints == NO_CONSTRAINTS) 00489 out << " None\n"; 00490 else 00491 { 00492 if(constraints & DIGITAL_SIGNATURE) 00493 out << " Digital Signature\n"; 00494 if(constraints & NON_REPUDIATION) 00495 out << " Non-Repuidation\n"; 00496 if(constraints & KEY_ENCIPHERMENT) 00497 out << " Key Encipherment\n"; 00498 if(constraints & DATA_ENCIPHERMENT) 00499 out << " Data Encipherment\n"; 00500 if(constraints & KEY_AGREEMENT) 00501 out << " Key Agreement\n"; 00502 if(constraints & KEY_CERT_SIGN) 00503 out << " Cert Sign\n"; 00504 if(constraints & CRL_SIGN) 00505 out << " CRL Sign\n"; 00506 } 00507 00508 std::vector<std::string> policies = this->policies(); 00509 if(!policies.empty()) 00510 { 00511 out << "Policies: " << "\n"; 00512 for(size_t i = 0; i != policies.size(); i++) 00513 out << " " << policies[i] << "\n"; 00514 } 00515 00516 std::vector<std::string> ex_constraints = this->ex_constraints(); 00517 if(!ex_constraints.empty()) 00518 { 00519 out << "Extended Constraints:\n"; 00520 for(size_t i = 0; i != ex_constraints.size(); i++) 00521 out << " " << ex_constraints[i] << "\n"; 00522 } 00523 00524 if(ocsp_responder() != "") 00525 out << "OCSP responder " << ocsp_responder() << "\n"; 00526 if(crl_distribution_point() != "") 00527 out << "CRL " << crl_distribution_point() << "\n"; 00528 00529 out << "Signature algorithm: " << 00530 OIDS::lookup(this->signature_algorithm().oid) << "\n"; 00531 00532 out << "Serial number: " << hex_encode(this->serial_number()) << "\n"; 00533 00534 if(this->authority_key_id().size()) 00535 out << "Authority keyid: " << hex_encode(this->authority_key_id()) << "\n"; 00536 00537 if(this->subject_key_id().size()) 00538 out << "Subject keyid: " << hex_encode(this->subject_key_id()) << "\n"; 00539 00540 std::unique_ptr<X509_PublicKey> pubkey(this->subject_public_key()); 00541 out << "Public Key:\n" << X509::PEM_encode(*pubkey); 00542 00543 return out.str(); 00544 } 00545 00546 /* 00547 * Create and populate a X509_DN 00548 */ 00549 X509_DN create_dn(const Data_Store& info) 00550 { 00551 auto names = info.search_for( 00552 [](const std::string& key, const std::string&) 00553 { 00554 return (key.find("X520.") != std::string::npos); 00555 }); 00556 00557 X509_DN dn; 00558 00559 for(auto i = names.begin(); i != names.end(); ++i) 00560 dn.add_attribute(i->first, i->second); 00561 00562 return dn; 00563 } 00564 00565 /* 00566 * Create and populate an AlternativeName 00567 */ 00568 AlternativeName create_alt_name(const Data_Store& info) 00569 { 00570 auto names = info.search_for( 00571 [](const std::string& key, const std::string&) 00572 { 00573 return (key == "RFC822" || 00574 key == "DNS" || 00575 key == "URI" || 00576 key == "IP"); 00577 }); 00578 00579 AlternativeName alt_name; 00580 00581 for(auto i = names.begin(); i != names.end(); ++i) 00582 alt_name.add_attribute(i->first, i->second); 00583 00584 return alt_name; 00585 } 00586 00587 }