From: Viktor Dukhovni Date: Sun, 17 Jan 2016 21:50:52 +0000 (-0500) Subject: Check Suite-B constraints with EE DANE records X-Git-Tag: OpenSSL_1_1_0-pre3~475 X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff_plain;h=6e32825631bea414c3fc70d16bbb413dac221722 Check Suite-B constraints with EE DANE records When DANE-EE(3) matches or either of DANE-EE/PKIX-EE fails, we don't build a chain at all, but rather succeed or fail with just the leaf certificate. In either case also check for Suite-B violations. As unlikely as it may seem that anyone would enable both DANE and Suite-B, we should do what the application asks. Took the opportunity to eliminate the "cb" variables in x509_vfy.c, just call ctx->verify_cb(ok, ctx) Reviewed-by: Dr. Stephen Henson --- diff --git a/crypto/x509/x509_cmp.c b/crypto/x509/x509_cmp.c index 2521e77b2a..2641d2e133 100644 --- a/crypto/x509/x509_cmp.c +++ b/crypto/x509/x509_cmp.c @@ -398,11 +398,12 @@ int X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain, unsigned long flags) { int rv, i, sign_nid; - EVP_PKEY *pk = NULL; - unsigned long tflags; + EVP_PKEY *pk; + unsigned long tflags = flags; + if (!(flags & X509_V_FLAG_SUITEB_128_LOS)) return X509_V_OK; - tflags = flags; + /* If no EE certificate passed in must be first in chain */ if (x == NULL) { x = sk_X509_value(chain, 0); @@ -410,6 +411,17 @@ int X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain, } else i = 0; + pk = X509_get0_pubkey(x); + + /* + * With DANE-EE(3) success, or DANE-EE(3)/PKIX-EE(1) failure we don't build + * a chain all, just report trust success or failure, but must also report + * Suite-B errors if applicable. This is indicated via a NULL chain + * pointer. All we need to do is check the leaf key algorithm. + */ + if (chain == NULL) + return check_suite_b(pk, -1, &tflags); + if (X509_get_version(x) != 2) { rv = X509_V_ERR_SUITE_B_INVALID_VERSION; /* Correct error depth */ @@ -417,7 +429,6 @@ int X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain, goto end; } - pk = X509_get0_pubkey(x); /* Check EE key only */ rv = check_suite_b(pk, -1, &tflags); if (rv != X509_V_OK) { diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c index ec9c3211cc..c9dd6fa60c 100644 --- a/crypto/x509/x509_vfy.c +++ b/crypto/x509/x509_vfy.c @@ -193,7 +193,6 @@ static X509 *lookup_cert_match(X509_STORE_CTX *ctx, X509 *x) static int verify_chain(X509_STORE_CTX *ctx) { - int (*cb) (int xok, X509_STORE_CTX *xctx) = ctx->verify_cb; int err; int ok; @@ -214,7 +213,7 @@ static int verify_chain(X509_STORE_CTX *ctx) if (err != X509_V_OK) { ctx->error = err; ctx->current_cert = sk_X509_value(ctx->chain, ctx->error_depth); - if ((ok = cb(0, ctx)) == 0) + if ((ok = ctx->verify_cb(0, ctx)) == 0) return ok; } @@ -373,11 +372,9 @@ static int check_chain_extensions(X509_STORE_CTX *ctx) { int i, ok = 0, must_be_ca, plen = 0; X509 *x; - int (*cb) (int xok, X509_STORE_CTX *xctx); int proxy_path_length = 0; int purpose; int allow_proxy_certs; - cb = ctx->verify_cb; /*- * must_be_ca can have 1 of 3 values: @@ -415,7 +412,7 @@ static int check_chain_extensions(X509_STORE_CTX *ctx) ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION; ctx->error_depth = i; ctx->current_cert = x; - ok = cb(0, ctx); + ok = ctx->verify_cb(0, ctx); if (!ok) goto end; } @@ -423,7 +420,7 @@ static int check_chain_extensions(X509_STORE_CTX *ctx) ctx->error = X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED; ctx->error_depth = i; ctx->current_cert = x; - ok = cb(0, ctx); + ok = ctx->verify_cb(0, ctx); if (!ok) goto end; } @@ -457,7 +454,7 @@ static int check_chain_extensions(X509_STORE_CTX *ctx) if (ret == 0) { ctx->error_depth = i; ctx->current_cert = x; - ok = cb(0, ctx); + ok = ctx->verify_cb(0, ctx); if (!ok) goto end; } @@ -469,7 +466,7 @@ static int check_chain_extensions(X509_STORE_CTX *ctx) ctx->error = X509_V_ERR_INVALID_PURPOSE; ctx->error_depth = i; ctx->current_cert = x; - ok = cb(0, ctx); + ok = ctx->verify_cb(0, ctx); if (!ok) goto end; } @@ -481,7 +478,7 @@ static int check_chain_extensions(X509_STORE_CTX *ctx) ctx->error = X509_V_ERR_PATH_LENGTH_EXCEEDED; ctx->error_depth = i; ctx->current_cert = x; - ok = cb(0, ctx); + ok = ctx->verify_cb(0, ctx); if (!ok) goto end; } @@ -498,7 +495,7 @@ static int check_chain_extensions(X509_STORE_CTX *ctx) ctx->error = X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED; ctx->error_depth = i; ctx->current_cert = x; - ok = cb(0, ctx); + ok = ctx->verify_cb(0, ctx); if (!ok) goto end; } @@ -595,7 +592,6 @@ static int check_trust(X509_STORE_CTX *ctx, int num_untrusted) int i, ok = 0; X509 *x = NULL; X509 *mx; - int (*cb) (int xok, X509_STORE_CTX *xctx) = ctx->verify_cb; struct dane_st *dane = (struct dane_st *)ctx->dane; int num = sk_X509_num(ctx->chain); int trust; @@ -676,7 +672,7 @@ static int check_trust(X509_STORE_CTX *ctx, int num_untrusted) ctx->error_depth = i; ctx->current_cert = x; ctx->error = X509_V_ERR_CERT_REJECTED; - ok = cb(0, ctx); + ok = ctx->verify_cb(0, ctx); if (!ok) return X509_TRUST_REJECTED; return X509_TRUST_UNTRUSTED; @@ -1568,9 +1564,6 @@ static int internal_verify(X509_STORE_CTX *ctx) int ok = 0, n; X509 *xs, *xi; EVP_PKEY *pkey = NULL; - int (*cb) (int xok, X509_STORE_CTX *xctx); - - cb = ctx->verify_cb; n = sk_X509_num(ctx->chain) - 1; ctx->error_depth = n; @@ -1597,7 +1590,7 @@ static int internal_verify(X509_STORE_CTX *ctx) if (n <= 0) { ctx->error = X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE; ctx->current_cert = xi; - ok = cb(0, ctx); + ok = ctx->verify_cb(0, ctx); goto end; } else { n--; @@ -1622,13 +1615,13 @@ static int internal_verify(X509_STORE_CTX *ctx) if ((pkey = X509_get0_pubkey(xi)) == NULL) { ctx->error = X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY; ctx->current_cert = xi; - ok = (*cb) (0, ctx); + ok = ctx->verify_cb(0, ctx); if (!ok) goto end; } else if (X509_verify(xs, pkey) <= 0) { ctx->error = X509_V_ERR_CERT_SIGNATURE_FAILURE; ctx->current_cert = xs; - ok = (*cb) (0, ctx); + ok = ctx->verify_cb(0, ctx); if (!ok) goto end; } @@ -1642,7 +1635,7 @@ static int internal_verify(X509_STORE_CTX *ctx) /* The last error (if any) is still in the error value */ ctx->current_issuer = xi; ctx->current_cert = xs; - ok = (*cb) (1, ctx); + ok = ctx->verify_cb(1, ctx); if (!ok) goto end; @@ -2584,10 +2577,21 @@ static void dane_reset(struct dane_st *dane) dane->pdpth = -1; } +static int check_leaf_suiteb(X509_STORE_CTX *ctx, X509 *cert) +{ + int err = X509_chain_check_suiteb(NULL, cert, NULL, ctx->param->flags); + + if (err == X509_V_OK) + return 1; + ctx->current_cert = cert; + ctx->error_depth = 0; + ctx->error = err; + return ctx->verify_cb(0, ctx); +} + static int dane_verify(X509_STORE_CTX *ctx) { X509 *cert = ctx->cert; - int (*cb)(int xok, X509_STORE_CTX *xctx) = ctx->verify_cb; struct dane_st *dane = (struct dane_st *)ctx->dane; int matched; int done; @@ -2601,9 +2605,11 @@ static int dane_verify(X509_STORE_CTX *ctx) X509_get_pubkey_parameters(NULL, ctx->chain); if (matched > 0) { + if (!check_leaf_suiteb(ctx, cert)) + return 0; ctx->error_depth = 0; ctx->current_cert = cert; - return cb(1, ctx); + return ctx->verify_cb(1, ctx); } if (matched < 0) { @@ -2615,10 +2621,12 @@ static int dane_verify(X509_STORE_CTX *ctx) if (done) { /* Fail early, TA-based success is not possible */ + if (!check_leaf_suiteb(ctx, cert)) + return 0; ctx->current_cert = cert; ctx->error_depth = 0; ctx->error = X509_V_ERR_CERT_UNTRUSTED; - return cb(0, ctx); + return ctx->verify_cb(0, ctx); } /* @@ -2631,7 +2639,6 @@ static int dane_verify(X509_STORE_CTX *ctx) static int build_chain(X509_STORE_CTX *ctx) { struct dane_st *dane = (struct dane_st *)ctx->dane; - int (*cb) (int, X509_STORE_CTX *) = ctx->verify_cb; int num = sk_X509_num(ctx->chain); X509 *cert = sk_X509_value(ctx->chain, num - 1); int ss = cert_self_signed(cert); @@ -2944,6 +2951,6 @@ static int build_chain(X509_STORE_CTX *ctx) ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT; if (DANETLS_ENABLED(dane)) dane_reset(dane); - return cb(0, ctx); + return ctx->verify_cb(0, ctx); } }