Botan  1.11.15
src/lib/cert/x509/x509cert.cpp
Go to the documentation of this file.
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 }