summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorViktor Dukhovni <openssl-users@dukhovni.org>2021-08-30 14:17:16 -0400
committerViktor Dukhovni <openssl-users@dukhovni.org>2021-09-03 00:16:19 -0400
commit5d9be38211fdb8b6a1d4c9257715e8c28832a317 (patch)
treeb4c49aa996d7ff1ea2c282ff50b2416f0e1d7a0e
parent9e72d1a3145a0585b96fa9b4e9ab31ce35a43aba (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>
-rw-r--r--crypto/x509/x509_vfy.c62
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;
}
/*