1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
|
#ifndef CERT_TRANS_LOG_CERT_CHECKER_H_
#define CERT_TRANS_LOG_CERT_CHECKER_H_
#include <openssl/pem.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "base/macros.h"
#include "log/cert.h"
#include "util/status.h"
#include "util/statusor.h"
namespace cert_trans {
class Cert;
class CertChain;
class PreCertChain;
// A class for doing sanity-checks on log submissions before accepting them.
// We don't necessarily want to do full certificate verification
// before accepting them. E.g., we may want to accept submissions of
// invalid (say, expired) certificates directly from clients,
// to detect attacks after the fact. We primarily only
// want to check that submissions chain to a whitelisted CA, so that
// (1) we know where a cert is coming from; and
// (2) we get some spam protection.
class CertChecker {
public:
CertChecker() = default;
virtual ~CertChecker() = default;
// Load a file of concatenated PEM-certs.
// Returns true if at least one certificate was successfully loaded, and no
// errors were encountered. Returns false otherwise (and will not load any
// certificates from this file).
virtual bool LoadTrustedCertificates(const std::string& trusted_cert_file);
// Load directly from |trusted_certs|, a vector of PEM-certs.
// Returns true if at least one of the supplied certs was loaded
// successfully.
virtual bool LoadTrustedCertificates(
const std::vector<std::string>& trusted_certs);
virtual const std::multimap<std::string, std::unique_ptr<const Cert>>&
GetTrustedCertificates() const {
return trusted_;
}
virtual size_t NumTrustedCertificates() const {
return trusted_.size();
}
// Check that:
// (1) Each certificate is correctly signed by the next one in the chain; and
// (2) The last certificate is issued by a certificate in our trusted store.
// We do not check that the certificates are otherwise valid. In particular,
// we accept certificates that have expired, are not yet valid, or have
// critical extensions we do not recognize.
// If verification succeeds, add the last self-signed cert to the chain
// (or replace with store version) - the resulting chain is guaranteed to
// contain at least one certificate. (Having exactly one certificate implies
// someone is trying to log a root cert, which is fine though unexciting.)
virtual util::Status CheckCertChain(CertChain* chain) const;
// Check that:
// (1) The PreCertChain is well-formed according to I-D rules.
// (2) Each certificate is correctly signed by the next one in the chain; and
// (3) The last certificate is issued by a certificate in our trusted store.
// If verification succeeds, add the last self-signed cert to the chain
// (or replace with store version) - the resulting chain is guaranteed to
// contain at least two certificates (three if there is a Precert Signing
// Certificate);
// If valid, also fills in the |issuer_key_hash| and |tbs_certificate|.
virtual util::Status CheckPreCertChain(PreCertChain* chain,
std::string* issuer_key_hash,
std::string* tbs_certificate) const;
private:
util::Status CheckIssuerChain(CertChain* chain) const;
// Look issuer up from the trusted store, and verify signature.
util::Status GetTrustedCa(CertChain* chain) const;
// Returns true if the cert is trusted, false if it's not,
// INVALID_ARGUMENT if something is wrong with the cert, and
// INTERNAL if something terrible happened.
util::StatusOr<bool> IsTrusted(const Cert& cert,
std::string* subject_name) const;
// A map by the DER encoding of the subject name.
// All code manipulating this container must ensure contained elements are
// deallocated appropriately.
std::multimap<std::string, std::unique_ptr<const Cert>> trusted_;
// Helper for LoadTrustedCertificates, whether reading from file or memory.
// Takes ownership of bio_in and frees it.
bool LoadTrustedCertificatesFromBIO(BIO* bio_in);
DISALLOW_COPY_AND_ASSIGN(CertChecker);
};
} // namespace cert_trans
#endif // CERT_TRANS_LOG_CERT_CHECKER_H_
|