diff --git a/src/crypto/fipsmodule/sha/internal.h b/src/crypto/fipsmodule/sha/internal.h index 7dbab6bd4..28975e16c 100644 --- a/src/crypto/fipsmodule/sha/internal.h +++ b/src/crypto/fipsmodule/sha/internal.h @@ -73,24 +73,17 @@ OPENSSL_INLINE int sha1_hw_capable(void) { #define SHA1_ASM_AVX2 OPENSSL_INLINE int sha1_avx2_capable(void) { - // TODO: Simplify this logic, which was extracted from the assembly: - // * Does AVX2 imply SSSE3? - // * sha1_block_data_order_avx2 does not seem to use SSSE3 instructions. return CRYPTO_is_AVX2_capable() && CRYPTO_is_BMI2_capable() && - CRYPTO_is_BMI1_capable() && CRYPTO_is_SSSE3_capable(); + CRYPTO_is_BMI1_capable(); } void sha1_block_data_order_avx2(uint32_t *state, const uint8_t *data, size_t num); #define SHA1_ASM_AVX OPENSSL_INLINE int sha1_avx_capable(void) { - // TODO: Simplify this logic, which was extracted from the assembly: - // * Does AVX imply SSSE3? - // * sha1_block_data_order_avx does not seem to use SSSE3 instructions. // Pre-Zen AMD CPUs had slow SHLD/SHRD; Zen added the SHA extension; see the // discussion in sha1-586.pl. - return CRYPTO_is_AVX_capable() && CRYPTO_is_SSSE3_capable() && - CRYPTO_is_intel_cpu(); + return CRYPTO_is_AVX_capable() && CRYPTO_is_intel_cpu(); } void sha1_block_data_order_avx(uint32_t *state, const uint8_t *data, size_t num); @@ -109,13 +102,9 @@ OPENSSL_INLINE int sha256_hw_capable(void) { #define SHA256_ASM_AVX OPENSSL_INLINE int sha256_avx_capable(void) { - // TODO: Simplify this logic, which was extracted from the assembly: - // * Does AVX imply SSSE3? - // * sha256_block_data_order_avx does not seem to use SSSE3 instructions. // Pre-Zen AMD CPUs had slow SHLD/SHRD; Zen added the SHA extension; see the // discussion in sha1-586.pl. - return CRYPTO_is_AVX_capable() && CRYPTO_is_SSSE3_capable() && - CRYPTO_is_intel_cpu(); + return CRYPTO_is_AVX_capable() && CRYPTO_is_intel_cpu(); } void sha256_block_data_order_avx(uint32_t *state, const uint8_t *data, size_t num); @@ -129,13 +118,9 @@ void sha256_block_data_order_ssse3(uint32_t *state, const uint8_t *data, #define SHA512_ASM_AVX OPENSSL_INLINE int sha512_avx_capable(void) { - // TODO: Simplify this logic, which was extracted from the assembly: - // * Does AVX imply SSSE3? - // * sha512_block_data_order_avx does not seem to use SSSE3 instructions. // Pre-Zen AMD CPUs had slow SHLD/SHRD; Zen added the SHA extension; see the // discussion in sha1-586.pl. - return CRYPTO_is_AVX_capable() && CRYPTO_is_SSSE3_capable() && - CRYPTO_is_intel_cpu(); + return CRYPTO_is_AVX_capable() && CRYPTO_is_intel_cpu(); } void sha512_block_data_order_avx(uint64_t *state, const uint8_t *data, size_t num); diff --git a/src/crypto/x509/internal.h b/src/crypto/x509/internal.h index 62eaa96f4..afc6cd7e7 100644 --- a/src/crypto/x509/internal.h +++ b/src/crypto/x509/internal.h @@ -587,6 +587,10 @@ GENERAL_NAMES *v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method, const X509V3_CTX *ctx, const STACK_OF(CONF_VALUE) *nval); +// TODO(https://crbug.com/boringssl/407): Make |issuer| const once the +// |X509_NAME| issue is resolved. +int X509_check_akid(X509 *issuer, const AUTHORITY_KEYID *akid); + #if defined(__cplusplus) } // extern C diff --git a/src/crypto/x509/v3_purp.c b/src/crypto/x509/v3_purp.c index 9a33a6959..a6c182e9a 100644 --- a/src/crypto/x509/v3_purp.c +++ b/src/crypto/x509/v3_purp.c @@ -592,14 +592,6 @@ static int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x, static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca) { return 1; } -// Various checks to see if one certificate issued the second. This can be -// used to prune a set of possible issuer certificates which have been looked -// up using some simple method such as by subject name. These are: 1. Check -// issuer_name(subject) == subject_name(issuer) 2. If akid(subject) exists -// check it matches issuer 3. If key_usage(issuer) exists check it supports -// certificate signing returns 0 for OK, positive for reason for mismatch, -// reasons match codes for X509_verify_cert() - int X509_check_issued(X509 *issuer, X509 *subject) { if (X509_NAME_cmp(X509_get_subject_name(issuer), X509_get_issuer_name(subject))) { @@ -622,7 +614,7 @@ int X509_check_issued(X509 *issuer, X509 *subject) { return X509_V_OK; } -int X509_check_akid(X509 *issuer, AUTHORITY_KEYID *akid) { +int X509_check_akid(X509 *issuer, const AUTHORITY_KEYID *akid) { if (!akid) { return X509_V_OK; } diff --git a/src/crypto/x509/v3_utl.c b/src/crypto/x509/v3_utl.c index 559143ba6..c6144d157 100644 --- a/src/crypto/x509/v3_utl.c +++ b/src/crypto/x509/v3_utl.c @@ -942,6 +942,9 @@ static int do_check_string(const ASN1_STRING *a, int cmp_type, equal_fn equal, } if (rv > 0 && peername) { *peername = OPENSSL_strndup((char *)a->data, a->length); + if (*peername == NULL) { + return -1; + } } } else { int astrlen; @@ -960,13 +963,16 @@ static int do_check_string(const ASN1_STRING *a, int cmp_type, equal_fn equal, } if (rv > 0 && peername) { *peername = OPENSSL_strndup((char *)astr, astrlen); + if (*peername == NULL) { + return -1; + } } OPENSSL_free(astr); } return rv; } -static int do_x509_check(X509 *x, const char *chk, size_t chklen, +static int do_x509_check(const X509 *x, const char *chk, size_t chklen, unsigned int flags, int check_type, char **peername) { int cnid = NID_undef; int alt_type; @@ -1033,8 +1039,8 @@ static int do_x509_check(X509 *x, const char *chk, size_t chklen, return 0; } -int X509_check_host(X509 *x, const char *chk, size_t chklen, unsigned int flags, - char **peername) { +int X509_check_host(const X509 *x, const char *chk, size_t chklen, + unsigned int flags, char **peername) { if (chk == NULL) { return -2; } @@ -1044,7 +1050,7 @@ int X509_check_host(X509 *x, const char *chk, size_t chklen, unsigned int flags, return do_x509_check(x, chk, chklen, flags, GEN_DNS, peername); } -int X509_check_email(X509 *x, const char *chk, size_t chklen, +int X509_check_email(const X509 *x, const char *chk, size_t chklen, unsigned int flags) { if (chk == NULL) { return -2; @@ -1055,15 +1061,15 @@ int X509_check_email(X509 *x, const char *chk, size_t chklen, return do_x509_check(x, chk, chklen, flags, GEN_EMAIL, NULL); } -int X509_check_ip(X509 *x, const unsigned char *chk, size_t chklen, +int X509_check_ip(const X509 *x, const unsigned char *chk, size_t chklen, unsigned int flags) { if (chk == NULL) { return -2; } - return do_x509_check(x, (char *)chk, chklen, flags, GEN_IPADD, NULL); + return do_x509_check(x, (const char *)chk, chklen, flags, GEN_IPADD, NULL); } -int X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags) { +int X509_check_ip_asc(const X509 *x, const char *ipasc, unsigned int flags) { unsigned char ipout[16]; size_t iplen; @@ -1074,7 +1080,7 @@ int X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags) { if (iplen == 0) { return -2; } - return do_x509_check(x, (char *)ipout, iplen, flags, GEN_IPADD, NULL); + return do_x509_check(x, (const char *)ipout, iplen, flags, GEN_IPADD, NULL); } // Convert IP addresses both IPv4 and IPv6 into an OCTET STRING compatible diff --git a/src/include/openssl/ssl.h b/src/include/openssl/ssl.h index 003e0a5f7..f1d4eb066 100644 --- a/src/include/openssl/ssl.h +++ b/src/include/openssl/ssl.h @@ -2587,8 +2587,19 @@ OPENSSL_EXPORT int (*SSL_get_verify_callback(const SSL *ssl))( // ineffective. Simply checking that a host has some certificate from a CA is // rarely meaningful—you have to check that the CA believed that the host was // who you expect to be talking to. +// +// By default, both subject alternative names and the subject's common name +// attribute are checked. The latter has long been deprecated, so callers should +// call |SSL_set_hostflags| with |X509_CHECK_FLAG_NEVER_CHECK_SUBJECT| to use +// the standard behavior. https://crbug.com/boringssl/464 tracks fixing the +// default. OPENSSL_EXPORT int SSL_set1_host(SSL *ssl, const char *hostname); +// SSL_set_hostflags calls |X509_VERIFY_PARAM_set_hostflags| on the +// |X509_VERIFY_PARAM| associated with this |SSL*|. |flags| should be some +// combination of the |X509_CHECK_*| constants. +OPENSSL_EXPORT void SSL_set_hostflags(SSL *ssl, unsigned flags); + // SSL_CTX_set_verify_depth sets the maximum depth of a certificate chain // accepted in verification. This number does not include the leaf, so a depth // of 1 allows the leaf and one CA certificate. @@ -2762,11 +2773,6 @@ OPENSSL_EXPORT int SSL_set_verify_algorithm_prefs(SSL *ssl, const uint16_t *prefs, size_t num_prefs); -// SSL_set_hostflags calls |X509_VERIFY_PARAM_set_hostflags| on the -// |X509_VERIFY_PARAM| associated with this |SSL*|. The |flags| argument -// should be one of the |X509_CHECK_*| constants. -OPENSSL_EXPORT void SSL_set_hostflags(SSL *ssl, unsigned flags); - // Client certificate CA list. // diff --git a/src/include/openssl/x509.h b/src/include/openssl/x509.h index 44c01397d..989b70909 100644 --- a/src/include/openssl/x509.h +++ b/src/include/openssl/x509.h @@ -2919,6 +2919,119 @@ OPENSSL_EXPORT int ASN1_item_sign_ctx(const ASN1_ITEM *it, X509_ALGOR *algor1, EVP_MD_CTX *ctx); +// Verification internals. +// +// The following functions expose portions of certificate validation. They are +// exported for compatibility with existing callers, or to support some obscure +// use cases. Most callers, however, will not need these functions and should +// instead use |X509_STORE_CTX| APIs. + +// X509_supported_extension returns one if |ex| is a critical X.509 certificate +// extension, supported by |X509_verify_cert|, and zero otherwise. +// +// Note this function only reports certificate extensions (as opposed to CRL or +// CRL extensions), and only extensions that are expected to be marked critical. +// Additionally, |X509_verify_cert| checks for unsupported critical extensions +// internally, so most callers will not need to call this function separately. +OPENSSL_EXPORT int X509_supported_extension(const X509_EXTENSION *ex); + +// X509_check_ca returns one if |x509| may be considered a CA certificate, +// according to basic constraints and key usage extensions. Otherwise, it +// returns zero. If |x509| is an X509v1 certificate, and thus has no extensions, +// it is considered eligible. +// +// This function returning one does not indicate that |x509| is trusted, only +// that it is eligible to be a CA. +// +// TODO(crbug.com/boringssl/407): |x509| should be const. +OPENSSL_EXPORT int X509_check_ca(X509 *x509); + +// X509_check_issued checks if |issuer| and |subject|'s name, authority key +// identifier, and key usage fields allow |issuer| to have issued |subject|. It +// returns |X509_V_OK| on success and an |X509_V_ERR_*| value otherwise. +// +// This function does not check the signature on |subject|. Rather, it is +// intended to prune the set of possible issuer certificates during +// path-building. +// +// TODO(crbug.com/boringssl/407): Both parameters should be const. +OPENSSL_EXPORT int X509_check_issued(X509 *issuer, X509 *subject); + +// NAME_CONSTRAINTS_check checks if |x509| satisfies name constraints in |nc|. +// It returns |X509_V_OK| on success and some |X509_V_ERR_*| constant on error. +// +// TODO(crbug.com/boringssl/407): Both parameters should be const. +OPENSSL_EXPORT int NAME_CONSTRAINTS_check(X509 *x509, NAME_CONSTRAINTS *nc); + +// X509_check_host checks if |x509| matches the DNS name |chk|. It returns one +// on match, zero on mismatch, or a negative number on error. |flags| should be +// some combination of |X509_CHECK_FLAG_*| and modifies the behavior. On match, +// if |out_peername| is non-NULL, it additionally sets |*out_peername| to a +// newly-allocated, NUL-terminated string containing the DNS name or wildcard in +// the certificate which matched. The caller must then free |*out_peername| with +// |OPENSSL_free| when done. +// +// By default, both subject alternative names and the subject's common name +// attribute are checked. The latter has long been deprecated, so callers should +// include |X509_CHECK_FLAG_NEVER_CHECK_SUBJECT| in |flags| to use the standard +// behavior. https://crbug.com/boringssl/464 tracks fixing the default. +// +// This function does not check if |x509| is a trusted certificate, only if, +// were it trusted, it would match |chk|. +// +// WARNING: This function differs from the usual calling convention and may +// return either 0 or a negative number on error. +// +// TODO(davidben): Make the error case also return zero. +OPENSSL_EXPORT int X509_check_host(const X509 *x509, const char *chk, + size_t chklen, unsigned int flags, + char **out_peername); + +// X509_check_email checks if |x509| matches the email address |chk|. It returns +// one on match, zero on mismatch, or a negative number on error. |flags| should +// be some combination of |X509_CHECK_FLAG_*| and modifies the behavior. +// +// By default, both subject alternative names and the subject's email address +// attribute are checked. The |X509_CHECK_FLAG_NEVER_CHECK_SUBJECT| flag may be +// used to change this behavior. +// +// This function does not check if |x509| is a trusted certificate, only if, +// were it trusted, it would match |chk|. +// +// WARNING: This function differs from the usual calling convention and may +// return either 0 or a negative number on error. +// +// TODO(davidben): Make the error case also return zero. +OPENSSL_EXPORT int X509_check_email(const X509 *x509, const char *chk, + size_t chklen, unsigned int flags); + +// X509_check_ip checks if |x509| matches the IP address |chk|. The IP address +// is represented in byte form and should be 4 bytes for an IPv4 address and 16 +// bytes for an IPv6 address. It returns one on match, zero on mismatch, or a +// negative number on error. |flags| should be some combination of +// |X509_CHECK_FLAG_*| and modifies the behavior. +// +// This function does not check if |x509| is a trusted certificate, only if, +// were it trusted, it would match |chk|. +// +// WARNING: This function differs from the usual calling convention and may +// return either 0 or a negative number on error. +// +// TODO(davidben): Make the error case also return zero. +OPENSSL_EXPORT int X509_check_ip(const X509 *x509, const uint8_t *chk, + size_t chklen, unsigned int flags); + +// X509_check_ip_asc behaves like |X509_check_ip| except the IP address is +// specified in textual form in |ipasc|. +// +// WARNING: This function differs from the usual calling convention and may +// return either 0 or a negative number on error. +// +// TODO(davidben): Make the error case also return zero. +OPENSSL_EXPORT int X509_check_ip_asc(const X509 *x509, const char *ipasc, + unsigned int flags); + + // X.509 information. // // |X509_INFO| is the return type for |PEM_X509_INFO_read_bio|, defined in @@ -3855,6 +3968,12 @@ OPENSSL_EXPORT int X509_VERIFY_PARAM_set1_policies( // X509_VERIFY_PARAM_set1_host configures |param| to check for the DNS name // specified by |name|. It returns one on success and zero on error. +// +// By default, both subject alternative names and the subject's common name +// attribute are checked. The latter has long been deprecated, so callers should +// call |X509_VERIFY_PARAM_set_hostflags| with +// |X509_CHECK_FLAG_NEVER_CHECK_SUBJECT| to use the standard behavior. +// https://crbug.com/boringssl/464 tracks fixing the default. OPENSSL_EXPORT int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param, const char *name, size_t name_len); @@ -3862,6 +3981,12 @@ OPENSSL_EXPORT int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param, // X509_VERIFY_PARAM_add1_host adds |name| to the list of names checked by // |param|. If any configured DNS name matches the certificate, verification // succeeds. It returns one on success and zero on error. +// +// By default, both subject alternative names and the subject's common name +// attribute are checked. The latter has long been deprecated, so callers should +// call |X509_VERIFY_PARAM_set_hostflags| with +// |X509_CHECK_FLAG_NEVER_CHECK_SUBJECT| to use the standard behavior. +// https://crbug.com/boringssl/464 tracks fixing the default. OPENSSL_EXPORT int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param, const char *name, size_t name_len); @@ -3873,6 +3998,10 @@ OPENSSL_EXPORT void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param, // X509_VERIFY_PARAM_set1_email configures |param| to check for the email // address specified by |email|. It returns one on success and zero on error. +// +// By default, both subject alternative names and the subject's email address +// attribute are checked. The |X509_CHECK_FLAG_NEVER_CHECK_SUBJECT| flag may be +// used to change this behavior. OPENSSL_EXPORT int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param, const char *email, size_t email_len); @@ -4136,8 +4265,6 @@ DECLARE_ASN1_FUNCTIONS(ISSUING_DIST_POINT) OPENSSL_EXPORT int DIST_POINT_set_dpname(DIST_POINT_NAME *dpn, X509_NAME *iname); -OPENSSL_EXPORT int NAME_CONSTRAINTS_check(X509 *x, NAME_CONSTRAINTS *nc); - // TODO(https://crbug.com/boringssl/407): This is not const because it contains // an |X509_NAME|. DECLARE_ASN1_FUNCTIONS(ACCESS_DESCRIPTION) @@ -4307,21 +4434,9 @@ OPENSSL_EXPORT X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, OPENSSL_EXPORT int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value, int crit, unsigned long flags); -OPENSSL_EXPORT int X509_check_ca(X509 *x); OPENSSL_EXPORT int X509_check_purpose(X509 *x, int id, int ca); -// X509_supported_extension returns one if |ex| is a critical X.509 certificate -// extension, supported by |X509_verify_cert|, and zero otherwise. -// -// Note this function only reports certificate extensions (as opposed to CRL or -// CRL extensions), and only extensions that are expected to be marked critical. -// Additionally, |X509_verify_cert| checks for unsupported critical extensions -// internally, so most callers will not need to call this function separately. -OPENSSL_EXPORT int X509_supported_extension(const X509_EXTENSION *ex); - OPENSSL_EXPORT int X509_PURPOSE_set(int *p, int purpose); -OPENSSL_EXPORT int X509_check_issued(X509 *issuer, X509 *subject); -OPENSSL_EXPORT int X509_check_akid(X509 *issuer, AUTHORITY_KEYID *akid); OPENSSL_EXPORT int X509_PURPOSE_get_count(void); OPENSSL_EXPORT const X509_PURPOSE *X509_PURPOSE_get0(int idx); @@ -4349,15 +4464,6 @@ OPENSSL_EXPORT int X509_PURPOSE_get_id(const X509_PURPOSE *); // Skip the subject common name fallback if subjectAltNames is missing. #define X509_CHECK_FLAG_NEVER_CHECK_SUBJECT 0x20 -OPENSSL_EXPORT int X509_check_host(X509 *x, const char *chk, size_t chklen, - unsigned int flags, char **peername); -OPENSSL_EXPORT int X509_check_email(X509 *x, const char *chk, size_t chklen, - unsigned int flags); -OPENSSL_EXPORT int X509_check_ip(X509 *x, const unsigned char *chk, - size_t chklen, unsigned int flags); -OPENSSL_EXPORT int X509_check_ip_asc(X509 *x, const char *ipasc, - unsigned int flags); - #if defined(__cplusplus) } // extern C