da7f0c65ef
(This change will be sent upstream. Since the legacy X.509 stack is just kept around for compatibility, if they decide to fix it in a different way, we may wish to revert this and apply their fix.) Dating back to SSLeay, X509_LOOKUP_METHOD had this X509_LU_RETRY machinery. But it's not documented and it appears to have never worked. Problems with the existing logic: - X509_LU_* is not sure whether it is a type enum (to be passed into X509_LOOKUP_by_*) or a return enum (to be retained by those same functions). - X509_LOOKUP_by_* is not sure whether it returns 0/1 or an X509_LU_* value. Looking at the functions themselves, one might think it's the latter, but for X509_LOOKUP_by_subject returning both 0 and X509_LU_FAIL. But looking at the call sites, some expect 0/1 (such as X509_STORE_get1_certs) while others expect an X509_LU_* enum (such as X509_STORE_CTX_get1_issuer). It is very fortunate that FAIL happens to be 0 and X509 happens to be 1. These functions primarily call to X509_LOOKUP_METHOD hooks. Looking through OpenSSL itself and code checked into Google, I found no evidence that any hooks have been implemented except for get_by_subject in by_dir.c. We take that one as definitive and observe it believes it returns 0/1. Notably, it returns 1 on success even if asked for a type other than X509_LU_X509. (X509_LU_X509 = 1. Others are different.) I found another piece of third-party software which corroborates this worldview. - X509_STORE_get_by_subject's handling of X509_LU_RETRY (it's the j < 0 check) is broken. It saves j into vs->current_method where it probably meant to save i. (This bug has existed since SSLeay.) It also returns j (supposedly X509_LU_RETRY) while all callers of X509_STORE_get_by_subject expect it to return 0/1 by checking with ! instead of <= 0. (Note that all other codepaths return 0 and 1 so this function did not actually believe it returned X509_LU_* most of the time.) This, in turn, gives us a free of uninitialized pointers in X509_STORE_get1_certs and other functions which expect that *ret is filled in if X509_STORE_get_by_subject returns success. GCC 4.9 with optimizations from the Android NDK noticed this, which trigged this saga. (It's only reachable if any X509_LOOKUP_METHOD returned X509_LU_RETRY.) - Although the code which expects X509_STORE_get_by_subject return 0/1 does not date to SSLeay, the X509_STORE_get_by_subject call in X509_STORE_CTX_get1_issuer *does* (though, at the time, it was inline in X509_verify_cert. That code believes X509_STORE_get_by_subject returns an X509_LU_* enum, but it doesn't work either! It believes *ret is filled in on X509_LU_RETRY, thus freeing another uninitialized pointer (GCC noticed this too). Since this "retry" code has clearly never worked, from SSLeay onwards, unwind it completely rather than attempt to fix it. No X509_LOOKUP_METHOD can possibly have depended on it. Matching all non-broken codepaths X509_LOOKUP_by_* now returns 0/1 and X509_STORE_get_by_subject returns 0/1. X509_LU_* is purely a type enum with X509_LU_{REJECT,FAIL} being legacy constants to keep old code compiling. (Upstream is recommended to remove those values altogether for 1.1.0.) On the off chance any get_by_* X509_LOOKUP_METHOD implementations did not return 0/1 (I have found no evidence anywhere of this, and I believe it wouldn't have worked anyway), the X509_LOOKUP_by_* wrapper functions will coerce the return values back to 0/1 before passing up to the callers which want 0/1. This both avoids the error-prone -1/0/1 calling convention and, more importantly, avoids problems with third-party callers which expect a X509_LU_* return code. 0/1 collide with FAIL/X509 while -1 will collide with RETRY and might confuse things. Change-Id: I98ecf6fa7342866b9124dc6f0b422cb9ce4a1ae7 Reviewed-on: https://boringssl-review.googlesource.com/8303 Reviewed-by: Adam Langley <agl@google.com> |
||
---|---|---|
.. | ||
aead.h | ||
aes.h | ||
arm_arch.h | ||
asn1_mac.h | ||
asn1.h | ||
asn1t.h | ||
base64.h | ||
base.h | ||
bio.h | ||
blowfish.h | ||
bn.h | ||
buf.h | ||
buffer.h | ||
bytestring.h | ||
cast.h | ||
chacha.h | ||
cipher.h | ||
cmac.h | ||
conf.h | ||
cpu.h | ||
crypto.h | ||
curve25519.h | ||
des.h | ||
dh.h | ||
digest.h | ||
dsa.h | ||
dtls1.h | ||
ec_key.h | ||
ec.h | ||
ecdh.h | ||
ecdsa.h | ||
engine.h | ||
err.h | ||
evp.h | ||
ex_data.h | ||
hkdf.h | ||
hmac.h | ||
lhash_macros.h | ||
lhash.h | ||
md4.h | ||
md5.h | ||
mem.h | ||
newhope.h | ||
nid.h | ||
obj_mac.h | ||
obj.h | ||
objects.h | ||
opensslconf.h | ||
opensslv.h | ||
ossl_typ.h | ||
pem.h | ||
pkcs7.h | ||
pkcs8.h | ||
pkcs12.h | ||
poly1305.h | ||
pqueue.h | ||
rand.h | ||
rc4.h | ||
ripemd.h | ||
rsa.h | ||
safestack.h | ||
sha.h | ||
srtp.h | ||
ssl3.h | ||
ssl.h | ||
stack_macros.h | ||
stack.h | ||
thread.h | ||
time_support.h | ||
tls1.h | ||
type_check.h | ||
x509_vfy.h | ||
x509.h | ||
x509v3.h |