boringssl/crypto/x509
David Benjamin da7f0c65ef Unwind X509_LU_RETRY and fix a lot of type confusion.
(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>
2016-06-16 16:24:44 +00:00
..
a_digest.c
a_sign.c
a_strex.c
a_verify.c
algorithm.c Align with upstream's error strings, take two. 2016-03-15 16:02:12 +00:00
asn1_gen.c Fix build when using Visual Studio 2015 Update 1. 2016-03-25 21:39:52 +00:00
by_dir.c Split unlock functions into read/write variants. 2016-05-31 21:09:29 +00:00
by_file.c
charmap.h
CMakeLists.txt
i2d_pr.c
internal.h
pkcs7_test.c Start assuming MSVC 2015. 2016-05-02 19:46:25 +00:00
pkcs7.c
rsa_pss.c Align with upstream's error strings, take two. 2016-03-15 16:02:12 +00:00
t_crl.c
t_req.c
t_x509.c Don't shift serial number into sign bit 2016-03-17 18:23:49 +00:00
t_x509a.c
vpm_int.h
x509_att.c
x509_cmp.c
x509_d2.c
x509_def.c
x509_ext.c
x509_lu.c Unwind X509_LU_RETRY and fix a lot of type confusion. 2016-06-16 16:24:44 +00:00
x509_obj.c Add checks to X509_NAME_oneline() 2016-05-03 16:34:59 +00:00
x509_r2x.c
x509_req.c
x509_set.c
x509_test.cc Fix some malloc test failures. 2016-03-28 17:17:32 +00:00
x509_trs.c
x509_txt.c Ensure verify error is set when X509_verify_cert() fails. 2016-06-09 17:29:39 +00:00
x509_v3.c
x509_vfy.c Ensure verify error is set when X509_verify_cert() fails. 2016-06-09 17:29:39 +00:00
x509_vpm.c
x509.c Align with upstream's error strings, take two. 2016-03-15 16:02:12 +00:00
x509cset.c
x509name.c
x509rset.c
x509spki.c
x509type.c
x_algor.c
x_all.c
x_attrib.c
x_crl.c Split unlock functions into read/write variants. 2016-05-31 21:09:29 +00:00
x_exten.c
x_info.c
x_name.c Remove ASN.1 print hooks. 2016-06-14 17:38:31 +00:00
x_pkey.c
x_pubkey.c Split unlock functions into read/write variants. 2016-05-31 21:09:29 +00:00
x_req.c
x_sig.c
x_spki.c
x_val.c
x_x509.c Make i2d_X509_AUX work if *pp = NULL. 2016-05-13 13:53:48 +00:00
x_x509a.c