update main-with-bazel from master branch
This commit is contained in:
@@ -272,6 +272,14 @@ struct X509_crl_st {
|
||||
// 5280) and C type is |X509_CRL*|.
|
||||
DECLARE_ASN1_ITEM(X509_CRL)
|
||||
|
||||
// GENERAL_NAME is an |ASN1_ITEM| whose ASN.1 type is GeneralName and C type is
|
||||
// |GENERAL_NAME*|.
|
||||
DECLARE_ASN1_ITEM(GENERAL_NAME)
|
||||
|
||||
// GENERAL_NAMES is an |ASN1_ITEM| whose ASN.1 type is SEQUENCE OF GeneralName
|
||||
// and C type is |GENERAL_NAMES*|, aka |STACK_OF(GENERAL_NAME)*|.
|
||||
DECLARE_ASN1_ITEM(GENERAL_NAMES)
|
||||
|
||||
struct X509_VERIFY_PARAM_st {
|
||||
int64_t check_time; // POSIX time to use
|
||||
unsigned long flags; // Various verify flags
|
||||
|
||||
@@ -61,6 +61,8 @@
|
||||
#include <openssl/conf.h>
|
||||
#include <openssl/x509.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
ASN1_SEQUENCE(AUTHORITY_KEYID) = {
|
||||
ASN1_IMP_OPT(AUTHORITY_KEYID, keyid, ASN1_OCTET_STRING, 0),
|
||||
|
||||
+11
-11
@@ -70,7 +70,7 @@ ASN1_SEQUENCE(OTHERNAME) = {
|
||||
ASN1_EXP(OTHERNAME, value, ASN1_ANY, 0),
|
||||
} ASN1_SEQUENCE_END(OTHERNAME)
|
||||
|
||||
IMPLEMENT_ASN1_FUNCTIONS_const(OTHERNAME)
|
||||
IMPLEMENT_ASN1_ALLOC_FUNCTIONS(OTHERNAME)
|
||||
|
||||
ASN1_SEQUENCE(EDIPARTYNAME) = {
|
||||
// DirectoryString is a CHOICE type, so use explicit tagging.
|
||||
@@ -78,7 +78,7 @@ ASN1_SEQUENCE(EDIPARTYNAME) = {
|
||||
ASN1_EXP(EDIPARTYNAME, partyName, DIRECTORYSTRING, 1),
|
||||
} ASN1_SEQUENCE_END(EDIPARTYNAME)
|
||||
|
||||
IMPLEMENT_ASN1_FUNCTIONS_const(EDIPARTYNAME)
|
||||
IMPLEMENT_ASN1_ALLOC_FUNCTIONS(EDIPARTYNAME)
|
||||
|
||||
ASN1_CHOICE(GENERAL_NAME) = {
|
||||
ASN1_IMP(GENERAL_NAME, d.otherName, OTHERNAME, GEN_OTHERNAME),
|
||||
@@ -208,9 +208,9 @@ void GENERAL_NAME_set0_value(GENERAL_NAME *a, int type, void *value) {
|
||||
a->type = type;
|
||||
}
|
||||
|
||||
void *GENERAL_NAME_get0_value(const GENERAL_NAME *a, int *ptype) {
|
||||
if (ptype) {
|
||||
*ptype = a->type;
|
||||
void *GENERAL_NAME_get0_value(const GENERAL_NAME *a, int *out_type) {
|
||||
if (out_type) {
|
||||
*out_type = a->type;
|
||||
}
|
||||
switch (a->type) {
|
||||
case GEN_X400:
|
||||
@@ -255,16 +255,16 @@ int GENERAL_NAME_set0_othername(GENERAL_NAME *gen, ASN1_OBJECT *oid,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GENERAL_NAME_get0_otherName(const GENERAL_NAME *gen, ASN1_OBJECT **poid,
|
||||
ASN1_TYPE **pvalue) {
|
||||
int GENERAL_NAME_get0_otherName(const GENERAL_NAME *gen, ASN1_OBJECT **out_oid,
|
||||
ASN1_TYPE **out_value) {
|
||||
if (gen->type != GEN_OTHERNAME) {
|
||||
return 0;
|
||||
}
|
||||
if (poid) {
|
||||
*poid = gen->d.otherName->type_id;
|
||||
if (out_oid != NULL) {
|
||||
*out_oid = gen->d.otherName->type_id;
|
||||
}
|
||||
if (pvalue) {
|
||||
*pvalue = gen->d.otherName->value;
|
||||
if (out_value != NULL) {
|
||||
*out_value = gen->d.otherName->value;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
+41
-9
@@ -19,24 +19,56 @@
|
||||
#include "../crypto/x509/internal.h"
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
|
||||
X509 *x509 = d2i_X509(NULL, &buf, len);
|
||||
if (x509 != NULL) {
|
||||
bssl::UniquePtr<X509> x509(d2i_X509(nullptr, &buf, len));
|
||||
if (x509 != nullptr) {
|
||||
// Extract the public key.
|
||||
EVP_PKEY_free(X509_get_pubkey(x509));
|
||||
EVP_PKEY_free(X509_get_pubkey(x509.get()));
|
||||
|
||||
// Fuzz some deferred parsing.
|
||||
x509v3_cache_extensions(x509);
|
||||
x509v3_cache_extensions(x509.get());
|
||||
|
||||
// Reserialize the structure.
|
||||
uint8_t *der = NULL;
|
||||
i2d_X509(x509, &der);
|
||||
// Fuzz every supported extension.
|
||||
for (int i = 0; i < X509_get_ext_count(x509.get()); i++) {
|
||||
const X509_EXTENSION *ext = X509_get_ext(x509.get(), i);
|
||||
void *parsed = X509V3_EXT_d2i(ext);
|
||||
if (parsed != nullptr) {
|
||||
int nid = OBJ_obj2nid(X509_EXTENSION_get_object(ext));
|
||||
BSSL_CHECK(nid != NID_undef);
|
||||
|
||||
// Reserialize the extension. This should succeed if we were able to
|
||||
// parse it.
|
||||
// TODO(crbug.com/boringssl/352): Ideally we would also assert that
|
||||
// |new_ext| is identical to |ext|, but our parser is not strict enough.
|
||||
bssl::UniquePtr<X509_EXTENSION> new_ext(
|
||||
X509V3_EXT_i2d(nid, X509_EXTENSION_get_critical(ext), parsed));
|
||||
BSSL_CHECK(new_ext != nullptr);
|
||||
|
||||
// This can only fail if |ext| was not a supported type, but then
|
||||
// |X509V3_EXT_d2i| should have failed.
|
||||
BSSL_CHECK(X509V3_EXT_free(nid, parsed));
|
||||
}
|
||||
}
|
||||
|
||||
// Reserialize |x509|. This should succeed if we were able to parse it.
|
||||
// TODO(crbug.com/boringssl/352): Ideally we would also assert the output
|
||||
// matches the input, but our parser is not strict enough.
|
||||
uint8_t *der = nullptr;
|
||||
int der_len = i2d_X509(x509.get(), &der);
|
||||
BSSL_CHECK(der_len > 0);
|
||||
OPENSSL_free(der);
|
||||
|
||||
// Reserialize |x509|'s TBSCertificate without reusing the cached encoding.
|
||||
// TODO(crbug.com/boringssl/352): Ideally we would also assert the output
|
||||
// matches the input TBSCertificate, but our parser is not strict enough.
|
||||
der = nullptr;
|
||||
der_len = i2d_re_X509_tbs(x509.get(), &der);
|
||||
BSSL_CHECK(der_len > 0);
|
||||
OPENSSL_free(der);
|
||||
|
||||
BIO *bio = BIO_new(BIO_s_mem());
|
||||
X509_print(bio, x509);
|
||||
X509_print(bio, x509.get());
|
||||
BIO_free(bio);
|
||||
}
|
||||
X509_free(x509);
|
||||
ERR_clear_error();
|
||||
return 0;
|
||||
}
|
||||
|
||||
+177
-69
@@ -1336,8 +1336,7 @@ DEFINE_STACK_OF(X509_NAME)
|
||||
// type is |X509_NAME*|.
|
||||
DECLARE_ASN1_ITEM(X509_NAME)
|
||||
|
||||
// X509_NAME_new returns a new, empty |X509_NAME_new|, or NULL on
|
||||
// error.
|
||||
// X509_NAME_new returns a new, empty |X509_NAME|, or NULL on error.
|
||||
OPENSSL_EXPORT X509_NAME *X509_NAME_new(void);
|
||||
|
||||
// X509_NAME_free releases memory associated with |name|.
|
||||
@@ -1468,8 +1467,7 @@ OPENSSL_EXPORT int X509_NAME_add_entry_by_txt(X509_NAME *name,
|
||||
ossl_ssize_t len, int loc,
|
||||
int set);
|
||||
|
||||
// X509_NAME_ENTRY_new returns a new, empty |X509_NAME_ENTRY_new|, or NULL on
|
||||
// error.
|
||||
// X509_NAME_ENTRY_new returns a new, empty |X509_NAME_ENTRY|, or NULL on error.
|
||||
OPENSSL_EXPORT X509_NAME_ENTRY *X509_NAME_ENTRY_new(void);
|
||||
|
||||
// X509_NAME_ENTRY_free releases memory associated with |entry|.
|
||||
@@ -1769,6 +1767,181 @@ OPENSSL_EXPORT STACK_OF(X509_EXTENSION) *X509v3_add_ext(
|
||||
STACK_OF(X509_EXTENSION) **x, const X509_EXTENSION *ex, int loc);
|
||||
|
||||
|
||||
// General names.
|
||||
//
|
||||
// A |GENERAL_NAME| represents an X.509 GeneralName structure, defined in RFC
|
||||
// 5280, Section 4.2.1.6. General names are distinct from names (|X509_NAME|). A
|
||||
// general name is a CHOICE type which may contain one of several name types,
|
||||
// most commonly a DNS name or an IP address. General names most commonly appear
|
||||
// in the subject alternative name (SAN) extension, though they are also used in
|
||||
// other extensions.
|
||||
//
|
||||
// Many extensions contain a SEQUENCE OF GeneralName, or GeneralNames, so
|
||||
// |STACK_OF(GENERAL_NAME)| is defined and aliased to |GENERAL_NAMES|.
|
||||
|
||||
typedef struct otherName_st {
|
||||
ASN1_OBJECT *type_id;
|
||||
ASN1_TYPE *value;
|
||||
} OTHERNAME;
|
||||
|
||||
typedef struct EDIPartyName_st {
|
||||
ASN1_STRING *nameAssigner;
|
||||
ASN1_STRING *partyName;
|
||||
} EDIPARTYNAME;
|
||||
|
||||
// GEN_* are constants for the |type| field of |GENERAL_NAME|, defined below.
|
||||
#define GEN_OTHERNAME 0
|
||||
#define GEN_EMAIL 1
|
||||
#define GEN_DNS 2
|
||||
#define GEN_X400 3
|
||||
#define GEN_DIRNAME 4
|
||||
#define GEN_EDIPARTY 5
|
||||
#define GEN_URI 6
|
||||
#define GEN_IPADD 7
|
||||
#define GEN_RID 8
|
||||
|
||||
// A |GENERAL_NAME_st|, aka |GENERAL_NAME|, represents an X.509 GeneralName. The
|
||||
// |type| field determines which member of |d| is active. A |GENERAL_NAME| may
|
||||
// also be empty, in which case |type| is -1 and |d| is NULL. Empty
|
||||
// |GENERAL_NAME|s are invalid and will never be returned from the parser, but
|
||||
// may be created temporarily, e.g. by |GENERAL_NAME_new|.
|
||||
struct GENERAL_NAME_st {
|
||||
int type;
|
||||
union {
|
||||
char *ptr;
|
||||
OTHERNAME *otherName;
|
||||
ASN1_IA5STRING *rfc822Name;
|
||||
ASN1_IA5STRING *dNSName;
|
||||
ASN1_STRING *x400Address;
|
||||
X509_NAME *directoryName;
|
||||
EDIPARTYNAME *ediPartyName;
|
||||
ASN1_IA5STRING *uniformResourceIdentifier;
|
||||
ASN1_OCTET_STRING *iPAddress;
|
||||
ASN1_OBJECT *registeredID;
|
||||
|
||||
// Old names
|
||||
ASN1_OCTET_STRING *ip; // iPAddress
|
||||
X509_NAME *dirn; // dirn
|
||||
ASN1_IA5STRING *ia5; // rfc822Name, dNSName, uniformResourceIdentifier
|
||||
ASN1_OBJECT *rid; // registeredID
|
||||
} d;
|
||||
} /* GENERAL_NAME */;
|
||||
|
||||
// GENERAL_NAME_new returns a new, empty |GENERAL_NAME|, or NULL on error.
|
||||
OPENSSL_EXPORT GENERAL_NAME *GENERAL_NAME_new(void);
|
||||
|
||||
// GENERAL_NAME_free releases memory associated with |gen|.
|
||||
OPENSSL_EXPORT void GENERAL_NAME_free(GENERAL_NAME *gen);
|
||||
|
||||
// d2i_GENERAL_NAME parses up to |len| bytes from |*inp| as a DER-encoded X.509
|
||||
// GeneralName (RFC 5280), as described in |d2i_SAMPLE|.
|
||||
OPENSSL_EXPORT GENERAL_NAME *d2i_GENERAL_NAME(GENERAL_NAME **out,
|
||||
const uint8_t **inp, long len);
|
||||
|
||||
// i2d_GENERAL_NAME marshals |in| as a DER-encoded X.509 GeneralName (RFC 5280),
|
||||
// as described in |i2d_SAMPLE|.
|
||||
//
|
||||
// TODO(https://crbug.com/boringssl/407): This function should be const and
|
||||
// thread-safe but is currently neither in some cases, notably if |in| is an
|
||||
// directoryName and the |X509_NAME| has been modified.
|
||||
OPENSSL_EXPORT int i2d_GENERAL_NAME(GENERAL_NAME *in, uint8_t **outp);
|
||||
|
||||
// GENERAL_NAME_dup returns a newly-allocated copy of |gen|, or NULL on error.
|
||||
// This function works by serializing the structure, so it will fail if |gen| is
|
||||
// empty.
|
||||
//
|
||||
// TODO(https://crbug.com/boringssl/407): This function should be const and
|
||||
// thread-safe but is currently neither in some cases, notably if |gen| is an
|
||||
// directoryName and the |X509_NAME| has been modified.
|
||||
OPENSSL_EXPORT GENERAL_NAME *GENERAL_NAME_dup(GENERAL_NAME *gen);
|
||||
|
||||
// GENERAL_NAMES_new returns a new, empty |GENERAL_NAMES|, or NULL on error.
|
||||
OPENSSL_EXPORT GENERAL_NAMES *GENERAL_NAMES_new(void);
|
||||
|
||||
// GENERAL_NAMES_free releases memory associated with |gens|.
|
||||
OPENSSL_EXPORT void GENERAL_NAMES_free(GENERAL_NAMES *gens);
|
||||
|
||||
// d2i_GENERAL_NAMES parses up to |len| bytes from |*inp| as a DER-encoded
|
||||
// SEQUENCE OF GeneralName, as described in |d2i_SAMPLE|.
|
||||
OPENSSL_EXPORT GENERAL_NAMES *d2i_GENERAL_NAMES(GENERAL_NAMES **out,
|
||||
const uint8_t **inp, long len);
|
||||
|
||||
// i2d_GENERAL_NAMES marshals |in| as a DER-encoded SEQUENCE OF GeneralName, as
|
||||
// described in |i2d_SAMPLE|.
|
||||
//
|
||||
// TODO(https://crbug.com/boringssl/407): This function should be const and
|
||||
// thread-safe but is currently neither in some cases, notably if some element
|
||||
// of |in| is an directoryName and the |X509_NAME| has been modified.
|
||||
OPENSSL_EXPORT int i2d_GENERAL_NAMES(GENERAL_NAMES *in, uint8_t **outp);
|
||||
|
||||
// OTHERNAME_new returns a new, empty |OTHERNAME|, or NULL on error.
|
||||
OPENSSL_EXPORT OTHERNAME *OTHERNAME_new(void);
|
||||
|
||||
// OTHERNAME_free releases memory associated with |name|.
|
||||
OPENSSL_EXPORT void OTHERNAME_free(OTHERNAME *name);
|
||||
|
||||
// EDIPARTYNAME_new returns a new, empty |EDIPARTYNAME|, or NULL on error.
|
||||
// EDIPartyName is rarely used in practice, so callers are unlikely to need this
|
||||
// function.
|
||||
OPENSSL_EXPORT EDIPARTYNAME *EDIPARTYNAME_new(void);
|
||||
|
||||
// EDIPARTYNAME_free releases memory associated with |name|. EDIPartyName is
|
||||
// rarely used in practice, so callers are unlikely to need this function.
|
||||
OPENSSL_EXPORT void EDIPARTYNAME_free(EDIPARTYNAME *name);
|
||||
|
||||
// GENERAL_NAME_set0_value set |gen|'s type and value to |type| and |value|.
|
||||
// |type| must be a |GEN_*| constant and |value| must be an object of the
|
||||
// corresponding type. |gen| takes ownership of |value|, so |value| must have
|
||||
// been an allocated object.
|
||||
//
|
||||
// WARNING: |gen| must be empty (typically as returned from |GENERAL_NAME_new|)
|
||||
// before calling this function. If |gen| already contained a value, the
|
||||
// previous contents will be leaked.
|
||||
OPENSSL_EXPORT void GENERAL_NAME_set0_value(GENERAL_NAME *gen, int type,
|
||||
void *value);
|
||||
|
||||
// GENERAL_NAME_get0_value returns the in-memory representation of |gen|'s
|
||||
// contents and, |out_type| is not NULL, sets |*out_type| to the type of |gen|,
|
||||
// which will be a |GEN_*| constant. If |gen| is incomplete, the return value
|
||||
// will be NULL and the type will be -1.
|
||||
//
|
||||
// WARNING: Casting the result of this function to the wrong type is a
|
||||
// potentially exploitable memory error. Callers must check |gen|'s type, either
|
||||
// via |*out_type| or checking |gen->type| directly, before inspecting the
|
||||
// result.
|
||||
//
|
||||
// WARNING: This function is not const-correct. The return value should be
|
||||
// const. Callers shoudl not mutate the returned object.
|
||||
OPENSSL_EXPORT void *GENERAL_NAME_get0_value(const GENERAL_NAME *gen,
|
||||
int *out_type);
|
||||
|
||||
// GENERAL_NAME_set0_othername sets |gen| to be an OtherName with type |oid| and
|
||||
// value |value|. On success, it returns one and takes ownership of |oid| and
|
||||
// |value|, which must be created in a way compatible with |ASN1_OBJECT_free|
|
||||
// and |ASN1_TYPE_free|, respectively. On allocation failure, it returns zero.
|
||||
// In the failure case, the caller retains ownership of |oid| and |value| and
|
||||
// must release them when done.
|
||||
//
|
||||
// WARNING: |gen| must be empty (typically as returned from |GENERAL_NAME_new|)
|
||||
// before calling this function. If |gen| already contained a value, the
|
||||
// previously contents will be leaked.
|
||||
OPENSSL_EXPORT int GENERAL_NAME_set0_othername(GENERAL_NAME *gen,
|
||||
ASN1_OBJECT *oid,
|
||||
ASN1_TYPE *value);
|
||||
|
||||
// GENERAL_NAME_get0_otherName, if |gen| is an OtherName, sets |*out_oid| and
|
||||
// |*out_value| to the OtherName's type-id and value, respectively, and returns
|
||||
// one. If |gen| is not an OtherName, it returns zero and leaves |*out_oid| and
|
||||
// |*out_value| unmodified. Either of |out_oid| or |out_value| may be NULL to
|
||||
// ignore the value.
|
||||
//
|
||||
// WARNING: This function is not const-correct. |out_oid| and |out_value| are
|
||||
// not const, but callers should not mutate the resulting objects.
|
||||
OPENSSL_EXPORT int GENERAL_NAME_get0_otherName(const GENERAL_NAME *gen,
|
||||
ASN1_OBJECT **out_oid,
|
||||
ASN1_TYPE **out_value);
|
||||
|
||||
|
||||
// Algorithm identifiers.
|
||||
//
|
||||
// An |X509_ALGOR| represents an AlgorithmIdentifier structure, used in X.509
|
||||
@@ -3105,7 +3278,6 @@ struct X509_algor_st {
|
||||
// the end of the certificate itself
|
||||
|
||||
DECLARE_STACK_OF(DIST_POINT)
|
||||
DECLARE_STACK_OF(GENERAL_NAME)
|
||||
|
||||
// This is used for a table of trust checking functions
|
||||
|
||||
@@ -3781,49 +3953,6 @@ struct BASIC_CONSTRAINTS_st {
|
||||
ASN1_INTEGER *pathlen;
|
||||
};
|
||||
|
||||
|
||||
typedef struct otherName_st {
|
||||
ASN1_OBJECT *type_id;
|
||||
ASN1_TYPE *value;
|
||||
} OTHERNAME;
|
||||
|
||||
typedef struct EDIPartyName_st {
|
||||
ASN1_STRING *nameAssigner;
|
||||
ASN1_STRING *partyName;
|
||||
} EDIPARTYNAME;
|
||||
|
||||
struct GENERAL_NAME_st {
|
||||
#define GEN_OTHERNAME 0
|
||||
#define GEN_EMAIL 1
|
||||
#define GEN_DNS 2
|
||||
#define GEN_X400 3
|
||||
#define GEN_DIRNAME 4
|
||||
#define GEN_EDIPARTY 5
|
||||
#define GEN_URI 6
|
||||
#define GEN_IPADD 7
|
||||
#define GEN_RID 8
|
||||
|
||||
int type;
|
||||
union {
|
||||
char *ptr;
|
||||
OTHERNAME *otherName; // otherName
|
||||
ASN1_IA5STRING *rfc822Name;
|
||||
ASN1_IA5STRING *dNSName;
|
||||
ASN1_STRING *x400Address;
|
||||
X509_NAME *directoryName;
|
||||
EDIPARTYNAME *ediPartyName;
|
||||
ASN1_IA5STRING *uniformResourceIdentifier;
|
||||
ASN1_OCTET_STRING *iPAddress;
|
||||
ASN1_OBJECT *registeredID;
|
||||
|
||||
// Old names
|
||||
ASN1_OCTET_STRING *ip; // iPAddress
|
||||
X509_NAME *dirn; // dirn
|
||||
ASN1_IA5STRING *ia5; // rfc822Name, dNSName, uniformResourceIdentifier
|
||||
ASN1_OBJECT *rid; // registeredID
|
||||
} d;
|
||||
} /* GENERAL_NAME */;
|
||||
|
||||
typedef struct ACCESS_DESCRIPTION_st {
|
||||
ASN1_OBJECT *method;
|
||||
GENERAL_NAME *location;
|
||||
@@ -3983,27 +4112,6 @@ DECLARE_ASN1_FUNCTIONS_const(BASIC_CONSTRAINTS)
|
||||
// an |X509_NAME|.
|
||||
DECLARE_ASN1_FUNCTIONS(AUTHORITY_KEYID)
|
||||
|
||||
// TODO(https://crbug.com/boringssl/407): This is not const because it contains
|
||||
// an |X509_NAME|.
|
||||
DECLARE_ASN1_FUNCTIONS(GENERAL_NAME)
|
||||
OPENSSL_EXPORT GENERAL_NAME *GENERAL_NAME_dup(GENERAL_NAME *a);
|
||||
|
||||
// TODO(https://crbug.com/boringssl/407): This is not const because it contains
|
||||
// an |X509_NAME|.
|
||||
DECLARE_ASN1_FUNCTIONS(GENERAL_NAMES)
|
||||
|
||||
DECLARE_ASN1_FUNCTIONS_const(OTHERNAME)
|
||||
DECLARE_ASN1_FUNCTIONS_const(EDIPARTYNAME)
|
||||
OPENSSL_EXPORT void GENERAL_NAME_set0_value(GENERAL_NAME *a, int type,
|
||||
void *value);
|
||||
OPENSSL_EXPORT void *GENERAL_NAME_get0_value(const GENERAL_NAME *a, int *ptype);
|
||||
OPENSSL_EXPORT int GENERAL_NAME_set0_othername(GENERAL_NAME *gen,
|
||||
ASN1_OBJECT *oid,
|
||||
ASN1_TYPE *value);
|
||||
OPENSSL_EXPORT int GENERAL_NAME_get0_otherName(const GENERAL_NAME *gen,
|
||||
ASN1_OBJECT **poid,
|
||||
ASN1_TYPE **pvalue);
|
||||
|
||||
DECLARE_ASN1_FUNCTIONS_const(EXTENDED_KEY_USAGE)
|
||||
|
||||
DECLARE_ASN1_FUNCTIONS_const(CERTIFICATEPOLICIES)
|
||||
|
||||
@@ -818,6 +818,12 @@ CertPathBuilder::Result CertPathBuilder::Run() {
|
||||
result_path->errors.GetOtherErrors()->AddError(
|
||||
cert_errors::kInternalError);
|
||||
}
|
||||
|
||||
// Allow the delegate to do any processing or logging of the partial
|
||||
// path. (This is for symmetry for the other CheckPathAfterVerification
|
||||
// which also gets called on partial paths.)
|
||||
delegate_->CheckPathAfterVerification(*this, result_path.get());
|
||||
|
||||
AddResultPath(std::move(result_path));
|
||||
}
|
||||
out_result_.iteration_count = iteration_count;
|
||||
@@ -840,11 +846,6 @@ CertPathBuilder::Result CertPathBuilder::Run() {
|
||||
&result_path->user_constrained_policy_set, &result_path->errors);
|
||||
}
|
||||
|
||||
if (delegate_->IsDebugLogEnabled()) {
|
||||
delegate_->DebugLog("CertPathBuilder VerifyCertificateChain errors:\n" +
|
||||
result_path->errors.ToDebugString(result_path->certs));
|
||||
}
|
||||
|
||||
// Give the delegate a chance to add errors to the path.
|
||||
delegate_->CheckPathAfterVerification(*this, result_path.get());
|
||||
|
||||
|
||||
@@ -88,10 +88,13 @@ struct OPENSSL_EXPORT CertPathBuilderResultPath {
|
||||
class OPENSSL_EXPORT CertPathBuilderDelegate
|
||||
: public VerifyCertificateChainDelegate {
|
||||
public:
|
||||
// This is called during path building on candidate paths which have already
|
||||
// been run through RFC 5280 verification. |path| may already have errors
|
||||
// and warnings set on it. Delegates can "reject" a candidate path from path
|
||||
// building by adding high severity errors.
|
||||
// This is called during path building on candidate paths. These are either
|
||||
// paths which have already been run through RFC 5280 verification, or
|
||||
// partial paths that the path builder cannot continue either due to not
|
||||
// finding a matching issuer or reaching a configured pathbuilding limit.
|
||||
// |path| may already have errors and warnings set on it. Delegates can
|
||||
// "reject" a candidate path from path building by adding high severity
|
||||
// errors.
|
||||
virtual void CheckPathAfterVerification(const CertPathBuilder &path_builder,
|
||||
CertPathBuilderResultPath *path) = 0;
|
||||
|
||||
|
||||
@@ -60,6 +60,24 @@ class TestPathBuilderDelegate : public SimplePathBuilderDelegate {
|
||||
MockSignatureVerifyCache cache_;
|
||||
};
|
||||
|
||||
class CertPathBuilderDelegateBase : public SimplePathBuilderDelegate {
|
||||
public:
|
||||
CertPathBuilderDelegateBase()
|
||||
: SimplePathBuilderDelegate(
|
||||
1024, SimplePathBuilderDelegate::DigestPolicy::kWeakAllowSha1) {}
|
||||
void CheckPathAfterVerification(const CertPathBuilder &path_builder,
|
||||
CertPathBuilderResultPath *path) override {
|
||||
ADD_FAILURE() << "Tests must override this";
|
||||
}
|
||||
};
|
||||
|
||||
class MockPathBuilderDelegate : public CertPathBuilderDelegateBase {
|
||||
public:
|
||||
MOCK_METHOD2(CheckPathAfterVerification,
|
||||
void(const CertPathBuilder &path_builder,
|
||||
CertPathBuilderResultPath *path));
|
||||
};
|
||||
|
||||
// AsyncCertIssuerSourceStatic always returns its certs asynchronously.
|
||||
class AsyncCertIssuerSourceStatic : public CertIssuerSource {
|
||||
public:
|
||||
@@ -628,8 +646,13 @@ TEST_F(PathBuilderMultiRootTest, TestIterationLimit) {
|
||||
for (const bool insufficient_limit : {true, false}) {
|
||||
SCOPED_TRACE(insufficient_limit);
|
||||
|
||||
StrictMock<MockPathBuilderDelegate> mock_delegate;
|
||||
// The CheckPathAfterVerification delegate should be called regardless if
|
||||
// the iteration limit is reached.
|
||||
EXPECT_CALL(mock_delegate, CheckPathAfterVerification(_, _));
|
||||
|
||||
CertPathBuilder path_builder(
|
||||
a_by_b_, &trust_store, &delegate_, time_, KeyPurpose::ANY_EKU,
|
||||
a_by_b_, &trust_store, &mock_delegate, time_, KeyPurpose::ANY_EKU,
|
||||
initial_explicit_policy_, user_initial_policy_set_,
|
||||
initial_policy_mapping_inhibit_, initial_any_policy_inhibit_);
|
||||
path_builder.AddCertIssuerSource(&sync_certs);
|
||||
@@ -1872,24 +1895,6 @@ TEST_F(PathBuilderDistrustTest, TargetIntermediateRoot) {
|
||||
class PathBuilderCheckPathAfterVerificationTest
|
||||
: public PathBuilderSimpleChainTest {};
|
||||
|
||||
class CertPathBuilderDelegateBase : public SimplePathBuilderDelegate {
|
||||
public:
|
||||
CertPathBuilderDelegateBase()
|
||||
: SimplePathBuilderDelegate(
|
||||
1024, SimplePathBuilderDelegate::DigestPolicy::kWeakAllowSha1) {}
|
||||
void CheckPathAfterVerification(const CertPathBuilder &path_builder,
|
||||
CertPathBuilderResultPath *path) override {
|
||||
ADD_FAILURE() << "Tests must override this";
|
||||
}
|
||||
};
|
||||
|
||||
class MockPathBuilderDelegate : public CertPathBuilderDelegateBase {
|
||||
public:
|
||||
MOCK_METHOD2(CheckPathAfterVerification,
|
||||
void(const CertPathBuilder &path_builder,
|
||||
CertPathBuilderResultPath *path));
|
||||
};
|
||||
|
||||
TEST_F(PathBuilderCheckPathAfterVerificationTest, NoOpToValidPath) {
|
||||
StrictMock<MockPathBuilderDelegate> delegate;
|
||||
// Just verify that the hook is called.
|
||||
|
||||
Reference in New Issue
Block a user