diff --git a/src/ssl.c b/src/ssl.c index bfe5ad46ad..fe81193482 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -5535,13 +5535,15 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) } } - if (ret == 0 && cert->isCA == 0 && type != WOLFSSL_USER_CA) { + if (ret == 0 && cert->isCA == 0 && type != WOLFSSL_USER_CA && + type != WOLFSSL_TEMP_CA) { WOLFSSL_MSG("\tCan't add as CA if not actually one"); ret = NOT_CA_ERROR; } #ifndef ALLOW_INVALID_CERTSIGN else if (ret == 0 && cert->isCA == 1 && type != WOLFSSL_USER_CA && - !cert->selfSigned && (cert->extKeyUsage & KEYUSE_KEY_CERT_SIGN) == 0) { + type != WOLFSSL_TEMP_CA && !cert->selfSigned && + (cert->extKeyUsage & KEYUSE_KEY_CERT_SIGN) == 0) { /* Intermediate CA certs are required to have the keyCertSign * extension set. User loaded root certs are not. */ WOLFSSL_MSG("\tDoesn't have key usage certificate signing"); diff --git a/src/ssl_certman.c b/src/ssl_certman.c index a5b622dede..346904eef0 100644 --- a/src/ssl_certman.c +++ b/src/ssl_certman.c @@ -455,11 +455,12 @@ int wolfSSL_CertManagerUnloadCAs(WOLFSSL_CERT_MANAGER* cm) return ret; } -int wolfSSL_CertManagerUnloadIntermediateCerts(WOLFSSL_CERT_MANAGER* cm) +static int wolfSSL_CertManagerUnloadIntermediateCertsEx( + WOLFSSL_CERT_MANAGER* cm, byte type) { int ret = WOLFSSL_SUCCESS; - WOLFSSL_ENTER("wolfSSL_CertManagerUnloadIntermediateCerts"); + WOLFSSL_ENTER("wolfSSL_CertManagerUnloadIntermediateCertsEx"); /* Validate parameter. */ if (cm == NULL) { @@ -471,7 +472,7 @@ int wolfSSL_CertManagerUnloadIntermediateCerts(WOLFSSL_CERT_MANAGER* cm) } if (ret == WOLFSSL_SUCCESS) { /* Dispose of CA table. */ - FreeSignerTableType(cm->caTable, CA_TABLE_SIZE, WOLFSSL_CHAIN_CA, + FreeSignerTableType(cm->caTable, CA_TABLE_SIZE, type, cm->heap); /* Unlock CA table. */ @@ -481,6 +482,22 @@ int wolfSSL_CertManagerUnloadIntermediateCerts(WOLFSSL_CERT_MANAGER* cm) return ret; } +#if defined(OPENSSL_EXTRA) +static int wolfSSL_CertManagerUnloadTempIntermediateCerts( + WOLFSSL_CERT_MANAGER* cm) +{ + WOLFSSL_ENTER("wolfSSL_CertManagerUnloadTempIntermediateCerts"); + return wolfSSL_CertManagerUnloadIntermediateCertsEx(cm, WOLFSSL_TEMP_CA); +} +#endif + +int wolfSSL_CertManagerUnloadIntermediateCerts( + WOLFSSL_CERT_MANAGER* cm) +{ + WOLFSSL_ENTER("wolfSSL_CertManagerUnloadIntermediateCerts"); + return wolfSSL_CertManagerUnloadIntermediateCertsEx(cm, WOLFSSL_CHAIN_CA); +} + #ifdef WOLFSSL_TRUST_PEER_CERT /* Unload the trusted peers table. * diff --git a/src/x509.c b/src/x509.c index d130f9fe19..18feff0225 100644 --- a/src/x509.c +++ b/src/x509.c @@ -5559,7 +5559,7 @@ WOLFSSL_EVP_PKEY* wolfSSL_X509_get_pubkey(WOLFSSL_X509* x509) * size of this subset and its memory usage */ #endif /* OPENSSL_EXTRA_X509_SMALL || KEEP_PEER_CERT || SESSION_CERTS */ -#if defined(OPENSSL_ALL) +#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) /* * Converts a and b to DER and then does an XMEMCMP to check if they match. * Returns 0 when certificates match and WOLFSSL_FATAL_ERROR when they don't. @@ -7536,7 +7536,6 @@ int wolfSSL_X509_LOOKUP_load_file(WOLFSSL_X509_LOOKUP* lookup, byte* pem = NULL; byte* curr = NULL; byte* prev = NULL; - WOLFSSL_X509* x509; const char* header = NULL; const char* footer = NULL; @@ -7597,12 +7596,8 @@ int wolfSSL_X509_LOOKUP_load_file(WOLFSSL_X509_LOOKUP* lookup, } else if (wc_PemGetHeaderFooter(CERT_TYPE, &header, &footer) == 0 && XSTRNSTR((char*)curr, header, (unsigned int)sz) != NULL) { - x509 = wolfSSL_X509_load_certificate_buffer(curr, (int)sz, - WOLFSSL_FILETYPE_PEM); - if (x509 == NULL) - goto end; - ret = wolfSSL_X509_STORE_add_cert(lookup->store, x509); - wolfSSL_X509_free(x509); + ret = X509StoreLoadCertBuffer(lookup->store, curr, + (word32)sz, WOLFSSL_FILETYPE_PEM); if (ret != WOLFSSL_SUCCESS) goto end; curr = (byte*)XSTRNSTR((char*)curr, footer, (unsigned int)sz); @@ -14210,6 +14205,9 @@ int wolfSSL_X509_NAME_digest(const WOLFSSL_X509_NAME *name, #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \ defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) +#if defined(OPENSSL_EXTRA) && \ + ((defined(SESSION_CERTS) && !defined(WOLFSSL_QT)) || \ + defined(WOLFSSL_SIGNER_DER_CERT)) /** * Find the issuing cert of the input cert. On a self-signed cert this @@ -14280,6 +14278,8 @@ static int x509GetIssuerFromCM(WOLFSSL_X509 **issuer, WOLFSSL_CERT_MANAGER* cm, return WOLFSSL_SUCCESS; } +#endif /* if defined(OPENSSL_EXTRA) && (defined(SESSION_CERTS) || \ + defined(WOLFSSL_SIGNER_DER_CERT)) */ void wolfSSL_X509_email_free(WOLF_STACK_OF(WOLFSSL_STRING) *sk) { diff --git a/src/x509_str.c b/src/x509_str.c index dfb11fb026..a659a73d46 100644 --- a/src/x509_str.c +++ b/src/x509_str.c @@ -36,9 +36,21 @@ #ifndef NO_CERTS -/******************************************************************************* +#ifdef OPENSSL_EXTRA +static int X509StoreGetIssuerEx(WOLFSSL_X509 **issuer, + WOLFSSL_STACK *certs, WOLFSSL_X509 *x); +static int X509StoreAddCa(WOLFSSL_X509_STORE* store, + WOLFSSL_X509* x509, int type); +#endif + +/* Based on OpenSSL default max depth */ +#ifndef WOLFSSL_X509_STORE_DEFAULT_MAX_DEPTH +#define WOLFSSL_X509_STORE_DEFAULT_MAX_DEPTH 100 +#endif + +/****************************************************************************** * START OF X509_STORE_CTX APIs - ******************************************************************************/ + *****************************************************************************/ /* This API is necessary outside of OPENSSL_EXTRA because it is used in * SetupStoreCtxCallback */ @@ -53,11 +65,16 @@ WOLFSSL_X509_STORE_CTX* wolfSSL_X509_STORE_CTX_new_ex(void* heap) XMEMSET(ctx, 0, sizeof(WOLFSSL_X509_STORE_CTX)); ctx->heap = heap; #ifdef OPENSSL_EXTRA - if (wolfSSL_X509_STORE_CTX_init(ctx, NULL, NULL, NULL) != - WOLFSSL_SUCCESS) { + if ((ctx->owned = wolfSSL_sk_X509_new_null()) == NULL) { XFREE(ctx, heap, DYNAMIC_TYPE_X509_CTX); ctx = NULL; } + if (ctx != NULL && + wolfSSL_X509_STORE_CTX_init(ctx, NULL, NULL, NULL) != + WOLFSSL_SUCCESS) { + wolfSSL_X509_STORE_CTX_free(ctx); + ctx = NULL; + } #endif } @@ -78,6 +95,17 @@ void wolfSSL_X509_STORE_CTX_free(WOLFSSL_X509_STORE_CTX* ctx) #ifdef OPENSSL_EXTRA XFREE(ctx->param, ctx->heap, DYNAMIC_TYPE_OPENSSL); ctx->param = NULL; + + if (ctx->chain != NULL) { + wolfSSL_sk_X509_free(ctx->chain); + } + if (ctx->owned != NULL) { + wolfSSL_sk_X509_pop_free(ctx->owned, NULL); + } + + if (ctx->current_issuer != NULL) { + wolfSSL_X509_free(ctx->current_issuer); + } #endif XFREE(ctx, ctx->heap, DYNAMIC_TYPE_X509_CTX); @@ -96,8 +124,6 @@ int wolfSSL_X509_STORE_CTX_init(WOLFSSL_X509_STORE_CTX* ctx, WOLFSSL_X509_STORE* store, WOLFSSL_X509* x509, WOLF_STACK_OF(WOLFSSL_X509)* sk) { - int ret = 0; - (void)sk; WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_init"); if (ctx != NULL) { @@ -106,51 +132,21 @@ int wolfSSL_X509_STORE_CTX_init(WOLFSSL_X509_STORE_CTX* ctx, ctx->current_cert = x509; #else if(x509 != NULL){ - ctx->current_cert = wolfSSL_X509_d2i_ex(NULL, x509->derCert->buffer, - x509->derCert->length, x509->heap); + ctx->current_cert = wolfSSL_X509_d2i_ex(NULL, + x509->derCert->buffer, + x509->derCert->length, + x509->heap); if(ctx->current_cert == NULL) return WOLFSSL_FAILURE; } else ctx->current_cert = NULL; #endif - ctx->chain = sk; - /* Add intermediate certs, that verify to a loaded CA, to the store */ - if (sk != NULL) { - byte addedAtLeastOne = 1; - WOLF_STACK_OF(WOLFSSL_X509)* head = wolfSSL_shallow_sk_dup(sk); - if (head == NULL) - return WOLFSSL_FAILURE; - while (addedAtLeastOne) { - WOLF_STACK_OF(WOLFSSL_X509)* cur = head; - WOLF_STACK_OF(WOLFSSL_X509)** prev = &head; - addedAtLeastOne = 0; - while (cur) { - WOLFSSL_X509* cert = cur->data.x509; - if (cert != NULL && cert->derCert != NULL && - wolfSSL_CertManagerVerifyBuffer(store->cm, - cert->derCert->buffer, - cert->derCert->length, - WOLFSSL_FILETYPE_ASN1) == WOLFSSL_SUCCESS) { - ret = wolfSSL_X509_STORE_add_cert(store, cert); - if (ret < 0) { - wolfSSL_sk_free(head); - return WOLFSSL_FAILURE; - } - addedAtLeastOne = 1; - *prev = cur->next; - wolfSSL_sk_free_node(cur); - cur = *prev; - } - else { - prev = &cur->next; - cur = cur->next; - } - } - } - wolfSSL_sk_free(head); + ctx->ctxIntermediates = sk; + if (ctx->chain != NULL) { + wolfSSL_sk_X509_free(ctx->chain); + ctx->chain = NULL; } - ctx->sesChain = NULL; ctx->domain = NULL; #ifdef HAVE_EX_DATA @@ -192,10 +188,11 @@ void wolfSSL_X509_STORE_CTX_cleanup(WOLFSSL_X509_STORE_CTX* ctx) } -void wolfSSL_X509_STORE_CTX_trusted_stack(WOLFSSL_X509_STORE_CTX *ctx, WOLF_STACK_OF(WOLFSSL_X509) *sk) +void wolfSSL_X509_STORE_CTX_trusted_stack(WOLFSSL_X509_STORE_CTX *ctx, + WOLF_STACK_OF(WOLFSSL_X509) *sk) { if (ctx != NULL) { - ctx->chain = sk; + ctx->setTrustedSk = sk; } } @@ -255,19 +252,16 @@ static void SetupStoreCtxError(WOLFSSL_X509_STORE_CTX* ctx, int ret) wolfSSL_X509_STORE_CTX_set_error_depth(ctx, depth); } -/* Verifies certificate chain using WOLFSSL_X509_STORE_CTX - * returns 0 on success or < 0 on failure. - */ -int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx) +static int X509StoreVerifyCert(WOLFSSL_X509_STORE_CTX* ctx) { - WOLFSSL_ENTER("wolfSSL_X509_verify_cert"); - - if (ctx != NULL && ctx->store != NULL && ctx->store->cm != NULL - && ctx->current_cert != NULL && ctx->current_cert->derCert != NULL) { - int ret = wolfSSL_CertManagerVerifyBuffer(ctx->store->cm, - ctx->current_cert->derCert->buffer, - ctx->current_cert->derCert->length, - WOLFSSL_FILETYPE_ASN1); + int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE); + WOLFSSL_ENTER("X509StoreVerifyCert"); + + if (ctx->current_cert != NULL && ctx->current_cert->derCert != NULL) { + ret = wolfSSL_CertManagerVerifyBuffer(ctx->store->cm, + ctx->current_cert->derCert->buffer, + ctx->current_cert->derCert->length, + WOLFSSL_FILETYPE_ASN1); SetupStoreCtxError(ctx, ret); #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) if (ctx->store && ctx->store->verify_cb) @@ -278,9 +272,9 @@ int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx) if (ret != WC_NO_ERR_TRACE(ASN_BEFORE_DATE_E) && ret != WC_NO_ERR_TRACE(ASN_AFTER_DATE_E)) { /* wolfSSL_CertManagerVerifyBuffer only returns ASN_AFTER_DATE_E or - ASN_BEFORE_DATE_E if there are no additional errors found in the - cert. Therefore, check if the cert is expired or not yet valid - in order to return the correct expected error. */ + * ASN_BEFORE_DATE_E if there are no additional errors found in the + * cert. Therefore, check if the cert is expired or not yet valid + * in order to return the correct expected error. */ byte *afterDate = ctx->current_cert->notAfter.data; byte *beforeDate = ctx->current_cert->notBefore.data; @@ -300,17 +294,197 @@ int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx) #endif } #endif + } + + return ret; +} - return ret >= 0 ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; +static int addAllButSelfSigned(WOLF_STACK_OF(WOLFSSL_X509)*to, + WOLF_STACK_OF(WOLFSSL_X509)*from, int *numAdded) +{ + int ret = WOLFSSL_SUCCESS; + int i = 0; + int cnt = 0; + WOLFSSL_X509 *x = NULL; + + for (i = 0; i < wolfSSL_sk_X509_num(from); i++) { + x = wolfSSL_sk_X509_value(from, i); + if (wolfSSL_X509_NAME_cmp(&x->issuer, &x->subject) != 0) { + if (wolfSSL_sk_X509_push(to, x) <= 0) { + ret = WOLFSSL_FAILURE; + goto exit; + } + cnt++; + } } - return WOLFSSL_FATAL_ERROR; + +exit: + if (numAdded != NULL) { + *numAdded = cnt; + } + return ret; +} + +/* Verifies certificate chain using WOLFSSL_X509_STORE_CTX + * returns 0 on success or < 0 on failure. + */ +int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx) +{ + int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE); + int done = 0; + int added = 0; + int i = 0; + int numInterAdd = 0; + int depth = 0; + WOLFSSL_X509 *issuer = NULL; + WOLFSSL_X509 *orig = NULL; + WOLF_STACK_OF(WOLFSSL_X509)* certs = NULL; + WOLF_STACK_OF(WOLFSSL_X509)* certsToUse = NULL; + WOLFSSL_ENTER("wolfSSL_X509_verify_cert"); + + if (ctx == NULL || ctx->store == NULL || ctx->store->cm == NULL + || ctx->current_cert == NULL || ctx->current_cert->derCert == NULL) { + return WOLFSSL_FATAL_ERROR; + } + + certs = ctx->store->certs; + if (ctx->setTrustedSk != NULL) { + certs = ctx->setTrustedSk; + } + + if (certs == NULL && + wolfSSL_sk_X509_num(ctx->ctxIntermediates) > 0) { + certsToUse = wolfSSL_sk_X509_new_null(); + ret = addAllButSelfSigned(certsToUse, ctx->ctxIntermediates, NULL); + } + else { + /* Add the intermediates provided on init to the list of untrusted + * intermediates to be used */ + ret = addAllButSelfSigned(certs, ctx->ctxIntermediates, &numInterAdd); + } + if (ret != WOLFSSL_SUCCESS) { + goto exit; + } + + if (ctx->chain != NULL) { + wolfSSL_sk_X509_free(ctx->chain); + } + ctx->chain = wolfSSL_sk_X509_new_null(); + + if (ctx->depth > 0) { + depth = ctx->depth + 1; + } + else { + depth = WOLFSSL_X509_STORE_DEFAULT_MAX_DEPTH + 1; + } + + orig = ctx->current_cert; + while(done == 0 && depth > 0) { + issuer = NULL; + + /* Try to find an untrusted issuer first */ + ret = X509StoreGetIssuerEx(&issuer, certs, + ctx->current_cert); + if (ret == WOLFSSL_SUCCESS) { + if (ctx->current_cert == issuer) { + wolfSSL_sk_X509_push(ctx->chain, ctx->current_cert); + break; + } + + /* We found our issuer in the non-trusted cert list, add it + * to the CM and verify the current cert against it */ + ret = X509StoreAddCa(ctx->store, issuer, + WOLFSSL_TEMP_CA); + if (ret != WOLFSSL_SUCCESS) { + goto exit; + } + + added = 1; + + ret = X509StoreVerifyCert(ctx); + if (ret != WOLFSSL_SUCCESS) { + goto exit; + } + + /* Add it to the current chain and look at the issuer cert next */ + wolfSSL_sk_X509_push(ctx->chain, ctx->current_cert); + ctx->current_cert = issuer; + } + else if (ret == WC_NO_ERR_TRACE(WOLFSSL_FAILURE)) { + /* Could not find in untrusted list, only place left is + * a trusted CA in the CM */ + ret = X509StoreVerifyCert(ctx); + if (ret != WOLFSSL_SUCCESS) { + if (((ctx->flags & WOLFSSL_PARTIAL_CHAIN) || + (ctx->store->param->flags & WOLFSSL_PARTIAL_CHAIN)) && + (added == 1)) { + wolfSSL_sk_X509_push(ctx->chain, ctx->current_cert); + ret = WOLFSSL_SUCCESS; + } + goto exit; + } + + /* Cert verified, finish building the chain */ + wolfSSL_sk_X509_push(ctx->chain, ctx->current_cert); + issuer = NULL; + #ifdef WOLFSSL_SIGNER_DER_CERT + x509GetIssuerFromCM(&issuer, ctx->store->cm, ctx->current_cert); + if (issuer != NULL && ctx->owned != NULL) { + wolfSSL_sk_X509_push(ctx->owned, issuer); + } + #else + if (ctx->setTrustedSk == NULL) { + X509StoreGetIssuerEx(&issuer, + ctx->store->trusted, ctx->current_cert); + } + else { + X509StoreGetIssuerEx(&issuer, + ctx->setTrustedSk, ctx->current_cert); + } + #endif + if (issuer != NULL) { + wolfSSL_sk_X509_push(ctx->chain, issuer); + } + + done = 1; + } + else { + goto exit; + } + + depth--; + } + +exit: + /* Remove additional intermediates from init from the store */ + if (ctx != NULL && numInterAdd > 0) { + for (i = 0; i < numInterAdd; i++) { + wolfSSL_sk_X509_pop(ctx->store->certs); + } + } + /* Remove intermediates that were added to CM */ + if (ctx != NULL) { + if (ctx->store != NULL) { + if (added == 1) { + wolfSSL_CertManagerUnloadTempIntermediateCerts(ctx->store->cm); + } + } + if (orig != NULL) { + ctx->current_cert = orig; + } + } + if (certsToUse != NULL) { + wolfSSL_sk_X509_free(certsToUse); + } + + return ret == WOLFSSL_SUCCESS ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; } #endif /* OPENSSL_EXTRA */ #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) WOLFSSL_X509* wolfSSL_X509_STORE_CTX_get_current_cert( - WOLFSSL_X509_STORE_CTX* ctx) + WOLFSSL_X509_STORE_CTX* ctx) { WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_current_cert"); if (ctx) @@ -408,14 +582,6 @@ int wolfSSL_X509_STORE_CTX_set_purpose(WOLFSSL_X509_STORE_CTX *ctx, WOLFSSL_STUB("wolfSSL_X509_STORE_CTX_set_purpose (not implemented)"); return 0; } - -void wolfSSL_X509_STORE_CTX_set_flags(WOLFSSL_X509_STORE_CTX *ctx, - unsigned long flags) -{ - (void)ctx; - (void)flags; - WOLFSSL_STUB("wolfSSL_X509_STORE_CTX_set_flags (not implemented)"); -} #endif /* !NO_WOLFSSL_STUB */ #endif /* WOLFSSL_QT || OPENSSL_ALL */ @@ -423,6 +589,14 @@ void wolfSSL_X509_STORE_CTX_set_flags(WOLFSSL_X509_STORE_CTX *ctx, #ifdef OPENSSL_EXTRA +void wolfSSL_X509_STORE_CTX_set_flags(WOLFSSL_X509_STORE_CTX *ctx, + unsigned long flags) +{ + if ((ctx != NULL) && (flags & WOLFSSL_PARTIAL_CHAIN)){ + ctx->flags |= WOLFSSL_PARTIAL_CHAIN; + } +} + /* set X509_STORE_CTX ex_data, max idx is MAX_EX_DATA. Return WOLFSSL_SUCCESS * on success, WOLFSSL_FAILURE on error. */ int wolfSSL_X509_STORE_CTX_set_ex_data(WOLFSSL_X509_STORE_CTX* ctx, int idx, @@ -454,8 +628,8 @@ int wolfSSL_X509_STORE_CTX_set_ex_data_with_cleanup( WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_set_ex_data_with_cleanup"); if (ctx != NULL) { - return wolfSSL_CRYPTO_set_ex_data_with_cleanup(&ctx->ex_data, idx, data, - cleanup_routine); + return wolfSSL_CRYPTO_set_ex_data_with_cleanup(&ctx->ex_data, idx, + data, cleanup_routine); } return WOLFSSL_FAILURE; } @@ -470,22 +644,24 @@ void wolfSSL_X509_STORE_CTX_set_depth(WOLFSSL_X509_STORE_CTX* ctx, int depth) } #endif - WOLFSSL_X509* wolfSSL_X509_STORE_CTX_get0_current_issuer( WOLFSSL_X509_STORE_CTX* ctx) { - int ret; - WOLFSSL_X509* issuer; - + WOLFSSL_STACK* node; WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get0_current_issuer"); - if (ctx == NULL) { + if (ctx == NULL) return NULL; - } - ret = wolfSSL_X509_STORE_CTX_get1_issuer(&issuer, ctx, ctx->current_cert); - if (ret == WOLFSSL_SUCCESS) { - return issuer; + /* get0 only checks currently built chain */ + if (ctx->chain != NULL) { + for (node = ctx->chain; node != NULL; node = node->next) { + if (wolfSSL_X509_check_issued(node->data.x509, + ctx->current_cert) == + WOLFSSL_X509_V_OK) { + return node->data.x509; + } + } } return NULL; @@ -505,7 +681,7 @@ void wolfSSL_X509_STORE_CTX_set_error(WOLFSSL_X509_STORE_CTX* ctx, int er) /* Set the error depth in the X509 STORE CTX */ void wolfSSL_X509_STORE_CTX_set_error_depth(WOLFSSL_X509_STORE_CTX* ctx, - int depth) + int depth) { WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_set_error_depth"); @@ -533,7 +709,8 @@ WOLFSSL_STACK* wolfSSL_X509_STORE_CTX_get_chain(WOLFSSL_X509_STORE_CTX* ctx) if (sk == NULL) return NULL; -#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \ + defined(OPENSSL_EXTRA) /* add CA used to verify top of chain to the list */ if (c->count > 0) { WOLFSSL_X509* x509 = wolfSSL_get_chain_X509(c, c->count - 1); @@ -734,34 +911,63 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_STORE_get1_certs( int wolfSSL_X509_STORE_CTX_get1_issuer(WOLFSSL_X509 **issuer, WOLFSSL_X509_STORE_CTX *ctx, WOLFSSL_X509 *x) { - WOLFSSL_STACK* node; + int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE); + WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get1_issuer"); if (issuer == NULL || ctx == NULL || x == NULL) return WOLFSSL_FATAL_ERROR; - if (ctx->chain != NULL) { - for (node = ctx->chain; node != NULL; node = node->next) { - if (wolfSSL_X509_check_issued(node->data.x509, x) == - WOLFSSL_X509_V_OK) { - *issuer = x; + ret = X509StoreGetIssuerEx(issuer, ctx->store->certs, x); + if ((ret == WOLFSSL_SUCCESS) && (*issuer != NULL)) { + return wolfSSL_X509_up_ref(*issuer); + } + +#ifdef WOLFSSL_SIGNER_DER_CERT + ret = x509GetIssuerFromCM(issuer, ctx->store->cm, x); +#else + ret = X509StoreGetIssuerEx(issuer, ctx->store->trusted, x); + if ((ret == WOLFSSL_SUCCESS) && (*issuer != NULL)) { + return wolfSSL_X509_up_ref(*issuer); + } +#endif + + return ret; +} +#endif /* WOLFSSL_NGINX || WOLFSSL_HAPROXY || OPENSSL_EXTRA || OPENSSL_ALL */ + +#ifdef OPENSSL_EXTRA + +static int X509StoreGetIssuerEx(WOLFSSL_X509 **issuer, + WOLFSSL_STACK * certs, WOLFSSL_X509 *x) +{ + int i; + + if (issuer == NULL || x == NULL) + return WOLFSSL_FATAL_ERROR; + + if (certs != NULL) { + for (i = 0; i < wolfSSL_sk_X509_num(certs); i++) { + if (wolfSSL_X509_check_issued( + wolfSSL_sk_X509_value(certs, i), x) == + WOLFSSL_X509_V_OK) { + *issuer = wolfSSL_sk_X509_value(certs, i); return WOLFSSL_SUCCESS; } } } - /* Result is ignored when passed to wolfSSL_OCSP_cert_to_id(). */ - - return x509GetIssuerFromCM(issuer, ctx->store->cm, x); + return WOLFSSL_FAILURE; } -#endif /* WOLFSSL_NGINX || WOLFSSL_HAPROXY || OPENSSL_EXTRA || OPENSSL_ALL */ -/******************************************************************************* +#endif + +/****************************************************************************** * END OF X509_STORE_CTX APIs - ******************************************************************************/ + *****************************************************************************/ -/******************************************************************************* +/****************************************************************************** * START OF X509_STORE APIs - ******************************************************************************/ + *****************************************************************************/ #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || \ defined(WOLFSSL_WPAS_SMALL) @@ -789,10 +995,25 @@ WOLFSSL_X509_STORE* wolfSSL_X509_STORE_new(void) if ((store->cm = wolfSSL_CertManagerNew()) == NULL) goto err_exit; +#ifdef OPENSSL_EXTRA + if ((store->certs = wolfSSL_sk_X509_new_null()) == NULL) + goto err_exit; + + if ((store->owned = wolfSSL_sk_X509_new_null()) == NULL) + goto err_exit; + +#if !defined(WOLFSSL_SIGNER_DER_CERT) + if ((store->trusted = wolfSSL_sk_X509_new_null()) == NULL) + goto err_exit; +#endif +#endif + #ifdef HAVE_CRL store->crl = store->cm->crl; #endif + store->numAdded = 0; + #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) /* Link store's new Certificate Manager to self by default */ @@ -827,6 +1048,30 @@ WOLFSSL_X509_STORE* wolfSSL_X509_STORE_new(void) return NULL; } +#ifdef OPENSSL_ALL +static void X509StoreFreeObjList(WOLFSSL_X509_STORE* store, + WOLF_STACK_OF(WOLFSSL_X509_OBJECT)* objs) +{ + int i; + WOLFSSL_X509_OBJECT *obj = NULL; + int cnt = store->numAdded; + + i = wolfSSL_sk_X509_OBJECT_num(objs) - 1; + while (cnt > 0 && i > 0) { + /* The inner X509 is owned by somebody else, NULL out the reference */ + obj = (WOLFSSL_X509_OBJECT *)wolfSSL_sk_X509_OBJECT_value(objs, i); + if (obj != NULL) { + obj->type = (WOLFSSL_X509_LOOKUP_TYPE)0; + obj->data.ptr = NULL; + } + cnt--; + i--; + } + + wolfSSL_sk_X509_OBJECT_pop_free(objs, NULL); +} +#endif + void wolfSSL_X509_STORE_free(WOLFSSL_X509_STORE* store) { int doFree = 0; @@ -849,9 +1094,25 @@ void wolfSSL_X509_STORE_free(WOLFSSL_X509_STORE* store) wolfSSL_CertManagerFree(store->cm); store->cm = NULL; } +#if defined(OPENSSL_EXTRA) + if (store->certs != NULL) { + wolfSSL_sk_X509_free(store->certs); + store->certs = NULL; + } + if (store->owned != NULL) { + wolfSSL_sk_X509_pop_free(store->owned, wolfSSL_X509_free); + store->owned = NULL; + } +#if !defined(WOLFSSL_SIGNER_DER_CERT) + if (store->trusted != NULL) { + wolfSSL_sk_X509_free(store->trusted); + store->trusted = NULL; + } +#endif +#endif #ifdef OPENSSL_ALL if (store->objs != NULL) { - wolfSSL_sk_X509_OBJECT_pop_free(store->objs, NULL); + X509StoreFreeObjList(store, store->objs); } #endif #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) @@ -861,7 +1122,8 @@ void wolfSSL_X509_STORE_free(WOLFSSL_X509_STORE* store) if (store->lookup.dirs != NULL) { #if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) if (store->lookup.dirs->dir_entry) { - wolfSSL_sk_BY_DIR_entry_free(store->lookup.dirs->dir_entry); + wolfSSL_sk_BY_DIR_entry_free( + store->lookup.dirs->dir_entry); } #endif wc_FreeMutex(&store->lookup.dirs->lock); @@ -923,7 +1185,7 @@ int wolfSSL_X509_STORE_up_ref(WOLFSSL_X509_STORE* store) * @return WOLFSSL_SUCCESS on success or WOLFSSL_FAILURE on failure */ int wolfSSL_X509_STORE_set_ex_data(WOLFSSL_X509_STORE* store, int idx, - void *data) + void *data) { WOLFSSL_ENTER("wolfSSL_X509_STORE_set_ex_data"); #ifdef HAVE_EX_DATA @@ -1010,22 +1272,68 @@ WOLFSSL_X509_LOOKUP* wolfSSL_X509_STORE_add_lookup(WOLFSSL_X509_STORE* store, return &store->lookup; } -int wolfSSL_X509_STORE_add_cert(WOLFSSL_X509_STORE* store, WOLFSSL_X509* x509) +static int X509StoreAddCa(WOLFSSL_X509_STORE* store, + WOLFSSL_X509* x509, int type) { int result = WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR); + DerBuffer* derCert = NULL; - WOLFSSL_ENTER("wolfSSL_X509_STORE_add_cert"); - if (store != NULL && store->cm != NULL && x509 != NULL - && x509->derCert != NULL) { - DerBuffer* derCert = NULL; - + WOLFSSL_ENTER("X509StoreAddCa"); + if (store != NULL && x509 != NULL && x509->derCert != NULL) { result = AllocDer(&derCert, x509->derCert->length, x509->derCert->type, NULL); if (result == 0) { /* AddCA() frees the buffer. */ XMEMCPY(derCert->buffer, x509->derCert->buffer, x509->derCert->length); - result = AddCA(store->cm, &derCert, WOLFSSL_USER_CA, VERIFY); + result = AddCA(store->cm, &derCert, type, VERIFY); + } + } + + return result; +} + + +int wolfSSL_X509_STORE_add_cert(WOLFSSL_X509_STORE* store, WOLFSSL_X509* x509) +{ + int result = WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR); + + WOLFSSL_ENTER("wolfSSL_X509_STORE_add_cert"); + if (store != NULL && store->cm != NULL && x509 != NULL + && x509->derCert != NULL) { + /* Mimic the openssl behavior, must be self signed to be considered + * trusted, addCA() internals will do additional checks for + * CA=TRUE */ + if (wolfSSL_X509_NAME_cmp(&x509->issuer, &x509->subject) == 0) { + result = X509StoreAddCa(store, x509, WOLFSSL_USER_CA); + #if !defined(WOLFSSL_SIGNER_DER_CERT) + if (result == WOLFSSL_SUCCESS && store->trusted != NULL) { + result = wolfSSL_sk_X509_push(store->trusted, x509); + if (result > 0) { + result = WOLFSSL_SUCCESS; + } + else { + result = WOLFSSL_FATAL_ERROR; + } + } + #endif + } + else { + if (store->certs != NULL) { + result = wolfSSL_sk_X509_push(store->certs, x509); + if (result > 0) { + result = WOLFSSL_SUCCESS; + } + else { + result = WOLFSSL_FATAL_ERROR; + } + } + else { + /* If store->certs is NULL, this is an X509_STORE managed by an + * SSL_CTX, preserve behavior and always add as USER_CA */ + result = X509StoreAddCa( + store, x509, WOLFSSL_USER_CA); + } } } @@ -1055,6 +1363,9 @@ int wolfSSL_X509_STORE_set_flags(WOLFSSL_X509_STORE* store, unsigned long flag) ret = wolfSSL_CertManagerDisableCRL(store->cm); } #endif + if (flag & WOLFSSL_PARTIAL_CHAIN) { + store->param->flags |= WOLFSSL_PARTIAL_CHAIN; + } return ret; } @@ -1065,13 +1376,107 @@ int wolfSSL_X509_STORE_set_default_paths(WOLFSSL_X509_STORE* store) return WOLFSSL_SUCCESS; } +int X509StoreLoadCertBuffer(WOLFSSL_X509_STORE *str, + byte *buf, word32 bufLen, int type) +{ + int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE); + WOLFSSL_X509 *x509 = NULL; + + if (str == NULL || buf == NULL) { + return WOLFSSL_FAILURE; + } + + /* OpenSSL X509_STORE_load_file fails on DER file, we will as well */ + x509 = wolfSSL_X509_load_certificate_buffer(buf, bufLen, type); + if (str->owned != NULL) { + wolfSSL_sk_X509_push(str->owned, x509); + } + ret = wolfSSL_X509_STORE_add_cert(str, x509); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Failed to load file"); + ret = WOLFSSL_FAILURE; + } + if (str->owned == NULL) { + wolfSSL_X509_free(x509); + } + + return ret; +} + #if !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + +static int X509StoreReadFile(const char *fname, + StaticBuffer *content, word32 *bytesRead, int *type) +{ + int ret = -1; + long sz = 0; +#ifdef HAVE_CRL + const char* header = NULL; + const char* footer = NULL; +#endif + + ret = wolfssl_read_file_static(fname, content, NULL, DYNAMIC_TYPE_FILE, + &sz); + if (ret == 0) { + *type = CERT_TYPE; + *bytesRead = (word32)sz; +#ifdef HAVE_CRL + /* Look for CRL header and footer. */ + if (wc_PemGetHeaderFooter(CRL_TYPE, &header, &footer) == 0 && + (XSTRNSTR((char*)content->buffer, header, (word32)sz) != + NULL)) { + *type = CRL_TYPE; + } +#endif + } + + return (ret == 0 ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE); +} + +static int X509StoreLoadFile(WOLFSSL_X509_STORE *str, + const char *fname) +{ + int ret = WOLFSSL_SUCCESS; + int type = 0; +#ifndef WOLFSSL_SMALL_STACK + byte stackBuffer[FILE_BUFFER_SIZE]; +#endif + StaticBuffer content; + word32 contentLen = 0; + +#ifdef WOLFSSL_SMALL_STACK + static_buffer_init(&content); +#else + static_buffer_init(&content, stackBuffer, FILE_BUFFER_SIZE); +#endif + + ret = X509StoreReadFile(fname, &content, &contentLen, &type); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Failed to load file"); + ret = WOLFSSL_FAILURE; + } + + if ((ret == WOLFSSL_SUCCESS) && (type == CERT_TYPE)) { + ret = X509StoreLoadCertBuffer(str, content.buffer, + contentLen, WOLFSSL_FILETYPE_PEM); + } +#ifdef HAVE_CRL + else if ((ret == WOLFSSL_SUCCESS) && (type == CRL_TYPE)) { + ret = BufferLoadCRL(str->cm->crl, content.buffer, contentLen, + WOLFSSL_FILETYPE_PEM, 0); + } +#endif + + static_buffer_free(&content, NULL, DYNAMIC_TYPE_FILE); + return ret; +} + /* Loads certificate(s) files in pem format into X509_STORE struct from either * a file or directory. * Returns WOLFSSL_SUCCESS on success or WOLFSSL_FAILURE if an error occurs. */ WOLFSSL_API int wolfSSL_X509_STORE_load_locations(WOLFSSL_X509_STORE *str, - const char *file, const char *dir) + const char *file, const char *dir) { WOLFSSL_CTX* ctx; char *name = NULL; @@ -1111,10 +1516,7 @@ WOLFSSL_API int wolfSSL_X509_STORE_load_locations(WOLFSSL_X509_STORE *str, /* Load individual file */ if (file) { - /* Try to process file with type DETECT_CERT_TYPE to parse the - correct certificate header and footer type */ - ret = ProcessFile(ctx, file, WOLFSSL_FILETYPE_PEM, DETECT_CERT_TYPE, - NULL, 0, str->cm->crl, 0); + ret = X509StoreLoadFile(str, file); if (ret != WOLFSSL_SUCCESS) { WOLFSSL_MSG("Failed to load file"); ret = WOLFSSL_FAILURE; @@ -1127,7 +1529,7 @@ WOLFSSL_API int wolfSSL_X509_STORE_load_locations(WOLFSSL_X509_STORE *str, #ifdef WOLFSSL_SMALL_STACK readCtx = (ReadDirCtx*)XMALLOC(sizeof(ReadDirCtx), ctx->heap, - DYNAMIC_TYPE_TMP_BUFFER); + DYNAMIC_TYPE_TMP_BUFFER); if (readCtx == NULL) { WOLFSSL_MSG("Memory error"); wolfSSL_CTX_free(ctx); @@ -1139,10 +1541,8 @@ WOLFSSL_API int wolfSSL_X509_STORE_load_locations(WOLFSSL_X509_STORE *str, ret = wc_ReadDirFirst(readCtx, dir, &name); while (ret == 0 && name) { WOLFSSL_MSG(name); - /* Try to process file with type DETECT_CERT_TYPE to parse the - correct certificate header and footer type */ - ret = ProcessFile(ctx, name, WOLFSSL_FILETYPE_PEM, DETECT_CERT_TYPE, - NULL, 0, str->cm->crl, 0); + + ret = X509StoreLoadFile(str, name); /* Not failing on load errors */ if (ret != WOLFSSL_SUCCESS) WOLFSSL_MSG("Failed to load file in path, continuing"); @@ -1185,17 +1585,23 @@ int wolfSSL_X509_CA_num(WOLFSSL_X509_STORE* store) } table = store->cm->caTable; - if (table){ + if (table || (store->certs != NULL)){ if (wc_LockMutex(&store->cm->caLock) == 0){ - int i = 0; - for (i = 0; i < CA_TABLE_SIZE; i++) { - Signer* signer = table[i]; - while (signer) { - Signer* next = signer->next; - cnt_ret++; - signer = next; + if (table) { + int i = 0; + for (i = 0; i < CA_TABLE_SIZE; i++) { + Signer* signer = table[i]; + while (signer) { + Signer* next = signer->next; + cnt_ret++; + signer = next; + } } } + + if (store->certs != NULL) { + cnt_ret += wolfSSL_sk_X509_num(store->certs); + } wc_UnLockMutex(&store->cm->caLock); } } @@ -1204,7 +1610,8 @@ int wolfSSL_X509_CA_num(WOLFSSL_X509_STORE* store) } /****************************************************************************** -* wolfSSL_X509_STORE_GetCerts - retrieve stack of X509 in a certificate store ctx +* wolfSSL_X509_STORE_GetCerts - retrieve stack of X509 in a certificate +* store ctx * * This API can be used in SSL verify callback function to view cert chain * See examples/client/client.c and myVerify() function in test.h @@ -1235,7 +1642,8 @@ WOLFSSL_STACK* wolfSSL_X509_STORE_GetCerts(WOLFSSL_X509_STORE_CTX* s) /* get certificate buffer */ cert = &s->certs[certIdx]; - dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT); + dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, + DYNAMIC_TYPE_DCERT); if (dCert == NULL) { goto error; @@ -1298,7 +1706,14 @@ WOLF_STACK_OF(WOLFSSL_X509_OBJECT)* wolfSSL_X509_STORE_get0_objects( { WOLFSSL_STACK* ret = NULL; WOLFSSL_STACK* cert_stack = NULL; +#if ((defined(WOLFSSL_SIGNER_DER_CERT) && !defined(NO_FILESYSTEM)) || \ + (defined(HAVE_CRL))) + WOLFSSL_X509_OBJECT* obj = NULL; +#endif +#if defined(WOLFSSL_SIGNER_DER_CERT) && !defined(NO_FILESYSTEM) WOLFSSL_X509* x509 = NULL; + int i = 0; +#endif WOLFSSL_ENTER("wolfSSL_X509_STORE_get0_objects"); if (store == NULL || store->cm == NULL) { @@ -1309,7 +1724,7 @@ WOLF_STACK_OF(WOLFSSL_X509_OBJECT)* wolfSSL_X509_STORE_get0_objects( if (store->objs != NULL) { #if defined(WOLFSSL_SIGNER_DER_CERT) && !defined(NO_FILESYSTEM) /* want to update objs stack by cm stack again before returning it*/ - wolfSSL_sk_X509_OBJECT_pop_free(store->objs, NULL); + X509StoreFreeObjList(store, store->objs); store->objs = NULL; #else if (wolfSSL_sk_X509_OBJECT_num(store->objs) == 0) { @@ -1329,9 +1744,17 @@ WOLF_STACK_OF(WOLFSSL_X509_OBJECT)* wolfSSL_X509_STORE_get0_objects( #if defined(WOLFSSL_SIGNER_DER_CERT) && !defined(NO_FILESYSTEM) cert_stack = wolfSSL_CertManagerGetCerts(store->cm); - /* wolfSSL_sk_X509_pop checks for NULL */ - while ((x509 = wolfSSL_sk_X509_pop(cert_stack)) != NULL) { - WOLFSSL_X509_OBJECT* obj = wolfSSL_X509_OBJECT_new(); + store->numAdded = 0; + for (i = 0; i < wolfSSL_sk_X509_num(store->certs); i++) { + wolfSSL_sk_X509_push(cert_stack, + wolfSSL_sk_X509_value(store->certs, i)); + store->numAdded++; + } + /* Do not modify stack until after we guarantee success to + * simplify cleanup logic handling cert merging above */ + for (i = 0; i < wolfSSL_sk_X509_num(cert_stack); i++) { + x509 = (WOLFSSL_X509 *)wolfSSL_sk_value(cert_stack, i); + obj = wolfSSL_X509_OBJECT_new(); if (obj == NULL) { WOLFSSL_MSG("wolfSSL_X509_OBJECT_new error"); goto err_cleanup; @@ -1345,11 +1768,15 @@ WOLF_STACK_OF(WOLFSSL_X509_OBJECT)* wolfSSL_X509_STORE_get0_objects( obj->data.x509 = x509; x509 = NULL; } + + while(wolfSSL_sk_X509_num(cert_stack) > 0) { + wolfSSL_sk_X509_pop(cert_stack); + } #endif #ifdef HAVE_CRL if (store->cm->crl != NULL) { - WOLFSSL_X509_OBJECT* obj = wolfSSL_X509_OBJECT_new(); + obj = wolfSSL_X509_OBJECT_new(); if (obj == NULL) { WOLFSSL_MSG("wolfSSL_X509_OBJECT_new error"); goto err_cleanup; @@ -1370,11 +1797,14 @@ WOLF_STACK_OF(WOLFSSL_X509_OBJECT)* wolfSSL_X509_STORE_get0_objects( return ret; err_cleanup: if (ret != NULL) - wolfSSL_sk_X509_OBJECT_pop_free(ret, NULL); - if (cert_stack != NULL) + X509StoreFreeObjList(store, ret); + if (cert_stack != NULL) { + while(store->numAdded > 0) { + wolfSSL_sk_X509_pop(cert_stack); + store->numAdded--; + } wolfSSL_sk_X509_pop_free(cert_stack, NULL); - if (x509 != NULL) - wolfSSL_X509_free(x509); + } return NULL; } #endif /* OPENSSL_ALL */ @@ -1400,9 +1830,9 @@ int wolfSSL_X509_STORE_set1_param(WOLFSSL_X509_STORE *ctx, #endif #endif -/******************************************************************************* +/****************************************************************************** * END OF X509_STORE APIs - ******************************************************************************/ + *****************************************************************************/ #endif /* NO_CERTS */ diff --git a/tests/api.c b/tests/api.c index 7481e24b43..c15e431b1e 100644 --- a/tests/api.c +++ b/tests/api.c @@ -225,6 +225,7 @@ #include #include #include + #include #ifdef OPENSSL_ALL #include #include @@ -59555,8 +59556,12 @@ static int test_wolfSSL_X509_LOOKUP_ctrl_file(void) ExpectNull(X509_STORE_CTX_get0_current_issuer(NULL)); issuer = X509_STORE_CTX_get0_current_issuer(ctx); - ExpectNotNull(issuer); + ExpectNull(issuer); + + ExpectIntEQ(X509_verify_cert(ctx), 1); + issuer = X509_STORE_CTX_get0_current_issuer(ctx); + ExpectNotNull(issuer); caName = X509_get_subject_name(x509Ca); ExpectNotNull(caName); issuerName = X509_get_subject_name(issuer); @@ -59565,7 +59570,6 @@ static int test_wolfSSL_X509_LOOKUP_ctrl_file(void) ExpectIntEQ(cmp, 0); /* load der format */ - X509_free(issuer); issuer = NULL; X509_STORE_CTX_free(ctx); ctx = NULL; @@ -59643,7 +59647,7 @@ static int test_wolfSSL_X509_STORE_CTX_trusted_stack_cleanup(void) return res; } -static int test_wolfSSL_X509_STORE_CTX_get0_current_issuer(void) +static int test_wolfSSL_X509_STORE_CTX_get_issuer(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_RSA) @@ -59665,16 +59669,23 @@ static int test_wolfSSL_X509_STORE_CTX_get0_current_issuer(void) ExpectIntEQ(X509_STORE_CTX_init(ctx, str, x509Svr, NULL), SSL_SUCCESS); + /* Issuer0 is not set until chain is built for verification */ ExpectNull(X509_STORE_CTX_get0_current_issuer(NULL)); - ExpectNotNull(issuer = X509_STORE_CTX_get0_current_issuer(ctx)); + ExpectNull(issuer = X509_STORE_CTX_get0_current_issuer(ctx)); + /* Issuer1 will use the store to make a new issuer */ + ExpectIntEQ(X509_STORE_CTX_get1_issuer(&issuer, ctx, x509Svr), 1); + ExpectNotNull(issuer); + X509_free(issuer); + + ExpectIntEQ(X509_verify_cert(ctx), 1); + ExpectNotNull(issuer = X509_STORE_CTX_get0_current_issuer(ctx)); ExpectNotNull(caName = X509_get_subject_name(x509Ca)); ExpectNotNull(issuerName = X509_get_subject_name(issuer)); #ifdef WOLFSSL_SIGNER_DER_CERT ExpectIntEQ(X509_NAME_cmp(caName, issuerName), 0); #endif - X509_free(issuer); X509_STORE_CTX_free(ctx); X509_free(x509Svr); X509_STORE_free(str); @@ -59821,11 +59832,9 @@ static int test_wolfSSL_X509_STORE_CTX(void) ExpectNotNull((ctx = X509_STORE_CTX_new())); ExpectIntEQ(X509_STORE_CTX_init(ctx, str, x5092, sk), 1); ExpectNull((sk2 = X509_STORE_CTX_get_chain(NULL))); - ExpectNotNull((sk2 = X509_STORE_CTX_get_chain(ctx))); - ExpectIntEQ(sk_num(sk2), 1); /* sanity, make sure chain has 1 cert */ + ExpectNull((sk2 = X509_STORE_CTX_get_chain(ctx))); ExpectNull((sk3 = X509_STORE_CTX_get1_chain(NULL))); - ExpectNotNull((sk3 = X509_STORE_CTX_get1_chain(ctx))); - ExpectIntEQ(sk_num(sk3), 1); /* sanity, make sure chain has 1 cert */ + ExpectNull((sk3 = X509_STORE_CTX_get1_chain(ctx))); X509_STORE_CTX_free(ctx); ctx = NULL; X509_STORE_free(str); @@ -59892,6 +59901,424 @@ static int test_wolfSSL_X509_STORE_CTX(void) return EXPECT_RESULT(); } +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) + +typedef struct { + const char *caFile; + const char *caIntFile; + const char *caInt2File; + const char *leafFile; + X509 *x509Ca; + X509 *x509CaInt; + X509 *x509CaInt2; + X509 *x509Leaf; + STACK_OF(X509)* expectedChain; +} X509_STORE_test_data; + +static X509 * test_wolfSSL_X509_STORE_CTX_ex_helper(const char *file) +{ + XFILE fp = XBADFILE; + X509 *x = NULL; + + fp = XFOPEN(file, "rb"); + if (fp == NULL) { + return NULL; + } + x = PEM_read_X509(fp, 0, 0, 0); + XFCLOSE(fp); + + return x; +} + +static int test_wolfSSL_X509_STORE_CTX_ex1(X509_STORE_test_data *testData) +{ + EXPECT_DECLS; + X509_STORE* store = NULL; + X509_STORE_CTX* ctx = NULL; + STACK_OF(X509)* chain = NULL; + int i = 0; + + /* Test case 1, add X509 certs to store and verify */ + ExpectNotNull(store = X509_STORE_new()); + ExpectIntEQ(X509_STORE_add_cert(store, testData->x509Ca), 1); + ExpectIntEQ(X509_STORE_add_cert(store, testData->x509CaInt), 1); + ExpectIntEQ(X509_STORE_add_cert(store, testData->x509CaInt2), 1); + ExpectNotNull(ctx = X509_STORE_CTX_new()); + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, testData->x509Leaf, NULL), 1); + ExpectIntEQ(X509_verify_cert(ctx), 1); + ExpectNotNull(chain = X509_STORE_CTX_get_chain(ctx)); + ExpectIntEQ(sk_X509_num(chain), sk_X509_num(testData->expectedChain)); + for (i = 0; i < sk_X509_num(chain); i++) { + ExpectIntEQ(X509_cmp(sk_X509_value(chain, i), + sk_X509_value(testData->expectedChain, i)), 0); + } + X509_STORE_CTX_free(ctx); + X509_STORE_free(store); + return EXPECT_RESULT(); +} + +static int test_wolfSSL_X509_STORE_CTX_ex2(X509_STORE_test_data *testData) +{ + EXPECT_DECLS; + X509_STORE* store = NULL; + X509_STORE_CTX* ctx = NULL; + STACK_OF(X509)* chain = NULL; + int i = 0; + + /* Test case 2, add certs by filename to store and verify */ + ExpectNotNull(store = X509_STORE_new()); + ExpectIntEQ(X509_STORE_load_locations( + store, testData->caFile, NULL), 1); + ExpectIntEQ(X509_STORE_load_locations( + store, testData->caIntFile, NULL), 1); + ExpectIntEQ(X509_STORE_load_locations( + store, testData->caInt2File, NULL), 1); + ExpectNotNull(ctx = X509_STORE_CTX_new()); + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, testData->x509Leaf, NULL), 1); + ExpectIntEQ(X509_verify_cert(ctx), 1); + ExpectNotNull(chain = X509_STORE_CTX_get_chain(ctx)); + ExpectIntEQ(sk_X509_num(chain), sk_X509_num(testData->expectedChain)); + for (i = 0; i < sk_X509_num(chain); i++) { + ExpectIntEQ(X509_cmp(sk_X509_value(chain, i), + sk_X509_value(testData->expectedChain, i)), 0); + } + X509_STORE_CTX_free(ctx); + X509_STORE_free(store); + return EXPECT_RESULT(); +} + +static int test_wolfSSL_X509_STORE_CTX_ex3(X509_STORE_test_data *testData) +{ + EXPECT_DECLS; + X509_STORE* store = NULL; + X509_STORE_CTX* ctx = NULL; + STACK_OF(X509)* chain = NULL; + int i = 0; + + /* Test case 3, mix and match X509 with files */ + ExpectNotNull(store = X509_STORE_new()); + ExpectIntEQ(X509_STORE_add_cert(store, testData->x509CaInt), 1); + ExpectIntEQ(X509_STORE_add_cert(store, testData->x509CaInt2), 1); + ExpectIntEQ(X509_STORE_load_locations( + store, testData->caFile, NULL), 1); + ExpectNotNull(ctx = X509_STORE_CTX_new()); + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, testData->x509Leaf, NULL), 1); + ExpectIntEQ(X509_verify_cert(ctx), 1); + ExpectNotNull(chain = X509_STORE_CTX_get_chain(ctx)); + ExpectIntEQ(sk_X509_num(chain), sk_X509_num(testData->expectedChain)); + for (i = 0; i < sk_X509_num(chain); i++) { + ExpectIntEQ(X509_cmp(sk_X509_value(chain, i), + sk_X509_value(testData->expectedChain, i)), 0); + } + X509_STORE_CTX_free(ctx); + X509_STORE_free(store); + return EXPECT_RESULT(); +} + +static int test_wolfSSL_X509_STORE_CTX_ex4(X509_STORE_test_data *testData) +{ + EXPECT_DECLS; + X509_STORE* store = NULL; + X509_STORE_CTX* ctx = NULL; + STACK_OF(X509)* chain = NULL; + STACK_OF(X509)* inter = NULL; + int i = 0; + + /* Test case 4, CA loaded by file, intermediates passed on init */ + ExpectNotNull(store = X509_STORE_new()); + ExpectIntEQ(X509_STORE_load_locations( + store, testData->caFile, NULL), 1); + ExpectNotNull(inter = sk_X509_new_null()); + ExpectIntGE(sk_X509_push(inter, testData->x509CaInt), 1); + ExpectIntGE(sk_X509_push(inter, testData->x509CaInt2), 1); + ExpectNotNull(ctx = X509_STORE_CTX_new()); + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, testData->x509Leaf, inter), 1); + ExpectIntEQ(X509_verify_cert(ctx), 1); + ExpectNotNull(chain = X509_STORE_CTX_get_chain(ctx)); + ExpectIntEQ(sk_X509_num(chain), sk_X509_num(testData->expectedChain)); + for (i = 0; i < sk_X509_num(chain); i++) { + ExpectIntEQ(X509_cmp(sk_X509_value(chain, i), + sk_X509_value(testData->expectedChain, i)), 0); + } + X509_STORE_CTX_free(ctx); + X509_STORE_free(store); + sk_X509_free(inter); + return EXPECT_RESULT(); +} + +static int test_wolfSSL_X509_STORE_CTX_ex5(X509_STORE_test_data *testData) +{ + EXPECT_DECLS; + X509_STORE* store = NULL; + X509_STORE_CTX* ctx = NULL; + STACK_OF(X509)* chain = NULL; + STACK_OF(X509)* trusted = NULL; + int i = 0; + + /* Test case 5, manually set trusted stack */ + ExpectNotNull(store = X509_STORE_new()); + ExpectNotNull(trusted = sk_X509_new_null()); + ExpectIntGE(sk_X509_push(trusted, testData->x509Ca), 1); + ExpectIntGE(sk_X509_push(trusted, testData->x509CaInt), 1); + ExpectIntGE(sk_X509_push(trusted, testData->x509CaInt2), 1); + ExpectNotNull(ctx = X509_STORE_CTX_new()); + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, testData->x509Leaf, NULL), 1); + X509_STORE_CTX_trusted_stack(ctx, trusted); + ExpectIntEQ(X509_verify_cert(ctx), 1); + ExpectNotNull(chain = X509_STORE_CTX_get_chain(ctx)); + ExpectIntEQ(sk_X509_num(chain), sk_X509_num(testData->expectedChain)); + for (i = 0; i < sk_X509_num(chain); i++) { + ExpectIntEQ(X509_cmp(sk_X509_value(chain, i), + sk_X509_value(testData->expectedChain, i)), 0); + } + X509_STORE_CTX_free(ctx); + X509_STORE_free(store); + sk_X509_free(trusted); + return EXPECT_RESULT(); +} + +static int test_wolfSSL_X509_STORE_CTX_ex6(X509_STORE_test_data *testData) +{ + EXPECT_DECLS; + X509_STORE* store = NULL; + X509_STORE_CTX* ctx = NULL; + STACK_OF(X509)* chain = NULL; + STACK_OF(X509)* trusted = NULL; + STACK_OF(X509)* inter = NULL; + int i = 0; + + /* Test case 6, manually set trusted stack will be unified with + * any intermediates provided on init */ + ExpectNotNull(store = X509_STORE_new()); + ExpectNotNull(trusted = sk_X509_new_null()); + ExpectNotNull(inter = sk_X509_new_null()); + ExpectIntGE(sk_X509_push(trusted, testData->x509Ca), 1); + ExpectIntGE(sk_X509_push(inter, testData->x509CaInt), 1); + ExpectIntGE(sk_X509_push(inter, testData->x509CaInt2), 1); + ExpectNotNull(ctx = X509_STORE_CTX_new()); + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, testData->x509Leaf, inter), 1); + X509_STORE_CTX_trusted_stack(ctx, trusted); + ExpectIntEQ(X509_verify_cert(ctx), 1); + ExpectNotNull(chain = X509_STORE_CTX_get_chain(ctx)); + ExpectIntEQ(sk_X509_num(chain), sk_X509_num(testData->expectedChain)); + for (i = 0; i < sk_X509_num(chain); i++) { + ExpectIntEQ(X509_cmp(sk_X509_value(chain, i), + sk_X509_value(testData->expectedChain, i)), 0); + } + X509_STORE_CTX_free(ctx); + X509_STORE_free(store); + sk_X509_free(trusted); + sk_X509_free(inter); + return EXPECT_RESULT(); +} + +static int test_wolfSSL_X509_STORE_CTX_ex7(X509_STORE_test_data *testData) +{ + EXPECT_DECLS; + X509_STORE* store = NULL; + X509_STORE_CTX* ctx = NULL; + STACK_OF(X509)* chain = NULL; + int i = 0; + + /* Test case 7, certs added to store after ctx init are still used */ + ExpectNotNull(store = X509_STORE_new()); + ExpectNotNull(ctx = X509_STORE_CTX_new()); + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, testData->x509Leaf, NULL), 1); + ExpectIntNE(X509_verify_cert(ctx), 1); + ExpectIntEQ(X509_STORE_add_cert(store, testData->x509CaInt2), 1); + ExpectIntEQ(X509_STORE_add_cert(store, testData->x509CaInt), 1); + ExpectIntEQ(X509_STORE_add_cert(store, testData->x509Ca), 1); + ExpectIntEQ(X509_verify_cert(ctx), 1); + ExpectNotNull(chain = X509_STORE_CTX_get_chain(ctx)); + ExpectIntEQ(sk_X509_num(chain), sk_X509_num(testData->expectedChain)); + for (i = 0; i < sk_X509_num(chain); i++) { + ExpectIntEQ(X509_cmp(sk_X509_value(chain, i), + sk_X509_value(testData->expectedChain, i)), 0); + } + X509_STORE_CTX_free(ctx); + X509_STORE_free(store); + return EXPECT_RESULT(); +} + +static int test_wolfSSL_X509_STORE_CTX_ex8(X509_STORE_test_data *testData) +{ + EXPECT_DECLS; + X509_STORE* store = NULL; + X509_STORE_CTX* ctx = NULL; + STACK_OF(X509)* chain = NULL; + int i = 0; + + /* Test case 8, Only full chain verifies */ + ExpectNotNull(store = X509_STORE_new()); + ExpectNotNull(ctx = X509_STORE_CTX_new()); + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, testData->x509Leaf, NULL), 1); + ExpectIntNE(X509_verify_cert(ctx), 1); + ExpectIntEQ(X509_STORE_add_cert(store, testData->x509CaInt2), 1); + ExpectIntNE(X509_verify_cert(ctx), 1); + ExpectIntEQ(X509_STORE_add_cert(store, testData->x509CaInt), 1); + ExpectIntNE(X509_verify_cert(ctx), 1); + ExpectIntEQ(X509_STORE_add_cert(store, testData->x509Ca), 1); + ExpectIntEQ(X509_verify_cert(ctx), 1); + ExpectNotNull(chain = X509_STORE_CTX_get_chain(ctx)); + ExpectIntEQ(sk_X509_num(chain), sk_X509_num(testData->expectedChain)); + for (i = 0; i < sk_X509_num(chain); i++) { + ExpectIntEQ(X509_cmp(sk_X509_value(chain, i), + sk_X509_value(testData->expectedChain, i)), 0); + } + X509_STORE_CTX_free(ctx); + X509_STORE_free(store); + return EXPECT_RESULT(); +} + +static int test_wolfSSL_X509_STORE_CTX_ex9(X509_STORE_test_data *testData) +{ + EXPECT_DECLS; + X509_STORE* store = NULL; + X509_STORE_CTX* ctx = NULL; + X509_STORE_CTX* ctx2 = NULL; + STACK_OF(X509)* trusted = NULL; + + /* Test case 9, certs added to store should not be reflected in ctx that + * has been manually set with a trusted stack, but are reflected in ctx + * that has not set trusted stack */ + ExpectNotNull(store = X509_STORE_new()); + ExpectNotNull(ctx = X509_STORE_CTX_new()); + ExpectNotNull(ctx2 = X509_STORE_CTX_new()); + ExpectNotNull(trusted = sk_X509_new_null()); + ExpectIntGE(sk_X509_push(trusted, testData->x509Ca), 1); + ExpectIntGE(sk_X509_push(trusted, testData->x509CaInt), 1); + ExpectIntGE(sk_X509_push(trusted, testData->x509CaInt2), 1); + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, testData->x509Leaf, NULL), 1); + ExpectIntEQ(X509_STORE_CTX_init(ctx2, store, testData->x509Leaf, NULL), 1); + ExpectIntNE(X509_verify_cert(ctx), 1); + ExpectIntNE(X509_verify_cert(ctx2), 1); + X509_STORE_CTX_trusted_stack(ctx, trusted); + /* CTX1 should now verify */ + ExpectIntEQ(X509_verify_cert(ctx), 1); + ExpectIntNE(X509_verify_cert(ctx2), 1); + ExpectIntEQ(X509_STORE_add_cert(store, testData->x509Ca), 1); + ExpectIntEQ(X509_STORE_add_cert(store, testData->x509CaInt), 1); + ExpectIntEQ(X509_STORE_add_cert(store, testData->x509CaInt2), 1); + /* CTX2 should now verify */ + ExpectIntEQ(X509_verify_cert(ctx2), 1); + X509_STORE_CTX_free(ctx); + X509_STORE_CTX_free(ctx2); + X509_STORE_free(store); + sk_X509_free(trusted); + return EXPECT_RESULT(); +} + +static int test_wolfSSL_X509_STORE_CTX_ex10(X509_STORE_test_data *testData) +{ + EXPECT_DECLS; + X509_STORE* store = NULL; + X509_STORE_CTX* ctx = NULL; + STACK_OF(X509)* chain = NULL; + + /* Test case 10, ensure partial chain flag works */ + ExpectNotNull(store = X509_STORE_new()); + ExpectIntEQ(X509_STORE_add_cert(store, testData->x509CaInt), 1); + ExpectIntEQ(X509_STORE_add_cert(store, testData->x509CaInt2), 1); + ExpectNotNull(ctx = X509_STORE_CTX_new()); + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, testData->x509Leaf, NULL), 1); + /* Fails because chain is incomplete */ + ExpectIntNE(X509_verify_cert(ctx), 1); + ExpectIntEQ(X509_STORE_set_flags(store, X509_V_FLAG_PARTIAL_CHAIN), 1); + /* Partial chain now OK */ + ExpectIntEQ(X509_verify_cert(ctx), 1); + ExpectNotNull(chain = X509_STORE_CTX_get_chain(ctx)); + X509_STORE_CTX_free(ctx); + X509_STORE_free(store); + return EXPECT_RESULT(); +} + +static int test_wolfSSL_X509_STORE_CTX_ex11(X509_STORE_test_data *testData) +{ + EXPECT_DECLS; + X509_STORE* store = NULL; + X509_STORE_CTX* ctx = NULL; + STACK_OF(X509)* chain = NULL; + + /* Test case 11, test partial chain flag on ctx itself */ + ExpectNotNull(store = X509_STORE_new()); + ExpectIntEQ(X509_STORE_add_cert(store, testData->x509CaInt), 1); + ExpectIntEQ(X509_STORE_add_cert(store, testData->x509CaInt2), 1); + ExpectNotNull(ctx = X509_STORE_CTX_new()); + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, testData->x509Leaf, NULL), 1); + /* Fails because chain is incomplete */ + ExpectIntNE(X509_verify_cert(ctx), 1); + X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_PARTIAL_CHAIN); + /* Partial chain now OK */ + ExpectIntEQ(X509_verify_cert(ctx), 1); + ExpectNotNull(chain = X509_STORE_CTX_get_chain(ctx)); + X509_STORE_CTX_free(ctx); + X509_STORE_free(store); + return EXPECT_RESULT(); +} +#endif + +static int test_wolfSSL_X509_STORE_CTX_ex(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) + X509_STORE_test_data testData; + XMEMSET((void *)&testData, 0, sizeof(X509_STORE_test_data)); + testData.caFile = "./certs/ca-cert.pem"; + testData.caIntFile = "./certs/intermediate/ca-int-cert.pem"; + testData.caInt2File = "./certs/intermediate/ca-int2-cert.pem"; + testData.leafFile = "./certs/intermediate/server-chain.pem"; + + ExpectNotNull(testData.x509Ca = \ + test_wolfSSL_X509_STORE_CTX_ex_helper(testData.caFile)); + ExpectNotNull(testData.x509CaInt = \ + test_wolfSSL_X509_STORE_CTX_ex_helper(testData.caIntFile)); + ExpectNotNull(testData.x509CaInt2 = \ + test_wolfSSL_X509_STORE_CTX_ex_helper(testData.caInt2File)); + ExpectNotNull(testData.x509Leaf = \ + test_wolfSSL_X509_STORE_CTX_ex_helper(testData.leafFile)); + ExpectNotNull(testData.expectedChain = sk_X509_new_null()); + ExpectIntGE(sk_X509_push(testData.expectedChain, testData.x509Leaf), 1); + ExpectIntGE(sk_X509_push(testData.expectedChain, testData.x509CaInt2), 1); + ExpectIntGE(sk_X509_push(testData.expectedChain, testData.x509CaInt), 1); + ExpectIntGE(sk_X509_push(testData.expectedChain, testData.x509Ca), 1); + + ExpectIntEQ(test_wolfSSL_X509_STORE_CTX_ex1(&testData), 1); + ExpectIntEQ(test_wolfSSL_X509_STORE_CTX_ex2(&testData), 1); + ExpectIntEQ(test_wolfSSL_X509_STORE_CTX_ex3(&testData), 1); + ExpectIntEQ(test_wolfSSL_X509_STORE_CTX_ex4(&testData), 1); + ExpectIntEQ(test_wolfSSL_X509_STORE_CTX_ex5(&testData), 1); + ExpectIntEQ(test_wolfSSL_X509_STORE_CTX_ex6(&testData), 1); + ExpectIntEQ(test_wolfSSL_X509_STORE_CTX_ex7(&testData), 1); + ExpectIntEQ(test_wolfSSL_X509_STORE_CTX_ex8(&testData), 1); + ExpectIntEQ(test_wolfSSL_X509_STORE_CTX_ex9(&testData), 1); + ExpectIntEQ(test_wolfSSL_X509_STORE_CTX_ex10(&testData), 1); + ExpectIntEQ(test_wolfSSL_X509_STORE_CTX_ex11(&testData), 1); + + if(testData.x509Ca) { + X509_free(testData.x509Ca); + } + if(testData.x509CaInt) { + X509_free(testData.x509CaInt); + } + if(testData.x509CaInt2) { + X509_free(testData.x509CaInt2); + } + if(testData.x509Leaf) { + X509_free(testData.x509Leaf); + } + if (testData.expectedChain) { + sk_X509_free(testData.expectedChain); + } + +#endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + * !defined(NO_FILESYSTEM) && !defined(NO_RSA) */ + + return EXPECT_RESULT(); +} + + #if defined(OPENSSL_EXTRA) && !defined(NO_RSA) static int test_X509_STORE_untrusted_load_cert_to_stack(const char* filename, STACK_OF(X509)* chain) @@ -59994,9 +60421,15 @@ static int test_X509_STORE_untrusted(void) /* Succeeds because path to loaded CA is available. */ ExpectIntEQ(test_X509_STORE_untrusted_certs(untrusted2, 1, 0, 1), TEST_SUCCESS); - /* Fails because root CA is in the untrusted stack */ + /* Root CA in untrusted chain is OK so long as CA has been loaded + * properly */ + ExpectIntEQ(test_X509_STORE_untrusted_certs(untrusted3, 1, 0, 1), + TEST_SUCCESS); + /* Still needs properly loaded CA, while including it in untrusted + * list is not an error, it also doesnt count for verify */ ExpectIntEQ(test_X509_STORE_untrusted_certs(untrusted3, 0, - X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, 0), TEST_SUCCESS); + X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, 0), + TEST_SUCCESS); /* Succeeds because path to loaded CA is available. */ ExpectIntEQ(test_X509_STORE_untrusted_certs(untrusted4, 1, 0, 1), TEST_SUCCESS); @@ -80147,7 +80580,7 @@ static int test_wolfSSL_X509_load_crl_file(void) #ifdef WC_RSA_PSS ExpectIntEQ(wolfSSL_CertManagerVerify(store->cm, "certs/rsapss/server-rsapss-cert.pem", WOLFSSL_FILETYPE_PEM), - WC_NO_ERR_TRACE(CRL_CERT_REVOKED)); + WC_NO_ERR_TRACE(ASN_NO_SIGNER_E)); #endif } /* once feeing store */ @@ -97559,9 +97992,10 @@ TEST_CASE testCases[] = { TEST_DECL(test_wolfSSL_TBS), TEST_DECL(test_wolfSSL_X509_STORE_CTX), + TEST_DECL(test_wolfSSL_X509_STORE_CTX_ex), TEST_DECL(test_X509_STORE_untrusted), TEST_DECL(test_wolfSSL_X509_STORE_CTX_trusted_stack_cleanup), - TEST_DECL(test_wolfSSL_X509_STORE_CTX_get0_current_issuer), + TEST_DECL(test_wolfSSL_X509_STORE_CTX_get_issuer), TEST_DECL(test_wolfSSL_X509_STORE_set_flags), TEST_DECL(test_wolfSSL_X509_LOOKUP_load_file), TEST_DECL(test_wolfSSL_X509_Name_canon), diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 1a6c97d8fb..c62ef351c9 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -2756,6 +2756,8 @@ WOLFSSL_LOCAL int SetupStoreCtxCallback(WOLFSSL_X509_STORE_CTX** store_pt, WOLFSSL_LOCAL void CleanupStoreCtxCallback(WOLFSSL_X509_STORE_CTX* store, WOLFSSL* ssl, void* heap, int x509Free); #endif /* !defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH) */ +WOLFSSL_LOCAL int X509StoreLoadCertBuffer(WOLFSSL_X509_STORE *str, + byte *buf, word32 bufLen, int type); #endif /* !defined NO_CERTS */ /* wolfSSL Sock Addr */ diff --git a/wolfssl/openssl/ssl.h b/wolfssl/openssl/ssl.h index a08a96db0f..f6d29f0b75 100644 --- a/wolfssl/openssl/ssl.h +++ b/wolfssl/openssl/ssl.h @@ -643,8 +643,8 @@ typedef WOLFSSL_X509_NAME_ENTRY X509_NAME_ENTRY; #define X509_V_FLAG_CRL_CHECK WOLFSSL_CRL_CHECK #define X509_V_FLAG_CRL_CHECK_ALL WOLFSSL_CRL_CHECKALL -#define X509_V_FLAG_PARTIAL_CHAIN 0 -#define X509_V_FLAG_TRUSTED_FIRST 0 +#define X509_V_FLAG_PARTIAL_CHAIN WOLFSSL_PARTIAL_CHAIN +#define X509_V_FLAG_TRUSTED_FIRST 0 /* dummy value needed for gRPC port */ #define X509_V_FLAG_USE_CHECK_TIME WOLFSSL_USE_CHECK_TIME #define X509_V_FLAG_NO_CHECK_TIME WOLFSSL_NO_CHECK_TIME diff --git a/wolfssl/openssl/x509_vfy.h b/wolfssl/openssl/x509_vfy.h index 8666a53fee..977e0c00f8 100644 --- a/wolfssl/openssl/x509_vfy.h +++ b/wolfssl/openssl/x509_vfy.h @@ -33,10 +33,13 @@ #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) WOLFSSL_API int wolfSSL_X509_STORE_CTX_set_purpose(WOLFSSL_X509_STORE_CTX *ctx, int purpose); +#endif +#ifdef OPENSSL_EXTRA WOLFSSL_API void wolfSSL_X509_STORE_CTX_set_flags(WOLFSSL_X509_STORE_CTX *ctx, unsigned long flags); #endif + #define X509_STORE_CTX_set_purpose wolfSSL_X509_STORE_CTX_set_purpose #define X509_STORE_CTX_set_flags wolfSSL_X509_STORE_CTX_set_flags diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 13abb0bb30..4bbdf6565c 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -600,6 +600,10 @@ struct WOLFSSL_X509_STORE { WOLFSSL_X509_CRL *crl; /* points to cm->crl */ #endif wolfSSL_Ref ref; + WOLF_STACK_OF(WOLFSSL_X509)* certs; + WOLF_STACK_OF(WOLFSSL_X509)* trusted; + WOLF_STACK_OF(WOLFSSL_X509)* owned; + word32 numAdded; /* Number of objs in objs that are in certs sk */ }; #define WOLFSSL_ALWAYS_CHECK_SUBJECT 0x1 @@ -612,6 +616,7 @@ struct WOLFSSL_X509_STORE { #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) #define WOLFSSL_USE_CHECK_TIME 0x2 #define WOLFSSL_NO_CHECK_TIME 0x200000 +#define WOLFSSL_PARTIAL_CHAIN 0x80000 #define WOLFSSL_HOST_NAME_MAX 256 #define WOLFSSL_VPARAM_DEFAULT 0x1 @@ -674,7 +679,7 @@ typedef struct WOLFSSL_BUFFER_INFO { struct WOLFSSL_X509_STORE_CTX { WOLFSSL_X509_STORE* store; /* Store full of a CA cert chain */ WOLFSSL_X509* current_cert; /* current X509 (OPENSSL_EXTRA) */ -#ifdef WOLFSSL_ASIO +#if defined(WOLFSSL_ASIO) || defined(OPENSSL_EXTRA) WOLFSSL_X509* current_issuer; /* asio dereference */ #endif WOLFSSL_X509_CHAIN* sesChain; /* pointer to WOLFSSL_SESSION peer chain */ @@ -697,6 +702,13 @@ struct WOLFSSL_X509_STORE_CTX { WOLFSSL_BUFFER_INFO* certs; /* peer certs */ WOLFSSL_X509_STORE_CTX_verify_cb verify_cb; /* verify callback */ void* heap; + int flags; + WOLF_STACK_OF(WOLFSSL_X509)* owned; /* Certs owned by this CTX */ + WOLF_STACK_OF(WOLFSSL_X509)* ctxIntermediates; /* Intermediates specified + * on store ctx init */ + WOLF_STACK_OF(WOLFSSL_X509)* setTrustedSk;/* A trusted stack override + * set with + * X509_STORE_CTX_trusted_stack*/ }; typedef char* WOLFSSL_STRING; @@ -3313,7 +3325,9 @@ enum { WOLFSSL_DTLSV1_3 = 7, WOLFSSL_USER_CA = 1, /* user added as trusted */ - WOLFSSL_CHAIN_CA = 2 /* added to cache from trusted chain */ + WOLFSSL_CHAIN_CA = 2, /* added to cache from trusted chain */ + WOLFSSL_TEMP_CA = 3 /* Temp intermediate CA, only for use by + * X509_STORE */ }; WOLFSSL_ABI WOLFSSL_API WC_RNG* wolfSSL_GetRNG(WOLFSSL* ssl);