diff options
author | Viktor Dukhovni <openssl-users@dukhovni.org> | 2021-08-30 14:17:16 -0400 |
---|---|---|
committer | Viktor Dukhovni <openssl-users@dukhovni.org> | 2021-09-03 00:16:19 -0400 |
commit | 5d9be38211fdb8b6a1d4c9257715e8c28832a317 (patch) | |
tree | b4c49aa996d7ff1ea2c282ff50b2416f0e1d7a0e /crypto/x509/x509_vfy.c | |
parent | 9e72d1a3145a0585b96fa9b4e9ab31ce35a43aba (diff) |
Prioritise DANE TLSA issuer certs over peer certs
When building the certificate chain, prioritise any Cert(0) Full(0)
certificates from TLSA records over certificates received from the peer.
This is important when the server sends a cross cert, but TLSA records include
the underlying root CA cert. We want to construct a chain with the issuer from
the TLSA record, which can then match the TLSA records (while the associated
cross cert may not).
Reviewed-by: Tomáš Mráz <tomas@openssl.org>
Diffstat (limited to 'crypto/x509/x509_vfy.c')
-rw-r--r-- | crypto/x509/x509_vfy.c | 62 |
1 files changed, 36 insertions, 26 deletions
diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c index 20a36e763c..e404fcc602 100644 --- a/crypto/x509/x509_vfy.c +++ b/crypto/x509/x509_vfy.c @@ -2924,6 +2924,26 @@ static int get_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *cert) return ok; } +static int augment_stack(STACK_OF(X509) *src, STACK_OF(X509) **dstPtr) +{ + if (src) { + STACK_OF(X509) *dst; + int i; + + if (*dstPtr == NULL) + return ((*dstPtr = sk_X509_dup(src)) != NULL); + + for (dst = *dstPtr, i = 0; i < sk_X509_num(src); ++i) { + if (!sk_X509_push(dst, sk_X509_value(src, i))) { + sk_X509_free(dst); + *dstPtr = NULL; + return 0; + } + } + } + return 1; +} + static int build_chain(X509_STORE_CTX *ctx) { SSL_DANE *dane = ctx->dane; @@ -2967,18 +2987,7 @@ static int build_chain(X509_STORE_CTX *ctx) } /* - * Shallow-copy the stack of untrusted certificates (with TLS, this is - * typically the content of the peer's certificate message) so can make - * multiple passes over it, while free to remove elements as we go. - */ - if (ctx->untrusted && (sktmp = sk_X509_dup(ctx->untrusted)) == NULL) { - X509err(X509_F_BUILD_CHAIN, ERR_R_MALLOC_FAILURE); - ctx->error = X509_V_ERR_OUT_OF_MEM; - return 0; - } - - /* - * If we got any "DANE-TA(2) Cert(0) Full(0)" trust-anchors from DNS, add + * If we got any "Cert(0) Full(0)" issuer certificates from DNS, *prepend* * them to our working copy of the untrusted certificate stack. Since the * caller of X509_STORE_CTX_init() may have provided only a leaf cert with * no corresponding stack of untrusted certificates, we may need to create @@ -2987,20 +2996,21 @@ static int build_chain(X509_STORE_CTX *ctx) * containing at least the leaf certificate, but we must be prepared for * this to change. ] */ - if (DANETLS_ENABLED(dane) && dane->certs != NULL) { - if (sktmp == NULL && (sktmp = sk_X509_new_null()) == NULL) { - X509err(X509_F_BUILD_CHAIN, ERR_R_MALLOC_FAILURE); - ctx->error = X509_V_ERR_OUT_OF_MEM; - return 0; - } - for (i = 0; i < sk_X509_num(dane->certs); ++i) { - if (!sk_X509_push(sktmp, sk_X509_value(dane->certs, i))) { - sk_X509_free(sktmp); - X509err(X509_F_BUILD_CHAIN, ERR_R_MALLOC_FAILURE); - ctx->error = X509_V_ERR_OUT_OF_MEM; - return 0; - } - } + if (DANETLS_ENABLED(dane) && !augment_stack(dane->certs, &sktmp)) { + X509err(X509_F_BUILD_CHAIN, ERR_R_MALLOC_FAILURE); + ctx->error = X509_V_ERR_OUT_OF_MEM; + return 0; + } + + /* + * Shallow-copy the stack of untrusted certificates (with TLS, this is + * typically the content of the peer's certificate message) so can make + * multiple passes over it, while free to remove elements as we go. + */ + if (!augment_stack(ctx->untrusted, &sktmp)) { + X509err(X509_F_BUILD_CHAIN, ERR_R_MALLOC_FAILURE); + ctx->error = X509_V_ERR_OUT_OF_MEM; + return 0; } /* |