/* test_ossl_x509_lu.c * * Copyright (C) 2006-2026 wolfSSL Inc. * * This file is part of wolfSSL. * * wolfSSL is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * wolfSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ #include #ifdef NO_INLINE #include #else #define WOLFSSL_MISC_INCLUDED #include #endif #include #include #include int test_wolfSSL_X509_LOOKUP_load_file(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && defined(HAVE_CRL) && \ !defined(NO_FILESYSTEM) && !defined(NO_RSA) && defined(HAVE_ECC) && \ (!defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH)) WOLFSSL_X509_STORE* store = NULL; WOLFSSL_X509_LOOKUP* lookup = NULL; ExpectNotNull(store = wolfSSL_X509_STORE_new()); ExpectNotNull(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file())); /* One RSA and one ECC certificate in file. */ ExpectIntEQ(wolfSSL_X509_LOOKUP_load_file(lookup, "certs/client-ca.pem", X509_FILETYPE_PEM), 1); ExpectIntEQ(wolfSSL_X509_LOOKUP_load_file(lookup, "certs/crl/crl2.pem", X509_FILETYPE_PEM), 1); if (store != NULL) { ExpectIntEQ(wolfSSL_CertManagerVerify(store->cm, cliCertFile, WOLFSSL_FILETYPE_PEM), 1); ExpectIntEQ(wolfSSL_CertManagerVerify(store->cm, svrCertFile, WOLFSSL_FILETYPE_PEM), WC_NO_ERR_TRACE(ASN_NO_SIGNER_E)); } ExpectIntEQ(wolfSSL_X509_LOOKUP_load_file(lookup, "certs/ca-cert.pem", X509_FILETYPE_PEM), 1); if (store != NULL) { ExpectIntEQ(wolfSSL_CertManagerVerify(store->cm, svrCertFile, WOLFSSL_FILETYPE_PEM), 1); } wolfSSL_X509_STORE_free(store); #endif /* defined(OPENSSL_EXTRA) && defined(HAVE_CRL) && * !defined(NO_FILESYSTEM) && !defined(NO_RSA) */ return EXPECT_RESULT(); } int test_wolfSSL_X509_LOOKUP_ctrl_file(void) { EXPECT_DECLS; #if defined(OPENSSL_ALL) && !defined(NO_CERTS) && \ !defined(NO_FILESYSTEM) && !defined(NO_RSA) && \ defined(WOLFSSL_SIGNER_DER_CERT) X509_STORE_CTX* ctx = NULL; X509_STORE* str = NULL; X509_LOOKUP* lookup = NULL; X509* cert1 = NULL; X509* x509Ca = NULL; X509* x509Svr = NULL; X509* issuer = NULL; WOLFSSL_STACK* sk = NULL; X509_NAME* caName = NULL; X509_NAME* issuerName = NULL; XFILE file1 = XBADFILE; int i; int cert_count = 0; int cmp; char der[] = "certs/ca-cert.der"; #ifdef HAVE_CRL char pem[][100] = { "./certs/crl/crl.pem", "./certs/crl/crl2.pem", "./certs/crl/caEccCrl.pem", "./certs/crl/eccCliCRL.pem", "./certs/crl/eccSrvCRL.pem", "" }; #endif ExpectTrue((file1 = XFOPEN("./certs/ca-cert.pem", "rb")) != XBADFILE); ExpectNotNull(cert1 = wolfSSL_PEM_read_X509(file1, NULL, NULL, NULL)); if (file1 != XBADFILE) XFCLOSE(file1); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectNotNull((str = wolfSSL_X509_STORE_new())); ExpectNotNull(lookup = X509_STORE_add_lookup(str, X509_LOOKUP_file())); ExpectIntEQ(wolfSSL_X509_load_cert_crl_file(NULL, NULL, WOLFSSL_FILETYPE_PEM), 0); ExpectIntEQ(wolfSSL_X509_load_cert_crl_file(lookup, NULL, WOLFSSL_FILETYPE_PEM), 0); ExpectIntEQ(wolfSSL_X509_load_cert_crl_file(NULL, caCertFile, WOLFSSL_FILETYPE_PEM), 0); ExpectIntEQ(wolfSSL_X509_load_cert_crl_file(NULL, der , WOLFSSL_FILETYPE_PEM), 0); ExpectIntEQ(X509_LOOKUP_ctrl(lookup, X509_L_FILE_LOAD, caCertFile, SSL_FILETYPE_PEM,NULL), 1); ExpectNotNull(sk = wolfSSL_CertManagerGetCerts(str->cm)); ExpectIntEQ((cert_count = sk_X509_num(sk)), 1); /* check if CA cert is loaded into the store */ for (i = 0; i < cert_count; i++) { x509Ca = sk_X509_value(sk, i); ExpectIntEQ(0, wolfSSL_X509_cmp(x509Ca, cert1)); } ExpectNotNull((x509Svr = wolfSSL_X509_load_certificate_file(svrCertFile, SSL_FILETYPE_PEM))); ExpectIntEQ(X509_STORE_CTX_init(ctx, str, x509Svr, NULL), SSL_SUCCESS); ExpectNull(X509_STORE_CTX_get0_current_issuer(NULL)); issuer = X509_STORE_CTX_get0_current_issuer(ctx); 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); ExpectNotNull(issuerName); cmp = X509_NAME_cmp(caName, issuerName); ExpectIntEQ(cmp, 0); /* load der format */ issuer = NULL; X509_STORE_CTX_free(ctx); ctx = NULL; X509_STORE_free(str); str = NULL; sk_X509_pop_free(sk, NULL); sk = NULL; X509_free(x509Svr); x509Svr = NULL; ExpectNotNull((str = wolfSSL_X509_STORE_new())); ExpectNotNull(lookup = X509_STORE_add_lookup(str, X509_LOOKUP_file())); ExpectIntEQ(X509_LOOKUP_ctrl(lookup, X509_L_FILE_LOAD, der, SSL_FILETYPE_ASN1,NULL), 1); ExpectNotNull(sk = wolfSSL_CertManagerGetCerts(str->cm)); ExpectIntEQ((cert_count = sk_X509_num(sk)), 1); /* check if CA cert is loaded into the store */ for (i = 0; i < cert_count; i++) { x509Ca = sk_X509_value(sk, i); ExpectIntEQ(0, wolfSSL_X509_cmp(x509Ca, cert1)); } X509_STORE_free(str); str = NULL; sk_X509_pop_free(sk, NULL); sk = NULL; X509_free(cert1); cert1 = NULL; #ifdef HAVE_CRL ExpectNotNull(str = wolfSSL_X509_STORE_new()); ExpectNotNull(lookup = X509_STORE_add_lookup(str, X509_LOOKUP_file())); ExpectIntEQ(X509_LOOKUP_ctrl(lookup, X509_L_FILE_LOAD, caCertFile, SSL_FILETYPE_PEM,NULL), 1); ExpectIntEQ(X509_LOOKUP_ctrl(lookup, X509_L_FILE_LOAD, "certs/server-revoked-cert.pem", SSL_FILETYPE_PEM,NULL), 1); if (str) { ExpectIntEQ(wolfSSL_CertManagerVerify(str->cm, svrCertFile, WOLFSSL_FILETYPE_PEM), 1); /* since store hasn't yet known the revoked cert*/ ExpectIntEQ(wolfSSL_CertManagerVerify(str->cm, "certs/server-revoked-cert.pem", WOLFSSL_FILETYPE_PEM), 1); } for (i = 0; pem[i][0] != '\0'; i++) { ExpectIntEQ(X509_LOOKUP_ctrl(lookup, X509_L_FILE_LOAD, pem[i], SSL_FILETYPE_PEM, NULL), 1); } if (str) { /* since store knows crl list */ ExpectIntEQ(wolfSSL_CertManagerVerify(str->cm, "certs/server-revoked-cert.pem", WOLFSSL_FILETYPE_PEM ), WC_NO_ERR_TRACE(CRL_CERT_REVOKED)); } ExpectIntEQ(X509_LOOKUP_ctrl(NULL, 0, NULL, 0, NULL), 0); X509_STORE_free(str); #endif #endif return EXPECT_RESULT(); } int test_wolfSSL_X509_LOOKUP_ctrl_hash_dir(void) { EXPECT_DECLS; #if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) const int MAX_DIR = 4; const char paths[][32] = { "./certs/ed25519", "./certs/ecc", "./certs/crl", "./certs/", }; char CertCrl_path[MAX_FILENAME_SZ]; char *p; X509_STORE* str = NULL; X509_LOOKUP* lookup = NULL; WOLFSSL_STACK* sk = NULL; int len, total_len, i; (void)sk; XMEMSET(CertCrl_path, 0, MAX_FILENAME_SZ); /* illegal string */ ExpectNotNull((str = wolfSSL_X509_STORE_new())); ExpectNotNull(lookup = X509_STORE_add_lookup(str, X509_LOOKUP_file())); ExpectIntEQ(X509_LOOKUP_ctrl(lookup, X509_L_ADD_DIR, "", SSL_FILETYPE_PEM, NULL), 0); ExpectIntEQ(X509_LOOKUP_ctrl(lookup, X509_L_ADD_STORE, "", SSL_FILETYPE_PEM, NULL), WOLFSSL_NOT_IMPLEMENTED); ExpectIntEQ(X509_LOOKUP_ctrl(lookup, X509_L_LOAD_STORE, "", SSL_FILETYPE_PEM, NULL), WOLFSSL_NOT_IMPLEMENTED); ExpectIntEQ(X509_LOOKUP_ctrl(lookup, 0, "", SSL_FILETYPE_PEM, NULL), WOLFSSL_FAILURE); /* free store */ X509_STORE_free(str); str = NULL; /* short folder string */ ExpectNotNull((str = wolfSSL_X509_STORE_new())); ExpectNotNull(lookup = X509_STORE_add_lookup(str, X509_LOOKUP_file())); ExpectIntEQ(X509_LOOKUP_ctrl(lookup, X509_L_ADD_DIR, "./", SSL_FILETYPE_PEM,NULL), 1); #if defined(WOLFSSL_INT_H) /* only available when including internal.h */ ExpectNotNull(sk = lookup->dirs->dir_entry); #endif /* free store */ X509_STORE_free(str); str = NULL; /* typical function check */ p = &CertCrl_path[0]; total_len = 0; for (i = MAX_DIR - 1; i>=0 && total_len < MAX_FILENAME_SZ; i--) { len = (int)XSTRLEN((const char*)&paths[i]); total_len += len; XSTRNCPY(p, paths[i], MAX_FILENAME_SZ - total_len); p += len; if (i != 0) *(p++) = SEPARATOR_CHAR; } ExpectNotNull((str = wolfSSL_X509_STORE_new())); ExpectNotNull(lookup = X509_STORE_add_lookup(str, X509_LOOKUP_file())); ExpectIntEQ(X509_LOOKUP_ctrl(lookup, X509_L_ADD_DIR, CertCrl_path, SSL_FILETYPE_PEM,NULL), 1); #if defined(WOLFSSL_INT_H) /* only available when including internal.h */ ExpectNotNull(sk = lookup->dirs->dir_entry); #endif X509_STORE_free(str); #endif return EXPECT_RESULT(); } int test_wolfSSL_X509_load_crl_file(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && defined(HAVE_CRL) && !defined(NO_FILESYSTEM) && \ !defined(NO_STDIO_FILESYSTEM) && !defined(NO_RSA) && !defined(NO_BIO) && \ !defined(WOLFSSL_CRL_ALLOW_MISSING_CDP) int i; char pem[][100] = { "./certs/crl/crl.pem", "./certs/crl/crl2.pem", "./certs/crl/caEccCrl.pem", "./certs/crl/eccCliCRL.pem", "./certs/crl/eccSrvCRL.pem", #ifdef WC_RSA_PSS "./certs/crl/crl_rsapss.pem", #endif "" }; int pemCount[] = { 1, 2, 1, 1, 1, #ifdef WC_RSA_PSS 1, #endif 0 }; char der[][100] = { "./certs/crl/crl.der", "./certs/crl/crl2.der", "" }; WOLFSSL_X509_STORE* store = NULL; WOLFSSL_X509_LOOKUP* lookup = NULL; ExpectNotNull(store = wolfSSL_X509_STORE_new()); ExpectNotNull(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file())); ExpectIntEQ(X509_LOOKUP_load_file(lookup, "certs/ca-cert.pem", X509_FILETYPE_PEM), 1); #ifdef WC_RSA_PSS ExpectIntEQ(X509_LOOKUP_load_file(lookup, "certs/rsapss/ca-rsapss.pem", X509_FILETYPE_PEM), 1); #endif ExpectIntEQ(X509_LOOKUP_load_file(lookup, "certs/server-revoked-cert.pem", X509_FILETYPE_PEM), 1); if (store) { ExpectIntEQ(wolfSSL_CertManagerVerify(store->cm, svrCertFile, WOLFSSL_FILETYPE_PEM), 1); /* since store hasn't yet known the revoked cert*/ ExpectIntEQ(wolfSSL_CertManagerVerify(store->cm, "certs/server-revoked-cert.pem", WOLFSSL_FILETYPE_PEM), 1); } ExpectIntEQ(X509_load_crl_file(lookup, pem[0], 0), 0); for (i = 0; pem[i][0] != '\0'; i++) { ExpectIntEQ(X509_load_crl_file(lookup, pem[i], WOLFSSL_FILETYPE_PEM), pemCount[i]); } if (store) { /* since store knows crl list */ ExpectIntEQ(wolfSSL_CertManagerVerify(store->cm, "certs/server-revoked-cert.pem", WOLFSSL_FILETYPE_PEM), WC_NO_ERR_TRACE(CRL_CERT_REVOKED)); #ifdef WC_RSA_PSS ExpectIntEQ(wolfSSL_CertManagerVerify(store->cm, "certs/rsapss/server-rsapss-cert.pem", WOLFSSL_FILETYPE_PEM), WC_NO_ERR_TRACE(ASN_NO_SIGNER_E)); #endif } /* once feeing store */ X509_STORE_free(store); store = NULL; ExpectNotNull(store = wolfSSL_X509_STORE_new()); ExpectNotNull(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file())); ExpectIntEQ(X509_LOOKUP_load_file(lookup, "certs/ca-cert.pem", X509_FILETYPE_PEM), 1); ExpectIntEQ(X509_LOOKUP_load_file(lookup, "certs/server-revoked-cert.pem", X509_FILETYPE_PEM), 1); if (store) { ExpectIntEQ(wolfSSL_CertManagerVerify(store->cm, svrCertFile, WOLFSSL_FILETYPE_PEM), 1); /* since store hasn't yet known the revoked cert*/ ExpectIntEQ(wolfSSL_CertManagerVerify(store->cm, "certs/server-revoked-cert.pem", WOLFSSL_FILETYPE_PEM), 1); } for (i = 0; der[i][0] != '\0'; i++) { ExpectIntEQ(X509_load_crl_file(lookup, der[i], WOLFSSL_FILETYPE_ASN1), 1); } if (store) { /* since store knows crl list */ ExpectIntEQ(wolfSSL_CertManagerVerify(store->cm, "certs/server-revoked-cert.pem", WOLFSSL_FILETYPE_PEM), WC_NO_ERR_TRACE(CRL_CERT_REVOKED)); } /* test for incorrect parameter */ ExpectIntEQ(X509_load_crl_file(NULL, pem[0], 0), 0); ExpectIntEQ(X509_load_crl_file(lookup, NULL, 0), 0); ExpectIntEQ(X509_load_crl_file(NULL, NULL, 0), 0); X509_STORE_free(store); store = NULL; /* Combine crl.pem (1 CRL), a server cert, and crl2.pem (2 CRLs) into a * single memory BIO. wolfSSL_PEM_read_bio_X509_CRL must walk past the * intervening certificate and hand back all three CRLs before NULL, * matching OpenSSL's PEM_read_bio_X509_CRL behaviour. */ { WOLFSSL_BIO* fileBio = NULL; WOLFSSL_BIO* memBio = NULL; WOLFSSL_X509_CRL* crl = NULL; unsigned char buf[4096]; int n; int crlCount = 0; const char* sources[] = { "./certs/crl/crl.pem", "./certs/server-cert.pem", "./certs/crl/crl2.pem", NULL }; ExpectNotNull(memBio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem())); for (i = 0; sources[i] != NULL; i++) { ExpectNotNull(fileBio = wolfSSL_BIO_new_file(sources[i], "rb")); while (fileBio != NULL && (n = wolfSSL_BIO_read(fileBio, buf, sizeof(buf))) > 0) { ExpectIntEQ(wolfSSL_BIO_write(memBio, buf, n), n); } wolfSSL_BIO_free(fileBio); fileBio = NULL; } while ((crl = wolfSSL_PEM_read_bio_X509_CRL(memBio, NULL, NULL, NULL)) != NULL) { crlCount++; wolfSSL_X509_CRL_free(crl); } ExpectIntEQ(crlCount, 3); wolfSSL_BIO_free(memBio); } #endif return EXPECT_RESULT(); } int test_X509_LOOKUP_add_dir(void) { EXPECT_DECLS; #if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \ !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) && \ (defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)) && \ defined(HAVE_CRL) && !defined(NO_RSA) X509_STORE * store = NULL; X509_STORE_CTX * storeCtx = NULL; X509_CRL * crl = NULL; X509 * ca = NULL; X509 * cert = NULL; const char cliCrlPem[] = "./certs/crl/cliCrl.pem"; const char srvCert[] = "./certs/server-cert.pem"; const char caCert[] = "./certs/ca-cert.pem"; const char caDir[] = "./certs/crl/hash_der"; XFILE fp = XBADFILE; X509_LOOKUP * lookup = NULL; ExpectNotNull(store = (X509_STORE *)X509_STORE_new()); /* Set up store with CA */ ExpectNotNull((ca = wolfSSL_X509_load_certificate_file(caCert, SSL_FILETYPE_PEM))); ExpectIntEQ(X509_STORE_add_cert(store, ca), SSL_SUCCESS); /* Add CRL lookup directory to store. * Test uses ./certs/crl/hash_der/0fdb2da4.r0, which is a copy * of crl.der */ ExpectNotNull((lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()))); ExpectIntEQ(X509_LOOKUP_add_dir(lookup, caDir, X509_FILETYPE_ASN1), SSL_SUCCESS); ExpectIntEQ(X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK), SSL_SUCCESS); /* Add CRL to store NOT containing the verified certificate, which * forces use of the CRL lookup directory */ ExpectTrue((fp = XFOPEN(cliCrlPem, "rb")) != XBADFILE); ExpectNotNull(crl = (X509_CRL *)PEM_read_X509_CRL(fp, (X509_CRL **)NULL, NULL, NULL)); if (fp != XBADFILE) { XFCLOSE(fp); fp = XBADFILE; } ExpectIntEQ(X509_STORE_add_crl(store, crl), SSL_SUCCESS); /* Create verification context outside of an SSL session */ ExpectNotNull((storeCtx = X509_STORE_CTX_new())); ExpectNotNull((cert = wolfSSL_X509_load_certificate_file(srvCert, SSL_FILETYPE_PEM))); ExpectIntEQ(X509_STORE_CTX_init(storeCtx, store, cert, NULL), SSL_SUCCESS); /* Perform verification, which should NOT return CRL missing */ ExpectIntNE(X509_verify_cert(storeCtx), WC_NO_ERR_TRACE(CRL_MISSING)); X509_CRL_free(crl); crl = NULL; X509_STORE_free(store); store = NULL; X509_STORE_CTX_free(storeCtx); storeCtx = NULL; X509_free(cert); cert = NULL; X509_free(ca); ca = NULL; /* Now repeat the same, but look for X509_FILETYPE_PEM. * We should get CRL_MISSING at the end, because the lookup * dir has only ASN1 CRLs. */ ExpectNotNull(store = (X509_STORE *)X509_STORE_new()); ExpectNotNull((ca = wolfSSL_X509_load_certificate_file(caCert, SSL_FILETYPE_PEM))); ExpectIntEQ(X509_STORE_add_cert(store, ca), SSL_SUCCESS); ExpectNotNull((lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()))); ExpectIntEQ(X509_LOOKUP_add_dir(lookup, caDir, X509_FILETYPE_PEM), SSL_SUCCESS); ExpectIntEQ(X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK), SSL_SUCCESS); ExpectTrue((fp = XFOPEN(cliCrlPem, "rb")) != XBADFILE); ExpectNotNull(crl = (X509_CRL *)PEM_read_X509_CRL(fp, (X509_CRL **)NULL, NULL, NULL)); if (fp != XBADFILE) { XFCLOSE(fp); fp = XBADFILE; } ExpectIntEQ(X509_STORE_add_crl(store, crl), SSL_SUCCESS); ExpectNotNull((storeCtx = X509_STORE_CTX_new())); ExpectNotNull((cert = wolfSSL_X509_load_certificate_file(srvCert, SSL_FILETYPE_PEM))); ExpectIntEQ(X509_STORE_CTX_init(storeCtx, store, cert, NULL), SSL_SUCCESS); /* Now we SHOULD get CRL_MISSING, because we looked for PEM * in dir containing only ASN1/DER. */ ExpectIntEQ(X509_verify_cert(storeCtx), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(X509_STORE_CTX_get_error(storeCtx), X509_V_ERR_UNABLE_TO_GET_CRL); X509_CRL_free(crl); X509_STORE_free(store); X509_STORE_CTX_free(storeCtx); X509_free(cert); X509_free(ca); #endif return EXPECT_RESULT(); }