update main-with-bazel from master branch

This commit is contained in:
BoringSSL Robot
2023-12-11 19:35:50 +00:00
8 changed files with 276 additions and 117 deletions
+8
View File
@@ -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
+2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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)
+6 -5
View File
@@ -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());
+7 -4
View File
@@ -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;
+24 -19
View File
@@ -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.