/* * Return information about the issuer */ std::vector<std::string> X509_Certificate::issuer_info(const std::string& req) const { if(issuer_dn().has_field(req)) return issuer_dn().get_attribute(req); if(issuer_alt_name().has_field(req)) return issuer_alt_name().get_attribute(req); // These will be removed later: if(req == "X509.Certificate.v2.key_id") return {hex_encode(this->v2_issuer_key_id())}; if(req == "X509v3.AuthorityKeyIdentifier") return {hex_encode(this->authority_key_id())}; if(req == "X509.Certificate.dn_bits") return {hex_encode(this->raw_issuer_dn())}; return data().m_issuer_ds.get(req); }
std::vector<X509_CRL> Certificate_Store_In_SQL::generate_crls() const { auto stmt = m_database->new_statement( "SELECT certificate,reason,time FROM " + m_prefix + "revoked " "JOIN " + m_prefix + "certificates ON " + m_prefix + "certificates.fingerprint == " + m_prefix + "revoked.fingerprint"); std::map<X509_DN,std::vector<CRL_Entry>> crls; while(stmt->step()) { auto blob = stmt->get_blob(0); auto cert = X509_Certificate( std::vector<uint8_t>(blob.first,blob.first + blob.second)); auto code = static_cast<CRL_Code>(stmt->get_size_t(1)); auto ent = CRL_Entry(cert,code); auto i = crls.find(cert.issuer_dn()); if(i == crls.end()) { crls.insert(std::make_pair(cert.issuer_dn(),std::vector<CRL_Entry>({ent}))); } else { i->second.push_back(ent); } } std::vector<X509_CRL> ret; X509_Time t(std::chrono::system_clock::now()); for(auto p: crls) { ret.push_back(X509_CRL(p.first,t,t,p.second)); } return ret; }
/** * Check if this particular certificate is listed in the CRL */ bool X509_CRL::is_revoked(const X509_Certificate& cert) const { /* If the cert wasn't issued by the CRL issuer, it's possible the cert is revoked, but not by this CRL. Maybe throw an exception instead? */ if(cert.issuer_dn() != issuer_dn()) return false; std::vector<uint8_t> crl_akid = authority_key_id(); std::vector<uint8_t> cert_akid = cert.authority_key_id(); if(!crl_akid.empty() && !cert_akid.empty()) { if(crl_akid != cert_akid) return false; } std::vector<uint8_t> cert_serial = cert.serial_number(); bool is_revoked = false; // FIXME would be nice to avoid a linear scan here - maybe sort the entries? for(const CRL_Entry& entry : get_revoked()) { if(cert_serial == entry.serial_number()) { if(entry.reason_code() == REMOVE_FROM_CRL) is_revoked = false; else is_revoked = true; } } return is_revoked; }
std::string X509_Certificate::to_string() const { std::ostringstream out; out << "Version: " << this->x509_version() << "\n"; out << "Subject: " << subject_dn() << "\n"; out << "Issuer: " << issuer_dn() << "\n"; out << "Issued: " << this->not_before().readable_string() << "\n"; out << "Expires: " << this->not_after().readable_string() << "\n"; out << "Constraints:\n"; Key_Constraints constraints = this->constraints(); if(constraints == NO_CONSTRAINTS) out << " None\n"; else { if(constraints & DIGITAL_SIGNATURE) out << " Digital Signature\n"; if(constraints & NON_REPUDIATION) out << " Non-Repudiation\n"; if(constraints & KEY_ENCIPHERMENT) out << " Key Encipherment\n"; if(constraints & DATA_ENCIPHERMENT) out << " Data Encipherment\n"; if(constraints & KEY_AGREEMENT) out << " Key Agreement\n"; if(constraints & KEY_CERT_SIGN) out << " Cert Sign\n"; if(constraints & CRL_SIGN) out << " CRL Sign\n"; if(constraints & ENCIPHER_ONLY) out << " Encipher Only\n"; if(constraints & DECIPHER_ONLY) out << " Decipher Only\n"; } const std::vector<OID> policies = this->certificate_policy_oids(); if(!policies.empty()) { out << "Policies: " << "\n"; for(auto oid : policies) out << " " << oid.as_string() << "\n"; } std::vector<OID> ex_constraints = this->extended_key_usage(); if(!ex_constraints.empty()) { out << "Extended Constraints:\n"; for(size_t i = 0; i != ex_constraints.size(); i++) out << " " << OIDS::oid2str(ex_constraints[i]) << "\n"; } const NameConstraints& name_constraints = this->name_constraints(); if(!name_constraints.permitted().empty() || !name_constraints.excluded().empty()) { out << "Name Constraints:\n"; if(!name_constraints.permitted().empty()) { out << " Permit"; for(auto st: name_constraints.permitted()) { out << " " << st.base(); } out << "\n"; } if(!name_constraints.excluded().empty()) { out << " Exclude"; for(auto st: name_constraints.excluded()) { out << " " << st.base(); } out << "\n"; } } if(!ocsp_responder().empty()) out << "OCSP responder " << ocsp_responder() << "\n"; std::vector<std::string> ca_issuers = this->ca_issuers(); if(!ca_issuers.empty()) { out << "CA Issuers:\n"; for(size_t i = 0; i != ca_issuers.size(); i++) out << " URI: " << ca_issuers[i] << "\n"; } if(!crl_distribution_point().empty()) out << "CRL " << crl_distribution_point() << "\n"; out << "Signature algorithm: " << OIDS::oid2str(this->signature_algorithm().get_oid()) << "\n"; out << "Serial number: " << hex_encode(this->serial_number()) << "\n"; if(this->authority_key_id().size()) out << "Authority keyid: " << hex_encode(this->authority_key_id()) << "\n"; if(this->subject_key_id().size()) out << "Subject keyid: " << hex_encode(this->subject_key_id()) << "\n"; try { std::unique_ptr<Public_Key> pubkey(this->subject_public_key()); out << "Public Key [" << pubkey->algo_name() << "-" << pubkey->key_length() << "]\n\n"; out << X509::PEM_encode(*pubkey); } catch(Decoding_Error&) { const AlgorithmIdentifier& alg_id = this->subject_public_key_algo(); out << "Failed to decode key with oid " << alg_id.get_oid().as_string() << "\n"; } return out.str(); }