/* api.c API unit tests * * 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 */ /* For AES-CBC, input lengths can optionally be validated to be a * multiple of the block size, by defining WOLFSSL_AES_CBC_LENGTH_CHECKS, * also available via the configure option --enable-aescbc-length-checks. */ /*----------------------------------------------------------------------------* | Includes *----------------------------------------------------------------------------*/ #include #include #include #if defined(WOLFSSL_STATIC_MEMORY) #include #endif #ifdef WOLFSSL_ASYNC_CRYPT #include #endif #ifdef HAVE_ECC #include /* wc_ecc_fp_free */ #ifdef WOLFSSL_SM2 #include #endif #endif #ifndef NO_ASN #include #endif #include #if defined(__linux__) || defined(__FreeBSD__) #include #include #endif #include /* compatibility layer */ #include #include #include #include #include #ifdef WOLFSSL_SWDEV #include "swdev/swdev_loader.h" #endif /* for testing compatibility layer callbacks */ #include "examples/server/server.h" #ifndef NO_SIG_WRAPPER #include #endif #ifdef WOLFSSL_SMALL_CERT_VERIFY #include #endif #ifndef NO_DSA #include #endif #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \ defined(OPENSSL_ALL) #include #ifndef NO_ASN /* for ASN_COMMON_NAME DN_tags enum */ #include #endif #ifdef HAVE_OCSP #include #endif #endif #ifdef OPENSSL_EXTRA #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef OPENSSL_ALL #include #include #endif #ifndef NO_AES #include #endif #ifndef NO_DES3 #include #endif #ifndef NO_RC4 #include #endif #ifdef HAVE_ECC #include #endif #ifdef HAVE_CURVE25519 #include #endif #ifdef HAVE_ED25519 #include #endif #ifdef HAVE_CURVE448 #include #endif #ifdef HAVE_ED448 #include #endif #endif /* OPENSSL_EXTRA */ #if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) && \ !defined(NO_SHA256) && !defined(RC_NO_RNG) #include #endif #if (defined(SESSION_CERTS) && defined(TEST_PEER_CERT_CHAIN)) || \ defined(HAVE_SESSION_TICKET) || (defined(OPENSSL_EXTRA) && \ defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CERT_GEN)) || \ defined(WOLFSSL_TEST_STATIC_BUILD) || defined(WOLFSSL_DTLS) || \ defined(HAVE_ECH) || defined(HAVE_EX_DATA) || !defined(NO_SESSION_CACHE) \ || !defined(WOLFSSL_NO_TLS12) || defined(WOLFSSL_TLS13) /* for testing SSL_get_peer_cert_chain, or SESSION_TICKET_HINT_DEFAULT, * for setting authKeyIdSrc in WOLFSSL_X509, or testing DTLS sequence * number tracking */ #include "wolfssl/internal.h" #endif #if defined(WOLFSSL_SNIFFER) && defined(WOLFSSL_SNIFFER_CHAIN_INPUT) #include #include #include #endif #ifdef HAVE_DILITHIUM #include #endif #if defined(WOLFSSL_HAVE_MLKEM) #include #endif #if defined(HAVE_PKCS7) #include #endif #if !defined(NO_BIG_INT) #include #endif /* include misc.c here regardless of NO_INLINE, because misc.c implementations * have default (hidden) visibility, and in the absence of visibility, it's * benign to mask out the library implementation. */ #define WOLFSSL_MISC_INCLUDED #include #include #include /* Gather test declarations to include them in the testCases array */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_TLS) && \ !defined(NO_RSA) && \ !defined(NO_WOLFSSL_SERVER) && !defined(NO_WOLFSSL_CLIENT) && \ !defined(WOLFSSL_TIRTOS) #define HAVE_SSL_MEMIO_TESTS_DEPENDENCIES #endif #if defined(WOLFSSL_STATIC_MEMORY) && !defined(WOLFCRYPT_ONLY) #if (defined(HAVE_ECC) && !defined(ALT_ECC_SIZE)) || \ defined(SESSION_CERTS) || defined(WOLFSSL_HAVE_MLKEM) #ifdef OPENSSL_EXTRA #define TEST_TLS_STATIC_MEMSZ (400000) #else #define TEST_TLS_STATIC_MEMSZ (320000) #endif #else #define TEST_TLS_STATIC_MEMSZ (80000) #endif #endif #ifdef WOLFSSL_DUMP_MEMIO_STREAM const char* currentTestName = NULL; char tmpDirName[16]; int tmpDirNameSet = 0; #endif /*----------------------------------------------------------------------------* | Constants *----------------------------------------------------------------------------*/ #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_TLS) && \ (!defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT)) static const char* bogusFile = #ifdef _WIN32 "NUL" #else "/dev/null" #endif ; #endif /* !NO_FILESYSTEM && !NO_CERTS && (!NO_WOLFSSL_SERVER || !NO_WOLFSSL_CLIENT) */ enum { TESTING_RSA = 1, TESTING_ECC = 2 }; #ifdef WOLFSSL_QNX_CAAM #include int testDevId = WOLFSSL_CAAM_DEVID; #else int testDevId = INVALID_DEVID; #endif #ifdef USE_WINDOWS_API #define MESSAGE_TYPE_CAST char* #else #define MESSAGE_TYPE_CAST void* #endif /*----------------------------------------------------------------------------* | BIO with fixed read/write size *----------------------------------------------------------------------------*/ #if defined(OPENSSL_EXTRA) && !defined(NO_BIO) static int wolfssl_bio_s_fixed_mem_write(WOLFSSL_BIO* bio, const char* data, int len) { if ((bio == NULL) || (bio->ptr.mem_buf_data == NULL) || (data == NULL)) { len = 0; } else { if (bio->wrSz - bio->wrIdx < len) { len = bio->wrSz - bio->wrIdx; } XMEMCPY(bio->ptr.mem_buf_data + bio->wrIdx, data, (size_t)len); bio->wrIdx += len; } return len; } static int wolfssl_bio_s_fixed_mem_read(WOLFSSL_BIO* bio, char* data, int len) { if ((bio == NULL) || (bio->ptr.mem_buf_data == NULL) || (data == NULL)) { len = 0; } else { if (bio->wrSz - bio->rdIdx < len) { len = bio->wrSz - bio->rdIdx; } XMEMCPY(data, bio->ptr.mem_buf_data + bio->rdIdx, (size_t)len); bio->rdIdx += len; } return len; } WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_fixed_mem(void) { static WOLFSSL_BIO_METHOD meth; meth.type = WOLFSSL_BIO_BIO; XMEMCPY(meth.name, "Fixed Memory Size", 18); meth.writeCb = wolfssl_bio_s_fixed_mem_write; meth.readCb = wolfssl_bio_s_fixed_mem_read; return &meth; } #endif /*----------------------------------------------------------------------------* | Setup *----------------------------------------------------------------------------*/ static int test_wolfSSL_Init(void) { EXPECT_DECLS; ExpectIntEQ(wolfSSL_Init(), WOLFSSL_SUCCESS); return EXPECT_RESULT(); } static int test_wolfSSL_Cleanup(void) { EXPECT_DECLS; ExpectIntEQ(wolfSSL_Cleanup(), WOLFSSL_SUCCESS); return EXPECT_RESULT(); } /* Initialize the wolfCrypt state. * POST: 0 success. */ static int test_wolfCrypt_Init(void) { EXPECT_DECLS; ExpectIntEQ(wolfCrypt_Init(), 0); return EXPECT_RESULT(); } /* END test_wolfCrypt_Init */ static int test_wolfCrypt_Cleanup(void) { EXPECT_DECLS; ExpectIntEQ(wolfCrypt_Cleanup(), 0); return EXPECT_RESULT(); } #ifdef WOLFSSL_STATIC_MEMORY #define TEST_LSM_STATIC_SIZE 440000 /* Create new bucket list, using the default list, adding * one dang large buffer size. */ #define TEST_LSM_DEF_BUCKETS (WOLFMEM_DEF_BUCKETS+1) #define TEST_LSM_BUCKETS WOLFMEM_BUCKETS,(LARGEST_MEM_BUCKET*2) #define TEST_LSM_DIST WOLFMEM_DIST,1 #endif static int test_wc_LoadStaticMemory_ex(void) { EXPECT_DECLS; #ifdef WOLFSSL_STATIC_MEMORY byte staticMemory[TEST_LSM_STATIC_SIZE]; word32 sizeList[TEST_LSM_DEF_BUCKETS] = { TEST_LSM_BUCKETS }; word32 distList[TEST_LSM_DEF_BUCKETS] = { TEST_LSM_DIST }; WOLFSSL_HEAP_HINT* heap; /* For this test, the size and dist lists will be the ones configured * for the build, or default. The value of WOLFMEM_DEF_BUCKETS is 9, * so these lists are 10 long. For most tests, the value of * WOLFMEM_DEF_BUCKETS is used. There's a test case where one is added * to that, to make sure the list size is larger than * WOLFMEM_MAX_BUCKETS. */ /* Pass in zero everything. */ ExpectIntEQ(wc_LoadStaticMemory_ex(NULL, 0, NULL, NULL, NULL, 0, 0, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* Set the heap pointer to NULL. */ ExpectIntEQ(wc_LoadStaticMemory_ex(NULL, WOLFMEM_DEF_BUCKETS, sizeList, distList, staticMemory, (word32)sizeof(staticMemory), 0, 1), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* Set other pointer values to NULL one at a time. */ heap = NULL; ExpectIntEQ(wc_LoadStaticMemory_ex(&heap, WOLFMEM_DEF_BUCKETS, NULL, distList, staticMemory, (word32)sizeof(staticMemory), 0, 1), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); heap = NULL; ExpectIntEQ(wc_LoadStaticMemory_ex(&heap, WOLFMEM_DEF_BUCKETS, sizeList, NULL, staticMemory, (word32)sizeof(staticMemory), 0, 1), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); heap = NULL; ExpectIntEQ(wc_LoadStaticMemory_ex(&heap, WOLFMEM_DEF_BUCKETS, sizeList, distList, NULL, (word32)sizeof(staticMemory), 0, 1), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* Set the size of the static buffer to 0. */ heap = NULL; ExpectIntEQ(wc_LoadStaticMemory_ex(&heap, WOLFMEM_DEF_BUCKETS, sizeList, distList, staticMemory, 0, 0, 1), WC_NO_ERR_TRACE(BUFFER_E)); /* Set the size of the static buffer to one less than minimum allowed. */ heap = NULL; ExpectIntEQ(wc_LoadStaticMemory_ex(&heap, WOLFMEM_DEF_BUCKETS, sizeList, distList, staticMemory, (word32)(sizeof(WOLFSSL_HEAP) + sizeof(WOLFSSL_HEAP_HINT)) - 1, 0, 1), WC_NO_ERR_TRACE(BUFFER_E)); /* Set the size of the static buffer to exactly the minimum size. */ heap = NULL; ExpectIntEQ(wc_LoadStaticMemory_ex(&heap, WOLFMEM_DEF_BUCKETS, sizeList, distList, staticMemory, (word32)(sizeof(WOLFSSL_HEAP) + sizeof(WOLFSSL_HEAP_HINT)), 0, 1), 0); wc_UnloadStaticMemory(heap); /* Use more buckets than able. Success case. */ heap = NULL; ExpectIntEQ(wc_LoadStaticMemory_ex(&heap, WOLFMEM_DEF_BUCKETS*2, sizeList, distList, staticMemory, (word32)sizeof(staticMemory), 0, 1), 0); wc_UnloadStaticMemory(heap); /* Success case. */ heap = NULL; ExpectIntEQ(wc_LoadStaticMemory_ex(&heap, WOLFMEM_DEF_BUCKETS, sizeList, distList, staticMemory, (word32)sizeof(staticMemory), 0, 1), 0); wc_UnloadStaticMemory(heap); #endif /* WOLFSSL_STATIC_MEMORY */ return EXPECT_RESULT(); } static int test_wc_LoadStaticMemory_CTX(void) { EXPECT_DECLS; #if defined(WOLFSSL_STATIC_MEMORY) && !defined(NO_WOLFSSL_CLIENT) byte staticMemory[TEST_LSM_STATIC_SIZE]; word32 sizeList[TEST_LSM_DEF_BUCKETS] = { TEST_LSM_BUCKETS }; word32 distList[TEST_LSM_DEF_BUCKETS] = { TEST_LSM_DIST }; WOLFSSL_HEAP_HINT* heap; WOLFSSL_CTX *ctx1 = NULL, *ctx2 = NULL; /* Set the size of the static buffer to exactly the minimum size. */ heap = NULL; ExpectIntEQ(wc_LoadStaticMemory_ex(&heap, WOLFMEM_DEF_BUCKETS, sizeList, distList, staticMemory, sizeof(staticMemory), 0, 1), 0); /* Creating two WOLFSSL_CTX objects from the same heap hint and free'ing * them should not cause issues. */ ExpectNotNull((ctx1 = wolfSSL_CTX_new_ex(wolfSSLv23_client_method_ex(heap), heap))); wolfSSL_CTX_free(ctx1); ExpectNotNull((ctx2 = wolfSSL_CTX_new_ex(wolfSSLv23_client_method_ex(heap), heap))); wolfSSL_CTX_free(ctx2); /* two CTX's at once */ ExpectNotNull((ctx1 = wolfSSL_CTX_new_ex(wolfSSLv23_client_method_ex(heap), heap))); ExpectNotNull((ctx2 = wolfSSL_CTX_new_ex(wolfSSLv23_client_method_ex(heap), heap))); wolfSSL_CTX_free(ctx1); wolfSSL_CTX_free(ctx2); wc_UnloadStaticMemory(heap); #endif /* WOLFSSL_STATIC_MEMORY */ return EXPECT_RESULT(); } /*----------------------------------------------------------------------------* | Platform dependent function test *----------------------------------------------------------------------------*/ static int test_fileAccess(void) { EXPECT_DECLS; #if defined(WOLFSSL_TEST_PLATFORMDEPEND) && !defined(NO_FILESYSTEM) const char *fname[] = { svrCertFile, svrKeyFile, caCertFile, eccCertFile, eccKeyFile, eccRsaCertFile, cliCertFile, cliCertDerFile, cliKeyFile, dhParamFile, cliEccKeyFile, cliEccCertFile, caEccCertFile, edCertFile, edKeyFile, cliEdCertFile, cliEdKeyFile, caEdCertFile, NULL }; const char derfile[] = "./certs/server-cert.der"; XFILE f = XBADFILE; size_t sz; byte *buff = NULL; int i; ExpectTrue(XFOPEN("badfilename", "rb") == XBADFILE); for (i=0; EXPECT_SUCCESS() && fname[i] != NULL ; i++) { ExpectTrue((f = XFOPEN(fname[i], "rb")) != XBADFILE); XFCLOSE(f); } ExpectTrue((f = XFOPEN(derfile, "rb")) != XBADFILE); ExpectTrue(XFSEEK(f, 0, XSEEK_END) == 0); ExpectIntGE(sz = (size_t) XFTELL(f), sizeof_server_cert_der_2048); ExpectTrue(XFSEEK(f, 0, XSEEK_SET) == 0); ExpectTrue((buff = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE)) != NULL); ExpectTrue(XFREAD(buff, 1, sz, f) == sz); ExpectIntEQ(XMEMCMP(server_cert_der_2048, buff, sz), 0); XFREE(buff, NULL, DYNAMIC_TYPE_FILE); XFCLOSE(f); #endif return EXPECT_RESULT(); } static int test_wc_FreeCertList(void) { EXPECT_DECLS; #if defined(HAVE_PKCS12) && !defined(NO_ASN) && \ !defined(NO_PWDBASED) && !defined(NO_HMAC) && !defined(NO_CERTS) && \ defined(USE_CERT_BUFFERS_2048) WC_DerCertList* list = NULL; void* heap = NULL; /* Test freeing a list with a single node */ list = (WC_DerCertList*)XMALLOC(sizeof(WC_DerCertList), heap, DYNAMIC_TYPE_PKCS); ExpectNotNull(list); if (list != NULL) { list->buffer = (byte*)XMALLOC(10, heap, DYNAMIC_TYPE_PKCS); ExpectNotNull(list->buffer); if (list->buffer != NULL) { list->bufferSz = 10; list->next = NULL; wc_FreeCertList(list, heap); } else { XFREE(list, heap, DYNAMIC_TYPE_PKCS); list = NULL; } } #endif return EXPECT_RESULT(); } /*----------------------------------------------------------------------------* | Method Allocators *----------------------------------------------------------------------------*/ static int test_wolfSSL_Method_Allocators(void) { EXPECT_DECLS; #define TEST_METHOD_ALLOCATOR(allocator, condition) \ do { \ WOLFSSL_METHOD *method = NULL; \ condition(method = allocator()); \ XFREE(method, 0, DYNAMIC_TYPE_METHOD); \ } while (0) #define TEST_VALID_METHOD_ALLOCATOR(a) \ TEST_METHOD_ALLOCATOR(a, ExpectNotNull) #define TEST_INVALID_METHOD_ALLOCATOR(a) \ TEST_METHOD_ALLOCATOR(a, ExpectNull) #ifndef NO_TLS #ifndef NO_OLD_TLS #ifdef WOLFSSL_ALLOW_SSLV3 #ifndef NO_WOLFSSL_SERVER TEST_VALID_METHOD_ALLOCATOR(wolfSSLv3_server_method); #endif #ifndef NO_WOLFSSL_CLIENT TEST_VALID_METHOD_ALLOCATOR(wolfSSLv3_client_method); #endif #endif #ifdef WOLFSSL_ALLOW_TLSV10 #ifndef NO_WOLFSSL_SERVER TEST_VALID_METHOD_ALLOCATOR(wolfTLSv1_server_method); #endif #ifndef NO_WOLFSSL_CLIENT TEST_VALID_METHOD_ALLOCATOR(wolfTLSv1_client_method); #endif #endif #ifndef NO_WOLFSSL_SERVER TEST_VALID_METHOD_ALLOCATOR(wolfTLSv1_1_server_method); #endif #ifndef NO_WOLFSSL_CLIENT TEST_VALID_METHOD_ALLOCATOR(wolfTLSv1_1_client_method); #endif #endif /* !NO_OLD_TLS */ #ifndef WOLFSSL_NO_TLS12 #ifndef NO_WOLFSSL_SERVER TEST_VALID_METHOD_ALLOCATOR(wolfTLSv1_2_server_method); #endif #ifndef NO_WOLFSSL_CLIENT TEST_VALID_METHOD_ALLOCATOR(wolfTLSv1_2_client_method); #endif #endif /* !WOLFSSL_NO_TLS12 */ #ifdef WOLFSSL_TLS13 #ifndef NO_WOLFSSL_SERVER TEST_VALID_METHOD_ALLOCATOR(wolfTLSv1_3_server_method); #endif #ifndef NO_WOLFSSL_CLIENT TEST_VALID_METHOD_ALLOCATOR(wolfTLSv1_3_client_method); #endif #endif /* WOLFSSL_TLS13 */ #ifndef NO_WOLFSSL_SERVER TEST_VALID_METHOD_ALLOCATOR(wolfSSLv23_server_method); #endif #ifndef NO_WOLFSSL_CLIENT TEST_VALID_METHOD_ALLOCATOR(wolfSSLv23_client_method); #endif #ifdef WOLFSSL_DTLS #ifndef NO_OLD_TLS #ifndef NO_WOLFSSL_SERVER TEST_VALID_METHOD_ALLOCATOR(wolfDTLSv1_server_method); #endif #ifndef NO_WOLFSSL_CLIENT TEST_VALID_METHOD_ALLOCATOR(wolfDTLSv1_client_method); #endif #endif #ifndef WOLFSSL_NO_TLS12 #ifndef NO_WOLFSSL_SERVER TEST_VALID_METHOD_ALLOCATOR(wolfDTLSv1_2_server_method); #endif #ifndef NO_WOLFSSL_CLIENT TEST_VALID_METHOD_ALLOCATOR(wolfDTLSv1_2_client_method); #endif #endif #endif /* WOLFSSL_DTLS */ #if !defined(NO_OLD_TLS) && defined(OPENSSL_EXTRA) /* Stubs */ #ifndef NO_WOLFSSL_SERVER TEST_INVALID_METHOD_ALLOCATOR(wolfSSLv2_server_method); #endif #ifndef NO_WOLFSSL_CLIENT TEST_INVALID_METHOD_ALLOCATOR(wolfSSLv2_client_method); #endif #endif /* Test Either Method (client or server) */ #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) TEST_VALID_METHOD_ALLOCATOR(wolfSSLv23_method); #ifndef NO_OLD_TLS #ifdef WOLFSSL_ALLOW_TLSV10 TEST_VALID_METHOD_ALLOCATOR(wolfTLSv1_method); #endif TEST_VALID_METHOD_ALLOCATOR(wolfTLSv1_1_method); #endif /* !NO_OLD_TLS */ #ifndef WOLFSSL_NO_TLS12 TEST_VALID_METHOD_ALLOCATOR(wolfTLSv1_2_method); #endif /* !WOLFSSL_NO_TLS12 */ #ifdef WOLFSSL_TLS13 TEST_VALID_METHOD_ALLOCATOR(wolfTLSv1_3_method); #endif /* WOLFSSL_TLS13 */ #ifdef WOLFSSL_DTLS TEST_VALID_METHOD_ALLOCATOR(wolfDTLS_method); #ifndef NO_OLD_TLS TEST_VALID_METHOD_ALLOCATOR(wolfDTLSv1_method); #endif /* !NO_OLD_TLS */ #ifndef WOLFSSL_NO_TLS12 TEST_VALID_METHOD_ALLOCATOR(wolfDTLSv1_2_method); #endif /* !WOLFSSL_NO_TLS12 */ #ifdef WOLFSSL_DTLS13 TEST_VALID_METHOD_ALLOCATOR(wolfDTLSv1_3_method); #endif /* WOLFSSL_DTLS13 */ #endif /* WOLFSSL_DTLS */ #endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */ #endif /* !NO_TLS */ return EXPECT_RESULT(); } #if defined(WOLFSSL_DUAL_ALG_CERTS) && !defined(NO_FILESYSTEM) /*----------------------------------------------------------------------------* | Dual algorithm Certificate Tests *----------------------------------------------------------------------------*/ #define LARGE_TEMP_SZ 4096 /* To better understand this, please see the X9.146 example in wolfssl-examples * repo. */ static int do_dual_alg_root_certgen(byte **out, char *caKeyFile, char *sapkiFile, char *altPrivFile) { EXPECT_DECLS; FILE* file = NULL; Cert newCert; DecodedCert preTBS; byte caKeyBuf[LARGE_TEMP_SZ]; word32 caKeySz = LARGE_TEMP_SZ; byte sapkiBuf[LARGE_TEMP_SZ]; word32 sapkiSz = LARGE_TEMP_SZ; byte altPrivBuf[LARGE_TEMP_SZ]; word32 altPrivSz = LARGE_TEMP_SZ; byte altSigAlgBuf[LARGE_TEMP_SZ]; word32 altSigAlgSz = LARGE_TEMP_SZ; byte scratchBuf[LARGE_TEMP_SZ]; word32 scratchSz = LARGE_TEMP_SZ; byte preTbsBuf[LARGE_TEMP_SZ]; word32 preTbsSz = LARGE_TEMP_SZ; byte altSigValBuf[LARGE_TEMP_SZ]; word32 altSigValSz = LARGE_TEMP_SZ; byte *outBuf = NULL; word32 outSz = LARGE_TEMP_SZ; WC_RNG rng; RsaKey caKey; ecc_key altCaKey; word32 idx = 0; XMEMSET(&rng, 0, sizeof(WC_RNG)); XMEMSET(&caKey, 0, sizeof(RsaKey)); XMEMSET(&altCaKey, 0, sizeof(ecc_key)); ExpectNotNull(outBuf = (byte*)XMALLOC(outSz, NULL, DYNAMIC_TYPE_TMP_BUFFER)); ExpectIntEQ(wc_InitRng(&rng), 0); XMEMSET(caKeyBuf, 0, caKeySz); ExpectNotNull(file = fopen(caKeyFile, "rb")); ExpectIntGT(caKeySz = (word32)fread(caKeyBuf, 1, caKeySz, file), 0); if (file) { fclose(file); file = NULL; } ExpectIntEQ(wc_InitRsaKey_ex(&caKey, NULL, INVALID_DEVID), 0); idx = 0; ExpectIntEQ(wc_RsaPrivateKeyDecode(caKeyBuf, &idx, &caKey, caKeySz), 0); XMEMSET(sapkiBuf, 0, sapkiSz); ExpectNotNull(file = fopen(sapkiFile, "rb")); ExpectIntGT(sapkiSz = (word32)fread(sapkiBuf, 1, sapkiSz, file), 0); if (file) { fclose(file); file = NULL; } XMEMSET(altPrivBuf, 0, altPrivSz); ExpectNotNull(file = fopen(altPrivFile, "rb")); ExpectIntGT(altPrivSz = (word32)fread(altPrivBuf, 1, altPrivSz, file), 0); if (file) { fclose(file); file = NULL; } wc_ecc_init(&altCaKey); idx = 0; ExpectIntEQ(wc_EccPrivateKeyDecode(altPrivBuf, &idx, &altCaKey, (word32)altPrivSz), 0); XMEMSET(altSigAlgBuf, 0, altSigAlgSz); ExpectIntGT(altSigAlgSz = SetAlgoID(CTC_SHA256wECDSA, altSigAlgBuf, oidSigType, 0), 0); wc_InitCert(&newCert); strncpy(newCert.subject.country, "US", CTC_NAME_SIZE); strncpy(newCert.subject.state, "MT", CTC_NAME_SIZE); strncpy(newCert.subject.locality, "Bozeman", CTC_NAME_SIZE); strncpy(newCert.subject.org, "wolfSSL", CTC_NAME_SIZE); strncpy(newCert.subject.unit, "Engineering", CTC_NAME_SIZE); strncpy(newCert.subject.commonName, "www.wolfssl.com", CTC_NAME_SIZE); strncpy(newCert.subject.email, "root@wolfssl.com", CTC_NAME_SIZE); strncpy((char*)newCert.beforeDate, "\x18\x0f""20250101000000Z", CTC_DATE_SIZE); newCert.beforeDateSz = 17; strncpy((char*)newCert.afterDate, "\x18\x0f""20493112115959Z", CTC_DATE_SIZE); newCert.afterDateSz = 17; newCert.sigType = CTC_SHA256wRSA; newCert.isCA = 1; ExpectIntEQ(wc_SetCustomExtension(&newCert, 0, "1.2.3.4.5", (const byte *)"This is NOT a critical extension", 32), 0); ExpectIntEQ(wc_SetCustomExtension(&newCert, 0, "2.5.29.72", sapkiBuf, sapkiSz), 0); ExpectIntEQ(wc_SetCustomExtension(&newCert, 0, "2.5.29.73", altSigAlgBuf, altSigAlgSz), 0); XMEMSET(scratchBuf, 0, scratchSz); ExpectIntGT(scratchSz = wc_MakeSelfCert(&newCert, scratchBuf, scratchSz, &caKey, &rng), 0); wc_InitDecodedCert(&preTBS, scratchBuf, scratchSz, 0); ExpectIntEQ(wc_ParseCert(&preTBS, CERT_TYPE, NO_VERIFY, NULL), 0); XMEMSET(preTbsBuf, 0, preTbsSz); ExpectIntGT(preTbsSz = wc_GeneratePreTBS(&preTBS, preTbsBuf, preTbsSz), 0); XMEMSET(altSigValBuf, 0, altSigValSz); ExpectIntGT(altSigValSz = wc_MakeSigWithBitStr(altSigValBuf, altSigValSz, CTC_SHA256wECDSA, preTbsBuf, preTbsSz, ECC_TYPE, &altCaKey, &rng), 0); ExpectIntEQ(wc_SetCustomExtension(&newCert, 0, "2.5.29.74", altSigValBuf, altSigValSz), 0); /* Finally, generate the new certificate. */ if (outBuf != NULL) { XMEMSET(outBuf, 0, outSz); } ExpectIntGT(outSz = wc_MakeSelfCert(&newCert, outBuf, outSz, &caKey, &rng), 0); *out = outBuf; wc_FreeRsaKey(&caKey); wc_FreeRng(&rng); wc_FreeDecodedCert(&preTBS); return outSz; } static int do_dual_alg_server_certgen(byte **out, char *caKeyFile, char *sapkiFile, char *altPrivFile, char *serverKeyFile, byte *caCertBuf, int caCertSz) { EXPECT_DECLS; FILE* file = NULL; Cert newCert; DecodedCert preTBS; byte serverKeyBuf[LARGE_TEMP_SZ]; word32 serverKeySz = LARGE_TEMP_SZ; byte caKeyBuf[LARGE_TEMP_SZ]; word32 caKeySz = LARGE_TEMP_SZ; byte sapkiBuf[LARGE_TEMP_SZ]; word32 sapkiSz = LARGE_TEMP_SZ; byte altPrivBuf[LARGE_TEMP_SZ]; word32 altPrivSz = LARGE_TEMP_SZ; byte altSigAlgBuf[LARGE_TEMP_SZ]; word32 altSigAlgSz = LARGE_TEMP_SZ; byte scratchBuf[LARGE_TEMP_SZ]; word32 scratchSz = LARGE_TEMP_SZ; byte preTbsBuf[LARGE_TEMP_SZ]; word32 preTbsSz = LARGE_TEMP_SZ; byte altSigValBuf[LARGE_TEMP_SZ]; word32 altSigValSz = LARGE_TEMP_SZ; byte *outBuf = NULL; word32 outSz = LARGE_TEMP_SZ; WC_RNG rng; RsaKey caKey; RsaKey serverKey; ecc_key altCaKey; word32 idx = 0; XMEMSET(&rng, 0, sizeof(WC_RNG)); XMEMSET(&caKey, 0, sizeof(RsaKey)); XMEMSET(&serverKey, 0, sizeof(RsaKey)); XMEMSET(&altCaKey, 0, sizeof(ecc_key)); ExpectNotNull(outBuf = (byte*)XMALLOC(outSz, NULL, DYNAMIC_TYPE_TMP_BUFFER)); ExpectIntEQ(wc_InitRng(&rng), 0); XMEMSET(serverKeyBuf, 0, serverKeySz); ExpectNotNull(file = fopen(serverKeyFile, "rb")); ExpectIntGT(serverKeySz = (word32)fread(serverKeyBuf, 1, serverKeySz, file), 0); if (file) { fclose(file); file = NULL; } ExpectIntEQ(wc_InitRsaKey_ex(&serverKey, NULL, INVALID_DEVID), 0); idx = 0; ExpectIntEQ(wc_RsaPrivateKeyDecode(serverKeyBuf, &idx, &serverKey, (word32)serverKeySz), 0); XMEMSET(caKeyBuf, 0, caKeySz); ExpectNotNull(file = fopen(caKeyFile, "rb")); ExpectIntGT(caKeySz = (word32)fread(caKeyBuf, 1, caKeySz, file), 0); if (file) { fclose(file); file = NULL; } ExpectIntEQ(wc_InitRsaKey_ex(&caKey, NULL, INVALID_DEVID), 0); idx = 0; ExpectIntEQ(wc_RsaPrivateKeyDecode(caKeyBuf, &idx, &caKey, (word32)caKeySz), 0); XMEMSET(sapkiBuf, 0, sapkiSz); ExpectNotNull(file = fopen(sapkiFile, "rb")); ExpectIntGT(sapkiSz = (word32)fread(sapkiBuf, 1, sapkiSz, file), 0); if (file) { fclose(file); file = NULL; } XMEMSET(altPrivBuf, 0, altPrivSz); ExpectNotNull(file = fopen(altPrivFile, "rb")); ExpectIntGT(altPrivSz = (word32)fread(altPrivBuf, 1, altPrivSz, file), 0); if (file) { fclose(file); file = NULL; } wc_ecc_init(&altCaKey); idx = 0; ExpectIntEQ(wc_EccPrivateKeyDecode(altPrivBuf, &idx, &altCaKey, (word32)altPrivSz), 0); XMEMSET(altSigAlgBuf, 0, altSigAlgSz); ExpectIntGT(altSigAlgSz = SetAlgoID(CTC_SHA256wECDSA, altSigAlgBuf, oidSigType, 0), 0); wc_InitCert(&newCert); strncpy(newCert.subject.country, "US", CTC_NAME_SIZE); strncpy(newCert.subject.state, "MT", CTC_NAME_SIZE); strncpy(newCert.subject.locality, "Bozeman", CTC_NAME_SIZE); strncpy(newCert.subject.org, "wolfSSL", CTC_NAME_SIZE); strncpy(newCert.subject.unit, "Engineering", CTC_NAME_SIZE); strncpy(newCert.subject.commonName, "www.wolfssl.com", CTC_NAME_SIZE); strncpy(newCert.subject.email, "server@wolfssl.com", CTC_NAME_SIZE); strncpy((char*)newCert.beforeDate, "\x18\x0f""20250101000000Z", CTC_DATE_SIZE); newCert.beforeDateSz = 17; strncpy((char*)newCert.afterDate, "\x18\x0f""20493112115959Z", CTC_DATE_SIZE); newCert.afterDateSz = 17; newCert.sigType = CTC_SHA256wRSA; newCert.isCA = 0; ExpectIntEQ(wc_SetIssuerBuffer(&newCert, caCertBuf, caCertSz), 0); ExpectIntEQ(wc_SetCustomExtension(&newCert, 0, "2.5.29.72", sapkiBuf, sapkiSz), 0); ExpectIntEQ(wc_SetCustomExtension(&newCert, 0, "2.5.29.73", altSigAlgBuf, altSigAlgSz), 0); XMEMSET(scratchBuf, 0, scratchSz); ExpectIntGT(wc_MakeCert(&newCert, scratchBuf, scratchSz, &serverKey, NULL, &rng), 0); ExpectIntGT(scratchSz = wc_SignCert(newCert.bodySz, newCert.sigType, scratchBuf, scratchSz, &caKey, NULL, &rng), 0); wc_InitDecodedCert(&preTBS, scratchBuf, scratchSz, 0); ExpectIntEQ(wc_ParseCert(&preTBS, CERT_TYPE, NO_VERIFY, NULL), 0); XMEMSET(preTbsBuf, 0, preTbsSz); ExpectIntGT(preTbsSz = wc_GeneratePreTBS(&preTBS, preTbsBuf, preTbsSz), 0); XMEMSET(altSigValBuf, 0, altSigValSz); ExpectIntGT(altSigValSz = wc_MakeSigWithBitStr(altSigValBuf, altSigValSz, CTC_SHA256wECDSA, preTbsBuf, preTbsSz, ECC_TYPE, &altCaKey, &rng), 0); ExpectIntEQ(wc_SetCustomExtension(&newCert, 0, "2.5.29.74", altSigValBuf, altSigValSz), 0); /* Finally, generate the new certificate. */ if (outBuf != NULL) { XMEMSET(outBuf, 0, outSz); } ExpectIntGT(wc_MakeCert(&newCert, outBuf, outSz, &serverKey, NULL, &rng), 0); ExpectIntGT(outSz = wc_SignCert(newCert.bodySz, newCert.sigType, outBuf, outSz, &caKey, NULL, &rng), 0); *out = outBuf; wc_FreeRsaKey(&caKey); wc_FreeRsaKey(&serverKey); wc_FreeRng(&rng); wc_FreeDecodedCert(&preTBS); return outSz; } static int do_dual_alg_tls13_connection(byte *caCert, word32 caCertSz, byte *serverCert, word32 serverCertSz, byte *serverKey, word32 serverKeySz, int negative_test) { EXPECT_DECLS; WOLFSSL_CTX *ctx_c = NULL; WOLFSSL_CTX *ctx_s = NULL; WOLFSSL *ssl_c = NULL; WOLFSSL *ssl_s = NULL; struct test_memio_ctx test_ctx; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup_ex(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, wolfTLSv1_3_client_method, wolfTLSv1_3_server_method, caCert, caCertSz, serverCert, serverCertSz, serverKey, serverKeySz), 0); if (negative_test) { ExpectTrue(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL) != 0); } else { ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); } wolfSSL_free(ssl_c); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_c); wolfSSL_CTX_free(ctx_s); return EXPECT_RESULT(); } /** * Function to generate a root certificate with dual algorithm support and * configurable criticality for extensions and path length constraints. * * @param out [out] Pointer to store the generated certificate * @param caKeyFile [in] Path to the CA key file * @param sapkiFile [in] Path to the subject alternative public key info file * @param altPrivFile [in] Path to the alternative private key file * @param setCrit [in] Flag to set criticality of extensions (1=critical, 0=non-critical) * @param setPathLen [in] Flag to set path length constraint (1=set, 0=don't set) * @param pathLen [in] Path length value (only used if setPathLen=1) * @return Size of the generated certificate or negative on error */ static int do_dual_alg_root_certgen_crit(byte **out, char *caKeyFile, char *sapkiFile, char *altPrivFile, int setCrit, int setPathLen, int pathLen) { EXPECT_DECLS; FILE* file = NULL; Cert newCert; DecodedCert preTBS; byte caKeyBuf[LARGE_TEMP_SZ]; word32 caKeySz = LARGE_TEMP_SZ; byte sapkiBuf[LARGE_TEMP_SZ]; word32 sapkiSz = LARGE_TEMP_SZ; byte altPrivBuf[LARGE_TEMP_SZ]; word32 altPrivSz = LARGE_TEMP_SZ; byte altSigAlgBuf[LARGE_TEMP_SZ]; word32 altSigAlgSz = LARGE_TEMP_SZ; byte scratchBuf[LARGE_TEMP_SZ]; word32 scratchSz = LARGE_TEMP_SZ; byte preTbsBuf[LARGE_TEMP_SZ]; word32 preTbsSz = LARGE_TEMP_SZ; byte altSigValBuf[LARGE_TEMP_SZ]; word32 altSigValSz = LARGE_TEMP_SZ; byte *outBuf = NULL; word32 outSz = LARGE_TEMP_SZ; WC_RNG rng; RsaKey caKey; ecc_key altCaKey; word32 idx = 0; XMEMSET(&rng, 0, sizeof(WC_RNG)); XMEMSET(&caKey, 0, sizeof(RsaKey)); XMEMSET(&altCaKey, 0, sizeof(ecc_key)); ExpectNotNull(outBuf = (byte*)XMALLOC(outSz, NULL, DYNAMIC_TYPE_TMP_BUFFER)); ExpectIntEQ(wc_InitRng(&rng), 0); XMEMSET(caKeyBuf, 0, caKeySz); ExpectNotNull(file = fopen(caKeyFile, "rb")); ExpectIntGT(caKeySz = (word32)fread(caKeyBuf, 1, caKeySz, file), 0); if (file) { fclose(file); file = NULL; } ExpectIntEQ(wc_InitRsaKey_ex(&caKey, NULL, INVALID_DEVID), 0); idx = 0; ExpectIntEQ(wc_RsaPrivateKeyDecode(caKeyBuf, &idx, &caKey, caKeySz), 0); XMEMSET(sapkiBuf, 0, sapkiSz); ExpectNotNull(file = fopen(sapkiFile, "rb")); ExpectIntGT(sapkiSz = (word32)fread(sapkiBuf, 1, sapkiSz, file), 0); if (file) { fclose(file); file = NULL; } XMEMSET(altPrivBuf, 0, altPrivSz); ExpectNotNull(file = fopen(altPrivFile, "rb")); ExpectIntGT(altPrivSz = (word32)fread(altPrivBuf, 1, altPrivSz, file), 0); if (file) { fclose(file); file = NULL; } wc_ecc_init(&altCaKey); idx = 0; ExpectIntEQ(wc_EccPrivateKeyDecode(altPrivBuf, &idx, &altCaKey, (word32)altPrivSz), 0); XMEMSET(altSigAlgBuf, 0, altSigAlgSz); ExpectIntGT(altSigAlgSz = SetAlgoID(CTC_SHA256wECDSA, altSigAlgBuf, oidSigType, 0), 0); wc_InitCert(&newCert); strncpy(newCert.subject.country, "US", CTC_NAME_SIZE); strncpy(newCert.subject.state, "MT", CTC_NAME_SIZE); strncpy(newCert.subject.locality, "Bozeman", CTC_NAME_SIZE); strncpy(newCert.subject.org, "wolfSSL", CTC_NAME_SIZE); strncpy(newCert.subject.unit, "Engineering", CTC_NAME_SIZE); strncpy(newCert.subject.commonName, "www.wolfssl.com", CTC_NAME_SIZE); strncpy(newCert.subject.email, "root@wolfssl.com", CTC_NAME_SIZE); strncpy((char*)newCert.beforeDate, "\x18\x0f""20250101000000Z", CTC_DATE_SIZE); newCert.beforeDateSz = 17; strncpy((char*)newCert.afterDate, "\x18\x0f""20493112115959Z", CTC_DATE_SIZE); newCert.afterDateSz = 17; newCert.sigType = CTC_SHA256wRSA; newCert.isCA = 1; /* Set criticality of basic constraint extension if requested */ if (setCrit) { newCert.basicConstCrit = 1; } /* Set pathlen if requested */ if (setPathLen) { newCert.pathLen = pathLen; newCert.pathLenSet = 1; } ExpectIntEQ(wc_SetCustomExtension(&newCert, 0, "1.2.3.4.5", (const byte *)"This is NOT a critical extension", 32), 0); ExpectIntEQ(wc_SetCustomExtension(&newCert, setCrit, "2.5.29.72", sapkiBuf, sapkiSz), 0); ExpectIntEQ(wc_SetCustomExtension(&newCert, setCrit, "2.5.29.73", altSigAlgBuf, altSigAlgSz), 0); XMEMSET(scratchBuf, 0, scratchSz); ExpectIntGT(scratchSz = wc_MakeSelfCert(&newCert, scratchBuf, scratchSz, &caKey, &rng), 0); wc_InitDecodedCert(&preTBS, scratchBuf, scratchSz, 0); ExpectIntEQ(wc_ParseCert(&preTBS, CERT_TYPE, NO_VERIFY, NULL), 0); XMEMSET(preTbsBuf, 0, preTbsSz); ExpectIntGT(preTbsSz = wc_GeneratePreTBS(&preTBS, preTbsBuf, preTbsSz), 0); XMEMSET(altSigValBuf, 0, altSigValSz); ExpectIntGT(altSigValSz = wc_MakeSigWithBitStr(altSigValBuf, altSigValSz, CTC_SHA256wECDSA, preTbsBuf, preTbsSz, ECC_TYPE, &altCaKey, &rng), 0); ExpectIntEQ(wc_SetCustomExtension(&newCert, setCrit, "2.5.29.74", altSigValBuf, altSigValSz), 0); /* Finally, generate the new certificate. */ if (outBuf != NULL) { XMEMSET(outBuf, 0, outSz); ExpectIntGT(outSz = wc_MakeSelfCert(&newCert, outBuf, outSz, &caKey, &rng), 0); *out = outBuf; } else { outSz = 0; } wc_FreeDecodedCert(&preTBS); wc_ecc_free(&altCaKey); wc_FreeRsaKey(&caKey); wc_FreeRng(&rng); return (int)outSz; } /** * Function to generate a server certificate with dual algorithm support and * configurable criticality for extensions and path length constraints. * * @param out [out] Pointer to store the generated certificate * @param caKeyFile [in] Path to the CA key file * @param sapkiFile [in] Path to the subject alternative public key info file * @param altPrivFile [in] Path to the alternative private key file * @param serverKeyFile [in] Path to the server key file * @param caCertBuf [in] Buffer containing the CA certificate * @param caCertSz [in] Size of the CA certificate buffer * @param setCrit [in] Flag to set criticality of extensions (1=critical, 0=non-critical) * @param setPathLen [in] Flag to set path length constraint (1=set, 0=don't set) * @param pathLen [in] Path length value (only used if setPathLen=1) * @return Size of the generated certificate or negative on error */ static int do_dual_alg_server_certgen_crit(byte **out, char *caKeyFile, char *sapkiFile, char *altPrivFile, char *serverKeyFile, byte *caCertBuf, int caCertSz, int setCrit) { EXPECT_DECLS; FILE* file = NULL; Cert newCert; DecodedCert preTBS; byte serverKeyBuf[LARGE_TEMP_SZ]; word32 serverKeySz = LARGE_TEMP_SZ; byte caKeyBuf[LARGE_TEMP_SZ]; word32 caKeySz = LARGE_TEMP_SZ; byte sapkiBuf[LARGE_TEMP_SZ]; word32 sapkiSz = LARGE_TEMP_SZ; byte altPrivBuf[LARGE_TEMP_SZ]; word32 altPrivSz = LARGE_TEMP_SZ; byte altSigAlgBuf[LARGE_TEMP_SZ]; word32 altSigAlgSz = LARGE_TEMP_SZ; byte scratchBuf[LARGE_TEMP_SZ]; word32 scratchSz = LARGE_TEMP_SZ; byte preTbsBuf[LARGE_TEMP_SZ]; word32 preTbsSz = LARGE_TEMP_SZ; byte altSigValBuf[LARGE_TEMP_SZ]; word32 altSigValSz = LARGE_TEMP_SZ; byte *outBuf = NULL; word32 outSz = LARGE_TEMP_SZ; WC_RNG rng; RsaKey caKey; RsaKey serverKey; ecc_key altCaKey; word32 idx = 0; XMEMSET(&rng, 0, sizeof(WC_RNG)); XMEMSET(&caKey, 0, sizeof(RsaKey)); XMEMSET(&serverKey, 0, sizeof(RsaKey)); XMEMSET(&altCaKey, 0, sizeof(ecc_key)); ExpectNotNull(outBuf = (byte*)XMALLOC(outSz, NULL, DYNAMIC_TYPE_TMP_BUFFER)); ExpectIntEQ(wc_InitRng(&rng), 0); XMEMSET(serverKeyBuf, 0, serverKeySz); ExpectNotNull(file = fopen(serverKeyFile, "rb")); ExpectIntGT(serverKeySz = (word32)fread(serverKeyBuf, 1, serverKeySz, file), 0); if (file) { fclose(file); file = NULL; } ExpectIntEQ(wc_InitRsaKey_ex(&serverKey, NULL, INVALID_DEVID), 0); idx = 0; ExpectIntEQ(wc_RsaPrivateKeyDecode(serverKeyBuf, &idx, &serverKey, serverKeySz), 0); XMEMSET(caKeyBuf, 0, caKeySz); ExpectNotNull(file = fopen(caKeyFile, "rb")); ExpectIntGT(caKeySz = (word32)fread(caKeyBuf, 1, caKeySz, file), 0); if (file) { fclose(file); file = NULL; } ExpectIntEQ(wc_InitRsaKey_ex(&caKey, NULL, INVALID_DEVID), 0); idx = 0; ExpectIntEQ(wc_RsaPrivateKeyDecode(caKeyBuf, &idx, &caKey, caKeySz), 0); XMEMSET(sapkiBuf, 0, sapkiSz); ExpectNotNull(file = fopen(sapkiFile, "rb")); ExpectIntGT(sapkiSz = (word32)fread(sapkiBuf, 1, sapkiSz, file), 0); if (file) { fclose(file); file = NULL; } XMEMSET(altPrivBuf, 0, altPrivSz); ExpectNotNull(file = fopen(altPrivFile, "rb")); ExpectIntGT(altPrivSz = (word32)fread(altPrivBuf, 1, altPrivSz, file), 0); if (file) { fclose(file); file = NULL; } wc_ecc_init(&altCaKey); idx = 0; ExpectIntEQ(wc_EccPrivateKeyDecode(altPrivBuf, &idx, &altCaKey, (word32)altPrivSz), 0); XMEMSET(altSigAlgBuf, 0, altSigAlgSz); ExpectIntGT(altSigAlgSz = SetAlgoID(CTC_SHA256wECDSA, altSigAlgBuf, oidSigType, 0), 0); wc_InitCert(&newCert); strncpy(newCert.subject.country, "US", CTC_NAME_SIZE); strncpy(newCert.subject.state, "MT", CTC_NAME_SIZE); strncpy(newCert.subject.locality, "Bozeman", CTC_NAME_SIZE); strncpy(newCert.subject.org, "wolfSSL", CTC_NAME_SIZE); strncpy(newCert.subject.unit, "Engineering", CTC_NAME_SIZE); strncpy(newCert.subject.commonName, "www.wolfssl.com", CTC_NAME_SIZE); strncpy(newCert.subject.email, "server@wolfssl.com", CTC_NAME_SIZE); strncpy((char*)newCert.beforeDate, "\x18\x0f""20250101000000Z", CTC_DATE_SIZE); newCert.beforeDateSz = 17; strncpy((char*)newCert.afterDate, "\x18\x0f""20493112115959Z", CTC_DATE_SIZE); newCert.afterDateSz = 17; newCert.sigType = CTC_SHA256wRSA; newCert.isCA = 0; ExpectIntEQ(wc_SetIssuerBuffer(&newCert, caCertBuf, caCertSz), 0); ExpectIntEQ(wc_SetCustomExtension(&newCert, setCrit, "2.5.29.72", sapkiBuf, sapkiSz), 0); ExpectIntEQ(wc_SetCustomExtension(&newCert, setCrit, "2.5.29.73", altSigAlgBuf, altSigAlgSz), 0); XMEMSET(scratchBuf, 0, scratchSz); ExpectIntGT(wc_MakeCert(&newCert, scratchBuf, scratchSz, &serverKey, NULL, &rng), 0); ExpectIntGT(scratchSz = wc_SignCert(newCert.bodySz, newCert.sigType, scratchBuf, scratchSz, &caKey, NULL, &rng), 0); wc_InitDecodedCert(&preTBS, scratchBuf, scratchSz, 0); ExpectIntEQ(wc_ParseCert(&preTBS, CERT_TYPE, NO_VERIFY, NULL), 0); XMEMSET(preTbsBuf, 0, preTbsSz); ExpectIntGT(preTbsSz = wc_GeneratePreTBS(&preTBS, preTbsBuf, preTbsSz), 0); XMEMSET(altSigValBuf, 0, altSigValSz); ExpectIntGT(altSigValSz = wc_MakeSigWithBitStr(altSigValBuf, altSigValSz, CTC_SHA256wECDSA, preTbsBuf, preTbsSz, ECC_TYPE, &altCaKey, &rng), 0); ExpectIntEQ(wc_SetCustomExtension(&newCert, setCrit, "2.5.29.74", altSigValBuf, altSigValSz), 0); /* Finally, generate the new certificate. */ if (outBuf != NULL) { XMEMSET(outBuf, 0, outSz); ExpectIntGT(outSz = wc_SignCert(newCert.bodySz, newCert.sigType, scratchBuf, outSz, &caKey, NULL, &rng), 0); *out = outBuf; } else { outSz = 0; } wc_FreeDecodedCert(&preTBS); wc_ecc_free(&altCaKey); wc_FreeRsaKey(&serverKey); wc_FreeRsaKey(&caKey); wc_FreeRng(&rng); return (int)outSz; } /** * Test dual-alg ECDSA + ML-DSA with critical extensions and path length * constraints: * - keygen + certgen * * TLS tests not designed to pass with these extensions marked critical. No * TLS connection. * */ static int test_dual_alg_crit_ext_support(void) { EXPECT_DECLS; /* Root CA and server keys will be the same. This is only appropriate for * testing. */ char keyFile[] = "./certs/ca-key.der"; char sapkiFile[] = "./certs/ecc-keyPub.der"; char altPrivFile[] = "./certs/ecc-key.der"; byte *serverKey = NULL; size_t serverKeySz = 0; byte *root = NULL; int rootSz = 0; byte *server = NULL; int serverSz = 0; ExpectIntEQ(load_file(keyFile, &serverKey, &serverKeySz), 0); /* Test with critical extensions and pathlen set to 1 */ if (EXPECT_SUCCESS()) { rootSz = do_dual_alg_root_certgen_crit(&root, keyFile, sapkiFile, altPrivFile, 1, 1, 1); } ExpectNotNull(root); ExpectIntGT(rootSz, 0); if (EXPECT_SUCCESS()) { serverSz = do_dual_alg_server_certgen_crit(&server, keyFile, sapkiFile, altPrivFile, keyFile, root, rootSz, 1); } ExpectNotNull(server); ExpectIntGT(serverSz, 0); XFREE(root, NULL, DYNAMIC_TYPE_TMP_BUFFER); root = NULL; XFREE(server, NULL, DYNAMIC_TYPE_TMP_BUFFER); server = NULL; /* Test with critical extensions and pathlen set to 0 */ if (EXPECT_SUCCESS()) { rootSz = do_dual_alg_root_certgen_crit(&root, keyFile, sapkiFile, altPrivFile, 1, 1, 0); } ExpectNotNull(root); ExpectIntGT(rootSz, 0); if (EXPECT_SUCCESS()) { serverSz = do_dual_alg_server_certgen_crit(&server, keyFile, sapkiFile, altPrivFile, keyFile, root, rootSz, 1); } ExpectNotNull(server); ExpectIntGT(serverSz, 0); XFREE(root, NULL, DYNAMIC_TYPE_TMP_BUFFER); root = NULL; XFREE(server, NULL, DYNAMIC_TYPE_TMP_BUFFER); server = NULL; /* Test with critical alt extensions and no pathlen set */ if (EXPECT_SUCCESS()) { rootSz = do_dual_alg_root_certgen_crit(&root, keyFile, sapkiFile, altPrivFile, 1, 0, 0); } ExpectNotNull(root); ExpectIntGT(rootSz, 0); if (EXPECT_SUCCESS()) { serverSz = do_dual_alg_server_certgen_crit(&server, keyFile, sapkiFile, altPrivFile, keyFile, root, rootSz, 0); } ExpectNotNull(server); ExpectIntGT(serverSz, 0); XFREE(root, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(server, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(serverKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); return EXPECT_RESULT(); } static int test_dual_alg_support(void) { EXPECT_DECLS; /* Root CA and server keys will be the same. This is only appropriate for * testing. */ char keyFile[] = "./certs/ca-key.der"; char sapkiFile[] = "./certs/ecc-keyPub.der"; char altPrivFile[] = "./certs/ecc-key.der"; char wrongPrivFile[] = "./certs/ecc-client-key.der"; byte *serverKey = NULL; size_t serverKeySz = 0; byte *root = NULL; int rootSz = 0; byte *server = NULL; int serverSz = 0; ExpectIntEQ(load_file(keyFile, &serverKey, &serverKeySz), 0); /* Base normal case. */ if (EXPECT_SUCCESS()) { rootSz = do_dual_alg_root_certgen(&root, keyFile, sapkiFile, altPrivFile); } ExpectNotNull(root); ExpectIntGT(rootSz, 0); if (EXPECT_SUCCESS()) { serverSz = do_dual_alg_server_certgen(&server, keyFile, sapkiFile, altPrivFile, keyFile, root, rootSz); } ExpectNotNull(server); ExpectIntGT(serverSz, 0); ExpectIntEQ(do_dual_alg_tls13_connection(root, rootSz, server, serverSz, serverKey, (word32)serverKeySz, 0), TEST_SUCCESS); XFREE(root, NULL, DYNAMIC_TYPE_TMP_BUFFER); root = NULL; XFREE(server, NULL, DYNAMIC_TYPE_TMP_BUFFER); server = NULL; /* Now we try a negative case. Note that we use wrongPrivFile to generate * the alternative signature and then set negative_test to true for the * call to do_dual_alg_tls13_connection(). Its expecting a failed connection * because the signature won't verify. The exception is if * WOLFSSL_TRUST_PEER_CERT is defined. In that case, no verification happens * and this is no longer a negative test. */ if (EXPECT_SUCCESS()) { rootSz = do_dual_alg_root_certgen(&root, keyFile, sapkiFile, wrongPrivFile); } ExpectNotNull(root); ExpectIntGT(rootSz, 0); if (EXPECT_SUCCESS()) { serverSz = do_dual_alg_server_certgen(&server, keyFile, sapkiFile, wrongPrivFile, keyFile, root, rootSz); } ExpectNotNull(server); ExpectIntGT(serverSz, 0); #ifdef WOLFSSL_TRUST_PEER_CERT ExpectIntEQ(do_dual_alg_tls13_connection(root, rootSz, server, serverSz, serverKey, (word32)serverKeySz, 0), TEST_SUCCESS); #else ExpectIntEQ(do_dual_alg_tls13_connection(root, rootSz, server, serverSz, serverKey, (word32)serverKeySz, 1), TEST_SUCCESS); #endif XFREE(root, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(server, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(serverKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); return EXPECT_RESULT(); } #else static int test_dual_alg_support(void) { return TEST_SKIPPED; } static int test_dual_alg_crit_ext_support(void) { return TEST_SKIPPED; } #endif /* WOLFSSL_DUAL_ALG_CERTS && !NO_FILESYSTEM */ /** * Test dual-alg ECDSA + ML-DSA: * - keygen + certgen + cert manager load * */ static int test_dual_alg_ecdsa_mldsa(void) { EXPECT_DECLS; #if defined(WOLFSSL_DUAL_ALG_CERTS) && defined(HAVE_DILITHIUM) && \ defined(HAVE_ECC) && !defined(WC_NO_RNG) && \ !defined(WOLFSSL_DILITHIUM_NO_MAKE_KEY) && \ !defined(WOLFSSL_DILITHIUM_NO_SIGN) && \ !defined(WOLFSSL_DILITHIUM_NO_VERIFY) && !defined(WOLFSSL_SMALL_STACK) WOLFSSL_CERT_MANAGER * cm = NULL; MlDsaKey alt_ca_key; ecc_key ca_key; WC_RNG rng; int ret = 0; DecodedCert d_cert; Cert new_cert; /* various tmp buffs. */ byte alt_pub_der[LARGE_TEMP_SZ]; word32 alt_pub_sz = LARGE_TEMP_SZ; byte alt_sig_alg[LARGE_TEMP_SZ]; word32 alt_sig_alg_sz = LARGE_TEMP_SZ; byte tbs_der[LARGE_TEMP_SZ]; word32 tbs_der_sz = LARGE_TEMP_SZ; byte alt_sig[LARGE_TEMP_SZ]; word32 alt_sig_sz = LARGE_TEMP_SZ; /* Intermediate der. */ byte der[LARGE_TEMP_SZ]; word32 der_sz = LARGE_TEMP_SZ; /* The final der will be large because of ML-DSA signature. */ byte final_der[2 * LARGE_TEMP_SZ]; word32 final_der_sz = 2 * LARGE_TEMP_SZ; XMEMSET(alt_pub_der, 0, alt_pub_sz); XMEMSET(alt_sig_alg, 0, alt_sig_alg_sz); XMEMSET(tbs_der, 0, tbs_der_sz); XMEMSET(alt_sig, 0, alt_sig_sz); XMEMSET(der, 0, der_sz); XMEMSET(final_der, 0, final_der_sz); ExpectIntEQ(wc_InitRng(&rng), 0); /** * ML-DSA key gen. * */ ret = wc_MlDsaKey_Init(&alt_ca_key, NULL, INVALID_DEVID); ExpectIntEQ(ret, 0); ret = wc_MlDsaKey_SetParams(&alt_ca_key, WC_ML_DSA_44); ExpectIntEQ(ret, 0); ret = wc_MlDsaKey_MakeKey(&alt_ca_key, &rng); ExpectIntEQ(ret, 0); alt_pub_sz = wc_MlDsaKey_PublicKeyToDer(&alt_ca_key, alt_pub_der, alt_pub_sz, 1); ExpectIntGT(alt_pub_sz, 0); alt_sig_alg_sz = SetAlgoID(CTC_SHA256wECDSA, alt_sig_alg, oidSigType, 0); ExpectIntGT(alt_sig_alg_sz, 0); /** * ECC key gen. * */ ret = wc_ecc_init(&ca_key); ExpectIntEQ(ret, 0); ret = wc_ecc_make_key(&rng, KEY32, &ca_key); ExpectIntEQ(ret, 0); /** * Cert gen. * */ wc_InitCert(&new_cert); strncpy(new_cert.subject.country, "US", CTC_NAME_SIZE); strncpy(new_cert.subject.state, "MT", CTC_NAME_SIZE); strncpy(new_cert.subject.locality, "Bozeman", CTC_NAME_SIZE); strncpy(new_cert.subject.org, "wolfSSL", CTC_NAME_SIZE); strncpy(new_cert.subject.unit, "Engineering", CTC_NAME_SIZE); strncpy(new_cert.subject.commonName, "www.wolfssl.com", CTC_NAME_SIZE); strncpy(new_cert.subject.email, "root@wolfssl.com", CTC_NAME_SIZE); new_cert.sigType = CTC_SHA256wECDSA; new_cert.isCA = 1; ret = wc_SetCustomExtension(&new_cert, 0, "1.2.3.4.5", (const byte *)"This is NOT a critical extension", 32); ExpectIntEQ(ret, 0); ExpectIntEQ(wc_SetCustomExtension(&new_cert, 0, "2.5.29.72", alt_pub_der, alt_pub_sz), 0); ExpectIntEQ(wc_SetCustomExtension(&new_cert, 0, "2.5.29.73", alt_sig_alg, alt_sig_alg_sz), 0); ret = wc_MakeCert_ex(&new_cert, der, der_sz, ECC_TYPE, &ca_key, &rng); ExpectIntGT(ret, 0); der_sz = wc_SignCert_ex(new_cert.bodySz, new_cert.sigType, der, der_sz, ECC_TYPE, &ca_key, &rng); ExpectIntGT(der_sz, 0); wc_InitDecodedCert(&d_cert, der, der_sz, 0); ret = wc_ParseCert(&d_cert, CERT_TYPE, NO_VERIFY, NULL); ExpectIntEQ(ret, 0); tbs_der_sz = wc_GeneratePreTBS(&d_cert, tbs_der, tbs_der_sz); ExpectIntGT(tbs_der_sz, 0); alt_sig_sz = wc_MakeSigWithBitStr(alt_sig, alt_sig_sz, CTC_ML_DSA_LEVEL2, tbs_der, tbs_der_sz, ML_DSA_LEVEL2_TYPE, &alt_ca_key, &rng); ExpectIntGT(alt_sig_sz, 0); ret = wc_SetCustomExtension(&new_cert, 0, "2.5.29.74", alt_sig, alt_sig_sz); ExpectIntEQ(ret, 0); /* Finally generate the new certificate. */ ret = wc_MakeCert_ex(&new_cert, final_der, final_der_sz, ECC_TYPE, &ca_key, &rng); ExpectIntGT(ret, 0); final_der_sz = wc_SignCert_ex(new_cert.bodySz, new_cert.sigType, final_der, final_der_sz, ECC_TYPE, &ca_key, &rng); ExpectIntGT(final_der_sz, 0); cm = wolfSSL_CertManagerNew(); ExpectNotNull(cm); /* Load the certificate into CertManager. */ if (cm != NULL && final_der_sz > 0) { ret = wolfSSL_CertManagerLoadCABuffer(cm, final_der, final_der_sz, WOLFSSL_FILETYPE_ASN1); ExpectIntEQ(ret, WOLFSSL_SUCCESS); } if (cm != NULL) { wolfSSL_CertManagerFree(cm); cm = NULL; } wc_FreeDecodedCert(&d_cert); wc_ecc_free(&ca_key); wc_MlDsaKey_Free(&alt_ca_key); wc_FreeRng(&rng); #endif /* WOLFSSL_DUAL_ALG_CERTS && DILITHIUM and more */ return EXPECT_RESULT(); } /* Test wolfSSL_use_AltPrivateKey_Id. * Verify that a valid key ID can be set successfully. Guards against an * inverted AllocDer return check (== 0 vs != 0) that would treat successful * allocation as failure. */ static int test_wolfSSL_use_AltPrivateKey_Id(void) { EXPECT_DECLS; #if defined(WOLF_PRIVATE_KEY_ID) && defined(WOLFSSL_DUAL_ALG_CERTS) && \ !defined(NO_TLS) && !defined(NO_WOLFSSL_CLIENT) WOLFSSL_CTX* ctx = NULL; WOLFSSL* ssl = NULL; const unsigned char id[] = { 0x01, 0x02, 0x03, 0x04 }; ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); ExpectNotNull(ssl = wolfSSL_new(ctx)); /* Negative tests. */ ExpectIntEQ(wolfSSL_use_AltPrivateKey_Id(NULL, id, sizeof(id), INVALID_DEVID), 0); ExpectIntEQ(wolfSSL_use_AltPrivateKey_Id(ssl, NULL, sizeof(id), INVALID_DEVID), 0); /* Positive test - valid ID should succeed. */ ExpectIntEQ(wolfSSL_use_AltPrivateKey_Id(ssl, id, sizeof(id), INVALID_DEVID), 1); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #endif /* WOLF_PRIVATE_KEY_ID && WOLFSSL_DUAL_ALG_CERTS && !NO_TLS && */ /* !NO_WOLFSSL_CLIENT */ return EXPECT_RESULT(); } /* Test wolfSSL_use_AltPrivateKey_Label. * Verify that a valid key label can be set successfully. Guards against an * inverted AllocDer return check (== 0 vs != 0) that would treat successful * allocation as failure. */ static int test_wolfSSL_use_AltPrivateKey_Label(void) { EXPECT_DECLS; #if defined(WOLF_PRIVATE_KEY_ID) && defined(WOLFSSL_DUAL_ALG_CERTS) && \ !defined(NO_TLS) && !defined(NO_WOLFSSL_CLIENT) WOLFSSL_CTX* ctx = NULL; WOLFSSL* ssl = NULL; ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); ExpectNotNull(ssl = wolfSSL_new(ctx)); /* Negative tests. */ ExpectIntEQ(wolfSSL_use_AltPrivateKey_Label(NULL, "label", INVALID_DEVID), 0); ExpectIntEQ(wolfSSL_use_AltPrivateKey_Label(ssl, NULL, INVALID_DEVID), 0); /* Positive test - valid label should succeed. */ ExpectIntEQ(wolfSSL_use_AltPrivateKey_Label(ssl, "test_label", INVALID_DEVID), 1); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #endif /* WOLF_PRIVATE_KEY_ID && WOLFSSL_DUAL_ALG_CERTS && !NO_TLS && */ /* !NO_WOLFSSL_CLIENT */ return EXPECT_RESULT(); } /*----------------------------------------------------------------------------* | Context *----------------------------------------------------------------------------*/ #if !defined(NO_WOLFSSL_SERVER) && !defined(NO_TLS) static int test_wolfSSL_CTX_new(void) { EXPECT_DECLS; WOLFSSL_CTX *ctx; WOLFSSL_METHOD* method = NULL; ExpectNull(ctx = wolfSSL_CTX_new(NULL)); ExpectNotNull(method = wolfSSLv23_server_method()); if (method != NULL) ExpectNotNull(ctx = wolfSSL_CTX_new(method)); wolfSSL_CTX_free(ctx); return EXPECT_RESULT(); } #endif #if (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) && \ !defined(NO_TLS) && \ (!defined(NO_RSA) || defined(HAVE_ECC)) && !defined(NO_FILESYSTEM) static int test_for_double_Free(void) { EXPECT_DECLS; WOLFSSL_CTX* ctx = NULL; WOLFSSL* ssl = NULL; int skipTest = 0; const char* testCertFile; const char* testKeyFile; char optionsCiphers[] = "RC4-SHA:RC4-MD5:DES-CBC3-SHA:AES128-SHA:AES256-SHA" ":NULL-SHA:NULL-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-PSK-AES256-GCM" "-SHA384:DHE-PSK-AES128-GCM-SHA256:PSK-AES256-GCM-SHA384:PSK-AES128-GCM-SHA256:" "DHE-PSK-AES256-CBC-SHA384:DHE-PSK-AES128-CBC-SHA256:PSK-AES256-CBC-SHA384:PSK-" "AES128-CBC-SHA256:PSK-AES128-CBC-SHA:PSK-AES256-CBC-SHA:DHE-PSK-AES128-CCM:DHE" "-PSK-AES256-CCM:PSK-AES128-CCM:PSK-AES256-CCM:PSK-AES128-CCM-8:PSK-AES256-CCM-" "8:DHE-PSK-NULL-SHA384:DHE-PSK-NULL-SHA256:PSK-NULL-SHA384:PSK-NULL-SHA256:PSK-" "NULL-SHA:AES128-CCM-8:AES256-CCM-8:ECDHE-ECDSA-" "AES128-CCM:ECDHE-ECDSA-AES128-CCM-8:ECDHE-ECDSA-AES256-CCM-8:ECDHE-RSA-AES128-" "SHA:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA:ECDHE-R" "SA-RC4-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-RC4-SHA:ECDHE-ECDSA-DES-CBC3-SHA" ":AES128-SHA256:AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:ECDH-" "RSA-AES128-SHA:ECDH-RSA-AES256-SHA:ECDH-ECDSA-AES128-SHA:ECDH-ECDSA-AES256-SHA" ":ECDH-RSA-RC4-SHA:ECDH-RSA-DES-CBC3-SHA:ECDH-ECDSA-RC4-SHA:ECDH-ECDSA-DES-CBC3" "-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES" "256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-E" "CDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDH-RSA-AES128-GCM-SHA25" "6:ECDH-RSA-AES256-GCM-SHA384:ECDH-ECDSA-AES128-GCM-SHA256:ECDH-ECDSA-AES256-GC" "M-SHA384:CAMELLIA128-SHA:DHE-RSA-CAMELLIA128-SHA:CAMELLIA256-SHA:DHE-RSA-CAMEL" "LIA256-SHA:CAMELLIA128-SHA256:DHE-RSA-CAMELLIA128-SHA256:CAMELLIA256-SHA256:DH" "E-RSA-CAMELLIA256-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECD" "H-RSA-AES128-SHA256:ECDH-ECDSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-ECD" "SA-AES256-SHA384:ECDH-RSA-AES256-SHA384:ECDH-ECDSA-AES256-SHA384:ECDHE-RSA-CHA" "CHA20-POLY1305:ECDHE-ECDSA-CHACHA20-POLY1305:DHE-RSA-CHACHA20-POLY1305:ECDHE-R" "SA-CHACHA20-POLY1305-OLD:ECDHE-ECDSA-CHACHA20-POLY1305-OLD:DHE-RSA-CHACHA20-PO" "LY1305-OLD:ECDHE-ECDSA-NULL-SHA:ECDHE-PSK-NULL-SHA256:ECDHE-PSK-A" "ES128-CBC-SHA256:PSK-CHACHA20-POLY1305:ECDHE-PSK-CHACHA20-POLY1305:DHE-PSK-CHA" "CHA20-POLY1305:EDH-RSA-DES-CBC3-SHA:TLS13-AES128-GCM-SHA256:TLS13-AES256-GCM-S" "HA384:TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES128-CCM-SHA256:TLS13-AES128-CCM-" "8-SHA256:TLS13-SHA256-SHA256:TLS13-SHA384-SHA384"; /* OpenVPN uses a "blacklist" method to specify which ciphers NOT to use */ #ifdef OPENSSL_EXTRA char openvpnCiphers[] = "DEFAULT:!EXP:!LOW:!MEDIUM:!kDH:!kECDH:!DSS:!PSK:" "!SRP:!kRSA:!aNULL:!eNULL"; #endif #ifndef NO_RSA testCertFile = svrCertFile; testKeyFile = svrKeyFile; #elif defined(HAVE_ECC) testCertFile = eccCertFile; testKeyFile = eccKeyFile; #else skipTest = 1; #endif if (skipTest != 1) { #ifndef NO_WOLFSSL_SERVER ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); #else ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); #endif ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx, testCertFile, CERT_FILETYPE)); ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, testKeyFile, CERT_FILETYPE)); ExpectNotNull(ssl = wolfSSL_new(ctx)); /* First test freeing SSL, then CTX */ wolfSSL_free(ssl); ssl = NULL; wolfSSL_CTX_free(ctx); ctx = NULL; #ifndef NO_WOLFSSL_CLIENT ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); #else ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); #endif ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx, testCertFile, CERT_FILETYPE)); ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, testKeyFile, CERT_FILETYPE)); ExpectNotNull(ssl = wolfSSL_new(ctx)); /* Next test freeing CTX then SSL */ wolfSSL_CTX_free(ctx); ctx = NULL; wolfSSL_free(ssl); ssl = NULL; #ifndef NO_WOLFSSL_SERVER ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); #else ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); #endif /* Test setting ciphers at ctx level */ ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx, testCertFile, CERT_FILETYPE)); ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, testKeyFile, CERT_FILETYPE)); ExpectTrue(wolfSSL_CTX_set_cipher_list(ctx, optionsCiphers)); #if defined(OPENSSL_EXTRA) && defined(WOLFSSL_TLS13) && defined(HAVE_AESGCM) && \ defined(WOLFSSL_SHA384) && defined(WOLFSSL_AES_256) /* only update TLSv13 suites */ ExpectTrue(wolfSSL_CTX_set_cipher_list(ctx, "TLS13-AES256-GCM-SHA384")); #endif #if defined(OPENSSL_EXTRA) && defined(HAVE_ECC) && defined(HAVE_AESGCM) && \ !defined(NO_SHA256) && !defined(WOLFSSL_NO_TLS12) && \ defined(WOLFSSL_AES_128) && !defined(NO_RSA) /* only update pre-TLSv13 suites */ ExpectTrue(wolfSSL_CTX_set_cipher_list(ctx, "ECDHE-RSA-AES128-GCM-SHA256")); #endif #ifdef OPENSSL_EXTRA ExpectTrue(wolfSSL_CTX_set_cipher_list(ctx, openvpnCiphers)); #endif ExpectNotNull(ssl = wolfSSL_new(ctx)); wolfSSL_CTX_free(ctx); ctx = NULL; wolfSSL_free(ssl); ssl = NULL; #ifndef NO_WOLFSSL_CLIENT ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); #else ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); #endif ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx, testCertFile, CERT_FILETYPE)); ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, testKeyFile, CERT_FILETYPE)); ExpectNotNull(ssl = wolfSSL_new(ctx)); /* test setting ciphers at SSL level */ ExpectTrue(wolfSSL_set_cipher_list(ssl, optionsCiphers)); #if defined(OPENSSL_EXTRA) && defined(WOLFSSL_TLS13) && defined(HAVE_AESGCM) && \ defined(WOLFSSL_SHA384) && defined(WOLFSSL_AES_256) /* only update TLSv13 suites */ ExpectTrue(wolfSSL_set_cipher_list(ssl, "TLS13-AES256-GCM-SHA384")); #endif #if defined(OPENSSL_EXTRA) && defined(HAVE_ECC) && defined(HAVE_AESGCM) && \ !defined(NO_SHA256) && !defined(WOLFSSL_NO_TLS12) && \ defined(WOLFSSL_AES_128) && !defined(NO_RSA) /* only update pre-TLSv13 suites */ ExpectTrue(wolfSSL_set_cipher_list(ssl, "ECDHE-RSA-AES128-GCM-SHA256")); #endif wolfSSL_CTX_free(ctx); ctx = NULL; wolfSSL_free(ssl); ssl = NULL; } return EXPECT_RESULT(); } #endif static int test_wolfSSL_CTX_set_cipher_list_bytes(void) { EXPECT_DECLS; #if (defined(OPENSSL_EXTRA) || defined(WOLFSSL_SET_CIPHER_BYTES)) && \ (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) && \ (!defined(NO_RSA) || defined(HAVE_ECC)) && !defined(NO_FILESYSTEM) && \ !defined(NO_TLS) const char* testCertFile; const char* testKeyFile; WOLFSSL_CTX* ctx = NULL; WOLFSSL* ssl = NULL; const byte cipherList[] = { /* TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA */ 0x00, 0x16, /* TLS_DHE_RSA_WITH_AES_256_CBC_SHA */ 0x00, 0x39, /* TLS_DHE_RSA_WITH_AES_128_CBC_SHA */ 0x00, 0x33, /* TLS_DH_anon_WITH_AES_128_CBC_SHA */ 0x00, 0x34, /* TLS_RSA_WITH_AES_256_CBC_SHA */ 0x00, 0x35, /* TLS_RSA_WITH_AES_128_CBC_SHA */ 0x00, 0x2F, /* TLS_RSA_WITH_NULL_MD5 */ 0x00, 0x01, /* TLS_RSA_WITH_NULL_SHA */ 0x00, 0x02, /* TLS_PSK_WITH_AES_256_CBC_SHA */ 0x00, 0x8d, /* TLS_PSK_WITH_AES_128_CBC_SHA256 */ 0x00, 0xae, /* TLS_PSK_WITH_AES_256_CBC_SHA384 */ 0x00, 0xaf, /* TLS_PSK_WITH_AES_128_CBC_SHA */ 0x00, 0x8c, /* TLS_PSK_WITH_NULL_SHA256 */ 0x00, 0xb0, /* TLS_PSK_WITH_NULL_SHA384 */ 0x00, 0xb1, /* TLS_PSK_WITH_NULL_SHA */ 0x00, 0x2c, /* SSL_RSA_WITH_RC4_128_SHA */ 0x00, 0x05, /* SSL_RSA_WITH_RC4_128_MD5 */ 0x00, 0x04, /* SSL_RSA_WITH_3DES_EDE_CBC_SHA */ 0x00, 0x0A, /* ECC suites, first byte is 0xC0 (ECC_BYTE) */ /* TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA */ 0xC0, 0x14, /* TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA */ 0xC0, 0x13, /* TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA */ 0xC0, 0x0A, /* TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA */ 0xC0, 0x09, /* TLS_ECDHE_RSA_WITH_RC4_128_SHA */ 0xC0, 0x11, /* TLS_ECDHE_ECDSA_WITH_RC4_128_SHA */ 0xC0, 0x07, /* TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA */ 0xC0, 0x12, /* TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA */ 0xC0, 0x08, /* TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 */ 0xC0, 0x27, /* TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256*/ 0xC0, 0x23, /* TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 */ 0xC0, 0x28, /* TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384*/ 0xC0, 0x24, /* TLS_ECDHE_ECDSA_WITH_NULL_SHA */ 0xC0, 0x06, /* TLS_ECDHE_PSK_WITH_NULL_SHA256 */ 0xC0, 0x3a, /* TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 */ 0xC0, 0x37, /* static ECDH, first byte is 0xC0 (ECC_BYTE) */ /* TLS_ECDH_RSA_WITH_AES_256_CBC_SHA */ 0xC0, 0x0F, /* TLS_ECDH_RSA_WITH_AES_128_CBC_SHA */ 0xC0, 0x0E, /* TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA */ 0xC0, 0x05, /* TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA */ 0xC0, 0x04, /* TLS_ECDH_RSA_WITH_RC4_128_SHA */ 0xC0, 0x0C, /* TLS_ECDH_ECDSA_WITH_RC4_128_SHA */ 0xC0, 0x02, /* TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA */ 0xC0, 0x0D, /* TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA */ 0xC0, 0x03, /* TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 */ 0xC0, 0x29, /* TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 */ 0xC0, 0x25, /* TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 */ 0xC0, 0x2A, /* TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 */ 0xC0, 0x26, /* WDM_WITH_NULL_SHA256 */ 0x00, 0xFE, /* wolfSSL DTLS Multicast */ /* SHA256 */ /* TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 */ 0x00, 0x6b, /* TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 */ 0x00, 0x67, /* TLS_RSA_WITH_AES_256_CBC_SHA256 */ 0x00, 0x3d, /* TLS_RSA_WITH_AES_128_CBC_SHA256 */ 0x00, 0x3c, /* TLS_RSA_WITH_NULL_SHA256 */ 0x00, 0x3b, /* TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 */ 0x00, 0xb2, /* TLS_DHE_PSK_WITH_NULL_SHA256 */ 0x00, 0xb4, /* SHA384 */ /* TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 */ 0x00, 0xb3, /* TLS_DHE_PSK_WITH_NULL_SHA384 */ 0x00, 0xb5, /* AES-GCM */ /* TLS_RSA_WITH_AES_128_GCM_SHA256 */ 0x00, 0x9c, /* TLS_RSA_WITH_AES_256_GCM_SHA384 */ 0x00, 0x9d, /* TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 */ 0x00, 0x9e, /* TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 */ 0x00, 0x9f, /* TLS_DH_anon_WITH_AES_256_GCM_SHA384 */ 0x00, 0xa7, /* TLS_PSK_WITH_AES_128_GCM_SHA256 */ 0x00, 0xa8, /* TLS_PSK_WITH_AES_256_GCM_SHA384 */ 0x00, 0xa9, /* TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 */ 0x00, 0xaa, /* TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 */ 0x00, 0xab, /* ECC AES-GCM, first byte is 0xC0 (ECC_BYTE) */ /* TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 */ 0xC0, 0x2b, /* TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 */ 0xC0, 0x2c, /* TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 */ 0xC0, 0x2d, /* TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 */ 0xC0, 0x2e, /* TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 */ 0xC0, 0x2f, /* TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 */ 0xC0, 0x30, /* TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 */ 0xC0, 0x31, /* TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 */ 0xC0, 0x32, /* AES-CCM, first byte is 0xC0 but isn't ECC, * also, in some of the other AES-CCM suites * there will be second byte number conflicts * with non-ECC AES-GCM */ /* TLS_RSA_WITH_AES_128_CCM_8 */ 0xC0, 0xa0, /* TLS_RSA_WITH_AES_256_CCM_8 */ 0xC0, 0xa1, /* TLS_ECDHE_ECDSA_WITH_AES_128_CCM */ 0xC0, 0xac, /* TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 */ 0xC0, 0xae, /* TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 */ 0xC0, 0xaf, /* TLS_PSK_WITH_AES_128_CCM */ 0xC0, 0xa4, /* TLS_PSK_WITH_AES_256_CCM */ 0xC0, 0xa5, /* TLS_PSK_WITH_AES_128_CCM_8 */ 0xC0, 0xa8, /* TLS_PSK_WITH_AES_256_CCM_8 */ 0xC0, 0xa9, /* TLS_DHE_PSK_WITH_AES_128_CCM */ 0xC0, 0xa6, /* TLS_DHE_PSK_WITH_AES_256_CCM */ 0xC0, 0xa7, /* Camellia */ /* TLS_RSA_WITH_CAMELLIA_128_CBC_SHA */ 0x00, 0x41, /* TLS_RSA_WITH_CAMELLIA_256_CBC_SHA */ 0x00, 0x84, /* TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 */ 0x00, 0xba, /* TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 */ 0x00, 0xc0, /* TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA */ 0x00, 0x45, /* TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA */ 0x00, 0x88, /* TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 */ 0x00, 0xbe, /* TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 */ 0x00, 0xc4, /* chacha20-poly1305 suites first byte is 0xCC (CHACHA_BYTE) */ /* TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 */ 0xCC, 0xa8, /* TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 */ 0xCC, 0xa9, /* TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 */ 0xCC, 0xaa, /* TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 */ 0xCC, 0xac, /* TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 */ 0xCC, 0xab, /* TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 */ 0xCC, 0xad, /* chacha20-poly1305 earlier version of nonce and padding (CHACHA_BYTE) */ /* TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 */ 0xCC, 0x13, /* TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 */ 0xCC, 0x14, /* TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 */ 0xCC, 0x15, /* ECDHE_PSK RFC8442, first byte is 0xD0 (ECDHE_PSK_BYTE) */ /* TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256 */ 0xD0, 0x01, /* TLS v1.3 cipher suites */ /* TLS_AES_128_GCM_SHA256 */ 0x13, 0x01, /* TLS_AES_256_GCM_SHA384 */ 0x13, 0x02, /* TLS_CHACHA20_POLY1305_SHA256 */ 0x13, 0x03, /* TLS_AES_128_CCM_SHA256 */ 0x13, 0x04, /* TLS_AES_128_CCM_8_SHA256 */ 0x13, 0x05, /* TLS v1.3 Integrity only cipher suites - 0xC0 (ECC) first byte */ /* TLS_SHA256_SHA256 */ 0xC0, 0xB4, /* TLS_SHA384_SHA384 */ 0xC0, 0xB5 }; #ifndef NO_RSA testCertFile = svrCertFile; testKeyFile = svrKeyFile; #elif defined(HAVE_ECC) testCertFile = eccCertFile; testKeyFile = eccKeyFile; #endif #ifndef NO_WOLFSSL_SERVER ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); #else ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); #endif ExpectTrue(wolfSSL_CTX_set_cipher_list_bytes(ctx, &cipherList[0U], sizeof(cipherList))); wolfSSL_CTX_free(ctx); ctx = NULL; #ifndef NO_WOLFSSL_SERVER ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); #else ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); #endif ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx, testCertFile, CERT_FILETYPE)); ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, testKeyFile, CERT_FILETYPE)); ExpectNotNull(ssl = wolfSSL_new(ctx)); ExpectTrue(wolfSSL_set_cipher_list_bytes(ssl, &cipherList[0U], sizeof(cipherList))); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #endif /* (OPENSSL_EXTRA || WOLFSSL_SET_CIPHER_BYTES) && (!NO_WOLFSSL_CLIENT || !NO_WOLFSSL_SERVER) && (!NO_RSA || HAVE_ECC) */ return EXPECT_RESULT(); } #if defined(OPENSSL_EXTRA) && defined(WOLFSSL_TLS13) && \ !defined(WOLFSSL_NO_TLS12) && \ !defined(NO_WOLFSSL_CLIENT) && \ !defined(HAVE_RENEGOTIATION_INDICATION) && \ defined(HAVE_AESGCM) && \ ((!defined(NO_RSA) && defined(HAVE_ECC)) || !defined(NO_ERROR_STRINGS)) /* Helper function to check if TLS 1.3 suites exist in the suites list */ static int suites_has_tls13(const byte* suites, word16 suiteSz) { word16 i; for (i = 0; i < suiteSz; i += 2) { if (suites[i] == 0x13) { /* TLS13_BYTE */ return 1; } } return 0; } /* Helper function to check if TLS 1.2 (non-1.3) suites exist in the suites list */ static int suites_has_tls12(const byte* suites, word16 suiteSz) { word16 i; for (i = 0; i < suiteSz; i += 2) { if (suites[i] != 0x13) { /* Not TLS13_BYTE */ return 1; } } return 0; } #endif /* Test 1: SSLv23 + set TLS 1.2 cipher -> TLS 1.3 suites should still be there */ static int test_wolfSSL_set_cipher_list_tls12_keeps_tls13(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && defined(WOLFSSL_TLS13) && \ !defined(WOLFSSL_NO_TLS12) && \ !defined(NO_WOLFSSL_CLIENT) && \ !defined(HAVE_RENEGOTIATION_INDICATION) && \ defined(HAVE_AESGCM) && defined(HAVE_ECC) && !defined(NO_RSA) WOLFSSL_CTX* ctx = NULL; WOLFSSL* ssl = NULL; ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); ExpectNotNull(ssl = wolfSSL_new(ctx)); /* Set only a TLS 1.2 cipher suite */ ExpectIntEQ(wolfSSL_set_cipher_list(ssl, "ECDHE-RSA-AES128-GCM-SHA256"), WOLFSSL_SUCCESS); /* TLS 1.3 suites should still be present (downgrade is enabled) */ ExpectNotNull(ssl->suites); ExpectTrue(suites_has_tls13(ssl->suites->suites, ssl->suites->suiteSz)); /* The TLS 1.2 suite we set should also be there */ ExpectTrue(suites_has_tls12(ssl->suites->suites, ssl->suites->suiteSz)); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } /* Test 2: SSLv23 + set TLS 1.3 cipher -> TLS 1.2 suites should still be there */ static int test_wolfSSL_set_cipher_list_tls13_keeps_tls12(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && defined(WOLFSSL_TLS13) && \ !defined(WOLFSSL_NO_TLS12) && \ !defined(NO_WOLFSSL_CLIENT) && \ !defined(HAVE_RENEGOTIATION_INDICATION) && \ defined(HAVE_AESGCM) && !defined(NO_ERROR_STRINGS) WOLFSSL_CTX* ctx = NULL; WOLFSSL* ssl = NULL; ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); ExpectNotNull(ssl = wolfSSL_new(ctx)); /* Set only a TLS 1.3 cipher suite */ ExpectIntEQ(wolfSSL_set_cipher_list(ssl, "TLS_AES_128_GCM_SHA256"), WOLFSSL_SUCCESS); /* TLS 1.2 suites should still be present (downgrade is enabled) */ ExpectNotNull(ssl->suites); ExpectTrue(suites_has_tls12(ssl->suites->suites, ssl->suites->suiteSz)); /* The TLS 1.3 suite we set should also be there */ ExpectTrue(suites_has_tls13(ssl->suites->suites, ssl->suites->suiteSz)); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } /* Test 3: SSLv23 + SetVersion(TLS 1.2) + set TLS 1.2 cipher -> only that cipher */ static int test_wolfSSL_set_cipher_list_tls12_with_version(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && defined(WOLFSSL_TLS13) && \ !defined(WOLFSSL_NO_TLS12) && \ !defined(NO_WOLFSSL_CLIENT) && \ !defined(HAVE_RENEGOTIATION_INDICATION) && \ defined(HAVE_AESGCM) && defined(HAVE_ECC) && !defined(NO_RSA) WOLFSSL_CTX* ctx = NULL; WOLFSSL* ssl = NULL; ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); ExpectNotNull(ssl = wolfSSL_new(ctx)); /* Set protocol version to TLS 1.2 (this disables downgrade) */ ExpectIntEQ(wolfSSL_SetVersion(ssl, WOLFSSL_TLSV1_2), WOLFSSL_SUCCESS); /* Set only a TLS 1.2 cipher suite */ ExpectIntEQ(wolfSSL_set_cipher_list(ssl, "ECDHE-RSA-AES128-GCM-SHA256"), WOLFSSL_SUCCESS); /* Should have only TLS 1.2 suites (no TLS 1.3) since downgrade is disabled */ ExpectNotNull(ssl->suites); ExpectFalse(suites_has_tls13(ssl->suites->suites, ssl->suites->suiteSz)); /* Should have the TLS 1.2 suite we set */ ExpectTrue(suites_has_tls12(ssl->suites->suites, ssl->suites->suiteSz)); /* Should have exactly one cipher suite (2 bytes) */ ExpectIntEQ(ssl->suites->suiteSz, 2); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } /* Test 4: SSLv23 + SetVersion(TLS 1.3) + set TLS 1.3 cipher -> only that cipher */ static int test_wolfSSL_set_cipher_list_tls13_with_version(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && defined(WOLFSSL_TLS13) && \ !defined(WOLFSSL_NO_TLS12) && \ !defined(NO_WOLFSSL_CLIENT) && \ !defined(HAVE_RENEGOTIATION_INDICATION) && \ defined(HAVE_AESGCM) && !defined(NO_ERROR_STRINGS) WOLFSSL_CTX* ctx = NULL; WOLFSSL* ssl = NULL; ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); ExpectNotNull(ssl = wolfSSL_new(ctx)); /* Set protocol version to TLS 1.3 (this disables downgrade) */ ExpectIntEQ(wolfSSL_SetVersion(ssl, WOLFSSL_TLSV1_3), WOLFSSL_SUCCESS); /* Set only a TLS 1.3 cipher suite */ ExpectIntEQ(wolfSSL_set_cipher_list(ssl, "TLS_AES_128_GCM_SHA256"), WOLFSSL_SUCCESS); /* Should have only TLS 1.3 suites (no TLS 1.2) since downgrade is disabled */ ExpectNotNull(ssl->suites); ExpectFalse(suites_has_tls12(ssl->suites->suites, ssl->suites->suiteSz)); /* Should have the TLS 1.3 suite we set */ ExpectTrue(suites_has_tls13(ssl->suites->suites, ssl->suites->suiteSz)); /* Should have exactly one cipher suite (2 bytes) */ ExpectIntEQ(ssl->suites->suiteSz, 2); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } static int test_wolfSSL_set_alpn_protos_default_fails(void) { EXPECT_DECLS; #if defined(HAVE_ALPN) && defined(OPENSSL_EXTRA) && !defined(NO_BIO) && \ !defined(NO_WOLFSSL_CLIENT) { WOLFSSL_CTX* ctx = NULL; WOLFSSL* ssl = NULL; unsigned char p[] = { 6, 's', 'p', 'd', 'y', '/', '3' }; TLSX* ext = NULL; ALPN* alpn = NULL; ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); ExpectNotNull(ssl = wolfSSL_new(ctx)); #ifdef WOLFSSL_ERROR_CODE_OPENSSL ExpectIntEQ(wolfSSL_set_alpn_protos(ssl, p, sizeof(p)), 0); #else ExpectIntEQ(wolfSSL_set_alpn_protos(ssl, p, sizeof(p)), WOLFSSL_SUCCESS); #endif if (ssl != NULL) { ext = TLSX_Find(ssl->extensions, TLSX_APPLICATION_LAYER_PROTOCOL); ExpectNotNull(ext); if (ext != NULL) { alpn = (ALPN*)ext->data; ExpectNotNull(alpn); if (alpn != NULL) { ExpectTrue((alpn->options & WOLFSSL_ALPN_FAILED_ON_MISMATCH) != 0); ExpectIntEQ(alpn->options & WOLFSSL_ALPN_CONTINUE_ON_MISMATCH, 0); } } } wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); } #if !defined(NO_WOLFSSL_SERVER) && !defined(WOLFSSL_NO_TLS12) && \ !defined(SINGLE_THREADED) && defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) { struct test_memio_ctx test_ctx; WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL; WOLFSSL *ssl_c = NULL, *ssl_s = NULL; unsigned char client_protos[] = { 6, 's', 'p', 'd', 'y', '/', '3' }; const char* server_protos = "http/2"; WOLFSSL_ALERT_HISTORY h; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, wolfTLSv1_2_client_method, wolfTLSv1_2_server_method), 0); #ifdef WOLFSSL_ERROR_CODE_OPENSSL ExpectIntEQ(wolfSSL_set_alpn_protos(ssl_c, client_protos, sizeof(client_protos)), 0); #else ExpectIntEQ(wolfSSL_set_alpn_protos(ssl_c, client_protos, sizeof(client_protos)), WOLFSSL_SUCCESS); #endif ExpectIntEQ(wolfSSL_UseALPN(ssl_s, (char*)server_protos, (word32)XSTRLEN(server_protos), WOLFSSL_ALPN_FAILED_ON_MISMATCH), WOLFSSL_SUCCESS); ExpectIntNE(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); ExpectIntEQ(wolfSSL_get_alert_history(ssl_s, &h), WOLFSSL_SUCCESS); ExpectIntEQ(h.last_tx.code, no_application_protocol); ExpectIntEQ(h.last_tx.level, alert_fatal); wolfSSL_free(ssl_c); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_c); wolfSSL_CTX_free(ctx_s); } #endif #endif return EXPECT_RESULT(); } static int test_wolfSSL_CTX_use_certificate(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) || \ defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(HAVE_STUNNEL) || \ defined(WOLFSSL_NGINX) || defined(HAVE_POCO_LIB) || \ defined(WOLFSSL_HAPROXY) #if !defined(NO_TLS) && \ (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) WOLFSSL_CTX* ctx = NULL; X509* x509 = NULL; #ifndef NO_WOLFSSL_SERVER ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); #else ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); #endif ExpectNotNull(x509 = wolfSSL_X509_new()); /* Negative tests. */ ExpectIntEQ(SSL_CTX_use_certificate(NULL, NULL), 0); ExpectIntEQ(SSL_CTX_use_certificate(ctx, NULL), 0); ExpectIntEQ(SSL_CTX_use_certificate(NULL, x509), 0); /* Empty certificate */ ExpectIntEQ(SSL_CTX_use_certificate(ctx, x509), 0); wolfSSL_X509_free(x509); wolfSSL_CTX_free(ctx); #endif /* !NO_TLS && (!NO_WOLFSSL_CLIENT || !NO_WOLFSSL_SERVER) */ #endif return EXPECT_RESULT(); } static int test_wolfSSL_CTX_use_certificate_file(void) { EXPECT_DECLS; #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_TLS) && \ !defined(NO_WOLFSSL_SERVER) WOLFSSL_CTX *ctx = NULL; ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); /* invalid context */ ExpectFalse(wolfSSL_CTX_use_certificate_file(NULL, svrCertFile, CERT_FILETYPE)); /* invalid cert file */ ExpectFalse(wolfSSL_CTX_use_certificate_file(ctx, bogusFile, CERT_FILETYPE)); /* invalid cert type */ ExpectFalse(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile, 9999)); #ifdef NO_RSA /* rsa needed */ ExpectFalse(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile, CERT_FILETYPE)); #else /* success */ ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile, CERT_FILETYPE)); #endif wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } #if (defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO)) && !defined(NO_RSA) static int test_wolfSSL_CTX_use_certificate_ASN1(void) { EXPECT_DECLS; #if !defined(NO_CERTS) && !defined(NO_WOLFSSL_SERVER) && !defined(NO_ASN) && \ !defined(NO_TLS) WOLFSSL_CTX* ctx = NULL; ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); /* Failure cases. */ ExpectIntEQ(SSL_CTX_use_certificate_ASN1(NULL, 0, NULL ), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(SSL_CTX_use_certificate_ASN1(ctx , 0, NULL ), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(SSL_CTX_use_certificate_ASN1(NULL, 0, server_cert_der_2048), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(SSL_CTX_use_certificate_ASN1(ctx , 0, server_cert_der_2048), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(SSL_CTX_use_certificate_ASN1(ctx, sizeof_server_cert_der_2048, server_cert_der_2048), WOLFSSL_SUCCESS); wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } #endif /* (OPENSSL_ALL || WOLFSSL_ASIO) && !NO_RSA */ /* Test function for wolfSSL_CTX_use_certificate_buffer. Load cert into * context using buffer. * PRE: NO_CERTS not defined; USE_CERT_BUFFERS_2048 defined; compile with * --enable-testcert flag. */ static int test_wolfSSL_CTX_use_certificate_buffer(void) { EXPECT_DECLS; #if !defined(NO_CERTS) && !defined(NO_TLS) && !defined(NO_WOLFSSL_SERVER) && \ defined(USE_CERT_BUFFERS_2048) && !defined(NO_RSA) WOLFSSL_CTX* ctx = NULL; ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); /* Invalid parameters. */ ExpectIntEQ(wolfSSL_CTX_use_certificate_buffer(NULL, NULL, 0, WOLFSSL_FILETYPE_ASN1), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_CTX_use_certificate_buffer(ctx, NULL, 0, WOLFSSL_FILETYPE_ASN1), WC_NO_ERR_TRACE(ASN_PARSE_E)); ExpectIntEQ(wolfSSL_CTX_use_certificate_buffer(NULL, server_cert_der_2048, 0, WOLFSSL_FILETYPE_ASN1), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_CTX_use_certificate_buffer(ctx, server_cert_der_2048, 0, WOLFSSL_FILETYPE_ASN1), WC_NO_ERR_TRACE(ASN_PARSE_E)); ExpectIntEQ(wolfSSL_CTX_use_certificate_buffer(ctx, server_cert_der_2048, sizeof_server_cert_der_2048, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } /* END test_wolfSSL_CTX_use_certificate_buffer */ static int test_wolfSSL_use_certificate_buffer(void) { EXPECT_DECLS; #if !defined(NO_CERTS) && !defined(NO_TLS) && !defined(NO_WOLFSSL_CLIENT) && \ defined(USE_CERT_BUFFERS_2048) && !defined(NO_RSA) WOLFSSL_CTX* ctx = NULL; WOLFSSL* ssl = NULL; ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); ExpectNotNull(ssl = wolfSSL_new(ctx)); /* Invalid parameters. */ ExpectIntEQ(wolfSSL_use_certificate_buffer(NULL, NULL, 0, WOLFSSL_FILETYPE_ASN1), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_use_certificate_buffer(ssl, NULL, 0, WOLFSSL_FILETYPE_ASN1), WC_NO_ERR_TRACE(ASN_PARSE_E)); ExpectIntEQ(wolfSSL_use_certificate_buffer(NULL, client_cert_der_2048, 0, WOLFSSL_FILETYPE_ASN1), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_use_certificate_buffer(ssl, client_cert_der_2048, 0, WOLFSSL_FILETYPE_ASN1), WC_NO_ERR_TRACE(ASN_PARSE_E)); ExpectIntEQ(wolfSSL_use_certificate_buffer(ssl, client_cert_der_2048, sizeof_client_cert_der_2048, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } static int test_wolfSSL_CTX_use_PrivateKey_file(void) { EXPECT_DECLS; #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_TLS) && \ !defined(NO_WOLFSSL_SERVER) WOLFSSL_CTX *ctx = NULL; ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); /* invalid context */ ExpectFalse(wolfSSL_CTX_use_PrivateKey_file(NULL, svrKeyFile, CERT_FILETYPE)); /* invalid key file */ ExpectFalse(wolfSSL_CTX_use_PrivateKey_file(ctx, bogusFile, CERT_FILETYPE)); /* invalid key type */ ExpectFalse(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, 9999)); /* invalid key format */ #ifdef WOLFSSL_PEM_TO_DER ExpectFalse(wolfSSL_CTX_use_PrivateKey_file(ctx, "./certs/dh-priv-2048.pem", WOLFSSL_FILETYPE_PEM)); #else ExpectFalse(wolfSSL_CTX_use_PrivateKey_file(ctx, "./certs/dh-priv-2048.der", WOLFSSL_FILETYPE_ASN1)); #endif /* success */ #ifdef NO_RSA /* rsa needed */ ExpectFalse(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, CERT_FILETYPE)); #else /* success */ ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, CERT_FILETYPE)); #endif wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } static int test_wolfSSL_CTX_use_RSAPrivateKey_file(void) { EXPECT_DECLS; #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_TLS) && \ !defined(NO_WOLFSSL_SERVER) && defined(OPENSSL_EXTRA) WOLFSSL_CTX *ctx = NULL; ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); /* invalid context */ ExpectIntEQ(wolfSSL_CTX_use_RSAPrivateKey_file(NULL, svrKeyFile, WOLFSSL_FILETYPE_PEM), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); /* invalid key file */ ExpectIntEQ(wolfSSL_CTX_use_RSAPrivateKey_file(ctx, bogusFile, WOLFSSL_FILETYPE_PEM), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); /* invalid key type */ ExpectIntEQ(wolfSSL_CTX_use_RSAPrivateKey_file(ctx, svrKeyFile, 9999), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); /* success */ #ifdef NO_RSA /* rsa needed */ ExpectIntEQ(wolfSSL_CTX_use_RSAPrivateKey_file(ctx, svrKeyFile, WOLFSSL_FILETYPE_PEM), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); #else /* success */ ExpectIntEQ(wolfSSL_CTX_use_RSAPrivateKey_file(ctx, svrKeyFile, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); #endif wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } static int test_wolfSSL_use_RSAPrivateKey_file(void) { EXPECT_DECLS; #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_TLS) && \ !defined(NO_WOLFSSL_CLIENT) && defined(OPENSSL_EXTRA) WOLFSSL_CTX* ctx = NULL; WOLFSSL* ssl = NULL; ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); ExpectNotNull(ssl = SSL_new(ctx)); /* invalid context */ ExpectIntEQ(wolfSSL_use_RSAPrivateKey_file(NULL, svrKeyFile, WOLFSSL_FILETYPE_PEM), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* invalid key file */ ExpectIntEQ(wolfSSL_use_RSAPrivateKey_file(ssl, bogusFile, WOLFSSL_FILETYPE_PEM), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); /* invalid key type */ ExpectIntEQ(wolfSSL_use_RSAPrivateKey_file(ssl, svrKeyFile, 9999), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); /* success */ #ifdef NO_RSA /* rsa needed */ ExpectIntEQ(wolfSSL_use_RSAPrivateKey_file(ssl, svrKeyFile, WOLFSSL_FILETYPE_PEM), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); #else /* success */ ExpectIntEQ(wolfSSL_use_RSAPrivateKey_file(ssl, svrKeyFile, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); #endif wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } static int test_wolfSSL_CTX_use_PrivateKey(void) { EXPECT_DECLS; #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_TLS) && \ !defined(NO_WOLFSSL_SERVER) && defined(OPENSSL_EXTRA) WOLFSSL_CTX *ctx = NULL; WOLFSSL_EVP_PKEY* pkey = NULL; const unsigned char* p; (void)p; ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); ExpectNotNull(pkey = wolfSSL_EVP_PKEY_new()); ExpectIntEQ(wolfSSL_CTX_use_PrivateKey(NULL, NULL), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_CTX_use_PrivateKey(ctx, NULL), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_CTX_use_PrivateKey(NULL, pkey), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); /* No data. */ ExpectIntEQ(wolfSSL_CTX_use_PrivateKey(ctx, pkey), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); wolfSSL_EVP_PKEY_free(pkey); pkey = NULL; #if defined(USE_CERT_BUFFERS_2048) #if !defined(NO_RSA) p = client_key_der_2048; ExpectNotNull(pkey = d2i_PrivateKey(EVP_PKEY_RSA, NULL, &p, sizeof_client_key_der_2048)); #if defined(WOLFSSL_KEY_GEN) ExpectIntEQ(wolfSSL_CTX_use_PrivateKey(ctx, pkey), WOLFSSL_SUCCESS); #else ExpectIntEQ(wolfSSL_CTX_use_PrivateKey(ctx, pkey), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); #endif wolfSSL_EVP_PKEY_free(pkey); pkey = NULL; #endif #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(WOLFSSL_OPENSSH) #ifndef NO_DSA p = dsa_key_der_2048; ExpectNotNull(pkey = d2i_PrivateKey(EVP_PKEY_DSA, NULL, &p, sizeof_dsa_key_der_2048)); #if !defined(HAVE_SELFTEST) && (defined(WOLFSSL_KEY_GEN) || \ defined(WOLFSSL_CERT_GEN)) /* Not supported in ProcessBuffer. */ ExpectIntEQ(wolfSSL_CTX_use_PrivateKey(ctx, pkey), WC_NO_ERR_TRACE(WOLFSSL_BAD_FILE)); #else ExpectIntEQ(wolfSSL_CTX_use_PrivateKey(ctx, pkey), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); #endif wolfSSL_EVP_PKEY_free(pkey); pkey = NULL; #endif #endif /* WOLFSSL_QT || OPENSSL_ALL || WOLFSSL_OPENSSH */ #if !defined(NO_DH) && defined(OPENSSL_ALL) && \ (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)) p = dh_ffdhe_statickey_der_2048; ExpectNotNull(pkey = d2i_PrivateKey(EVP_PKEY_DH, NULL, &p, sizeof_dh_ffdhe_statickey_der_2048)); /* Not supported. */ ExpectIntEQ(wolfSSL_CTX_use_PrivateKey(ctx, pkey), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); wolfSSL_EVP_PKEY_free(pkey); pkey = NULL; #endif #endif /* USE_CERT_BUFFERS_2048 */ #if defined(HAVE_ECC) && defined(USE_CERT_BUFFERS_256) p = ecc_clikey_der_256; ExpectNotNull(pkey = d2i_PrivateKey(EVP_PKEY_EC, NULL, &p, sizeof_ecc_clikey_der_256)); ExpectIntEQ(wolfSSL_CTX_use_PrivateKey(ctx, pkey), WOLFSSL_SUCCESS); wolfSSL_EVP_PKEY_free(pkey); pkey = NULL; #endif ExpectNotNull(pkey = wolfSSL_EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, (unsigned char*)"01234567012345670123456701234567", 32)); ExpectIntEQ(wolfSSL_CTX_use_PrivateKey(ctx, pkey), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); wolfSSL_EVP_PKEY_free(pkey); pkey = NULL; wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } /* test both file and buffer versions along with unloading trusted peer certs */ static int test_wolfSSL_CTX_trust_peer_cert(void) { EXPECT_DECLS; #if !defined(NO_CERTS) && defined(WOLFSSL_TRUST_PEER_CERT) && \ !defined(NO_TLS) && !defined(NO_WOLFSSL_CLIENT) && !defined(NO_RSA) WOLFSSL_CTX *ctx = NULL; WOLFSSL* ssl = NULL; ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); ExpectNotNull(ssl = wolfSSL_new(ctx)); #if !defined(NO_FILESYSTEM) /* invalid file */ ExpectIntNE(wolfSSL_CTX_trust_peer_cert(ctx, NULL, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); ExpectIntNE(wolfSSL_CTX_trust_peer_cert(ctx, bogusFile, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); ExpectIntNE(wolfSSL_CTX_trust_peer_cert(ctx, cliCertFile, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); /* success */ ExpectIntEQ(wolfSSL_CTX_trust_peer_cert(ctx, cliCertFile, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); /* unload cert */ ExpectIntNE(wolfSSL_CTX_Unload_trust_peers(NULL), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_Unload_trust_peers(ctx), WOLFSSL_SUCCESS); /* invalid file */ ExpectIntNE(wolfSSL_trust_peer_cert(ssl, NULL, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); ExpectIntNE(wolfSSL_trust_peer_cert(ssl, bogusFile, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); ExpectIntNE(wolfSSL_trust_peer_cert(ssl, cliCertFile, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); /* success */ ExpectIntEQ(wolfSSL_trust_peer_cert(ssl, cliCertFile, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); #ifdef WOLFSSL_LOCAL_X509_STORE /* unload cert */ ExpectIntNE(wolfSSL_Unload_trust_peers(NULL), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_Unload_trust_peers(ssl), WOLFSSL_SUCCESS); #endif #endif /* Test of loading certs from buffers */ /* invalid buffer */ ExpectIntNE(wolfSSL_CTX_trust_peer_buffer(ctx, NULL, -1, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); /* success */ #ifdef USE_CERT_BUFFERS_1024 ExpectIntEQ(wolfSSL_CTX_trust_peer_buffer(ctx, client_cert_der_1024, sizeof_client_cert_der_1024, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); #endif #ifdef USE_CERT_BUFFERS_2048 ExpectIntEQ(wolfSSL_CTX_trust_peer_buffer(ctx, client_cert_der_2048, sizeof_client_cert_der_2048, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); #endif /* unload cert */ ExpectIntNE(wolfSSL_CTX_Unload_trust_peers(NULL), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_Unload_trust_peers(ctx), WOLFSSL_SUCCESS); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } static int test_wolfSSL_CTX_load_verify_locations(void) { EXPECT_DECLS; #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_TLS) && \ !defined(NO_WOLFSSL_CLIENT) WOLFSSL_CTX *ctx = NULL; #ifndef NO_RSA WOLFSSL_CERT_MANAGER* cm = NULL; #ifdef PERSIST_CERT_CACHE int cacheSz = 0; unsigned char* cache = NULL; int used = 0; #ifndef NO_FILESYSTEM const char* cacheFile = "./tests/cert_cache.tmp"; #endif int i; int t; int* p; #endif #endif #if !defined(NO_WOLFSSL_DIR) && !defined(WOLFSSL_TIRTOS) && \ defined(WOLFSSL_PEM_TO_DER) const char* load_certs_path = "./certs/external"; const char* load_no_certs_path = "./examples"; const char* load_expired_path = "./certs/test/expired"; #endif ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); /* invalid arguments */ ExpectIntEQ(wolfSSL_CTX_load_verify_locations(NULL, caCertFile, NULL), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx, NULL, NULL), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); /* invalid ca file */ ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx, bogusFile, NULL), WS_RETURN_CODE(WC_NO_ERR_TRACE(WOLFSSL_BAD_FILE), WC_NO_ERR_TRACE(WOLFSSL_FAILURE))); #if !defined(NO_WOLFSSL_DIR) && !defined(WOLFSSL_TIRTOS) && \ ((defined(WOLFSSL_QT) || defined(WOLFSSL_IGNORE_BAD_CERT_PATH)) && \ !(WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS & WOLFSSL_LOAD_FLAG_IGNORE_BAD_PATH_ERR)) /* invalid path */ ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx, NULL, bogusFile), WS_RETURN_CODE(WC_NO_ERR_TRACE(BAD_PATH_ERROR),WC_NO_ERR_TRACE(WOLFSSL_FAILURE))); #endif #if defined(WOLFSSL_QT) || defined(WOLFSSL_IGNORE_BAD_CERT_PATH) /* test ignoring the invalid path */ ExpectIntEQ(wolfSSL_CTX_load_verify_locations_ex(ctx, NULL, bogusFile, WOLFSSL_LOAD_FLAG_IGNORE_BAD_PATH_ERR), WOLFSSL_SUCCESS); #endif /* load ca cert */ #ifdef NO_RSA ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx, caCertFile, NULL), WS_RETURN_CODE(WC_NO_ERR_TRACE(ASN_UNKNOWN_OID_E),WC_NO_ERR_TRACE(WOLFSSL_FAILURE))); #else /* Skip the following test without RSA certs. */ ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx, caCertFile, NULL), WOLFSSL_SUCCESS); #ifdef PERSIST_CERT_CACHE /* Get cert cache size */ ExpectIntGT(cacheSz = wolfSSL_CTX_get_cert_cache_memsize(ctx), 0); ExpectNotNull(cache = (byte*)XMALLOC((size_t)cacheSz, NULL, DYNAMIC_TYPE_TMP_BUFFER)); ExpectIntEQ(wolfSSL_CTX_memsave_cert_cache(NULL, NULL, -1, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_CTX_memsave_cert_cache(ctx, NULL, -1, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_CTX_memsave_cert_cache(NULL, cache, -1, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_CTX_memsave_cert_cache(NULL, NULL, cacheSz, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_CTX_memsave_cert_cache(NULL, NULL, -1, &used), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_CTX_memsave_cert_cache(NULL, cache, cacheSz, &used), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_CTX_memsave_cert_cache(ctx, NULL, cacheSz, &used), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_CTX_memsave_cert_cache(ctx, cache, -1, &used), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_CTX_memsave_cert_cache(ctx, cache, cacheSz, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_CTX_memsave_cert_cache(ctx, cache, cacheSz - 10, &used), WC_NO_ERR_TRACE(BUFFER_E)); ExpectIntEQ(wolfSSL_CTX_memsave_cert_cache(ctx, cache, cacheSz, &used), 1); ExpectIntEQ(cacheSz, used); ExpectIntEQ(wolfSSL_CTX_memrestore_cert_cache(NULL, NULL, -1), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_CTX_memrestore_cert_cache(ctx, NULL, -1), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_CTX_memrestore_cert_cache(NULL, cache, -1), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_CTX_memrestore_cert_cache(NULL, NULL, cacheSz), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_CTX_memrestore_cert_cache(NULL, cache, cacheSz), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_CTX_memrestore_cert_cache(ctx, NULL, cacheSz), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_CTX_memrestore_cert_cache(ctx, cache, -1), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* Smaller than header. */ ExpectIntEQ(wolfSSL_CTX_memrestore_cert_cache(ctx, cache, 1), WC_NO_ERR_TRACE(BUFFER_E)); for (i = 1; i < cacheSz; i++) { ExpectIntEQ(wolfSSL_CTX_memrestore_cert_cache(ctx, cache, cacheSz - i), WC_NO_ERR_TRACE(BUFFER_E)); } if (EXPECT_SUCCESS()) { /* Modify header for bad results! */ p = (int*)cache; /* version */ t = p[0]; p[0] = 0xff; ExpectIntEQ(wolfSSL_CTX_memrestore_cert_cache(ctx, cache, cacheSz), WC_NO_ERR_TRACE(CACHE_MATCH_ERROR)); p[0] = t; p++; /* rows */ t = p[0]; p[0] = 0xff; ExpectIntEQ(wolfSSL_CTX_memrestore_cert_cache(ctx, cache, cacheSz), WC_NO_ERR_TRACE(CACHE_MATCH_ERROR)); p[0] = t; p++; /* columns[0] */ t = p[0]; p[0] = -1; ExpectIntEQ(wolfSSL_CTX_memrestore_cert_cache(ctx, cache, cacheSz), WC_NO_ERR_TRACE(PARSE_ERROR)); p[0] = t; p += CA_TABLE_SIZE; /* signerSz*/ t = p[0]; p[0] = 0xff; ExpectIntEQ(wolfSSL_CTX_memrestore_cert_cache(ctx, cache, cacheSz), WC_NO_ERR_TRACE(CACHE_MATCH_ERROR)); p[0] = t; } ExpectIntEQ(wolfSSL_CTX_memrestore_cert_cache(ctx, cache, cacheSz), 1); ExpectIntEQ(cacheSz = wolfSSL_CTX_get_cert_cache_memsize(ctx), used); #ifndef NO_FILESYSTEM ExpectIntEQ(wolfSSL_CTX_save_cert_cache(NULL, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_CTX_save_cert_cache(ctx, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_CTX_save_cert_cache(NULL, cacheFile), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_CTX_save_cert_cache(ctx, cacheFile), 1); ExpectIntEQ(wolfSSL_CTX_restore_cert_cache(NULL, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_CTX_restore_cert_cache(ctx, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_CTX_restore_cert_cache(NULL, cacheFile), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_CTX_restore_cert_cache(ctx, "no-file"), WC_NO_ERR_TRACE(WOLFSSL_BAD_FILE)); ExpectIntEQ(wolfSSL_CTX_restore_cert_cache(ctx, cacheFile), 1); /* File contents is not a cache. */ ExpectIntEQ(wolfSSL_CTX_restore_cert_cache(ctx, "./certs/ca-cert.pem"), WC_NO_ERR_TRACE(CACHE_MATCH_ERROR)); #endif XFREE(cache, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif /* Test unloading CA's */ ExpectIntEQ(wolfSSL_CTX_UnloadCAs(ctx), WOLFSSL_SUCCESS); #ifdef PERSIST_CERT_CACHE /* Verify no certs (result is less than cacheSz) */ ExpectIntGT(cacheSz, wolfSSL_CTX_get_cert_cache_memsize(ctx)); #endif /* load ca cert again */ ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx, caCertFile, NULL), WOLFSSL_SUCCESS); /* Test getting CERT_MANAGER */ ExpectNotNull(cm = wolfSSL_CTX_GetCertManager(ctx)); /* Test unloading CA's using CM */ ExpectIntEQ(wolfSSL_CertManagerUnloadCAs(cm), WOLFSSL_SUCCESS); #ifdef PERSIST_CERT_CACHE /* Verify no certs (result is less than cacheSz) */ ExpectIntGT(cacheSz, wolfSSL_CTX_get_cert_cache_memsize(ctx)); #endif #endif #if !defined(NO_WOLFSSL_DIR) && !defined(WOLFSSL_TIRTOS) && \ defined(WOLFSSL_PEM_TO_DER) /* Test loading CA certificates using a path */ #ifdef NO_RSA /* failure here okay since certs in external directory are RSA */ ExpectIntNE(wolfSSL_CTX_load_verify_locations_ex(ctx, NULL, load_certs_path, WOLFSSL_LOAD_FLAG_PEM_CA_ONLY), WOLFSSL_SUCCESS); #else ExpectIntEQ(wolfSSL_CTX_load_verify_locations_ex(ctx, NULL, load_certs_path, WOLFSSL_LOAD_FLAG_PEM_CA_ONLY), WOLFSSL_SUCCESS); #endif /* Test loading path with no files */ ExpectIntEQ(wolfSSL_CTX_load_verify_locations_ex(ctx, NULL, load_no_certs_path, WOLFSSL_LOAD_FLAG_PEM_CA_ONLY), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); /* Test loading expired CA certificates */ #ifdef NO_RSA ExpectIntNE(wolfSSL_CTX_load_verify_locations_ex(ctx, NULL, load_expired_path, WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY | WOLFSSL_LOAD_FLAG_PEM_CA_ONLY), WOLFSSL_SUCCESS); #else ExpectIntEQ(wolfSSL_CTX_load_verify_locations_ex(ctx, NULL, load_expired_path, WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY | WOLFSSL_LOAD_FLAG_PEM_CA_ONLY), WOLFSSL_SUCCESS); #endif /* Test loading CA certificates and ignoring all errors */ #ifdef NO_RSA ExpectIntEQ(wolfSSL_CTX_load_verify_locations_ex(ctx, NULL, load_certs_path, WOLFSSL_LOAD_FLAG_IGNORE_ERR), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); #else ExpectIntEQ(wolfSSL_CTX_load_verify_locations_ex(ctx, NULL, load_certs_path, WOLFSSL_LOAD_FLAG_IGNORE_ERR), WOLFSSL_SUCCESS); #endif #endif wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } static int test_wolfSSL_CTX_load_system_CA_certs(void) { int res = TEST_SKIPPED; #if defined(WOLFSSL_SYS_CA_CERTS) && !defined(NO_WOLFSSL_CLIENT) && \ !defined(NO_TLS) && (!defined(NO_RSA) || defined(HAVE_ECC)) && \ defined(WOLFSSL_PEM_TO_DER) WOLFSSL_CTX* ctx; byte dirValid = 0; int ret = 0; ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); if (ctx == NULL) { fprintf(stderr, "wolfSSL_CTX_new failed.\n"); ret = -1; } if (ret == 0) { #if defined(USE_WINDOWS_API) || defined(__APPLE__) || \ defined(NO_WOLFSSL_DIR) dirValid = 1; #else word32 numDirs; const char** caDirs = wolfSSL_get_system_CA_dirs(&numDirs); if (caDirs == NULL || numDirs == 0) { fprintf(stderr, "wolfSSL_get_system_CA_dirs failed.\n"); ret = -1; } else { ReadDirCtx dirCtx; word32 i; for (i = 0; i < numDirs; ++i) { if (wc_ReadDirFirst(&dirCtx, caDirs[i], NULL) == 0) { /* Directory isn't empty. */ dirValid = 1; wc_ReadDirClose(&dirCtx); break; } } } #endif } /* * If the directory isn't empty, we should be able to load CA * certs from it. On Windows/Mac, we assume the CA cert stores are * usable. */ if (ret == 0 && dirValid && wolfSSL_CTX_load_system_CA_certs(ctx) != WOLFSSL_SUCCESS) { fprintf(stderr, "wolfSSL_CTX_load_system_CA_certs failed.\n"); ret = -1; } #ifdef OPENSSL_EXTRA if (ret == 0 && wolfSSL_CTX_set_default_verify_paths(ctx) != WOLFSSL_SUCCESS) { fprintf(stderr, "wolfSSL_CTX_set_default_verify_paths failed.\n"); ret = -1; } #endif /* OPENSSL_EXTRA */ wolfSSL_CTX_free(ctx); res = TEST_RES_CHECK(ret == 0); #endif /* WOLFSSL_SYS_CA_CERTS && !NO_WOLFSSL_CLIENT */ return res; } static int test_wolfSSL_CheckOCSPResponse(void) { EXPECT_DECLS; #if defined(HAVE_OCSP) && defined(OPENSSL_EXTRA) && \ !defined(NO_RSA) && !defined(NO_SHA) const char* responseFile = "./certs/ocsp/test-response.der"; const char* responseMultiFile = "./certs/ocsp/test-multi-response.der"; const char* responseNoInternFile = "./certs/ocsp/test-response-nointern.der"; const char* caFile = "./certs/ocsp/root-ca-cert.pem"; OcspResponse* res = NULL; byte data[4096]; const unsigned char* pt; int dataSz = 0; /* initialize to mitigate spurious maybe-uninitialized from * gcc sanitizer with --enable-heapmath. */ XFILE f = XBADFILE; WOLFSSL_OCSP_BASICRESP* bs = NULL; WOLFSSL_X509_STORE* st = NULL; WOLFSSL_X509* issuer = NULL; ExpectTrue((f = XFOPEN(responseFile, "rb")) != XBADFILE); ExpectIntGT(dataSz = (word32)XFREAD(data, 1, sizeof(data), f), 0); if (f != XBADFILE) { XFCLOSE(f); f = XBADFILE; } pt = data; ExpectNotNull(res = wolfSSL_d2i_OCSP_RESPONSE(NULL, &pt, dataSz)); ExpectPtrEq(pt, data + dataSz); ExpectNotNull(issuer = wolfSSL_X509_load_certificate_file(caFile, SSL_FILETYPE_PEM)); ExpectNotNull(st = wolfSSL_X509_STORE_new()); ExpectIntEQ(wolfSSL_X509_STORE_add_cert(st, issuer), WOLFSSL_SUCCESS); ExpectNotNull(bs = wolfSSL_OCSP_response_get1_basic(res)); ExpectIntEQ(wolfSSL_OCSP_basic_verify(bs, NULL, st, 0), WOLFSSL_SUCCESS); wolfSSL_OCSP_BASICRESP_free(bs); bs = NULL; wolfSSL_OCSP_RESPONSE_free(res); res = NULL; wolfSSL_X509_STORE_free(st); st = NULL; wolfSSL_X509_free(issuer); issuer = NULL; /* check loading a response with optional certs */ ExpectTrue((f = XFOPEN(responseNoInternFile, "rb")) != XBADFILE); ExpectIntGT(dataSz = (word32)XFREAD(data, 1, sizeof(data), f), 0); if (f != XBADFILE) XFCLOSE(f); f = XBADFILE; pt = data; ExpectNotNull(res = wolfSSL_d2i_OCSP_RESPONSE(NULL, &pt, dataSz)); ExpectPtrEq(pt, data + dataSz); wolfSSL_OCSP_RESPONSE_free(res); res = NULL; /* check loading a response with multiple certs */ { WOLFSSL_CERT_MANAGER* cm = NULL; OcspEntry *entry = NULL; CertStatus* status = NULL; OcspRequest* request = NULL; byte serial1[] = {0x01}; byte serial[] = {0x02}; byte issuerHash[] = { 0x44, 0xA8, 0xDB, 0xD1, 0xBC, 0x97, 0x0A, 0x83, 0x3B, 0x5B, 0x31, 0x9A, 0x4C, 0xB8, 0xD2, 0x52, 0x37, 0x15, 0x8A, 0x88 }; byte issuerKeyHash[] = { 0x73, 0xB0, 0x1C, 0xA4, 0x2F, 0x82, 0xCB, 0xCF, 0x47, 0xA5, 0x38, 0xD7, 0xB0, 0x04, 0x82, 0x3A, 0x7E, 0x72, 0x15, 0x21 }; ExpectNotNull(entry = (OcspEntry*)XMALLOC(sizeof(OcspEntry), NULL, DYNAMIC_TYPE_OPENSSL)); ExpectNotNull(status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, DYNAMIC_TYPE_OPENSSL)); if (entry != NULL) XMEMSET(entry, 0, sizeof(OcspEntry)); if (status != NULL) XMEMSET(status, 0, sizeof(CertStatus)); ExpectNotNull(request = wolfSSL_OCSP_REQUEST_new()); ExpectNotNull(request->serial = (byte*)XMALLOC(sizeof(serial), NULL, DYNAMIC_TYPE_OCSP_REQUEST)); if (request != NULL && request->serial != NULL) { request->serialSz = sizeof(serial); XMEMCPY(request->serial, serial, sizeof(serial)); XMEMCPY(request->issuerHash, issuerHash, sizeof(issuerHash)); XMEMCPY(request->issuerKeyHash, issuerKeyHash, sizeof(issuerKeyHash)); } ExpectNotNull(cm = wolfSSL_CertManagerNew_ex(NULL)); ExpectIntEQ(wolfSSL_CertManagerEnableOCSP(cm, 0), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CertManagerLoadCA(cm, caFile, NULL), WOLFSSL_SUCCESS); ExpectTrue((f = XFOPEN(responseMultiFile, "rb")) != XBADFILE); ExpectIntGT(dataSz = (word32)XFREAD(data, 1, sizeof(data), f), 0); if (f != XBADFILE) XFCLOSE(f); f = XBADFILE; ExpectIntEQ(wolfSSL_CertManagerCheckOCSPResponse(cm, data, dataSz, NULL, status, entry, request), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CertManagerCheckOCSPResponse(cm, data, dataSz, NULL, entry->status, entry, request), WOLFSSL_SUCCESS); ExpectNotNull(entry->status); if (request != NULL && request->serial != NULL) XMEMCPY(request->serial, serial1, sizeof(serial1)); ExpectIntEQ(wolfSSL_CertManagerCheckOCSPResponse(cm, data, dataSz, NULL, status, entry, request), WOLFSSL_SUCCESS); /* store both status's in the entry to check that "next" is not * overwritten */ if (EXPECT_SUCCESS() && status != NULL && entry != NULL) { status->next = entry->status; entry->status = status; } if (request != NULL && request->serial != NULL) XMEMCPY(request->serial, serial, sizeof(serial)); ExpectIntEQ(wolfSSL_CertManagerCheckOCSPResponse(cm, data, dataSz, NULL, entry->status, entry, request), WOLFSSL_SUCCESS); ExpectNotNull(entry->status->next); /* compare the status found */ ExpectIntEQ(status->serialSz, entry->status->serialSz); ExpectIntEQ(XMEMCMP(status->serial, entry->status->serial, status->serialSz), 0); if (status != NULL && entry != NULL && entry->status != status) { XFREE(status, NULL, DYNAMIC_TYPE_OPENSSL); } wolfSSL_OCSP_CERTID_free(entry); wolfSSL_OCSP_REQUEST_free(request); wolfSSL_CertManagerFree(cm); } /* FIPS v2 and below don't support long salts. */ #if defined(WC_RSA_PSS) && \ (!defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \ (HAVE_FIPS_VERSION > 2))) && (!defined(HAVE_SELFTEST) || \ (defined(HAVE_SELFTEST_VERSION) && (HAVE_SELFTEST_VERSION > 2))) { const char* responsePssFile = "./certs/ocsp/test-response-rsapss.der"; /* check loading a response with RSA-PSS signature */ ExpectTrue((f = XFOPEN(responsePssFile, "rb")) != XBADFILE); ExpectIntGT(dataSz = (word32)XFREAD(data, 1, sizeof(data), f), 0); if (f != XBADFILE) XFCLOSE(f); pt = data; ExpectNotNull(res = wolfSSL_d2i_OCSP_RESPONSE(NULL, &pt, dataSz)); ExpectPtrEq(pt, data + dataSz); /* try to verify the response */ ExpectNotNull(issuer = wolfSSL_X509_load_certificate_file(caFile, SSL_FILETYPE_PEM)); ExpectNotNull(st = wolfSSL_X509_STORE_new()); ExpectIntEQ(wolfSSL_X509_STORE_add_cert(st, issuer), WOLFSSL_SUCCESS); ExpectNotNull(bs = wolfSSL_OCSP_response_get1_basic(res)); ExpectIntEQ(wolfSSL_OCSP_basic_verify(bs, NULL, st, 0), WOLFSSL_SUCCESS); wolfSSL_OCSP_BASICRESP_free(bs); wolfSSL_OCSP_RESPONSE_free(res); wolfSSL_X509_STORE_free(st); wolfSSL_X509_free(issuer); } #endif #endif /* HAVE_OCSP */ return EXPECT_RESULT(); } static int test_wolfSSL_FPKI(void) { EXPECT_DECLS; #if defined(WOLFSSL_FPKI) && !defined(NO_RSA) && !defined(NO_FILESYSTEM) XFILE f = XBADFILE; const char* fpkiCert = "./certs/fpki-cert.der"; const char* fpkiCertPolCert = "./certs/fpki-certpol-cert.der"; DecodedCert cert; byte buf[4096]; byte* uuid = NULL; byte* fascn = NULL; word32 fascnSz; word32 uuidSz; int bytes = 0; ExpectTrue((f = XFOPEN(fpkiCert, "rb")) != XBADFILE); ExpectIntGT(bytes = (int)XFREAD(buf, 1, sizeof(buf), f), 0); if (f != XBADFILE) XFCLOSE(f); wc_InitDecodedCert(&cert, buf, (word32)bytes, NULL); ExpectIntEQ(wc_ParseCert(&cert, CERT_TYPE, 0, NULL), 0); ExpectIntEQ(wc_GetFASCNFromCert(&cert, NULL, &fascnSz), WC_NO_ERR_TRACE(LENGTH_ONLY_E)); ExpectNotNull(fascn = (byte*)XMALLOC(fascnSz, NULL, DYNAMIC_TYPE_TMP_BUFFER)); ExpectIntEQ(wc_GetFASCNFromCert(&cert, fascn, &fascnSz), 0); XFREE(fascn, NULL, DYNAMIC_TYPE_TMP_BUFFER); fascn = NULL; ExpectIntEQ(wc_GetUUIDFromCert(&cert, NULL, &uuidSz), WC_NO_ERR_TRACE(LENGTH_ONLY_E)); ExpectNotNull(uuid = (byte*)XMALLOC(uuidSz, NULL, DYNAMIC_TYPE_TMP_BUFFER)); ExpectIntEQ(wc_GetUUIDFromCert(&cert, uuid, &uuidSz), 0); XFREE(uuid, NULL, DYNAMIC_TYPE_TMP_BUFFER); uuid = NULL; wc_FreeDecodedCert(&cert); XMEMSET(buf, 0, 4096); fascnSz = uuidSz = bytes = 0; f = XBADFILE; ExpectTrue((f = XFOPEN(fpkiCertPolCert, "rb")) != XBADFILE); ExpectIntGT(bytes = (int)XFREAD(buf, 1, sizeof(buf), f), 0); if (f != XBADFILE) XFCLOSE(f); wc_InitDecodedCert(&cert, buf, (word32)bytes, NULL); ExpectIntEQ(wc_ParseCert(&cert, CERT_TYPE, 0, NULL), 0); ExpectIntEQ(wc_GetFASCNFromCert(&cert, NULL, &fascnSz), WC_NO_ERR_TRACE(LENGTH_ONLY_E)); ExpectNotNull(fascn = (byte*)XMALLOC(fascnSz, NULL, DYNAMIC_TYPE_TMP_BUFFER)); ExpectIntEQ(wc_GetFASCNFromCert(&cert, fascn, &fascnSz), 0); XFREE(fascn, NULL, DYNAMIC_TYPE_TMP_BUFFER); ExpectIntEQ(wc_GetUUIDFromCert(&cert, NULL, &uuidSz), WC_NO_ERR_TRACE(LENGTH_ONLY_E)); ExpectNotNull(uuid = (byte*)XMALLOC(uuidSz, NULL, DYNAMIC_TYPE_TMP_BUFFER)); ExpectIntEQ(wc_GetUUIDFromCert(&cert, uuid, &uuidSz), 0); XFREE(uuid, NULL, DYNAMIC_TYPE_TMP_BUFFER); wc_FreeDecodedCert(&cert); #endif return EXPECT_RESULT(); } /* use RID in confuncture with other names to test parsing of unknown other * names */ static int test_wolfSSL_OtherName(void) { EXPECT_DECLS; #if !defined(NO_RSA) && !defined(NO_FILESYSTEM) XFILE f = XBADFILE; const char* ridCert = "./certs/rid-cert.der"; DecodedCert cert; byte buf[4096]; int bytes = 0; ExpectTrue((f = XFOPEN(ridCert, "rb")) != XBADFILE); ExpectIntGT(bytes = (int)XFREAD(buf, 1, sizeof(buf), f), 0); if (f != XBADFILE) XFCLOSE(f); wc_InitDecodedCert(&cert, buf, (word32)bytes, NULL); ExpectIntEQ(wc_ParseCert(&cert, CERT_TYPE, 0, NULL), 0); wc_FreeDecodedCert(&cert); #endif return EXPECT_RESULT(); } #ifdef HAVE_CERT_CHAIN_VALIDATION #ifndef WOLFSSL_TEST_APPLE_NATIVE_CERT_VALIDATION static int test_wolfSSL_CertRsaPss(void) { EXPECT_DECLS; /* FIPS v2 and below don't support long salts. */ #if !defined(NO_RSA) && defined(WC_RSA_PSS) && !defined(NO_FILESYSTEM) && \ (!defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \ (HAVE_FIPS_VERSION > 2))) && (!defined(HAVE_SELFTEST) || \ (defined(HAVE_SELFTEST_VERSION) && (HAVE_SELFTEST_VERSION > 2))) XFILE f = XBADFILE; #ifndef NO_SHA256 const char* rsaPssSha256Cert = "./certs/rsapss/ca-rsapss.der"; #ifdef WOLFSSL_PEM_TO_DER const char* rsaPssRootSha256Cert = "./certs/rsapss/root-rsapss.pem"; #else const char* rsaPssRootSha256Cert = "./certs/rsapss/root-rsapss.der"; #endif #endif #if defined(WOLFSSL_SHA384) && defined(WOLFSSL_PSS_LONG_SALT) && \ RSA_MAX_SIZE >= 3072 const char* rsaPssSha384Cert = "./certs/rsapss/ca-3072-rsapss.der"; #endif #if defined(WOLFSSL_SHA384) && RSA_MAX_SIZE >= 3072 #ifdef WOLFSSL_PEM_TO_DER const char* rsaPssRootSha384Cert = "./certs/rsapss/root-3072-rsapss.pem"; #else const char* rsaPssRootSha384Cert = "./certs/rsapss/root-3072-rsapss.der"; #endif #endif DecodedCert cert; byte buf[4096]; int bytes = 0; WOLFSSL_CERT_MANAGER* cm = NULL; ExpectNotNull(cm = wolfSSL_CertManagerNew()); #ifndef NO_SHA256 ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CertManagerLoadCA(cm, rsaPssRootSha256Cert, NULL)); #endif #if defined(WOLFSSL_SHA384) && RSA_MAX_SIZE >= 3072 ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CertManagerLoadCA(cm, rsaPssRootSha384Cert, NULL)); #endif #ifndef NO_SHA256 ExpectTrue((f = XFOPEN(rsaPssSha256Cert, "rb")) != XBADFILE); ExpectIntGT(bytes = (int)XFREAD(buf, 1, sizeof(buf), f), 0); if (f != XBADFILE) { XFCLOSE(f); f = XBADFILE; } wc_InitDecodedCert(&cert, buf, (word32)bytes, NULL); ExpectIntEQ(wc_ParseCert(&cert, CERT_TYPE, VERIFY, cm), 0); wc_FreeDecodedCert(&cert); #endif #if defined(WOLFSSL_SHA384) && defined(WOLFSSL_PSS_LONG_SALT) && \ RSA_MAX_SIZE >= 3072 ExpectTrue((f = XFOPEN(rsaPssSha384Cert, "rb")) != XBADFILE); ExpectIntGT(bytes = (int)XFREAD(buf, 1, sizeof(buf), f), 0); if (f != XBADFILE) XFCLOSE(f); wc_InitDecodedCert(&cert, buf, (word32)bytes, NULL); ExpectIntEQ(wc_ParseCert(&cert, CERT_TYPE, VERIFY, cm), 0); wc_FreeDecodedCert(&cert); #endif wolfSSL_CertManagerFree(cm); (void)buf; (void)bytes; #endif return EXPECT_RESULT(); } #endif /* WOLFSSL_TEST_APPLE_NATIVE_CERT_VALIDATION */ #endif /* HAVE_CERT_CHAIN_VALIDATION */ static int test_wolfSSL_CTX_load_verify_locations_ex(void) { EXPECT_DECLS; #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_TLS) && \ !defined(NO_WOLFSSL_CLIENT) && !defined(NO_RSA) WOLFSSL_CTX* ctx = NULL; #ifdef WOLFSSL_PEM_TO_DER const char* ca_cert = "./certs/ca-cert.pem"; const char* ca_expired_cert = "./certs/test/expired/expired-ca.pem"; #else const char* ca_cert = "./certs/ca-cert.der"; const char* ca_expired_cert = "./certs/test/expired/expired-ca.der"; #endif ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); /* test good CA */ ExpectTrue(WOLFSSL_SUCCESS == wolfSSL_CTX_load_verify_locations_ex(ctx, ca_cert, NULL, WOLFSSL_LOAD_FLAG_NONE)); /* test expired CA */ #if !defined(OPENSSL_COMPATIBLE_DEFAULTS) && !defined(NO_ASN_TIME) ExpectIntNE(wolfSSL_CTX_load_verify_locations_ex(ctx, ca_expired_cert, NULL, WOLFSSL_LOAD_FLAG_NONE), WOLFSSL_SUCCESS); #else ExpectIntEQ(wolfSSL_CTX_load_verify_locations_ex(ctx, ca_expired_cert, NULL, WOLFSSL_LOAD_FLAG_NONE), WOLFSSL_SUCCESS); #endif ExpectIntEQ(wolfSSL_CTX_load_verify_locations_ex(ctx, ca_expired_cert, NULL, WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY), WOLFSSL_SUCCESS); wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } static int test_wolfSSL_CTX_load_verify_buffer_ex(void) { EXPECT_DECLS; #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_TLS) && \ !defined(NO_RSA) && \ (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) WOLFSSL_CTX* ctx; const char* ca_expired_cert_file = "./certs/test/expired/expired-ca.der"; byte ca_expired_cert[TWOK_BUF]; word32 sizeof_ca_expired_cert = 0; XFILE fp = XBADFILE; #ifndef NO_WOLFSSL_CLIENT ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); #else ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()); #endif ExpectNotNull(ctx); #if defined(USE_CERT_BUFFERS_2048) /* test good CA */ ExpectTrue(WOLFSSL_SUCCESS == wolfSSL_CTX_load_verify_buffer_ex(ctx, ca_cert_der_2048, sizeof_ca_cert_der_2048, WOLFSSL_FILETYPE_ASN1, 0, WOLFSSL_LOAD_FLAG_NONE)); #endif /* load expired CA */ XMEMSET(ca_expired_cert, 0, sizeof(ca_expired_cert)); ExpectTrue((fp = XFOPEN(ca_expired_cert_file, "rb")) != XBADFILE); ExpectIntGT(sizeof_ca_expired_cert = (word32)XFREAD(ca_expired_cert, 1, sizeof(ca_expired_cert), fp), 0); if (fp != XBADFILE) XFCLOSE(fp); /* test expired CA failure */ #if !defined(OPENSSL_COMPATIBLE_DEFAULTS) && !defined(NO_ASN_TIME) ExpectIntNE(wolfSSL_CTX_load_verify_buffer_ex(ctx, ca_expired_cert, sizeof_ca_expired_cert, WOLFSSL_FILETYPE_ASN1, 0, WOLFSSL_LOAD_FLAG_NONE), WOLFSSL_SUCCESS); #else ExpectIntEQ(wolfSSL_CTX_load_verify_buffer_ex(ctx, ca_expired_cert, sizeof_ca_expired_cert, WOLFSSL_FILETYPE_ASN1, 0, WOLFSSL_LOAD_FLAG_NONE), WOLFSSL_SUCCESS); #endif /* test expired CA success */ ExpectIntEQ(wolfSSL_CTX_load_verify_buffer_ex(ctx, ca_expired_cert, sizeof_ca_expired_cert, WOLFSSL_FILETYPE_ASN1, 0, WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY), WOLFSSL_SUCCESS); /* Fail when ctx is NULL. */ ExpectIntEQ(wolfSSL_CTX_load_verify_buffer_ex(NULL, ca_expired_cert, sizeof_ca_expired_cert, WOLFSSL_FILETYPE_ASN1, 0, WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* Load as modified cert - bad initial length. */ ca_expired_cert[2] = 0x7f; ExpectIntEQ(wolfSSL_CTX_load_verify_buffer_ex(ctx, ca_expired_cert, sizeof_ca_expired_cert, WOLFSSL_FILETYPE_ASN1, 1, WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY), WC_NO_ERR_TRACE(ASN_PARSE_E)); wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } static int test_wolfSSL_CTX_load_verify_chain_buffer_format(void) { EXPECT_DECLS; #if !defined(NO_CERTS) && !defined(NO_RSA) && defined(OPENSSL_EXTRA) && \ defined(USE_CERT_BUFFERS_2048) && (WOLFSSL_MIN_RSA_BITS <= 1024) && \ !defined(NO_TLS) && \ (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) WOLFSSL_CTX* ctx = NULL; #ifndef NO_WOLFSSL_CLIENT ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); #else ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); #endif /* Public key 140 bytes??? */ ExpectIntEQ(wolfSSL_CTX_load_verify_chain_buffer_format(ctx, ca_cert_chain_der, sizeof_ca_cert_chain_der, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } static int test_wolfSSL_CTX_add1_chain_cert(void) { EXPECT_DECLS; #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && defined(OPENSSL_EXTRA) && \ defined(KEEP_OUR_CERT) && !defined(NO_RSA) && !defined(NO_TLS) && \ !defined(NO_WOLFSSL_CLIENT) WOLFSSL_CTX* ctx; WOLFSSL* ssl = NULL; const char *certChain[] = { "./certs/intermediate/client-int-cert.pem", "./certs/intermediate/ca-int2-cert.pem", "./certs/intermediate/ca-int-cert.pem", "./certs/ca-cert.pem", NULL }; const char** cert; WOLFSSL_X509* x509 = NULL; WOLF_STACK_OF(X509)* chain = NULL; ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); ExpectNotNull(ssl = wolfSSL_new(ctx)); ExpectNotNull(x509 = wolfSSL_X509_new()); ExpectIntEQ(SSL_CTX_add1_chain_cert(ctx, x509), 0); ExpectIntEQ(SSL_CTX_add0_chain_cert(ctx, x509), 0); ExpectIntEQ(SSL_add1_chain_cert(ssl, x509), 0); ExpectIntEQ(SSL_add0_chain_cert(ssl, x509), 0); wolfSSL_X509_free(x509); x509 = NULL; for (cert = certChain; EXPECT_SUCCESS() && *cert != NULL; cert++) { ExpectNotNull(x509 = wolfSSL_X509_load_certificate_file(*cert, WOLFSSL_FILETYPE_PEM)); /* Do negative tests once */ if (cert == certChain) { /* Negative tests. */ ExpectIntEQ(SSL_CTX_add1_chain_cert(NULL, NULL), 0); ExpectIntEQ(SSL_CTX_add1_chain_cert(ctx, NULL), 0); ExpectIntEQ(SSL_CTX_add1_chain_cert(NULL, x509), 0); ExpectIntEQ(SSL_CTX_add0_chain_cert(NULL, NULL), 0); ExpectIntEQ(SSL_CTX_add0_chain_cert(ctx, NULL), 0); ExpectIntEQ(SSL_CTX_add0_chain_cert(NULL, x509), 0); } ExpectIntEQ(SSL_CTX_add1_chain_cert(ctx, x509), 1); /* add1 must increment ref count (was 1, now 2). Verifies the * up_ref return value is assigned, not just compared. */ if (EXPECT_SUCCESS() && x509 != NULL) { ExpectIntEQ(wolfSSL_RefCur(x509->ref), 2); } X509_free(x509); x509 = NULL; } for (cert = certChain; EXPECT_SUCCESS() && *cert != NULL; cert++) { ExpectNotNull(x509 = wolfSSL_X509_load_certificate_file(*cert, WOLFSSL_FILETYPE_PEM)); /* Do negative tests once */ if (cert == certChain) { /* Negative tests. */ ExpectIntEQ(SSL_add1_chain_cert(NULL, NULL), 0); ExpectIntEQ(SSL_add1_chain_cert(ssl, NULL), 0); ExpectIntEQ(SSL_add1_chain_cert(NULL, x509), 0); ExpectIntEQ(SSL_add0_chain_cert(NULL, NULL), 0); ExpectIntEQ(SSL_add0_chain_cert(ssl, NULL), 0); ExpectIntEQ(SSL_add0_chain_cert(NULL, x509), 0); } ExpectIntEQ(SSL_add1_chain_cert(ssl, x509), 1); /* add1 must increment ref count (was 1, now 2) */ if (EXPECT_SUCCESS() && x509 != NULL) { ExpectIntEQ(wolfSSL_RefCur(x509->ref), 2); } X509_free(x509); x509 = NULL; } ExpectIntEQ(SSL_CTX_get0_chain_certs(ctx, &chain), 1); ExpectIntEQ(sk_X509_num(chain), 3); ExpectIntEQ(SSL_get0_chain_certs(ssl, &chain), 1); ExpectIntEQ(sk_X509_num(chain), 3); SSL_free(ssl); SSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } /* Test that wolfssl_add_to_chain rejects sizes that would overflow word32. * ZD #21241 */ static int test_wolfSSL_add_to_chain_overflow(void) { EXPECT_DECLS; #if !defined(NO_CERTS) && defined(OPENSSL_EXTRA) && \ defined(KEEP_OUR_CERT) && !defined(NO_RSA) && !defined(NO_TLS) && \ !defined(NO_WOLFSSL_CLIENT) && !defined(NO_FILESYSTEM) WOLFSSL_CTX* ctx = NULL; WOLFSSL_X509* x509 = NULL; DerBuffer* fakeChain = NULL; ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); /* Load a real cert so ctx->certificate is set (first add goes there). */ ExpectNotNull(x509 = wolfSSL_X509_load_certificate_file( "./certs/intermediate/client-int-cert.pem", WOLFSSL_FILETYPE_PEM)); ExpectIntEQ(SSL_CTX_add1_chain_cert(ctx, x509), 1); wolfSSL_X509_free(x509); x509 = NULL; /* Now ctx->certificate is set, next add goes to certChain via * wolfssl_add_to_chain. Fake a chain whose length is near UINT32_MAX * so the size calculation (len + CERT_HEADER_SZ + certSz) overflows. */ fakeChain = (DerBuffer*)XMALLOC(sizeof(DerBuffer) + 16, ctx->heap, DYNAMIC_TYPE_CERT); ExpectNotNull(fakeChain); if (EXPECT_SUCCESS()) { XMEMSET(fakeChain, 0, sizeof(DerBuffer) + 16); fakeChain->buffer = (byte*)(fakeChain + 1); fakeChain->length = WOLFSSL_MAX_32BIT - 2; /* will overflow with any cert */ fakeChain->type = CERT_TYPE; fakeChain->dynType = DYNAMIC_TYPE_CERT; /* Replace the real chain with our fake one. */ if (ctx->certChain != NULL) { XFREE(ctx->certChain, ctx->heap, DYNAMIC_TYPE_CERT); } ctx->certChain = fakeChain; } else { XFREE(fakeChain, ctx ? ctx->heap : NULL, DYNAMIC_TYPE_CERT); } /* Try to add another cert - this MUST fail due to overflow guard. */ ExpectNotNull(x509 = wolfSSL_X509_load_certificate_file( "./certs/intermediate/ca-int2-cert.pem", WOLFSSL_FILETYPE_PEM)); ExpectIntEQ(SSL_CTX_add1_chain_cert(ctx, x509), 0); wolfSSL_X509_free(x509); wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } static int test_wolfSSL_CTX_use_certificate_chain_buffer_format(void) { EXPECT_DECLS; #if !defined(NO_CERTS) && !defined(NO_TLS) && \ !defined(NO_WOLFSSL_CLIENT) && !defined(NO_RSA) && \ (!defined(NO_FILESYSTEM) || defined(USE_CERT_BUFFERS_2048)) WOLFSSL_CTX* ctx = NULL; WOLFSSL* ssl = NULL; #ifndef NO_FILESYSTEM const char* cert = svrCertFile; unsigned char* buf = NULL; size_t len = 0; ExpectIntEQ(load_file(cert, &buf, &len), 0); #endif ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); ExpectNotNull(ssl = wolfSSL_new(ctx)); /* Invalid parameters. */ #ifndef NO_FILESYSTEM ExpectIntEQ(wolfSSL_CTX_use_certificate_chain_buffer_format(NULL, NULL, 0, WOLFSSL_FILETYPE_ASN1), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_CTX_use_certificate_chain_buffer_format(ctx, NULL, 0, WOLFSSL_FILETYPE_ASN1), WC_NO_ERR_TRACE(ASN_PARSE_E)); ExpectIntEQ(wolfSSL_CTX_use_certificate_chain_buffer(NULL, NULL, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); #ifdef WOLFSSL_PEM_TO_DER ExpectIntEQ(wolfSSL_CTX_use_certificate_chain_buffer(ctx, NULL, 0), WC_NO_ERR_TRACE(ASN_NO_PEM_HEADER)); #endif ExpectIntEQ(wolfSSL_CTX_use_certificate_chain_buffer(NULL, buf, (sword32)len), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_use_certificate_chain_buffer(NULL, NULL, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); #ifdef WOLFSSL_PEM_TO_DER ExpectIntEQ(wolfSSL_use_certificate_chain_buffer(ssl, NULL, 0), WC_NO_ERR_TRACE(ASN_NO_PEM_HEADER)); #endif ExpectIntEQ(wolfSSL_use_certificate_chain_buffer(NULL, buf, (sword32)len), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_CTX_use_certificate_chain_buffer_format(ctx, buf, (sword32)len, CERT_FILETYPE), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_use_certificate_chain_buffer(ctx, buf, (sword32)len), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_use_certificate_chain_buffer(ssl, buf, (sword32)len), WOLFSSL_SUCCESS); #endif /* !NO_FILESYSTEM */ ExpectIntEQ(wolfSSL_CTX_use_certificate_chain_buffer_format(NULL, server_cert_der_2048, sizeof_server_cert_der_2048, WOLFSSL_FILETYPE_ASN1), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_CTX_use_certificate_chain_buffer_format(ctx, server_cert_der_2048, sizeof_server_cert_der_2048, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); #ifdef WOLFSSL_PEM_TO_DER ExpectIntEQ(wolfSSL_CTX_use_certificate_chain_buffer(ctx, server_cert_der_2048, sizeof_server_cert_der_2048), WC_NO_ERR_TRACE(ASN_NO_PEM_HEADER)); ExpectIntEQ(wolfSSL_use_certificate_chain_buffer(ssl, server_cert_der_2048, sizeof_server_cert_der_2048), WC_NO_ERR_TRACE(ASN_NO_PEM_HEADER)); #endif wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #ifndef NO_FILESYSTEM if (buf != NULL) { XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); } #endif #endif return EXPECT_RESULT(); } static int test_wolfSSL_CTX_use_certificate_chain_file_format(void) { EXPECT_DECLS; #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_TLS) && \ !defined(NO_RSA) && \ (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) const char* server_chain_der = "./certs/server-cert-chain.der"; const char* client_single_pem = cliCertFile; WOLFSSL_CTX* ctx = NULL; (void)server_chain_der; (void)client_single_pem; (void)ctx; #ifndef NO_WOLFSSL_CLIENT ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); #else ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); #endif ExpectIntEQ(wolfSSL_CTX_use_certificate_chain_file_format(ctx, server_chain_der, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_use_certificate_chain_file_format(ctx, client_single_pem, CERT_FILETYPE), WOLFSSL_SUCCESS); wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } static int test_wolfSSL_use_certificate_chain_file(void) { EXPECT_DECLS; #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_TLS) && \ !defined(NO_WOLFSSL_CLIENT) && !defined(NO_RSA) const char* server_chain_der = "./certs/server-cert-chain.der"; const char* client_single_pem = cliCertFile; WOLFSSL_CTX* ctx = NULL; WOLFSSL* ssl = NULL; (void)server_chain_der; (void)client_single_pem; ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); ExpectNotNull(ssl = wolfSSL_new(ctx)); /* Invalid parameters. */ ExpectIntEQ(wolfSSL_use_certificate_chain_file_format(NULL, NULL, WOLFSSL_FILETYPE_ASN1), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_use_certificate_chain_file_format(ssl, NULL, WOLFSSL_FILETYPE_ASN1), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_use_certificate_chain_file_format(NULL, server_chain_der, WOLFSSL_FILETYPE_ASN1), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_use_certificate_chain_file(NULL, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_use_certificate_chain_file(ssl, NULL), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_use_certificate_chain_file(NULL, client_single_pem), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); #ifdef WOLFSSL_PEM_TO_DER ExpectIntEQ(wolfSSL_use_certificate_chain_file(ssl, server_chain_der), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); #endif ExpectIntEQ(wolfSSL_use_certificate_chain_file_format(ssl, server_chain_der, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_use_certificate_chain_file_format(ssl, client_single_pem, CERT_FILETYPE), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_use_certificate_chain_file(ssl, client_single_pem), WOLFSSL_SUCCESS); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } static int test_wolfSSL_CTX_SetTmpDH_file(void) { EXPECT_DECLS; #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_TLS) && \ !defined(NO_DH) && \ (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) WOLFSSL_CTX *ctx = NULL; #if defined(WOLFSSL_WPAS) && !defined(NO_DSA) #if defined(WOLFSSL_PEM_TO_DER) const char* dsaParamFile = "./certs/dsaparams.pem"; #else const char* dsaParamFile = "./certs/dsaparams.der"; #endif #endif (void)ctx; #ifndef NO_WOLFSSL_CLIENT ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); #else ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); #endif /* invalid context */ ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_SetTmpDH_file(NULL, dhParamFile, CERT_FILETYPE)); /* invalid dhParamFile file */ ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_SetTmpDH_file(ctx, NULL, CERT_FILETYPE)); ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_SetTmpDH_file(ctx, bogusFile, CERT_FILETYPE)); /* success */ ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_SetTmpDH_file(ctx, dhParamFile, CERT_FILETYPE)); #if defined(WOLFSSL_WPAS) && !defined(NO_DSA) ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_SetTmpDH_file(ctx, dsaParamFile, CERT_FILETYPE)); #endif wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } static int test_wolfSSL_CTX_SetTmpDH_buffer(void) { EXPECT_DECLS; #if !defined(NO_CERTS) && !defined(NO_TLS) && !defined(NO_DH) && \ (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) WOLFSSL_CTX *ctx = NULL; #ifndef NO_WOLFSSL_CLIENT ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); #else ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); #endif /* invalid context */ ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_SetTmpDH_buffer(NULL, dh_key_der_2048, sizeof_dh_key_der_2048, WOLFSSL_FILETYPE_ASN1)); /* invalid dhParamFile file */ ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_SetTmpDH_buffer(NULL, NULL, 0, WOLFSSL_FILETYPE_ASN1)); ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_SetTmpDH_buffer(ctx, NULL, 0, WOLFSSL_FILETYPE_ASN1)); ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_SetTmpDH_buffer(ctx, dsa_key_der_2048, sizeof_dsa_key_der_2048, WOLFSSL_FILETYPE_ASN1)); /* invalid file format */ ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_SetTmpDH_buffer(ctx, dh_key_der_2048, sizeof_dh_key_der_2048, -1)); /* success */ ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_SetTmpDH_buffer(ctx, dh_key_der_2048, sizeof_dh_key_der_2048, WOLFSSL_FILETYPE_ASN1)); wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } static int test_wc_DhSetNamedKey(void) { EXPECT_DECLS; #if !defined(HAVE_SELFTEST) && !defined(NO_DH) && \ !defined(WOLFSSL_NO_MALLOC) && defined(HAVE_FFDHE) && \ (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)) DhKey *key = NULL; key = (DhKey*)XMALLOC(sizeof(DhKey), HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); ExpectNotNull(key); if (key != NULL){ #ifdef HAVE_FFDHE_2048 if (wc_InitDhKey_ex(key, HEAP_HINT, INVALID_DEVID) == 0){ ExpectIntEQ(wc_DhSetNamedKey(key, WC_FFDHE_2048), 0); ExpectIntEQ(wc_DhGetNamedKeyMinSize(WC_FFDHE_2048), 29); wc_FreeDhKey(key); } #endif #ifdef HAVE_FFDHE_3072 if (wc_InitDhKey_ex(key, HEAP_HINT, INVALID_DEVID) == 0){ ExpectIntEQ(wc_DhSetNamedKey(key, WC_FFDHE_3072), 0); ExpectIntEQ(wc_DhGetNamedKeyMinSize(WC_FFDHE_3072), 34); wc_FreeDhKey(key); } #endif #ifdef HAVE_FFDHE_4096 if (wc_InitDhKey_ex(key, HEAP_HINT, INVALID_DEVID) == 0){ ExpectIntEQ(wc_DhSetNamedKey(key, WC_FFDHE_4096), 0); ExpectIntEQ(wc_DhGetNamedKeyMinSize(WC_FFDHE_4096), 39); wc_FreeDhKey(key); } #endif #ifdef HAVE_FFDHE_6144 if (wc_InitDhKey_ex(key, HEAP_HINT, INVALID_DEVID) == 0){ ExpectIntEQ(wc_DhSetNamedKey(key, WC_FFDHE_6144), 0); ExpectIntEQ(wc_DhGetNamedKeyMinSize(WC_FFDHE_6144), 46); wc_FreeDhKey(key); } #endif #ifdef HAVE_FFDHE_8192 if (wc_InitDhKey_ex(key, HEAP_HINT, INVALID_DEVID) == 0){ ExpectIntEQ(wc_DhSetNamedKey(key, WC_FFDHE_8192), 0); ExpectIntEQ(wc_DhGetNamedKeyMinSize(WC_FFDHE_8192), 52); wc_FreeDhKey(key); } #endif XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); } #endif return EXPECT_RESULT(); } static int test_wolfSSL_CTX_SetMinMaxDhKey_Sz(void) { EXPECT_DECLS; #if !defined(NO_CERTS) && !defined(NO_TLS) && !defined(NO_DH) && \ (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) WOLFSSL_CTX *ctx; (void)ctx; #ifndef NO_WOLFSSL_CLIENT ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); #else ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()); #endif ExpectNotNull(ctx); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_SetMinDhKey_Sz(ctx, 3072)); ExpectIntEQ(WC_NO_ERR_TRACE(DH_KEY_SIZE_E), wolfSSL_CTX_SetTmpDH_buffer(ctx, dh_key_der_2048, sizeof_dh_key_der_2048, WOLFSSL_FILETYPE_ASN1)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_SetMinDhKey_Sz(ctx, 2048)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_SetTmpDH_buffer(ctx, dh_key_der_2048, sizeof_dh_key_der_2048, WOLFSSL_FILETYPE_ASN1)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_SetMaxDhKey_Sz(ctx, 1024)); ExpectIntEQ(WC_NO_ERR_TRACE(DH_KEY_SIZE_E), wolfSSL_CTX_SetTmpDH_buffer(ctx, dh_key_der_2048, sizeof_dh_key_der_2048, WOLFSSL_FILETYPE_ASN1)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_SetMaxDhKey_Sz(ctx, 2048)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_SetTmpDH_buffer(ctx, dh_key_der_2048, sizeof_dh_key_der_2048, WOLFSSL_FILETYPE_ASN1)); wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } static int test_wolfSSL_CTX_der_load_verify_locations(void) { EXPECT_DECLS; #if !defined(NO_FILESYSTEM) && defined(WOLFSSL_DER_LOAD) && \ !defined(NO_TLS) && \ (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) WOLFSSL_CTX* ctx = NULL; const char* derCert = "./certs/server-cert.der"; const char* nullPath = NULL; const char* invalidPath = "./certs/this-cert-does-not-exist.der"; const char* emptyPath = ""; /* der load Case 1 ctx NULL */ ExpectIntEQ(wolfSSL_CTX_der_load_verify_locations(ctx, derCert, WOLFSSL_FILETYPE_ASN1), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); #ifndef NO_WOLFSSL_CLIENT ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); #else ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); #endif /* Case 2 filePath NULL */ ExpectIntEQ(wolfSSL_CTX_der_load_verify_locations(ctx, nullPath, WOLFSSL_FILETYPE_ASN1), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); /* Case 3 invalid format */ ExpectIntEQ(wolfSSL_CTX_der_load_verify_locations(ctx, derCert, WOLFSSL_FILETYPE_PEM), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); /* Case 4 filePath not valid */ ExpectIntEQ(wolfSSL_CTX_der_load_verify_locations(ctx, invalidPath, WOLFSSL_FILETYPE_ASN1), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); /* Case 5 filePath empty */ ExpectIntEQ(wolfSSL_CTX_der_load_verify_locations(ctx, emptyPath, WOLFSSL_FILETYPE_ASN1), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); #ifndef NO_RSA /* Case 6 success case */ ExpectIntEQ(wolfSSL_CTX_der_load_verify_locations(ctx, derCert, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); #endif wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } static int test_wolfSSL_CTX_enable_disable(void) { EXPECT_DECLS; #if !defined(NO_CERTS) && !defined(NO_TLS) WOLFSSL_CTX* ctx = NULL; #ifdef HAVE_CRL ExpectIntEQ(wolfSSL_CTX_DisableCRL(ctx), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_CTX_EnableCRL(ctx, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); #endif #ifdef HAVE_OCSP ExpectIntEQ(wolfSSL_CTX_DisableOCSP(ctx), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_CTX_EnableOCSP(ctx, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); #endif #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \ defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) ExpectIntEQ(wolfSSL_CTX_DisableOCSPStapling(ctx), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_CTX_EnableOCSPStapling(ctx), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_CTX_DisableOCSPMustStaple(ctx), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_CTX_EnableOCSPMustStaple(ctx), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); #endif #ifndef NO_WOLFSSL_CLIENT #ifdef HAVE_EXTENDED_MASTER ExpectIntEQ(wolfSSL_CTX_DisableExtendedMasterSecret(ctx), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); #endif ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); #ifdef HAVE_EXTENDED_MASTER ExpectIntEQ(wolfSSL_CTX_DisableExtendedMasterSecret(ctx), WOLFSSL_SUCCESS); #endif #elif !defined(NO_WOLFSSL_SERVER) ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); #endif #if !defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER) #ifdef HAVE_CRL ExpectIntEQ(wolfSSL_CTX_DisableCRL(ctx), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_EnableCRL(ctx, 0), WOLFSSL_SUCCESS); #endif #ifdef HAVE_OCSP ExpectIntEQ(wolfSSL_CTX_DisableOCSP(ctx), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_EnableOCSP(ctx, WOLFSSL_OCSP_URL_OVERRIDE), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_EnableOCSP(ctx, WOLFSSL_OCSP_NO_NONCE), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_EnableOCSP(ctx, WOLFSSL_OCSP_CHECKALL), WOLFSSL_SUCCESS); #endif #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \ defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) ExpectIntEQ(wolfSSL_CTX_DisableOCSPStapling(ctx), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_EnableOCSPStapling(ctx), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_DisableOCSPMustStaple(ctx), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_DisableOCSPMustStaple(ctx), WOLFSSL_SUCCESS); #endif wolfSSL_CTX_free(ctx); #endif /* !NO_WOLFSSL_CLIENT || !NO_WOLFSSL_SERVER */ #endif /* !NO_CERTS && !NO_CERTS */ return EXPECT_RESULT(); } static int test_wolfSSL_CTX_ticket_API(void) { EXPECT_DECLS; #if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER) && \ !defined(NO_TLS) WOLFSSL_CTX* ctx = NULL; void *userCtx = (void*)"this is my ctx"; ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_set_TicketEncCtx(ctx, userCtx)); ExpectTrue(userCtx == wolfSSL_CTX_get_TicketEncCtx(ctx)); wolfSSL_CTX_free(ctx); ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_set_TicketEncCtx(NULL, userCtx)); ExpectNull(wolfSSL_CTX_get_TicketEncCtx(NULL)); #endif /* HAVE_SESSION_TICKET && !NO_WOLFSSL_SERVER && !NO_TLS */ return EXPECT_RESULT(); } static int test_wolfSSL_set_minmax_proto_version(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_TLS) WOLFSSL_CTX *ctx = NULL; WOLFSSL *ssl = NULL; (void)ssl; #ifndef NO_WOLFSSL_CLIENT ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); ExpectNotNull(ssl = wolfSSL_new(ctx)); ExpectIntEQ(wolfSSL_CTX_set_min_proto_version(NULL, 0), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_CTX_set_max_proto_version(NULL, 0), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_CTX_set_min_proto_version(ctx, 0), SSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_set_max_proto_version(ctx, 0), SSL_SUCCESS); ExpectIntEQ(wolfSSL_set_min_proto_version(NULL, 0), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_set_min_proto_version(ssl, 0), SSL_SUCCESS); ExpectIntEQ(wolfSSL_set_max_proto_version(NULL, 0), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_set_max_proto_version(ssl, 0), SSL_SUCCESS); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); ctx = NULL; #endif #ifndef NO_WOLFSSL_SERVER ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); ExpectIntEQ(wolfSSL_CTX_set_min_proto_version(NULL, 0), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_CTX_set_max_proto_version(NULL, 0), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_CTX_set_min_proto_version(ctx, 0), SSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_set_max_proto_version(ctx, 0), SSL_SUCCESS); wolfSSL_CTX_free(ctx); #endif #endif return EXPECT_RESULT(); } #if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_NO_TLS12) && \ defined(OPENSSL_EXTRA) && defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) static int test_wolfSSL_CTX_set_max_proto_version_on_result(WOLFSSL* ssl) { EXPECT_DECLS; ExpectStrEQ(wolfSSL_get_version(ssl), "TLSv1.2"); return EXPECT_RESULT(); } static int test_wolfSSL_CTX_set_max_proto_version_ctx_ready(WOLFSSL_CTX* ctx) { EXPECT_DECLS; /* Set TLS 1.2 */ ExpectIntEQ(wolfSSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION), WOLFSSL_SUCCESS); return EXPECT_RESULT(); } /* Test using wolfSSL_CTX_set_max_proto_version to limit the version below * what was set at ctx creation. */ static int test_wolfSSL_CTX_set_max_proto_version(void) { EXPECT_DECLS; test_ssl_cbf client_cbs; test_ssl_cbf server_cbs; XMEMSET(&client_cbs, 0, sizeof(client_cbs)); XMEMSET(&server_cbs, 0, sizeof(server_cbs)); client_cbs.method = wolfTLS_client_method; server_cbs.method = wolfTLS_server_method; server_cbs.ctx_ready = test_wolfSSL_CTX_set_max_proto_version_ctx_ready; client_cbs.on_result = test_wolfSSL_CTX_set_max_proto_version_on_result; server_cbs.on_result = test_wolfSSL_CTX_set_max_proto_version_on_result; ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&client_cbs, &server_cbs, NULL), TEST_SUCCESS); return EXPECT_RESULT(); } #else static int test_wolfSSL_CTX_set_max_proto_version(void) { return TEST_SKIPPED; } #endif /*----------------------------------------------------------------------------* | SSL *----------------------------------------------------------------------------*/ static int test_server_wolfSSL_new(void) { EXPECT_DECLS; #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_TLS) && \ !defined(NO_WOLFSSL_SERVER) && !defined(NO_RSA) WOLFSSL_CTX *ctx = NULL; WOLFSSL_CTX *ctx_nocert = NULL; WOLFSSL *ssl = NULL; ExpectNotNull(ctx_nocert = wolfSSL_CTX_new(wolfSSLv23_server_method())); ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile, CERT_FILETYPE)); ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, CERT_FILETYPE)); /* invalid context */ ExpectNull(ssl = wolfSSL_new(NULL)); #if !defined(WOLFSSL_SESSION_EXPORT) && !defined(WOLFSSL_QT) && \ !defined(OPENSSL_EXTRA) && !defined(WOLFSSL_NO_INIT_CTX_KEY) ExpectNull(ssl = wolfSSL_new(ctx_nocert)); #endif /* success */ ExpectNotNull(ssl = wolfSSL_new(ctx)); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); wolfSSL_CTX_free(ctx_nocert); #endif return EXPECT_RESULT(); } static int test_client_wolfSSL_new(void) { EXPECT_DECLS; #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_TLS) && \ !defined(NO_WOLFSSL_CLIENT) && !defined(NO_RSA) WOLFSSL_CTX *ctx = NULL; WOLFSSL_CTX *ctx_nocert = NULL; WOLFSSL *ssl = NULL; ExpectNotNull(ctx_nocert = wolfSSL_CTX_new(wolfSSLv23_client_method())); ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); ExpectTrue(wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0)); /* invalid context */ ExpectNull(ssl = wolfSSL_new(NULL)); /* success */ ExpectNotNull(ssl = wolfSSL_new(ctx_nocert)); wolfSSL_free(ssl); ssl = NULL; /* success */ ExpectNotNull(ssl = wolfSSL_new(ctx)); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); wolfSSL_CTX_free(ctx_nocert); #endif return EXPECT_RESULT(); } static int test_wolfSSL_SetTmpDH_file(void) { EXPECT_DECLS; #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_TLS) && \ !defined(NO_WOLFSSL_SERVER) && !defined(NO_DH) WOLFSSL_CTX *ctx = NULL; WOLFSSL *ssl = NULL; #ifdef WOLFSSL_PEM_TO_DER const char* dhX942ParamFile = "./certs/x942dh2048.pem"; #if defined(WOLFSSL_WPAS) && !defined(NO_DSA) const char* dsaParamFile = "./certs/dsaparams.pem"; #endif #else const char* dhX942ParamFile = "./certs/x942dh2048.der"; #if defined(WOLFSSL_WPAS) && !defined(NO_DSA) const char* dsaParamFile = "./certs/dsaparams.der"; #endif #endif ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); #ifndef NO_RSA ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile, CERT_FILETYPE)); ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, CERT_FILETYPE)); #elif defined(HAVE_ECC) ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx, eccCertFile, CERT_FILETYPE)); ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, eccKeyFile, CERT_FILETYPE)); #elif defined(HAVE_ED25519) ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx, edCertFile, CERT_FILETYPE)); ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, edKeyFile, CERT_FILETYPE)); #elif defined(HAVE_ED448) ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx, ed448CertFile, CERT_FILETYPE)); ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, ed448KeyFile, CERT_FILETYPE)); #endif ExpectNotNull(ssl = wolfSSL_new(ctx)); /* invalid ssl */ ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_SetTmpDH_file(NULL, dhParamFile, CERT_FILETYPE)); /* invalid dhParamFile file */ ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_SetTmpDH_file(ssl, NULL, CERT_FILETYPE)); ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_SetTmpDH_file(ssl, bogusFile, CERT_FILETYPE)); /* success */ ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_SetTmpDH_file(ssl, dhParamFile, CERT_FILETYPE)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_SetTmpDH_file(ssl, dhX942ParamFile, CERT_FILETYPE)); #if defined(WOLFSSL_WPAS) && !defined(NO_DSA) ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_SetTmpDH_file(ctx, dsaParamFile, CERT_FILETYPE)); #endif wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } static int test_wolfSSL_SetTmpDH_buffer(void) { EXPECT_DECLS; #if !defined(NO_CERTS) && !defined(NO_TLS) && !defined(NO_WOLFSSL_SERVER) && \ !defined(NO_DH) WOLFSSL_CTX *ctx = NULL; WOLFSSL *ssl = NULL; ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); ExpectTrue(wolfSSL_CTX_use_certificate_buffer(ctx, server_cert_der_2048, sizeof_server_cert_der_2048, WOLFSSL_FILETYPE_ASN1)); ExpectTrue(wolfSSL_CTX_use_PrivateKey_buffer(ctx, server_key_der_2048, sizeof_server_key_der_2048, WOLFSSL_FILETYPE_ASN1)); ExpectNotNull(ssl = wolfSSL_new(ctx)); /* invalid ssl */ ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_SetTmpDH_buffer(NULL, dh_key_der_2048, sizeof_dh_key_der_2048, WOLFSSL_FILETYPE_ASN1)); /* invalid dhParamFile file */ ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_SetTmpDH_buffer(NULL, NULL, 0, WOLFSSL_FILETYPE_ASN1)); ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_SetTmpDH_buffer(ssl, NULL, 0, WOLFSSL_FILETYPE_ASN1)); ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_SetTmpDH_buffer(ssl, dsa_key_der_2048, sizeof_dsa_key_der_2048, WOLFSSL_FILETYPE_ASN1)); /* success */ ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_SetTmpDH_buffer(ssl, dh_key_der_2048, sizeof_dh_key_der_2048, WOLFSSL_FILETYPE_ASN1)); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } static int test_wolfSSL_SetMinMaxDhKey_Sz(void) { EXPECT_DECLS; #if !defined(NO_CERTS) && !defined(NO_TLS) && !defined(NO_WOLFSSL_SERVER) && \ !defined(NO_DH) WOLFSSL_CTX *ctx = NULL; WOLFSSL_CTX *ctx2 = NULL; WOLFSSL *ssl = NULL; WOLFSSL *ssl2 = NULL; ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); ExpectTrue(wolfSSL_CTX_use_certificate_buffer(ctx, server_cert_der_2048, sizeof_server_cert_der_2048, WOLFSSL_FILETYPE_ASN1)); ExpectTrue(wolfSSL_CTX_use_PrivateKey_buffer(ctx, server_key_der_2048, sizeof_server_key_der_2048, WOLFSSL_FILETYPE_ASN1)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_SetMinDhKey_Sz(ctx, 3072)); ExpectNotNull(ssl = wolfSSL_new(ctx)); ExpectNotNull(ctx2 = wolfSSL_CTX_new(wolfSSLv23_server_method())); ExpectTrue(wolfSSL_CTX_use_certificate_buffer(ctx2, server_cert_der_2048, sizeof_server_cert_der_2048, WOLFSSL_FILETYPE_ASN1)); ExpectTrue(wolfSSL_CTX_use_PrivateKey_buffer(ctx2, server_key_der_2048, sizeof_server_key_der_2048, WOLFSSL_FILETYPE_ASN1)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_SetMaxDhKey_Sz(ctx, 1024)); ExpectNotNull(ssl2 = wolfSSL_new(ctx2)); ExpectIntEQ(WC_NO_ERR_TRACE(DH_KEY_SIZE_E), wolfSSL_SetTmpDH_buffer(ssl, dh_key_der_2048, sizeof_dh_key_der_2048, WOLFSSL_FILETYPE_ASN1)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_SetMinDhKey_Sz(ssl, 2048)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_SetTmpDH_buffer(ssl, dh_key_der_2048, sizeof_dh_key_der_2048, WOLFSSL_FILETYPE_ASN1)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_SetMinDhKey_Sz(ssl, 3072)); ExpectIntEQ(WC_NO_ERR_TRACE(DH_KEY_SIZE_E), wolfSSL_SetTmpDH_buffer(ssl, dh_key_der_2048, sizeof_dh_key_der_2048, WOLFSSL_FILETYPE_ASN1)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_SetTmpDH_buffer(ssl2, dh_key_der_2048, sizeof_dh_key_der_2048, WOLFSSL_FILETYPE_ASN1)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_SetMaxDhKey_Sz(ssl2, 2048)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_SetTmpDH_buffer(ssl2, dh_key_der_2048, sizeof_dh_key_der_2048, WOLFSSL_FILETYPE_ASN1)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_SetMaxDhKey_Sz(ssl2, 1024)); ExpectIntEQ(WC_NO_ERR_TRACE(DH_KEY_SIZE_E), wolfSSL_SetTmpDH_buffer(ssl, dh_key_der_2048, sizeof_dh_key_der_2048, WOLFSSL_FILETYPE_ASN1)); wolfSSL_free(ssl2); wolfSSL_CTX_free(ctx2); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } /* Test function for wolfSSL_SetMinVersion. Sets the minimum downgrade version * allowed. * POST: return 1 on success. */ static int test_wolfSSL_SetMinVersion(void) { int res = TEST_SKIPPED; #if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_TLS) int failFlag = WOLFSSL_SUCCESS; WOLFSSL_CTX* ctx = NULL; WOLFSSL* ssl = NULL; int itr; #ifndef NO_OLD_TLS const int versions[] = { #ifdef WOLFSSL_ALLOW_TLSV10 WOLFSSL_TLSV1, #endif WOLFSSL_TLSV1_1, WOLFSSL_TLSV1_2}; #elif !defined(WOLFSSL_NO_TLS12) const int versions[] = { WOLFSSL_TLSV1_2 }; #else const int versions[] = { WOLFSSL_TLSV1_3 }; #endif ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); ssl = wolfSSL_new(ctx); for (itr = 0; itr < (int)(sizeof(versions)/sizeof(int)); itr++) { if (wolfSSL_SetMinVersion(ssl, *(versions + itr)) != WOLFSSL_SUCCESS) { failFlag = WOLFSSL_FAILURE; } } wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); res = TEST_RES_CHECK(failFlag == WOLFSSL_SUCCESS); #endif return res; } /* END test_wolfSSL_SetMinVersion */ #include /*----------------------------------------------------------------------------* | IO *----------------------------------------------------------------------------*/ #if defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) || \ defined(HAVE_IO_TESTS_DEPENDENCIES) #ifdef WOLFSSL_HAVE_TLS_UNIQUE byte server_side_msg1[WC_MAX_DIGEST_SIZE]; /* msg sent by server */ byte server_side_msg2[WC_MAX_DIGEST_SIZE]; /* msg received from client */ byte client_side_msg1[WC_MAX_DIGEST_SIZE]; /* msg sent by client */ byte client_side_msg2[WC_MAX_DIGEST_SIZE]; /* msg received from server */ #endif /* WOLFSSL_HAVE_TLS_UNIQUE */ /* TODO: Expand and enable this when EVP_chacha20_poly1305 is supported */ #if defined(HAVE_SESSION_TICKET) && defined(OPENSSL_EXTRA) && \ defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_256) typedef struct openssl_key_ctx { byte name[WOLFSSL_TICKET_NAME_SZ]; /* server name */ byte key[WOLFSSL_TICKET_KEY_SZ]; /* cipher key */ byte hmacKey[WOLFSSL_TICKET_NAME_SZ]; /* hmac key */ byte iv[WOLFSSL_TICKET_IV_SZ]; /* cipher iv */ } openssl_key_ctx; static THREAD_LS_T openssl_key_ctx myOpenSSLKey_ctx; static THREAD_LS_T WC_RNG myOpenSSLKey_rng; static WC_INLINE int OpenSSLTicketInit(void) { int ret = wc_InitRng(&myOpenSSLKey_rng); if (ret != 0) return ret; ret = wc_RNG_GenerateBlock(&myOpenSSLKey_rng, myOpenSSLKey_ctx.name, sizeof(myOpenSSLKey_ctx.name)); if (ret != 0) return ret; ret = wc_RNG_GenerateBlock(&myOpenSSLKey_rng, myOpenSSLKey_ctx.key, sizeof(myOpenSSLKey_ctx.key)); if (ret != 0) return ret; ret = wc_RNG_GenerateBlock(&myOpenSSLKey_rng, myOpenSSLKey_ctx.hmacKey, sizeof(myOpenSSLKey_ctx.hmacKey)); if (ret != 0) return ret; ret = wc_RNG_GenerateBlock(&myOpenSSLKey_rng, myOpenSSLKey_ctx.iv, sizeof(myOpenSSLKey_ctx.iv)); if (ret != 0) return ret; return 0; } static int myTicketEncCbOpenSSL(WOLFSSL* ssl, byte name[WOLFSSL_TICKET_NAME_SZ], byte iv[WOLFSSL_TICKET_IV_SZ], WOLFSSL_EVP_CIPHER_CTX *ectx, WOLFSSL_HMAC_CTX *hctx, int enc) { (void)ssl; if (enc) { XMEMCPY(name, myOpenSSLKey_ctx.name, sizeof(myOpenSSLKey_ctx.name)); XMEMCPY(iv, myOpenSSLKey_ctx.iv, sizeof(myOpenSSLKey_ctx.iv)); } else if (XMEMCMP(name, myOpenSSLKey_ctx.name, sizeof(myOpenSSLKey_ctx.name)) != 0 || XMEMCMP(iv, myOpenSSLKey_ctx.iv, sizeof(myOpenSSLKey_ctx.iv)) != 0) { return 0; } HMAC_Init_ex(hctx, myOpenSSLKey_ctx.hmacKey, WOLFSSL_TICKET_NAME_SZ, EVP_sha256(), NULL); if (enc) EVP_EncryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, myOpenSSLKey_ctx.key, iv); else EVP_DecryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, myOpenSSLKey_ctx.key, iv); return 1; } static WC_INLINE void OpenSSLTicketCleanup(void) { wc_FreeRng(&myOpenSSLKey_rng); } #endif #endif /* helper functions */ #ifdef HAVE_SSL_MEMIO_TESTS_DEPENDENCIES static WC_INLINE int test_ssl_memio_write_cb(WOLFSSL *ssl, char *data, int sz, void *ctx) { struct test_ssl_memio_ctx *test_ctx; byte *buf; int *len; int *msg_sizes; int *msg_count; test_ctx = (struct test_ssl_memio_ctx*)ctx; if (wolfSSL_GetSide(ssl) == WOLFSSL_SERVER_END) { buf = test_ctx->c_buff; len = &test_ctx->c_len; msg_sizes = test_ctx->c_msg_sizes; msg_count = &test_ctx->c_msg_count; } else { buf = test_ctx->s_buff; len = &test_ctx->s_len; msg_sizes = test_ctx->s_msg_sizes; msg_count = &test_ctx->s_msg_count; } if ((unsigned)(*len + sz) > TEST_SSL_MEMIO_BUF_SZ) return WOLFSSL_CBIO_ERR_WANT_WRITE; if (*msg_count >= TEST_MEMIO_MAX_MSGS) return WOLFSSL_CBIO_ERR_WANT_WRITE; XMEMCPY(buf + *len, data, sz); msg_sizes[*msg_count] = sz; (*msg_count)++; *len += sz; #ifdef WOLFSSL_DUMP_MEMIO_STREAM { /* This can be imported into Wireshark by transforming the file with * od -Ax -tx1 -v test_output.dump > test_output.dump.hex * And then loading test_output.dump.hex into Wireshark using the * "Import from Hex Dump..." option ion and selecting the TCP * encapsulation option. */ char dump_file_name[64]; XFILE dump_file; sprintf(dump_file_name, "%s/%s.dump", tmpDirName, currentTestName); dump_file = XFOPEN(dump_file_name, "ab"); if (dump_file != XBADFILE) { (void)XFWRITE(data, 1, (size_t)sz, dump_file); XFCLOSE(dump_file); } } #endif return sz; } static WC_INLINE int test_ssl_memio_read_cb(WOLFSSL *ssl, char *data, int sz, void *ctx) { struct test_ssl_memio_ctx *test_ctx; int read_sz; byte *buf; int *len; int *msg_sizes; int *msg_count; int *msg_pos; int is_dtls; test_ctx = (struct test_ssl_memio_ctx*)ctx; is_dtls = wolfSSL_dtls(ssl); if (wolfSSL_GetSide(ssl) == WOLFSSL_SERVER_END) { buf = test_ctx->s_buff; len = &test_ctx->s_len; msg_sizes = test_ctx->s_msg_sizes; msg_count = &test_ctx->s_msg_count; msg_pos = &test_ctx->s_msg_pos; } else { buf = test_ctx->c_buff; len = &test_ctx->c_len; msg_sizes = test_ctx->c_msg_sizes; msg_count = &test_ctx->c_msg_count; msg_pos = &test_ctx->c_msg_pos; } if (*len == 0 || *msg_pos >= *msg_count) return WOLFSSL_CBIO_ERR_WANT_READ; /* Calculate how much we can read from current message */ read_sz = msg_sizes[*msg_pos]; if (read_sz > sz) read_sz = sz; if (read_sz > *len) return WOLFSSL_CBIO_ERR_GENERAL; /* Copy data from current message */ XMEMCPY(data, buf, (size_t)read_sz); /* remove the read data from the buffer */ XMEMMOVE(buf, buf + read_sz, (size_t)(*len - read_sz)); *len -= read_sz; msg_sizes[*msg_pos] -= read_sz; /* if we are on dtls, discard the rest of the message */ if (is_dtls && msg_sizes[*msg_pos] > 0) { XMEMMOVE(buf, buf + msg_sizes[*msg_pos], (size_t)(*len - msg_sizes[*msg_pos])); *len -= msg_sizes[*msg_pos]; msg_sizes[*msg_pos] = 0; } /* If we've read the entire message */ if (msg_sizes[*msg_pos] == 0) { /* Move to next message */ (*msg_pos)++; if (*msg_pos >= *msg_count) { *msg_pos = 0; *msg_count = 0; } } return read_sz; } int test_ssl_memio_setup(test_ssl_memio_ctx *ctx) { EXPECT_DECLS_NO_MSGS(-2000); #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) int c_sharedCtx = 0; int s_sharedCtx = 0; #endif const char* clientCertFile = cliCertFile; const char* clientKeyFile = cliKeyFile; const char* serverCertFile = svrCertFile; const char* serverKeyFile = svrKeyFile; /******************************** * Create WOLFSSL_CTX for client. ********************************/ #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) if (ctx->c_ctx != NULL) { c_sharedCtx = ctx->c_cb.isSharedCtx; } else #endif { WOLFSSL_METHOD* method = NULL; if (ctx->c_cb.method != NULL) { method = ctx->c_cb.method(); } else { method = wolfSSLv23_client_method(); } ExpectNotNull(ctx->c_ctx = wolfSSL_CTX_new(method)); } wolfSSL_SetIORecv(ctx->c_ctx, test_ssl_memio_read_cb); wolfSSL_SetIOSend(ctx->c_ctx, test_ssl_memio_write_cb); #ifdef WOLFSSL_ENCRYPTED_KEYS wolfSSL_CTX_set_default_passwd_cb(ctx->c_ctx, PasswordCallBack); #endif if (ctx->c_cb.caPemFile == NULL) ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx->c_ctx, caCertFile, 0), WOLFSSL_SUCCESS); else if (*ctx->c_cb.caPemFile != '\0') ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx->c_ctx, ctx->c_cb.caPemFile, 0), WOLFSSL_SUCCESS); if (ctx->c_cb.certPemFile != NULL) { clientCertFile = ctx->c_cb.certPemFile; } if (ctx->c_cb.keyPemFile != NULL) { clientKeyFile = ctx->c_cb.keyPemFile; } #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) if (!c_sharedCtx) #endif { if (*clientCertFile != '\0') { ExpectIntEQ(wolfSSL_CTX_use_certificate_chain_file(ctx->c_ctx, clientCertFile), WOLFSSL_SUCCESS); } if (*clientKeyFile != '\0') { ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_file(ctx->c_ctx, clientKeyFile, CERT_FILETYPE), WOLFSSL_SUCCESS); } } #ifdef HAVE_CRL if (ctx->c_cb.crlPemFile != NULL) { ExpectIntEQ(wolfSSL_CTX_EnableCRL(ctx->c_ctx, WOLFSSL_CRL_CHECKALL), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_LoadCRLFile(ctx->c_ctx, ctx->c_cb.crlPemFile, CERT_FILETYPE), WOLFSSL_SUCCESS); } #endif if (ctx->c_ciphers != NULL) { ExpectIntEQ(wolfSSL_CTX_set_cipher_list(ctx->c_ctx, ctx->c_ciphers), WOLFSSL_SUCCESS); } if (ctx->c_cb.ctx_ready != NULL) { ExpectIntEQ(ctx->c_cb.ctx_ready(ctx->c_ctx), TEST_SUCCESS); } /******************************** * Create WOLFSSL_CTX for server. ********************************/ if (ctx->s_ctx != NULL) { #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) s_sharedCtx = 1; #endif ctx->s_cb.isSharedCtx = 1; } else { WOLFSSL_METHOD* method = NULL; if (ctx->s_cb.method != NULL) { method = ctx->s_cb.method(); } else { method = wolfSSLv23_server_method(); } ExpectNotNull(ctx->s_ctx = wolfSSL_CTX_new(method)); ctx->s_cb.isSharedCtx = 0; } if (!ctx->s_cb.ticNoInit && (ctx->s_ctx != NULL)) { #if defined(HAVE_SESSION_TICKET) && \ ((defined(HAVE_CHACHA) && defined(HAVE_POLY1305)) || defined(HAVE_AESGCM)) #if defined(OPENSSL_EXTRA) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_256) OpenSSLTicketInit(); wolfSSL_CTX_set_tlsext_ticket_key_cb(ctx->s_ctx, myTicketEncCbOpenSSL); #elif defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) TicketInit(); wolfSSL_CTX_set_TicketEncCb(ctx->s_ctx, myTicketEncCb); #endif #endif } wolfSSL_SetIORecv(ctx->s_ctx, test_ssl_memio_read_cb); wolfSSL_SetIOSend(ctx->s_ctx, test_ssl_memio_write_cb); wolfSSL_CTX_set_verify(ctx->s_ctx, WOLFSSL_VERIFY_PEER | WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0); if (ctx->s_cb.caPemFile == NULL) ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx->s_ctx, cliCertFile, 0), WOLFSSL_SUCCESS); else if (*ctx->s_cb.caPemFile != '\0') ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx->s_ctx, ctx->s_cb.caPemFile, 0), WOLFSSL_SUCCESS); #ifdef WOLFSSL_ENCRYPTED_KEYS wolfSSL_CTX_set_default_passwd_cb(ctx->s_ctx, PasswordCallBack); #endif if (ctx->s_cb.certPemFile != NULL) { serverCertFile = ctx->s_cb.certPemFile; } #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) if (!s_sharedCtx) #endif { if (*serverCertFile != '\0') { ExpectIntEQ(wolfSSL_CTX_use_certificate_chain_file(ctx->s_ctx, serverCertFile), WOLFSSL_SUCCESS); } } if (ctx->s_cb.keyPemFile != NULL) { serverKeyFile = ctx->s_cb.keyPemFile; } #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) if (!s_sharedCtx) #endif { if (*serverKeyFile != '\0') { ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_file(ctx->s_ctx, serverKeyFile, CERT_FILETYPE), WOLFSSL_SUCCESS); } } if (ctx->s_ciphers != NULL) { ExpectIntEQ(wolfSSL_CTX_set_cipher_list(ctx->s_ctx, ctx->s_ciphers), WOLFSSL_SUCCESS); } if (ctx->s_cb.ctx_ready != NULL) { ExpectIntEQ(ctx->s_cb.ctx_ready(ctx->s_ctx), TEST_SUCCESS); } /**************************** * Create WOLFSSL for client. ****************************/ ExpectNotNull(ctx->c_ssl = wolfSSL_new(ctx->c_ctx)); wolfSSL_SetIOWriteCtx(ctx->c_ssl, ctx); wolfSSL_SetIOReadCtx(ctx->c_ssl, ctx); #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) if (c_sharedCtx) { if (*clientCertFile != '\0') { ExpectIntEQ(wolfSSL_use_certificate_chain_file(ctx->c_ssl, clientCertFile), WOLFSSL_SUCCESS); } if (*clientKeyFile != '\0') { ExpectIntEQ(wolfSSL_use_PrivateKey_file(ctx->c_ssl, clientKeyFile, CERT_FILETYPE), WOLFSSL_SUCCESS); } } #endif if (ctx->c_cb.ssl_ready != NULL) { ExpectIntEQ(ctx->c_cb.ssl_ready(ctx->c_ssl), TEST_SUCCESS); } /**************************** * Create WOLFSSL for server. ****************************/ ExpectNotNull(ctx->s_ssl = wolfSSL_new(ctx->s_ctx)); wolfSSL_SetIOWriteCtx(ctx->s_ssl, ctx); wolfSSL_SetIOReadCtx(ctx->s_ssl, ctx); #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) if (s_sharedCtx) { if (*serverCertFile != '\0') { ExpectIntEQ(wolfSSL_use_certificate_chain_file(ctx->s_ssl, serverCertFile), WOLFSSL_SUCCESS); } if (*serverKeyFile != '\0') { ExpectIntEQ(wolfSSL_use_PrivateKey_file(ctx->s_ssl, serverKeyFile, CERT_FILETYPE), WOLFSSL_SUCCESS); } } #endif #if !defined(NO_FILESYSTEM) && !defined(NO_DH) wolfSSL_SetTmpDH_file(ctx->s_ssl, dhParamFile, CERT_FILETYPE); #elif !defined(NO_DH) /* will repick suites with DHE, higher priority than PSK */ SetDH(ctx->s_ssl); #endif if (ctx->s_cb.ssl_ready != NULL) { ExpectIntEQ(ctx->s_cb.ssl_ready(ctx->s_ssl), TEST_SUCCESS); } return EXPECT_RESULT(); } int test_ssl_memio_do_handshake(test_ssl_memio_ctx* ctx, int max_rounds, int* rounds) { int handshake_complete = 0; int hs_c = 0; int hs_s = 0; int failing_s = 0; int failing_c = 0; int ret; int err; if (rounds != NULL) { *rounds = 0; } while ((!handshake_complete) && (max_rounds > 0)) { if (!hs_c) { wolfSSL_SetLoggingPrefix("client"); ret = wolfSSL_connect(ctx->c_ssl); wolfSSL_SetLoggingPrefix(NULL); if (ret == WOLFSSL_SUCCESS) { hs_c = 1; } else { err = wolfSSL_get_error(ctx->c_ssl, ret); if (err == WC_NO_ERR_TRACE(MP_WOULDBLOCK)) { /* retry non-blocking math */ } else if (err != WOLFSSL_ERROR_WANT_READ && err != WOLFSSL_ERROR_WANT_WRITE && err != WC_NO_ERR_TRACE(OCSP_WANT_READ)) { char buff[WOLFSSL_MAX_ERROR_SZ]; fprintf(stderr, "error = %d, %s\n", err, wolfSSL_ERR_error_string((word32)err, buff)); failing_c = 1; hs_c = 1; if (failing_c && failing_s) { break; } } } } if (!hs_s) { wolfSSL_SetLoggingPrefix("server"); ret = wolfSSL_accept(ctx->s_ssl); wolfSSL_SetLoggingPrefix(NULL); if (ret == WOLFSSL_SUCCESS) { hs_s = 1; } else { err = wolfSSL_get_error(ctx->s_ssl, ret); if (err == WC_NO_ERR_TRACE(MP_WOULDBLOCK)) { /* retry non-blocking math */ } else if (err != WOLFSSL_ERROR_WANT_READ && err != WOLFSSL_ERROR_WANT_WRITE && err != WC_NO_ERR_TRACE(OCSP_WANT_READ)) { char buff[WOLFSSL_MAX_ERROR_SZ]; fprintf(stderr, "error = %d, %s\n", err, wolfSSL_ERR_error_string((word32)err, buff)); failing_s = 1; hs_s = 1; if (failing_c && failing_s) { break; } } } } handshake_complete = hs_c && hs_s; max_rounds--; if (rounds != NULL) { *rounds += 1; } } if (!handshake_complete || failing_c || failing_s) { return TEST_FAIL; } return TEST_SUCCESS; } static int test_ssl_memio_read_write(test_ssl_memio_ctx* ctx) { EXPECT_DECLS_NO_MSGS(-3000); char input[1024]; int idx = 0; const char* msg_c = "hello wolfssl!"; int msglen_c = (int)XSTRLEN(msg_c); const char* msg_s = "I hear you fa shizzle!"; int msglen_s = (int)XSTRLEN(msg_s); if (ctx->c_msg != NULL) { msg_c = ctx->c_msg; msglen_c = ctx->c_msglen; } if (ctx->s_msg != NULL) { msg_s = ctx->s_msg; msglen_s = ctx->s_msglen; } wolfSSL_SetLoggingPrefix("client"); ExpectIntEQ(wolfSSL_write(ctx->c_ssl, msg_c, msglen_c), msglen_c); wolfSSL_SetLoggingPrefix("server"); ExpectIntGT(idx = wolfSSL_read(ctx->s_ssl, input, sizeof(input) - 1), 0); if (idx >= 0) { input[idx] = '\0'; } ExpectIntGT(fprintf(stderr, "Client message: %s\n", input), 0); ExpectIntEQ(wolfSSL_write(ctx->s_ssl, msg_s, msglen_s), msglen_s); ctx->s_cb.return_code = EXPECT_RESULT(); wolfSSL_SetLoggingPrefix("client"); ExpectIntGT(idx = wolfSSL_read(ctx->c_ssl, input, sizeof(input) - 1), 0); wolfSSL_SetLoggingPrefix(NULL); if (idx >= 0) { input[idx] = '\0'; } ExpectIntGT(fprintf(stderr, "Server response: %s\n", input), 0); ctx->c_cb.return_code = EXPECT_RESULT(); if (ctx->c_cb.on_result != NULL) { ExpectIntEQ(ctx->c_cb.on_result(ctx->c_ssl), TEST_SUCCESS); } if (ctx->s_cb.on_result != NULL) { ExpectIntEQ(ctx->s_cb.on_result(ctx->s_ssl), TEST_SUCCESS); } return EXPECT_RESULT(); } void test_ssl_memio_cleanup(test_ssl_memio_ctx* ctx) { ctx->c_cb.last_err = wolfSSL_get_error(ctx->c_ssl, 0); ctx->s_cb.last_err = wolfSSL_get_error(ctx->s_ssl, 0); if (ctx->c_cb.on_cleanup != NULL) { ctx->c_cb.on_cleanup(ctx->c_ssl); } if (ctx->s_cb.on_cleanup != NULL) { ctx->s_cb.on_cleanup(ctx->s_ssl); } wolfSSL_shutdown(ctx->s_ssl); wolfSSL_shutdown(ctx->c_ssl); wolfSSL_free(ctx->s_ssl); wolfSSL_free(ctx->c_ssl); if (ctx->c_cb.on_ctx_cleanup != NULL) { ctx->c_cb.on_ctx_cleanup(ctx->c_ctx); } if (!ctx->c_cb.isSharedCtx) { wolfSSL_CTX_free(ctx->c_ctx); ctx->c_ctx = NULL; } if (ctx->s_cb.on_ctx_cleanup != NULL) { ctx->s_cb.on_ctx_cleanup(ctx->s_ctx); } if (!ctx->s_cb.isSharedCtx) { wolfSSL_CTX_free(ctx->s_ctx); ctx->s_ctx = NULL; } if (!ctx->s_cb.ticNoInit) { #if defined(HAVE_SESSION_TICKET) && \ ((defined(HAVE_CHACHA) && defined(HAVE_POLY1305)) || defined(HAVE_AESGCM)) #if defined(OPENSSL_EXTRA) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_256) OpenSSLTicketCleanup(); #elif defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) TicketCleanup(); #endif #endif } } static int test_wolfSSL_client_server_nofail_memio_ex(test_ssl_cbf* client_cb, test_ssl_cbf* server_cb, cbType client_on_handshake, cbType server_on_handshake) { /* We use EXPECT_DECLS_NO_MSGS() here because this helper routine is used * for numerous but varied expected-to-fail scenarios that should not emit * error messages on the expected failures. Instead, we return a distinct * code for each failure point, allowing the caller to assert on a * particular mode of expected failure. On success, the usual TEST_SUCCESS * is returned. */ EXPECT_DECLS_NO_MSGS(-1000); struct test_ssl_memio_ctx test_ctx; #ifdef WOLFSSL_HAVE_TLS_UNIQUE size_t msg_len; #endif /* WOLFSSL_HAVE_TLS_UNIQUE */ XMEMSET(&test_ctx, 0, sizeof(test_ctx)); XMEMCPY(&test_ctx.c_cb, client_cb, sizeof(test_ssl_cbf)); XMEMCPY(&test_ctx.s_cb, server_cb, sizeof(test_ssl_cbf)); test_ctx.c_ctx = client_cb->ctx; test_ctx.s_ctx = server_cb->ctx; test_ctx.c_cb.return_code = EXPECT_FAILURE_CODEPOINT_ID; test_ctx.s_cb.return_code = EXPECT_FAILURE_CODEPOINT_ID; ExpectIntEQ(test_ssl_memio_setup(&test_ctx), TEST_SUCCESS); ExpectIntEQ(test_ssl_memio_do_handshake(&test_ctx, 10, NULL), TEST_SUCCESS); if (client_on_handshake != NULL) { ExpectIntEQ(client_on_handshake(test_ctx.c_ctx, test_ctx.c_ssl), TEST_SUCCESS); } if (server_on_handshake != NULL) { ExpectIntEQ(server_on_handshake(test_ctx.s_ctx, test_ctx.s_ssl), TEST_SUCCESS); } if (client_cb->on_handshake != NULL) { ExpectIntEQ(client_cb->on_handshake(&test_ctx.c_ctx, &test_ctx.c_ssl), TEST_SUCCESS); } if (server_cb->on_handshake != NULL) { ExpectIntEQ(server_cb->on_handshake(&test_ctx.s_ctx, &test_ctx.s_ssl), TEST_SUCCESS); } #ifdef WOLFSSL_HAVE_TLS_UNIQUE XMEMSET(server_side_msg2, 0, WC_MAX_DIGEST_SIZE); msg_len = wolfSSL_get_peer_finished(test_ctx.s_ssl, server_side_msg2, WC_MAX_DIGEST_SIZE); ExpectIntGE(msg_len, 0); XMEMSET(server_side_msg1, 0, WC_MAX_DIGEST_SIZE); msg_len = wolfSSL_get_finished(test_ctx.s_ssl, server_side_msg1, WC_MAX_DIGEST_SIZE); ExpectIntGE(msg_len, 0); #endif /* WOLFSSL_HAVE_TLS_UNIQUE */ ExpectIntEQ(test_ssl_memio_read_write(&test_ctx), TEST_SUCCESS); test_ssl_memio_cleanup(&test_ctx); client_cb->return_code = test_ctx.c_cb.return_code; client_cb->last_err = test_ctx.c_cb.last_err; server_cb->return_code = test_ctx.s_cb.return_code; server_cb->last_err = test_ctx.s_cb.last_err; return EXPECT_RESULT(); } int test_wolfSSL_client_server_nofail_memio(test_ssl_cbf* client_cb, test_ssl_cbf* server_cb, cbType client_on_handshake) { return (test_wolfSSL_client_server_nofail_memio_ex(client_cb, server_cb, client_on_handshake, NULL)); } #endif #ifdef HAVE_IO_TESTS_DEPENDENCIES #ifdef WOLFSSL_SESSION_EXPORT #ifdef WOLFSSL_DTLS /* set up function for sending session information */ static int test_export(WOLFSSL* inSsl, byte* buf, word32 sz, void* userCtx) { WOLFSSL_CTX* ctx = NULL; WOLFSSL* ssl = NULL; AssertNotNull(inSsl); AssertNotNull(buf); AssertIntNE(0, sz); /* Set ctx to DTLS 1.2 */ ctx = wolfSSL_CTX_new(wolfDTLSv1_2_server_method()); AssertNotNull(ctx); ssl = wolfSSL_new(ctx); AssertNotNull(ssl); AssertIntGE(wolfSSL_dtls_import(ssl, buf, sz), 0); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); (void)userCtx; return 0; } #endif /* returns negative value on fail and positive (including 0) on success */ static int nonblocking_accept_read(void* args, WOLFSSL* ssl, SOCKET_T* sockfd) { int ret, err, loop_count, count, timeout = 10; char msg[] = "I hear you fa shizzle!"; char input[1024]; loop_count = ((func_args*)args)->argc; #ifdef WOLFSSL_ASYNC_CRYPT err = 0; /* Reset error */ #endif do { #ifdef WOLFSSL_ASYNC_CRYPT if (err == WC_NO_ERR_TRACE(WC_PENDING_E)) { ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); if (ret < 0) { break; } else if (ret == 0) { continue; } } #endif ret = wolfSSL_accept(ssl); err = wolfSSL_get_error(ssl, 0); if (err == WOLFSSL_ERROR_WANT_READ || err == WOLFSSL_ERROR_WANT_WRITE) { int select_ret; err = WC_PENDING_E; select_ret = tcp_select(*sockfd, timeout); if (select_ret == TEST_TIMEOUT) { return WOLFSSL_FATAL_ERROR; } } } while (err == WC_NO_ERR_TRACE(WC_PENDING_E)); if (ret != WOLFSSL_SUCCESS) { char buff[WOLFSSL_MAX_ERROR_SZ]; fprintf(stderr, "error = %d, %s\n", err, wolfSSL_ERR_error_string(err, buff)); return ret; } for (count = 0; count < loop_count; count++) { int select_ret; select_ret = tcp_select(*sockfd, timeout); if (select_ret == TEST_TIMEOUT) { ret = WOLFSSL_FATAL_ERROR; break; } do { ret = wolfSSL_read(ssl, input, sizeof(input)-1); if (ret > 0) { input[ret] = '\0'; fprintf(stderr, "Client message: %s\n", input); } } while (err == WOLFSSL_ERROR_WANT_READ && ret != WOLFSSL_SUCCESS); do { if ((ret = wolfSSL_write(ssl, msg, sizeof(msg))) != sizeof(msg)) { return WOLFSSL_FATAL_ERROR; } err = wolfSSL_get_error(ssl, ret); } while (err == WOLFSSL_ERROR_WANT_READ && ret != WOLFSSL_SUCCESS); } return ret; } #endif /* WOLFSSL_SESSION_EXPORT */ THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args) { SOCKET_T sockfd = 0; SOCKET_T clientfd = 0; word16 port; callback_functions* cbf; WOLFSSL_CTX* ctx = NULL; WOLFSSL* ssl = NULL; func_args* opts = (func_args*)args; char msg[] = "I hear you fa shizzle!"; char input[1024]; int idx; int ret, err = 0; int sharedCtx = 0; int doUdp = 0; SOCKADDR_IN_T cliAddr; socklen_t cliLen; const char* certFile = svrCertFile; const char* keyFile = svrKeyFile; #ifdef WOLFSSL_HAVE_TLS_UNIQUE size_t msg_len = 0; #endif wolfSSL_SetLoggingPrefix("server"); #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); #endif opts->return_code = TEST_FAIL; cbf = opts->callbacks; if (cbf != NULL && cbf->ctx) { ctx = cbf->ctx; sharedCtx = 1; } else { WOLFSSL_METHOD* method = NULL; if (cbf != NULL && cbf->method != NULL) { method = cbf->method(); } else { method = wolfSSLv23_server_method(); } ctx = wolfSSL_CTX_new(method); } if (ctx == NULL) { /* Release the wait for TCP ready. */ signal_ready(opts->signal); goto done; } if (cbf == NULL || !cbf->ticNoInit) { #if defined(HAVE_SESSION_TICKET) && \ ((defined(HAVE_CHACHA) && defined(HAVE_POLY1305)) || defined(HAVE_AESGCM)) #if defined(OPENSSL_EXTRA) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_256) OpenSSLTicketInit(); wolfSSL_CTX_set_tlsext_ticket_key_cb(ctx, myTicketEncCbOpenSSL); #elif defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) TicketInit(); wolfSSL_CTX_set_TicketEncCb(ctx, myTicketEncCb); #endif #endif } #if defined(USE_WINDOWS_API) port = opts->signal->port; #elif defined(NO_MAIN_DRIVER) && !defined(WOLFSSL_SNIFFER) && \ !defined(WOLFSSL_MDK_SHELL) && !defined(WOLFSSL_TIRTOS) /* Let tcp_listen assign port */ port = 0; #else /* Use default port */ port = wolfSSLPort; #endif if (cbf != NULL) doUdp = cbf->doUdp; /* do it here to detect failure */ tcp_accept( &sockfd, &clientfd, opts, port, 0, doUdp, 0, 0, 1, 0, 0); if (doUdp) { cliLen = sizeof(cliAddr); idx = (int)recvfrom(sockfd, input, sizeof(input), MSG_PEEK, (struct sockaddr*)&cliAddr, &cliLen); AssertIntGT(idx, 0); } else { CloseSocket(sockfd); } wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER | WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0); #ifdef WOLFSSL_ENCRYPTED_KEYS wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); #endif if (wolfSSL_CTX_load_verify_locations(ctx, cliCertFile, 0) != WOLFSSL_SUCCESS) { /*err_sys("can't load ca file, Please run from wolfSSL home dir");*/ goto done; } if (cbf != NULL && cbf->certPemFile != NULL) certFile = cbf->certPemFile; #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) if (!sharedCtx && wolfSSL_CTX_use_certificate_file(ctx, certFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) { #else if (wolfSSL_CTX_use_certificate_file(ctx, certFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) { #endif /*err_sys("can't load server cert chain file, " "Please run from wolfSSL home dir");*/ goto done; } if (cbf != NULL && cbf->keyPemFile != NULL) keyFile = cbf->keyPemFile; #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) if (!sharedCtx && wolfSSL_CTX_use_PrivateKey_file(ctx, keyFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) { #else if (wolfSSL_CTX_use_PrivateKey_file(ctx, keyFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) { #endif /*err_sys("can't load server key file, " "Please run from wolfSSL home dir");*/ goto done; } #ifdef HAVE_CRL if (cbf != NULL && cbf->crlPemFile != NULL) { if (wolfSSL_CTX_EnableCRL(ctx, WOLFSSL_CRL_CHECKALL) != WOLFSSL_SUCCESS) goto done; if (wolfSSL_CTX_LoadCRLFile(ctx, cbf->crlPemFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) goto done; } #endif /* call ctx setup callback */ if (cbf != NULL && cbf->ctx_ready != NULL) { cbf->ctx_ready(ctx); } ssl = wolfSSL_new(ctx); if (ssl == NULL) { goto done; } if (doUdp) { err = wolfSSL_dtls_set_peer(ssl, &cliAddr, cliLen); if (err != WOLFSSL_SUCCESS) goto done; } #ifdef WOLFSSL_SESSION_EXPORT /* only add in more complex nonblocking case with session export tests */ if (args && opts->argc > 0) { /* set as nonblock and time out for waiting on read/write */ tcp_set_nonblocking(&clientfd); wolfSSL_dtls_set_using_nonblock(ssl, 1); } #endif #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) if (sharedCtx && wolfSSL_use_certificate_file(ssl, certFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) { #else if (wolfSSL_use_certificate_file(ssl, certFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) { #endif /*err_sys("can't load server cert chain file, " "Please run from wolfSSL home dir");*/ goto done; } #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) if (sharedCtx && wolfSSL_use_PrivateKey_file(ssl, keyFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) { #else if (wolfSSL_use_PrivateKey_file(ssl, keyFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) { #endif /*err_sys("can't load server key file, " "Please run from wolfSSL home dir");*/ goto done; } if (wolfSSL_set_fd(ssl, clientfd) != WOLFSSL_SUCCESS) { /*err_sys("SSL_set_fd failed");*/ goto done; } #if !defined(NO_FILESYSTEM) && !defined(NO_DH) wolfSSL_SetTmpDH_file(ssl, dhParamFile, CERT_FILETYPE); #elif !defined(NO_DH) SetDH(ssl); /* will repick suites with DHE, higher priority than PSK */ #endif /* call ssl setup callback */ if (cbf != NULL && cbf->ssl_ready != NULL) { cbf->ssl_ready(ssl); } #ifdef WOLFSSL_SESSION_EXPORT /* only add in more complex nonblocking case with session export tests */ if (opts->argc > 0) { ret = nonblocking_accept_read(args, ssl, &clientfd); if (ret >= 0) { opts->return_code = TEST_SUCCESS; } #ifdef WOLFSSL_TIRTOS Task_yield(); #endif goto done; } #endif WOLFSSL_ASYNC_WHILE_PENDING(ret = wolfSSL_negotiate(ssl), ret != WOLFSSL_SUCCESS); if (ret != WOLFSSL_SUCCESS) { char buff[WOLFSSL_MAX_ERROR_SZ]; fprintf(stderr, "error = %d, %s\n", err, wolfSSL_ERR_error_string((word32)err, buff)); /*err_sys("SSL_accept failed");*/ goto done; } #ifdef WOLFSSL_HAVE_TLS_UNIQUE XMEMSET(server_side_msg2, 0, WC_MAX_DIGEST_SIZE); msg_len = wolfSSL_get_peer_finished(ssl, server_side_msg2, WC_MAX_DIGEST_SIZE); AssertIntGE(msg_len, 0); XMEMSET(server_side_msg1, 0, WC_MAX_DIGEST_SIZE); msg_len = wolfSSL_get_finished(ssl, server_side_msg1, WC_MAX_DIGEST_SIZE); AssertIntGE(msg_len, 0); #endif /* WOLFSSL_HAVE_TLS_UNIQUE */ idx = wolfSSL_read(ssl, input, sizeof(input)-1); if (idx > 0) { input[idx] = '\0'; fprintf(stderr, "Client message: %s\n", input); } else if (idx < 0) { goto done; } if (wolfSSL_write(ssl, msg, sizeof(msg)) != sizeof(msg)) { /*err_sys("SSL_write failed");*/ goto done; } if (cbf != NULL && cbf->on_result != NULL) cbf->on_result(ssl); #ifdef WOLFSSL_TIRTOS Task_yield(); #endif opts->return_code = TEST_SUCCESS; done: if (cbf != NULL) cbf->last_err = err; if (cbf != NULL && cbf->on_cleanup != NULL) cbf->on_cleanup(ssl); wolfSSL_shutdown(ssl); wolfSSL_free(ssl); if (!sharedCtx) wolfSSL_CTX_free(ctx); CloseSocket(clientfd); #ifdef WOLFSSL_TIRTOS fdCloseSession(Task_self()); #endif #if defined(NO_MAIN_DRIVER) && defined(HAVE_ECC) && defined(FP_ECC) \ && defined(HAVE_THREAD_LS) wc_ecc_fp_free(); /* free per thread cache */ #endif if (cbf == NULL || !cbf->ticNoInit) { #if defined(HAVE_SESSION_TICKET) && \ ((defined(HAVE_CHACHA) && defined(HAVE_POLY1305)) || defined(HAVE_AESGCM)) #if defined(OPENSSL_EXTRA) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_256) OpenSSLTicketCleanup(); #elif defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) TicketCleanup(); #endif #endif } wolfSSL_SetLoggingPrefix(NULL); WOLFSSL_RETURN_FROM_THREAD(0); } #if defined(OPENSSL_EXTRA) && !defined(NO_SESSION_CACHE) && \ !defined(WOLFSSL_NO_TLS12) static THREAD_RETURN WOLFSSL_THREAD test_server_loop(void* args) { SOCKET_T sockfd; SOCKET_T clientfd = -1; word16 port; callback_functions* cbf; WOLFSSL_CTX* ctx = 0; WOLFSSL* ssl = 0; char msg[] = "I hear you fa shizzle!"; char input[1024]; int idx; int ret, err = 0; int sharedCtx = 0; func_args* opts = (func_args*)args; int loop_count = opts->argc; int count = 0; #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); #endif opts->return_code = TEST_FAIL; cbf = opts->callbacks; #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) if (cbf != NULL && cbf->ctx) { ctx = cbf->ctx; sharedCtx = 1; } else #endif { WOLFSSL_METHOD* method = NULL; if (cbf != NULL && cbf->method != NULL) { method = cbf->method(); } else { method = wolfSSLv23_server_method(); } ctx = wolfSSL_CTX_new(method); } #if defined(USE_WINDOWS_API) port = opts->signal->port; #elif defined(NO_MAIN_DRIVER) && !defined(WOLFSSL_SNIFFER) && \ !defined(WOLFSSL_MDK_SHELL) && !defined(WOLFSSL_TIRTOS) /* Let tcp_listen assign port */ port = 0; #else /* Use default port */ port = wolfSSLPort; #endif wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER | WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0); #ifdef WOLFSSL_ENCRYPTED_KEYS wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); #endif if (wolfSSL_CTX_load_verify_locations(ctx, cliCertFile, 0) != WOLFSSL_SUCCESS) { /*err_sys("can't load ca file, Please run from wolfSSL home dir");*/ /* Release the wait for TCP ready. */ signal_ready(opts->signal); goto done; } if (!sharedCtx && wolfSSL_CTX_use_certificate_file(ctx, svrCertFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) { /*err_sys("can't load server cert chain file, " "Please run from wolfSSL home dir");*/ /* Release the wait for TCP ready. */ signal_ready(opts->signal); goto done; } if (!sharedCtx && wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) { /*err_sys("can't load server key file, " "Please run from wolfSSL home dir");*/ /* Release the wait for TCP ready. */ signal_ready(opts->signal); goto done; } /* call ctx setup callback */ if (cbf != NULL && cbf->ctx_ready != NULL) { cbf->ctx_ready(ctx); } while (count != loop_count) { ssl = wolfSSL_new(ctx); if (ssl == NULL) { signal_ready(opts->signal); goto done; } if (sharedCtx && wolfSSL_use_certificate_file(ssl, svrCertFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) { /*err_sys("can't load server cert chain file, " "Please run from wolfSSL home dir");*/ /* Release the wait for TCP ready. */ signal_ready(opts->signal); goto done; } if (sharedCtx && wolfSSL_use_PrivateKey_file(ssl, svrKeyFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) { /*err_sys("can't load server key file, " "Please run from wolfSSL home dir");*/ /* Release the wait for TCP ready. */ signal_ready(opts->signal); goto done; } #if !defined(NO_FILESYSTEM) && !defined(NO_DH) wolfSSL_SetTmpDH_file(ssl, dhParamFile, CERT_FILETYPE); #elif !defined(NO_DH) SetDH(ssl); /* will repick suites with DHE, higher priority than PSK */ #endif /* call ssl setup callback */ if (cbf != NULL && cbf->ssl_ready != NULL) { cbf->ssl_ready(ssl); } /* do it here to detect failure */ tcp_accept(&sockfd, &clientfd, (func_args*)args, port, 0, 0, 0, 0, 1, 0, 0); CloseSocket(sockfd); if (wolfSSL_set_fd(ssl, clientfd) != WOLFSSL_SUCCESS) { /*err_sys("SSL_set_fd failed");*/ goto done; } WOLFSSL_ASYNC_WHILE_PENDING(ret = wolfSSL_accept(ssl), ret != WOLFSSL_SUCCESS); if (ret != WOLFSSL_SUCCESS) { char buff[WOLFSSL_MAX_ERROR_SZ]; fprintf(stderr, "error = %d, %s\n", err, wolfSSL_ERR_error_string(err, buff)); /*err_sys("SSL_accept failed");*/ goto done; } idx = wolfSSL_read(ssl, input, sizeof(input)-1); if (idx > 0) { input[idx] = '\0'; fprintf(stderr, "Client message: %s\n", input); } if (wolfSSL_write(ssl, msg, sizeof(msg)) != sizeof(msg)) { /*err_sys("SSL_write failed");*/ goto done; } /* free ssl for this connection */ wolfSSL_shutdown(ssl); wolfSSL_free(ssl); ssl = NULL; CloseSocket(clientfd); clientfd = -1; count++; } #ifdef WOLFSSL_TIRTOS Task_yield(); #endif opts->return_code = TEST_SUCCESS; done: if (ssl != NULL) { wolfSSL_shutdown(ssl); wolfSSL_free(ssl); } if (!sharedCtx) wolfSSL_CTX_free(ctx); if (clientfd != SOCKET_INVALID) CloseSocket(clientfd); #ifdef WOLFSSL_TIRTOS fdCloseSession(Task_self()); #endif #if defined(NO_MAIN_DRIVER) && defined(HAVE_ECC) && defined(FP_ECC) \ && defined(HAVE_THREAD_LS) wc_ecc_fp_free(); /* free per thread cache */ #endif WOLFSSL_RETURN_FROM_THREAD(0); } #endif /* defined(OPENSSL_EXTRA) && !defined(NO_SESSION_CACHE) && !defined(WOLFSSL_TLS13) */ int test_client_nofail(void* args, cbType cb) { #if !defined(NO_WOLFSSL_CLIENT) SOCKET_T sockfd = 0; callback_functions* cbf; WOLFSSL_CTX* ctx = 0; WOLFSSL* ssl = 0; WOLFSSL_CIPHER* cipher; char msg[64] = "hello wolfssl!"; char reply[1024]; int input; int msgSz = (int)XSTRLEN(msg); int ret, err = 0; int cipherSuite; int sharedCtx = 0; int doUdp = 0; const char* cipherName1, *cipherName2; wolfSSL_SetLoggingPrefix("client"); #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); #endif ((func_args*)args)->return_code = TEST_FAIL; cbf = ((func_args*)args)->callbacks; #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) if (cbf != NULL && cbf->ctx) { ctx = cbf->ctx; sharedCtx = cbf->isSharedCtx; } else #endif { WOLFSSL_METHOD* method = NULL; if (cbf != NULL && cbf->method != NULL) { method = cbf->method(); } else { method = wolfSSLv23_client_method(); } ctx = wolfSSL_CTX_new(method); } if (cbf != NULL) doUdp = cbf->doUdp; #ifdef WOLFSSL_ENCRYPTED_KEYS wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); #endif /* Do connect here so server detects failures */ tcp_connect(&sockfd, wolfSSLIP, ((func_args*)args)->signal->port, doUdp, 0, NULL); /* Connect the socket so that we don't have to set the peer later on */ if (doUdp) udp_connect(&sockfd, wolfSSLIP, ((func_args*)args)->signal->port); if (wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0) != WOLFSSL_SUCCESS) { /* err_sys("can't load ca file, Please run from wolfSSL home dir");*/ goto done; } #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) if (!sharedCtx && wolfSSL_CTX_use_certificate_file(ctx, cliCertFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) { #else if (wolfSSL_CTX_use_certificate_file(ctx, cliCertFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) { #endif /*err_sys("can't load client cert file, " "Please run from wolfSSL home dir");*/ goto done; } #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) if (!sharedCtx && wolfSSL_CTX_use_PrivateKey_file(ctx, cliKeyFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) { #else if (wolfSSL_CTX_use_PrivateKey_file(ctx, cliKeyFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) { #endif /*err_sys("can't load client key file, " "Please run from wolfSSL home dir");*/ goto done; } #ifdef WOLFSSL_SRTP /* make sure that NULL (error condition) returns 1 */ if (wolfSSL_CTX_set_tlsext_use_srtp(ctx, NULL) != 1) { goto done; } #endif #ifdef HAVE_CRL if (cbf != NULL && cbf->crlPemFile != NULL) { if (wolfSSL_CTX_EnableCRL(ctx, WOLFSSL_CRL_CHECKALL) != WOLFSSL_SUCCESS) goto done; if (wolfSSL_CTX_LoadCRLFile(ctx, cbf->crlPemFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) goto done; } #endif /* call ctx setup callback */ if (cbf != NULL && cbf->ctx_ready != NULL) { cbf->ctx_ready(ctx); } ssl = wolfSSL_new(ctx); if (ssl == NULL) { goto done; } #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) if (sharedCtx && wolfSSL_use_certificate_file(ssl, cliCertFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) { #else if (wolfSSL_use_certificate_file(ssl, cliCertFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) { #endif /*err_sys("can't load client cert file, " "Please run from wolfSSL home dir");*/ goto done; } #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) if (sharedCtx && wolfSSL_use_PrivateKey_file(ssl, cliKeyFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) { #else if (wolfSSL_use_PrivateKey_file(ssl, cliKeyFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) { #endif /*err_sys("can't load client key file, " "Please run from wolfSSL home dir");*/ goto done; } #ifdef WOLFSSL_SRTP /* make sure that NULL (error condition) returns 1 */ if (wolfSSL_set_tlsext_use_srtp(ssl, NULL) != 1) { goto done; } #endif if (!doUdp) { if (wolfSSL_set_fd(ssl, sockfd) != WOLFSSL_SUCCESS) { /*err_sys("SSL_set_fd failed");*/ goto done; } } else { #ifdef WOLFSSL_DTLS if (wolfSSL_set_dtls_fd_connected(ssl, sockfd) != WOLFSSL_SUCCESS) { /*err_sys("SSL_set_fd failed");*/ goto done; } #else goto done; #endif } /* call ssl setup callback */ if (cbf != NULL && cbf->ssl_ready != NULL) { cbf->ssl_ready(ssl); } WOLFSSL_ASYNC_WHILE_PENDING(ret = wolfSSL_negotiate(ssl), ret != WOLFSSL_SUCCESS); if (ret != WOLFSSL_SUCCESS) { char buff[WOLFSSL_MAX_ERROR_SZ]; fprintf(stderr, "error = %d, %s\n", err, wolfSSL_ERR_error_string((word32)err, buff)); /*err_sys("SSL_connect failed");*/ goto done; } /* test the various get cipher methods */ /* Internal cipher suite names */ cipherSuite = wolfSSL_get_current_cipher_suite(ssl); cipherName1 = wolfSSL_get_cipher_name(ssl); cipherName2 = wolfSSL_get_cipher_name_from_suite( (byte)(cipherSuite >> 8), cipherSuite & 0xFF); AssertStrEQ(cipherName1, cipherName2); /* IANA Cipher Suites Names */ /* Unless WOLFSSL_CIPHER_INTERNALNAME or NO_ERROR_STRINGS, then it's the internal cipher suite name */ cipher = wolfSSL_get_current_cipher(ssl); cipherName1 = wolfSSL_CIPHER_get_name(cipher); cipherName2 = wolfSSL_get_cipher(ssl); AssertStrEQ(cipherName1, cipherName2); #if !defined(WOLFSSL_CIPHER_INTERNALNAME) && !defined(NO_ERROR_STRINGS) && \ !defined(WOLFSSL_QT) cipherName1 = wolfSSL_get_cipher_name_iana_from_suite( (byte)(cipherSuite >> 8), cipherSuite & 0xFF); AssertStrEQ(cipherName1, cipherName2); #endif if (cb != NULL) (cb)(ctx, ssl); if (wolfSSL_write(ssl, msg, msgSz) != msgSz) { /*err_sys("SSL_write failed");*/ goto done; } input = wolfSSL_read(ssl, reply, sizeof(reply)-1); if (input > 0) { reply[input] = '\0'; fprintf(stderr, "Server response: %s\n", reply); } if (cbf != NULL && cbf->on_result != NULL) cbf->on_result(ssl); ((func_args*)args)->return_code = TEST_SUCCESS; done: if (cbf != NULL) cbf->last_err = err; if (cbf != NULL && cbf->on_cleanup != NULL) cbf->on_cleanup(ssl); wolfSSL_free(ssl); if (!sharedCtx) wolfSSL_CTX_free(ctx); CloseSocket(sockfd); #ifdef WOLFSSL_TIRTOS fdCloseSession(Task_self()); #endif #if defined(NO_MAIN_DRIVER) && defined(HAVE_ECC) && defined(FP_ECC) \ && defined(HAVE_THREAD_LS) wc_ecc_fp_free(); /* free per thread cache */ #endif #else (void)args; (void)cb; #endif /* !NO_WOLFSSL_CLIENT */ wolfSSL_SetLoggingPrefix(NULL); return 0; } void test_wolfSSL_client_server_nofail_ex(callback_functions* client_cb, callback_functions* server_cb, cbType client_on_handshake) { func_args client_args; func_args server_args; tcp_ready ready; THREAD_TYPE serverThread; XMEMSET(&client_args, 0, sizeof(func_args)); XMEMSET(&server_args, 0, sizeof(func_args)); #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); #endif StartTCP(); InitTcpReady(&ready); server_args.signal = &ready; server_args.callbacks = server_cb; client_args.signal = &ready; client_args.callbacks = client_cb; start_thread(test_server_nofail, &server_args, &serverThread); wait_tcp_ready(&server_args); test_client_nofail(&client_args, client_on_handshake); join_thread(serverThread); client_cb->return_code = client_args.return_code; server_cb->return_code = server_args.return_code; FreeTcpReady(&ready); #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); #endif } void test_wolfSSL_client_server_nofail(callback_functions* client_cb, callback_functions* server_cb) { test_wolfSSL_client_server_nofail_ex(client_cb, server_cb, NULL); } #if defined(OPENSSL_EXTRA) && !defined(NO_SESSION_CACHE) && \ !defined(WOLFSSL_NO_TLS12) && !defined(NO_WOLFSSL_CLIENT) static void test_client_reuse_WOLFSSLobj(void* args, cbType cb, void* server_args) { SOCKET_T sockfd = 0; callback_functions* cbf; WOLFSSL_CTX* ctx = 0; WOLFSSL* ssl = 0; WOLFSSL_SESSION* session = NULL; char msg[64] = "hello wolfssl!"; char reply[1024]; int input; int msgSz = (int)XSTRLEN(msg); int ret, err = 0; int sharedCtx = 0; #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); #endif ((func_args*)args)->return_code = TEST_FAIL; cbf = ((func_args*)args)->callbacks; #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) if (cbf != NULL && cbf->ctx) { ctx = cbf->ctx; sharedCtx = 1; } else #endif { WOLFSSL_METHOD* method = NULL; if (cbf != NULL && cbf->method != NULL) { method = cbf->method(); } else { method = wolfSSLv23_client_method(); } ctx = wolfSSL_CTX_new(method); } #ifdef WOLFSSL_ENCRYPTED_KEYS wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); #endif /* Do connect here so server detects failures */ tcp_connect(&sockfd, wolfSSLIP, ((func_args*)args)->signal->port, 0, 0, NULL); if (wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0) != WOLFSSL_SUCCESS) { /* err_sys("can't load ca file, Please run from wolfSSL home dir");*/ goto done; } if (!sharedCtx && wolfSSL_CTX_use_certificate_file(ctx, cliCertFile, WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS) { /*err_sys("can't load client cert file, " "Please run from wolfSSL home dir");*/ goto done; } if (!sharedCtx && wolfSSL_CTX_use_PrivateKey_file(ctx, cliKeyFile, WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS) { /*err_sys("can't load client key file, " "Please run from wolfSSL home dir");*/ goto done; } /* call ctx setup callback */ if (cbf != NULL && cbf->ctx_ready != NULL) { cbf->ctx_ready(ctx); } ssl = wolfSSL_new(ctx); if (ssl == NULL) { goto done; } /* keep handshake resources for reusing WOLFSSL obj */ wolfSSL_KeepArrays(ssl); if (wolfSSL_KeepHandshakeResources(ssl)) { /* err_sys("SSL_KeepHandshakeResources failed"); */ goto done; } if (sharedCtx && wolfSSL_use_certificate_file(ssl, cliCertFile, WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS) { /*err_sys("can't load client cert file, " "Please run from wolfSSL home dir");*/ goto done; } if (sharedCtx && wolfSSL_use_PrivateKey_file(ssl, cliKeyFile, WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS) { /*err_sys("can't load client key file, " "Please run from wolfSSL home dir");*/ goto done; } if (wolfSSL_set_fd(ssl, sockfd) != WOLFSSL_SUCCESS) { /*err_sys("SSL_set_fd failed");*/ goto done; } /* call ssl setup callback */ if (cbf != NULL && cbf->ssl_ready != NULL) { cbf->ssl_ready(ssl); } WOLFSSL_ASYNC_WHILE_PENDING(ret = wolfSSL_connect(ssl), ret != WOLFSSL_SUCCESS); if (ret != WOLFSSL_SUCCESS) { char buff[WOLFSSL_MAX_ERROR_SZ]; fprintf(stderr, "error = %d, %s\n", err, wolfSSL_ERR_error_string(err, buff)); /*err_sys("SSL_connect failed");*/ goto done; } /* Build first session */ if (cb != NULL) cb(ctx, ssl); if (wolfSSL_write(ssl, msg, msgSz) != msgSz) { /*err_sys("SSL_write failed");*/ goto done; } input = wolfSSL_read(ssl, reply, sizeof(reply)-1); if (input > 0) { reply[input] = '\0'; fprintf(stderr, "Server response: %s\n", reply); } /* Session Resumption by reusing WOLFSSL object */ wolfSSL_set_quiet_shutdown(ssl, 1); if (wolfSSL_shutdown(ssl) != WOLFSSL_SUCCESS) { /* err_sys ("SSL shutdown failed"); */ goto done; } session = wolfSSL_get1_session(ssl); if (wolfSSL_clear(ssl) != WOLFSSL_SUCCESS) { wolfSSL_SESSION_free(session); /* err_sys ("SSL_clear failed"); */ goto done; } wolfSSL_set_session(ssl, session); wolfSSL_SESSION_free(session); session = NULL; /* close socket once */ CloseSocket(sockfd); sockfd = 0; /* wait until server ready */ wait_tcp_ready((func_args*)server_args); fprintf(stderr, "session resumption\n"); /* Do re-connect */ tcp_connect(&sockfd, wolfSSLIP, ((func_args*)args)->signal->port, 0, 0, NULL); if (wolfSSL_set_fd(ssl, sockfd) != WOLFSSL_SUCCESS) { /*err_sys("SSL_set_fd failed");*/ goto done; } WOLFSSL_ASYNC_WHILE_PENDING(ret = wolfSSL_connect(ssl), ret != WOLFSSL_SUCCESS); if (ret != WOLFSSL_SUCCESS) { char buff[WOLFSSL_MAX_ERROR_SZ]; fprintf(stderr, "error = %d, %s\n", err, wolfSSL_ERR_error_string(err, buff)); /*err_sys("SSL_connect failed");*/ goto done; } /* Build first session */ if (cb != NULL) cb(ctx, ssl); if (wolfSSL_write(ssl, msg, msgSz) != msgSz) { /*err_sys("SSL_write failed");*/ goto done; } input = wolfSSL_read(ssl, reply, sizeof(reply)-1); if (input > 0) { reply[input] = '\0'; fprintf(stderr, "Server response: %s\n", reply); } ((func_args*)args)->return_code = TEST_SUCCESS; done: wolfSSL_free(ssl); if (!sharedCtx) wolfSSL_CTX_free(ctx); CloseSocket(sockfd); #ifdef WOLFSSL_TIRTOS fdCloseSession(Task_self()); #endif return; } #endif /* defined(OPENSSL_EXTRA) && !defined(NO_SESSION_CACHE) && !defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_CLIENT) */ #if (defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || \ defined(WOLFSSL_HAPROXY) || defined(HAVE_LIGHTY)) && \ defined(HAVE_ALPN) && defined(HAVE_SNI) && \ defined(HAVE_IO_TESTS_DEPENDENCIES) && !defined(NO_BIO) #define HAVE_ALPN_PROTOS_SUPPORT #endif /* Generic TLS client / server with callbacks for API unit tests * Used by SNI / ALPN / crypto callback helper functions */ #if defined(HAVE_IO_TESTS_DEPENDENCIES) && \ (defined(HAVE_SNI) || defined(HAVE_ALPN) || \ (defined(WOLF_CRYPTO_CB) && \ !defined(WOLF_CRYPTO_CB_ONLY_RSA) && !defined(WOLF_CRYPTO_CB_ONLY_ECC) && \ !defined(WOLF_CRYPTO_CB_ONLY_SHA256) && !defined(WOLF_CRYPTO_CB_ONLY_AES)) || \ defined(HAVE_ALPN_PROTOS_SUPPORT)) || defined(WOLFSSL_STATIC_MEMORY) #define ENABLE_TLS_CALLBACK_TEST #endif #if defined(ENABLE_TLS_CALLBACK_TEST) || \ (defined(WOLFSSL_DTLS) && defined(WOLFSSL_SESSION_EXPORT)) /* TLS server for API unit testing - generic */ static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args) { callback_functions* callbacks = ((func_args*)args)->callbacks; WOLFSSL_CTX* ctx = NULL; WOLFSSL* ssl = NULL; SOCKET_T sfd = 0; SOCKET_T cfd = 0; word16 port; char msg[] = "I hear you fa shizzle!"; int len = (int) XSTRLEN(msg); char input[1024]; int idx; int ret, err = 0; ((func_args*)args)->return_code = TEST_FAIL; #if defined(USE_WINDOWS_API) port = ((func_args*)args)->signal->port; #elif defined(NO_MAIN_DRIVER) && !defined(WOLFSSL_SNIFFER) && \ !defined(WOLFSSL_MDK_SHELL) && !defined(WOLFSSL_TIRTOS) /* Let tcp_listen assign port */ port = 0; #else /* Use default port */ port = wolfSSLPort; #endif #ifdef WOLFSSL_DTLS if (callbacks->method == wolfDTLS_server_method #ifdef WOLFSSL_STATIC_MEMORY || callbacks->method_ex == wolfDTLS_server_method_ex #endif #ifndef NO_OLD_TLS || callbacks->method == wolfDTLSv1_server_method #ifdef WOLFSSL_STATIC_MEMORY || callbacks->method_ex == wolfDTLSv1_server_method_ex #endif #endif #ifndef WOLFSSL_NO_TLS12 || callbacks->method == wolfDTLSv1_2_server_method #ifdef WOLFSSL_STATIC_MEMORY || callbacks->method_ex == wolfDTLSv1_2_server_method_ex #endif #endif #ifdef WOLFSSL_DTLS13 || callbacks->method == wolfDTLSv1_3_server_method #ifdef WOLFSSL_STATIC_MEMORY || callbacks->method_ex == wolfDTLSv1_3_server_method_ex #endif #endif ) { tcp_accept(&sfd, &cfd, (func_args*)args, port, 0, 1, 0, 0, 0, 0, 0); } else #endif { tcp_accept(&sfd, &cfd, (func_args*)args, port, 0, 0, 0, 0, 1, 0, 0); } #ifdef WOLFSSL_STATIC_MEMORY if (callbacks->method_ex != NULL && callbacks->mem != NULL && callbacks->memSz > 0) { ret = wolfSSL_CTX_load_static_memory(&ctx, callbacks->method_ex, callbacks->mem, callbacks->memSz, 0, 1); if (ret != WOLFSSL_SUCCESS) { fprintf(stderr, "CTX static new failed %d\n", ret); goto cleanup; } } #else ctx = wolfSSL_CTX_new(callbacks->method()); #endif if (ctx == NULL) { fprintf(stderr, "CTX new failed\n"); goto cleanup; } /* set defaults */ if (callbacks->caPemFile == NULL) callbacks->caPemFile = cliCertFile; if (callbacks->certPemFile == NULL) callbacks->certPemFile = svrCertFile; if (callbacks->keyPemFile == NULL) callbacks->keyPemFile = svrKeyFile; #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); #endif wolfSSL_CTX_SetDevId(ctx, callbacks->devId); wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER | WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0); #ifdef WOLFSSL_ENCRYPTED_KEYS wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); #endif #if defined(WOLFSSL_SESSION_EXPORT) && defined(WOLFSSL_DTLS) if (callbacks->method == wolfDTLSv1_2_server_method) { if (wolfSSL_CTX_dtls_set_export(ctx, test_export) != WOLFSSL_SUCCESS) goto cleanup; } #endif if (wolfSSL_CTX_load_verify_locations(ctx, callbacks->caPemFile, 0) != WOLFSSL_SUCCESS) { goto cleanup; } if (wolfSSL_CTX_use_certificate_file(ctx, callbacks->certPemFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) { goto cleanup; } if (wolfSSL_CTX_use_PrivateKey_file(ctx, callbacks->keyPemFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) { goto cleanup; } #ifdef HAVE_CRL if (callbacks->crlPemFile != NULL) { if (wolfSSL_CTX_LoadCRLFile(ctx, callbacks->crlPemFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) { goto cleanup; } } #endif if (callbacks->ctx_ready) callbacks->ctx_ready(ctx); ssl = wolfSSL_new(ctx); if (ssl == NULL) { fprintf(stderr, "SSL new failed\n"); goto cleanup; } if (wolfSSL_dtls(ssl)) { SOCKADDR_IN_T cliAddr; socklen_t cliLen; cliLen = sizeof(cliAddr); idx = (int)recvfrom(sfd, input, sizeof(input), MSG_PEEK, (struct sockaddr*)&cliAddr, &cliLen); if (idx <= 0) { goto cleanup; } wolfSSL_dtls_set_peer(ssl, &cliAddr, cliLen); } else { CloseSocket(sfd); } if (wolfSSL_set_fd(ssl, cfd) != WOLFSSL_SUCCESS) { goto cleanup; } if (callbacks->loadToSSL) { wolfSSL_SetDevId(ssl, callbacks->devId); if (wolfSSL_use_certificate_file(ssl, callbacks->certPemFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) { goto cleanup; } if (wolfSSL_use_PrivateKey_file(ssl, callbacks->keyPemFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) { goto cleanup; } } #ifdef NO_PSK #if !defined(NO_FILESYSTEM) && !defined(NO_DH) wolfSSL_SetTmpDH_file(ssl, dhParamFile, CERT_FILETYPE); #elif !defined(NO_DH) SetDH(ssl); /* will repick suites with DHE, higher priority than PSK */ #endif #endif if (callbacks->ssl_ready) callbacks->ssl_ready(ssl); WOLFSSL_ASYNC_WHILE_PENDING(ret = wolfSSL_accept(ssl), ret != WOLFSSL_SUCCESS); if (ret != WOLFSSL_SUCCESS) { char buff[WOLFSSL_MAX_ERROR_SZ]; fprintf(stderr, "accept error = %d, %s\n", err, wolfSSL_ERR_error_string((word32)err, buff)); /*err_sys("SSL_accept failed");*/ } else { WOLFSSL_ASYNC_WHILE_PENDING(idx = wolfSSL_read(ssl, input, sizeof(input)-1), idx <= 0); if (idx > 0) { input[idx] = 0; fprintf(stderr, "Client message: %s\n", input); } WOLFSSL_ASYNC_WHILE_PENDING(ret = wolfSSL_write(ssl, msg, len), len != ret); if (len != ret) { goto cleanup; } #if defined(WOLFSSL_SESSION_EXPORT) && !defined(HAVE_IO_POOL) && \ defined(WOLFSSL_DTLS) if (wolfSSL_dtls(ssl)) { byte* import; word32 sz; wolfSSL_dtls_export(ssl, NULL, &sz); import = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (import == NULL) { goto cleanup; } idx = wolfSSL_dtls_export(ssl, import, &sz); if (idx < 0) { goto cleanup; } if (wolfSSL_dtls_import(ssl, import, idx) < 0) { goto cleanup; } XFREE(import, NULL, DYNAMIC_TYPE_TMP_BUFFER); } #endif #ifdef WOLFSSL_TIRTOS Task_yield(); #endif ((func_args*)args)->return_code = TEST_SUCCESS; } if (callbacks->on_result) callbacks->on_result(ssl); wolfSSL_shutdown(ssl); cleanup: wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); CloseSocket(cfd); #ifdef WOLFSSL_TIRTOS fdCloseSession(Task_self()); #endif #if defined(NO_MAIN_DRIVER) && defined(HAVE_ECC) && defined(FP_ECC) \ && defined(HAVE_THREAD_LS) wc_ecc_fp_free(); /* free per thread cache */ #endif WOLFSSL_RETURN_FROM_THREAD(0); } /* TLS Client for API unit testing - generic */ static void run_wolfssl_client(void* args) { callback_functions* callbacks = ((func_args*)args)->callbacks; WOLFSSL_CTX* ctx = NULL; WOLFSSL* ssl = NULL; SOCKET_T sfd = 0; char msg[] = "hello wolfssl server!"; int len = (int) XSTRLEN(msg); char input[1024]; int ret, err = 0; ((func_args*)args)->return_code = TEST_FAIL; /* set defaults */ if (callbacks->caPemFile == NULL) callbacks->caPemFile = caCertFile; if (callbacks->certPemFile == NULL) callbacks->certPemFile = cliCertFile; if (callbacks->keyPemFile == NULL) callbacks->keyPemFile = cliKeyFile; #ifdef WOLFSSL_STATIC_MEMORY if (callbacks->method_ex != NULL && callbacks->mem != NULL && callbacks->memSz > 0) { ret = wolfSSL_CTX_load_static_memory(&ctx, callbacks->method_ex, callbacks->mem, callbacks->memSz, 0, 1); if (ret != WOLFSSL_SUCCESS) { fprintf(stderr, "CTX static new failed %d\n", ret); goto cleanup; } } #else ctx = wolfSSL_CTX_new(callbacks->method()); #endif if (ctx == NULL) { fprintf(stderr, "CTX new failed\n"); goto cleanup; } #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); #endif if (!callbacks->loadToSSL) { wolfSSL_CTX_SetDevId(ctx, callbacks->devId); } #ifdef WOLFSSL_ENCRYPTED_KEYS wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); #endif if (wolfSSL_CTX_load_verify_locations(ctx, callbacks->caPemFile, 0) != WOLFSSL_SUCCESS) { goto cleanup; } if (!callbacks->loadToSSL) { if (wolfSSL_CTX_use_certificate_file(ctx, callbacks->certPemFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) { goto cleanup; } if (wolfSSL_CTX_use_PrivateKey_file(ctx, callbacks->keyPemFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) { goto cleanup; } } #ifdef HAVE_CRL if (callbacks->crlPemFile != NULL) { if (wolfSSL_CTX_LoadCRLFile(ctx, callbacks->crlPemFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) { goto cleanup; } } #endif if (callbacks->ctx_ready) callbacks->ctx_ready(ctx); ssl = wolfSSL_new(ctx); if (wolfSSL_dtls(ssl)) { tcp_connect(&sfd, wolfSSLIP, ((func_args*)args)->signal->port, 1, 0, ssl); } else { tcp_connect(&sfd, wolfSSLIP, ((func_args*)args)->signal->port, 0, 0, ssl); } if (wolfSSL_set_fd(ssl, sfd) != WOLFSSL_SUCCESS) { goto cleanup; } if (callbacks->loadToSSL) { wolfSSL_SetDevId(ssl, callbacks->devId); if (wolfSSL_use_certificate_file(ssl, callbacks->certPemFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) { goto cleanup; } if (wolfSSL_use_PrivateKey_file(ssl, callbacks->keyPemFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) { goto cleanup; } } if (callbacks->ssl_ready) callbacks->ssl_ready(ssl); WOLFSSL_ASYNC_WHILE_PENDING(ret = wolfSSL_connect(ssl), ret != WOLFSSL_SUCCESS); if (ret != WOLFSSL_SUCCESS) { char buff[WOLFSSL_MAX_ERROR_SZ]; fprintf(stderr, "error = %d, %s\n", err, wolfSSL_ERR_error_string((word32)err, buff)); /*err_sys("SSL_connect failed");*/ } else { WOLFSSL_ASYNC_WHILE_PENDING(ret = wolfSSL_write(ssl, msg, len), ret != len); if (len != ret) goto cleanup; WOLFSSL_ASYNC_WHILE_PENDING(ret = wolfSSL_read(ssl, input, sizeof(input)-1), ret <= 0); if (ret > 0) { input[ret] = '\0'; /* null term */ fprintf(stderr, "Server response: %s\n", input); } ((func_args*)args)->return_code = TEST_SUCCESS; } if (callbacks->on_result) callbacks->on_result(ssl); cleanup: wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); CloseSocket(sfd); #ifdef WOLFSSL_TIRTOS fdCloseSession(Task_self()); #endif } #endif /* ENABLE_TLS_CALLBACK_TEST */ static int test_wolfSSL_read_write(void) { EXPECT_DECLS; #ifndef NO_SHA256 /* The unit testing for read and write shall happen simultaneously, since * one can't do anything with one without the other. (Except for a failure * test case.) This function will call all the others that will set up, * execute, and report their test findings. * * Set up the success case first. This function will become the template * for the other tests. This should eventually be renamed * * The success case isn't interesting, how can this fail? * - Do not give the client context a CA certificate. The connect should * fail. Do not need server for this? * - Using NULL for the ssl object on server. Do not need client for this. * - Using NULL for the ssl object on client. Do not need server for this. * - Good ssl objects for client and server. Client write() without server * read(). * - Good ssl objects for client and server. Server write() without client * read(). * - Forgetting the password callback? */ tcp_ready ready; func_args client_args; func_args server_args; THREAD_TYPE serverThread; XMEMSET(&client_args, 0, sizeof(func_args)); XMEMSET(&server_args, 0, sizeof(func_args)); #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); #endif StartTCP(); InitTcpReady(&ready); server_args.signal = &ready; client_args.signal = &ready; start_thread(test_server_nofail, &server_args, &serverThread); wait_tcp_ready(&server_args); test_client_nofail(&client_args, NULL); join_thread(serverThread); ExpectTrue(client_args.return_code); ExpectTrue(server_args.return_code); FreeTcpReady(&ready); #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); #endif #endif return EXPECT_RESULT(); } static int test_wolfSSL_read_write_ex(void) { EXPECT_DECLS; WOLFSSL_CTX *ctx_c = NULL; WOLFSSL_CTX *ctx_s = NULL; WOLFSSL *ssl_c = NULL; WOLFSSL *ssl_s = NULL; struct test_memio_ctx test_ctx; const char *test_str = "test"; int test_str_size; size_t count; byte buf[255]; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, wolfSSLv23_client_method, wolfSSLv23_server_method), 0); ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); test_str_size = XSTRLEN("test") + 1; ExpectIntEQ(wolfSSL_write_ex(ssl_c, test_str, test_str_size, &count), WOLFSSL_SUCCESS); ExpectIntEQ(count, test_str_size); count = 0; ExpectIntEQ(wolfSSL_read_ex(ssl_s, buf, sizeof(buf), &count), WOLFSSL_SUCCESS); ExpectIntEQ(count, test_str_size); ExpectIntEQ(XSTRCMP((char*)buf, test_str), 0); ExpectIntEQ(wolfSSL_shutdown(ssl_c), WOLFSSL_SHUTDOWN_NOT_DONE); ExpectIntEQ(wolfSSL_shutdown(ssl_s), WOLFSSL_SHUTDOWN_NOT_DONE); ExpectIntEQ(wolfSSL_shutdown(ssl_c), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_shutdown(ssl_s), WOLFSSL_SUCCESS); wolfSSL_free(ssl_c); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_c); wolfSSL_CTX_free(ctx_s); /* XXX this should be return EXPECT_RESULT(); */ return TEST_SUCCESS; } static int test_wolfSSL_reuse_WOLFSSLobj(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_SESSION_CACHE) && \ !defined(WOLFSSL_NO_TLS12) /* The unit test for session resumption by reusing WOLFSSL object. * WOLFSSL object is not cleared after first session. It reuse the object * for second connection. */ tcp_ready ready; func_args client_args; func_args server_args; THREAD_TYPE serverThread; callback_functions client_cbf; callback_functions server_cbf; XMEMSET(&client_args, 0, sizeof(func_args)); XMEMSET(&server_args, 0, sizeof(func_args)); XMEMSET(&client_cbf, 0, sizeof(callback_functions)); XMEMSET(&server_cbf, 0, sizeof(callback_functions)); #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); #endif StartTCP(); InitTcpReady(&ready); client_cbf.method = wolfTLSv1_2_client_method; server_cbf.method = wolfTLSv1_2_server_method; client_args.callbacks = &client_cbf; server_args.callbacks = &server_cbf; server_args.signal = &ready; client_args.signal = &ready; /* the var is used for loop number */ server_args.argc = 2; start_thread(test_server_loop, &server_args, &serverThread); wait_tcp_ready(&server_args); test_client_reuse_WOLFSSLobj(&client_args, NULL, &server_args); join_thread(serverThread); ExpectTrue(client_args.return_code); ExpectTrue(server_args.return_code); FreeTcpReady(&ready); #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); #endif #endif /* defined(OPENSSL_EXTRA) && !defined(NO_SESSION_CACHE) && * !defined(WOLFSSL_TLS13) */ return EXPECT_RESULT(); } #if defined(OPENSSL_EXTRA) && defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) static int test_wolfSSL_CTX_verifyDepth_ServerClient_1_ctx_ready( WOLFSSL_CTX* ctx) { wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, myVerify); myVerifyAction = VERIFY_USE_PREVERIFY; wolfSSL_CTX_set_verify_depth(ctx, 2); return TEST_SUCCESS; } #endif static int test_wolfSSL_CTX_verifyDepth_ServerClient_1(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) test_ssl_cbf client_cbf; test_ssl_cbf server_cbf; XMEMSET(&client_cbf, 0, sizeof(client_cbf)); XMEMSET(&server_cbf, 0, sizeof(server_cbf)); #ifdef WOLFSSL_TLS13 client_cbf.method = wolfTLSv1_3_client_method; #endif /* WOLFSSL_TLS13 */ client_cbf.ctx_ready = test_wolfSSL_CTX_verifyDepth_ServerClient_1_ctx_ready; /* test case 1 verify depth is equal to peer chain */ ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&client_cbf, &server_cbf, NULL), TEST_SUCCESS); ExpectIntEQ(client_cbf.return_code, TEST_SUCCESS); ExpectIntEQ(server_cbf.return_code, TEST_SUCCESS); #endif /* OPENSSL_EXTRA && HAVE_SSL_MEMIO_TESTS_DEPENDENCIES */ return EXPECT_RESULT(); } #if defined(OPENSSL_EXTRA) && defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) static int test_wolfSSL_CTX_verifyDepth_ServerClient_2_ctx_ready( WOLFSSL_CTX* ctx) { wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, myVerify); myVerifyAction = VERIFY_OVERRIDE_ERROR; wolfSSL_CTX_set_verify_depth(ctx, 0); return TEST_SUCCESS; } #endif static int test_wolfSSL_CTX_verifyDepth_ServerClient_2(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) test_ssl_cbf client_cbf; test_ssl_cbf server_cbf; XMEMSET(&client_cbf, 0, sizeof(client_cbf)); XMEMSET(&server_cbf, 0, sizeof(server_cbf)); #ifdef WOLFSSL_TLS13 client_cbf.method = wolfTLSv1_3_client_method; #endif /* WOLFSSL_TLS13 */ client_cbf.ctx_ready = test_wolfSSL_CTX_verifyDepth_ServerClient_2_ctx_ready; /* test case 2 * verify depth is zero, number of peer's chain is 2. * verify result becomes MAX_CHAIN_ERROR, but it is overridden in * callback. */ ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&client_cbf, &server_cbf, NULL), TEST_SUCCESS); ExpectIntEQ(client_cbf.return_code, TEST_SUCCESS); ExpectIntEQ(server_cbf.return_code, TEST_SUCCESS); #endif /* OPENSSL_EXTRA && HAVE_SSL_MEMIO_TESTS_DEPENDENCIES */ return EXPECT_RESULT(); } #if defined(OPENSSL_EXTRA) && defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) static int test_wolfSSL_CTX_verifyDepth_ServerClient_3_ctx_ready( WOLFSSL_CTX* ctx) { wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, myVerify); myVerifyAction = VERIFY_USE_PREVERIFY; wolfSSL_CTX_set_verify_depth(ctx, 0); return TEST_SUCCESS; } #endif static int test_wolfSSL_CTX_verifyDepth_ServerClient_3(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) test_ssl_cbf client_cbf; test_ssl_cbf server_cbf; XMEMSET(&client_cbf, 0, sizeof(client_cbf)); XMEMSET(&server_cbf, 0, sizeof(server_cbf)); #ifdef WOLFSSL_TLS13 client_cbf.method = wolfTLSv1_3_client_method; #endif /* WOLFSSL_TLS13 */ client_cbf.ctx_ready = test_wolfSSL_CTX_verifyDepth_ServerClient_3_ctx_ready; /* test case 3 * verify depth is zero, number of peer's chain is 2 * verify result becomes MAX_CHAIN_ERRO. call-back returns failure. * therefore, handshake becomes failure. */ ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&client_cbf, &server_cbf, NULL), -1001); ExpectIntEQ(client_cbf.return_code, -1000); ExpectIntEQ(server_cbf.return_code, -1000); ExpectIntEQ(client_cbf.last_err, WC_NO_ERR_TRACE(MAX_CHAIN_ERROR)); ExpectIntEQ(server_cbf.last_err, WC_NO_ERR_TRACE(FATAL_ERROR)); #endif /* OPENSSL_EXTRA && HAVE_SSL_MEMIO_TESTS_DEPENDENCIES */ return EXPECT_RESULT(); } #if defined(OPENSSL_ALL) && defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && \ !defined(WOLFSSL_NO_TLS12) && \ defined(HAVE_ECC) && !defined(NO_AES) && !defined(NO_SHA256) static int test_wolfSSL_CTX_set_cipher_list_server_ctx_ready(WOLFSSL_CTX* ctx) { EXPECT_DECLS; ExpectTrue(wolfSSL_CTX_set_cipher_list(ctx, "DEFAULT:!NULL")); return EXPECT_RESULT(); } static int test_wolfSSL_CTX_set_cipher_list_client_ctx_ready(WOLFSSL_CTX* ctx) { EXPECT_DECLS; ExpectTrue(wolfSSL_CTX_set_cipher_list(ctx, "ECDHE-RSA-AES128-SHA256")); return EXPECT_RESULT(); } #endif static int test_wolfSSL_CTX_set_cipher_list(void) { EXPECT_DECLS; #if defined(OPENSSL_ALL) && defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && \ defined(HAVE_ECC) && !defined(NO_AES) && !defined(NO_SHA256) #if !defined(WOLFSSL_NO_TLS12) WOLFSSL_CTX* ctxClient = NULL; WOLFSSL* sslClient = NULL; test_ssl_cbf client_cbf; test_ssl_cbf server_cbf; XMEMSET(&client_cbf, 0, sizeof(client_cbf)); XMEMSET(&server_cbf, 0, sizeof(server_cbf)); server_cbf.method = wolfTLSv1_2_server_method; server_cbf.ctx_ready = test_wolfSSL_CTX_set_cipher_list_server_ctx_ready; client_cbf.method = wolfTLSv1_2_client_method; client_cbf.ctx_ready = test_wolfSSL_CTX_set_cipher_list_client_ctx_ready; ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&client_cbf, &server_cbf, NULL), TEST_SUCCESS); ExpectIntEQ(client_cbf.return_code, TEST_SUCCESS); ExpectIntEQ(server_cbf.return_code, TEST_SUCCESS); /* check with cipher string that has '+' */ ExpectNotNull((ctxClient = wolfSSL_CTX_new(wolfTLSv1_2_client_method()))); /* Use trailing : with nothing to test for ASAN */ ExpectTrue(wolfSSL_CTX_set_cipher_list(ctxClient, "ECDHE+AESGCM:")); ExpectNotNull((sslClient = wolfSSL_new(ctxClient))); /* check for the existence of an ECDHE ECDSA cipher suite */ if (EXPECT_SUCCESS()) { int i = 0; int found = 0; const char* suite; WOLF_STACK_OF(WOLFSSL_CIPHER)* sk = NULL; WOLFSSL_CIPHER* current; ExpectNotNull((sk = wolfSSL_get_ciphers_compat(sslClient))); do { current = wolfSSL_sk_SSL_CIPHER_value(sk, i++); if (current) { suite = wolfSSL_CIPHER_get_name(current); if (suite && XSTRSTR(suite, "ECDSA")) { found = 1; break; } } } while (current); ExpectIntEQ(found, 1); } wolfSSL_free(sslClient); wolfSSL_CTX_free(ctxClient); #endif /* !WOLFSSL_NO_TLS12 */ #endif return EXPECT_RESULT(); } #if defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && \ defined(WOLFSSL_HAVE_TLS_UNIQUE) static int test_wolfSSL_get_finished_client_on_handshake(WOLFSSL_CTX* ctx, WOLFSSL* ssl) { EXPECT_DECLS; size_t msg_len; (void)ctx; /* get_finished test */ /* 1. get own sent message */ XMEMSET(client_side_msg1, 0, WC_MAX_DIGEST_SIZE); msg_len = wolfSSL_get_finished(ssl, client_side_msg1, WC_MAX_DIGEST_SIZE); ExpectIntGE(msg_len, 0); /* 2. get peer message */ XMEMSET(client_side_msg2, 0, WC_MAX_DIGEST_SIZE); msg_len = wolfSSL_get_peer_finished(ssl, client_side_msg2, WC_MAX_DIGEST_SIZE); ExpectIntGE(msg_len, 0); return EXPECT_RESULT(); } #endif static int test_wolfSSL_get_finished(void) { EXPECT_DECLS; #if defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && \ defined(WOLFSSL_HAVE_TLS_UNIQUE) test_ssl_cbf client_cbf; test_ssl_cbf server_cbf; XMEMSET(&client_cbf, 0, sizeof(client_cbf)); XMEMSET(&server_cbf, 0, sizeof(server_cbf)); ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&client_cbf, &server_cbf, test_wolfSSL_get_finished_client_on_handshake), TEST_SUCCESS); /* test received msg vs sent msg */ ExpectIntEQ(0, XMEMCMP(client_side_msg1, server_side_msg2, WC_MAX_DIGEST_SIZE)); ExpectIntEQ(0, XMEMCMP(client_side_msg2, server_side_msg1, WC_MAX_DIGEST_SIZE)); #endif /* HAVE_SSL_MEMIO_TESTS_DEPENDENCIES && WOLFSSL_HAVE_TLS_UNIQUE */ return EXPECT_RESULT(); } #if defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(HAVE_EXT_CACHE) && \ !defined(SINGLE_THREADED) && defined(WOLFSSL_TLS13) && \ !defined(NO_SESSION_CACHE) /* Sessions to restore/store */ static WOLFSSL_SESSION* test_wolfSSL_CTX_add_session_client_sess; static WOLFSSL_SESSION* test_wolfSSL_CTX_add_session_server_sess; static WOLFSSL_CTX* test_wolfSSL_CTX_add_session_server_ctx; static void test_wolfSSL_CTX_add_session_ctx_ready(WOLFSSL_CTX* ctx) { /* Don't store sessions. Lookup is still enabled. */ AssertIntEQ(wolfSSL_CTX_set_session_cache_mode(ctx, WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE), WOLFSSL_SUCCESS); #ifdef OPENSSL_EXTRA AssertIntEQ(wolfSSL_CTX_get_session_cache_mode(ctx) & WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE, WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE); #endif /* Require both peers to provide certs */ wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, NULL); } static void test_wolfSSL_CTX_add_session_on_result(WOLFSSL* ssl) { WOLFSSL_SESSION** sess; #ifdef WOLFSSL_MUTEX_INITIALIZER static wolfSSL_Mutex m = WOLFSSL_MUTEX_INITIALIZER(m); (void)wc_LockMutex(&m); #endif if (wolfSSL_is_server(ssl)) sess = &test_wolfSSL_CTX_add_session_server_sess; else sess = &test_wolfSSL_CTX_add_session_client_sess; if (*sess == NULL) { #ifdef NO_SESSION_CACHE_REF *sess = wolfSSL_get1_session(ssl); AssertNotNull(*sess); #else /* Test for backwards compatibility */ if (wolfSSL_is_server(ssl)) { *sess = wolfSSL_get1_session(ssl); AssertNotNull(*sess); } else { *sess = wolfSSL_get_session(ssl); AssertNotNull(*sess); } #endif /* Now save the session in the internal store to make it available * for lookup. For TLS 1.3, we can't save the session without * WOLFSSL_TICKET_HAVE_ID because there is no way to retrieve the * session from cache. */ if (wolfSSL_is_server(ssl) #ifndef WOLFSSL_TICKET_HAVE_ID && wolfSSL_version(ssl) != TLS1_3_VERSION #endif ) AssertIntEQ(wolfSSL_CTX_add_session(wolfSSL_get_SSL_CTX(ssl), *sess), WOLFSSL_SUCCESS); } else { /* If we have a session retrieved then remaining connections should be * resuming on that session */ AssertIntEQ(wolfSSL_session_reused(ssl), 1); } #ifdef WOLFSSL_MUTEX_INITIALIZER wc_UnLockMutex(&m); #endif /* Save CTX to be able to decrypt tickets */ if (wolfSSL_is_server(ssl) && test_wolfSSL_CTX_add_session_server_ctx == NULL) { test_wolfSSL_CTX_add_session_server_ctx = wolfSSL_get_SSL_CTX(ssl); AssertNotNull(test_wolfSSL_CTX_add_session_server_ctx); AssertIntEQ(wolfSSL_CTX_up_ref(wolfSSL_get_SSL_CTX(ssl)), WOLFSSL_SUCCESS); } #if defined(SESSION_CERTS) && !defined(WOLFSSL_NO_CLIENT_AUTH) #ifndef WOLFSSL_TICKET_HAVE_ID if (wolfSSL_version(ssl) != TLS1_3_VERSION && wolfSSL_session_reused(ssl)) #endif { /* With WOLFSSL_TICKET_HAVE_ID the peer certs should be available * for all connections. TLS 1.3 only has tickets so if we don't * include the session id in the ticket then the certificates * will not be available on resumption. */ #ifdef KEEP_PEER_CERT WOLFSSL_X509* peer = wolfSSL_get_peer_certificate(ssl); AssertNotNull(peer); wolfSSL_X509_free(peer); #endif AssertNotNull(wolfSSL_SESSION_get_peer_chain(*sess)); #ifdef OPENSSL_EXTRA AssertNotNull(SSL_SESSION_get0_peer(*sess)); #endif } #endif /* SESSION_CERTS && !WOLFSSL_NO_CLIENT_AUTH */ } static void test_wolfSSL_CTX_add_session_ssl_ready(WOLFSSL* ssl) { /* Set the session to reuse for the client */ AssertIntEQ(wolfSSL_set_session(ssl, test_wolfSSL_CTX_add_session_client_sess), WOLFSSL_SUCCESS); } #endif static int test_wolfSSL_CTX_add_session(void) { EXPECT_DECLS; #if defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(HAVE_EXT_CACHE) && \ !defined(SINGLE_THREADED) && defined(WOLFSSL_TLS13) && \ !defined(NO_SESSION_CACHE) tcp_ready ready; func_args client_args; func_args server_args; THREAD_TYPE serverThread; callback_functions client_cb; callback_functions server_cb; method_provider methods[][2] = { #if !defined(NO_OLD_TLS) && ((!defined(NO_AES) && !defined(NO_AES_CBC)) || \ !defined(NO_DES3)) /* Without AES there are almost no ciphersuites available. This leads * to no ciphersuites being available and an error. */ { wolfTLSv1_1_client_method, wolfTLSv1_1_server_method }, #endif #ifndef WOLFSSL_NO_TLS12 { wolfTLSv1_2_client_method, wolfTLSv1_2_server_method }, #endif /* Needs the default ticket callback since it is tied to the * connection context and this makes it easy to carry over the ticket * crypto context between connections */ #if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) && \ defined(HAVE_SESSION_TICKET) { wolfTLSv1_3_client_method, wolfTLSv1_3_server_method }, #endif }; const size_t methodsLen = sizeof(methods)/sizeof(*methods); size_t i, j; for (i = 0; i < methodsLen; i++) { /* First run creates a connection while the second+ run will attempt * to resume the connection. The trick is that the internal cache * is turned off. wolfSSL_CTX_add_session should put the session in * the cache anyway. */ test_wolfSSL_CTX_add_session_client_sess = NULL; test_wolfSSL_CTX_add_session_server_sess = NULL; test_wolfSSL_CTX_add_session_server_ctx = NULL; #ifdef NO_SESSION_CACHE_REF for (j = 0; j < 4; j++) { #else /* The session may be overwritten in this case. Do only one resumption * to stop this test from failing intermittently. */ for (j = 0; j < 2; j++) { #endif #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); #endif StartTCP(); InitTcpReady(&ready); XMEMSET(&client_args, 0, sizeof(func_args)); XMEMSET(&server_args, 0, sizeof(func_args)); XMEMSET(&client_cb, 0, sizeof(callback_functions)); XMEMSET(&server_cb, 0, sizeof(callback_functions)); client_cb.method = methods[i][0]; server_cb.method = methods[i][1]; server_args.signal = &ready; server_args.callbacks = &server_cb; client_args.signal = &ready; client_args.callbacks = &client_cb; if (test_wolfSSL_CTX_add_session_server_ctx != NULL) { server_cb.ctx = test_wolfSSL_CTX_add_session_server_ctx; server_cb.isSharedCtx = 1; } server_cb.ctx_ready = test_wolfSSL_CTX_add_session_ctx_ready; client_cb.ctx_ready = test_wolfSSL_CTX_add_session_ctx_ready; if (j != 0) client_cb.ssl_ready = test_wolfSSL_CTX_add_session_ssl_ready; server_cb.on_result = test_wolfSSL_CTX_add_session_on_result; client_cb.on_result = test_wolfSSL_CTX_add_session_on_result; server_cb.ticNoInit = 1; /* Use default builtin */ start_thread(test_server_nofail, &server_args, &serverThread); wait_tcp_ready(&server_args); test_client_nofail(&client_args, NULL); join_thread(serverThread); ExpectTrue(client_args.return_code); ExpectTrue(server_args.return_code); FreeTcpReady(&ready); if (EXPECT_FAIL()) break; } wolfSSL_SESSION_free(test_wolfSSL_CTX_add_session_client_sess); wolfSSL_SESSION_free(test_wolfSSL_CTX_add_session_server_sess); wolfSSL_CTX_free(test_wolfSSL_CTX_add_session_server_ctx); if (EXPECT_FAIL()) break; } #endif return EXPECT_RESULT(); } #if defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && defined(HAVE_EXT_CACHE) && \ defined(WOLFSSL_TLS13) && !defined(NO_SESSION_CACHE) && \ defined(OPENSSL_EXTRA) && defined(SESSION_CERTS) && \ defined(HAVE_SESSION_TICKET) && \ !defined(TITAN_SESSION_CACHE) && \ !defined(HUGE_SESSION_CACHE) && \ !defined(BIG_SESSION_CACHE) && \ !defined(MEDIUM_SESSION_CACHE) /* twcase - prefix for test_wolfSSL_CTX_add_session_ext */ /* Sessions to restore/store */ static WOLFSSL_SESSION* twcase_server_first_session_ptr; static WOLFSSL_SESSION* twcase_client_first_session_ptr; static WOLFSSL_CTX* twcase_server_current_ctx_ptr; static int twcase_new_session_called = 0; static int twcase_remove_session_called = 0; static int twcase_get_session_called = 0; /* Test default, SESSIONS_PER_ROW*SESSION_ROWS = 3*11, see ssl.c */ #define SESSION_CACHE_SIZE 33 typedef struct { const byte* key; /* key, altSessionID, session ID, NULL if empty */ WOLFSSL_SESSION* value; } hashTable_entry; typedef struct { hashTable_entry entries[SESSION_CACHE_SIZE]; /* hash slots */ size_t capacity; /* size of entries */ size_t length; /* number of items in the hash table */ wolfSSL_Mutex htLock; /* lock */ }hashTable; static hashTable server_sessionCache; static int twcase_new_sessionCb(WOLFSSL *ssl, WOLFSSL_SESSION *sess) { int i; unsigned int len; (void)ssl; /* * This example uses a hash table. * Steps you should take for a non-demo code: * - acquire a lock for the file named according to the session id * - open the file * - encrypt and write the SSL_SESSION object to the file * - release the lock * * Return: * 0: The callback does not wish to hold a reference of the sess * 1: The callback wants to hold a reference of the sess. The callback is * now also responsible for calling wolfSSL_SESSION_free() on sess. */ if (sess == NULL) return 0; if (wc_LockMutex(&server_sessionCache.htLock) != 0) { return 0; } for (i = 0; i < SESSION_CACHE_SIZE; i++) { if (server_sessionCache.entries[i].value == NULL) { server_sessionCache.entries[i].key = SSL_SESSION_get_id(sess, &len); server_sessionCache.entries[i].value = sess; server_sessionCache.length++; break; } } ++twcase_new_session_called; wc_UnLockMutex(&server_sessionCache.htLock); fprintf(stderr, "\t\ttwcase_new_session_called %d\n", twcase_new_session_called); return 1; } static void twcase_remove_sessionCb(WOLFSSL_CTX *ctx, WOLFSSL_SESSION *sess) { int i; (void)ctx; (void)sess; if (sess == NULL) return; /* * This example uses a hash table. * Steps you should take for a non-demo code: * - acquire a lock for the file named according to the session id * - remove the file * - release the lock */ if (wc_LockMutex(&server_sessionCache.htLock) != 0) { return; } for (i = 0; i < SESSION_CACHE_SIZE; i++) { if (server_sessionCache.entries[i].key != NULL && XMEMCMP(server_sessionCache.entries[i].key, sess->sessionID, SSL_MAX_SSL_SESSION_ID_LENGTH) == 0) { wolfSSL_SESSION_free(server_sessionCache.entries[i].value); server_sessionCache.entries[i].value = NULL; server_sessionCache.entries[i].key = NULL; server_sessionCache.length--; break; } } ++twcase_remove_session_called; wc_UnLockMutex(&server_sessionCache.htLock); fprintf(stderr, "\t\ttwcase_remove_session_called %d\n", twcase_remove_session_called); } static WOLFSSL_SESSION *twcase_get_sessionCb(WOLFSSL *ssl, const unsigned char *id, int len, int *ref) { int i; (void)ssl; (void)id; (void)len; /* * This example uses a hash table. * Steps you should take for a non-demo code: * - acquire a lock for the file named according to the session id in the * 2nd arg * - read and decrypt contents of file and create a new SSL_SESSION * - object release the lock * - return the new session object */ fprintf(stderr, "\t\ttwcase_get_session_called %d\n", ++twcase_get_session_called); /* This callback want to retain a copy of the object. If we want wolfSSL to * be responsible for the pointer then set to 0. */ *ref = 1; for (i = 0; i < SESSION_CACHE_SIZE; i++) { if (server_sessionCache.entries[i].key != NULL && XMEMCMP(server_sessionCache.entries[i].key, id, SSL_MAX_SSL_SESSION_ID_LENGTH) == 0) { return server_sessionCache.entries[i].value; } } return NULL; } static int twcase_get_sessionCb_cleanup(void) { int i; int cnt = 0; /* If twcase_get_sessionCb sets *ref = 1, the application is responsible * for freeing sessions */ for (i = 0; i < SESSION_CACHE_SIZE; i++) { if (server_sessionCache.entries[i].value != NULL) { wolfSSL_SESSION_free(server_sessionCache.entries[i].value); cnt++; } } fprintf(stderr, "\t\ttwcase_get_sessionCb_cleanup freed %d sessions\n", cnt); return TEST_SUCCESS; } static int twcase_cache_intOff_extOff(WOLFSSL_CTX* ctx) { EXPECT_DECLS; /* off - Disable internal cache */ ExpectIntEQ(wolfSSL_CTX_set_session_cache_mode(ctx, WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE), WOLFSSL_SUCCESS); #ifdef OPENSSL_EXTRA ExpectIntEQ(wolfSSL_CTX_get_session_cache_mode(ctx) & WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE, WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE); #endif /* off - Do not setup external cache */ /* Require both peers to provide certs */ wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, NULL); return EXPECT_RESULT(); } static int twcase_cache_intOn_extOff(WOLFSSL_CTX* ctx) { /* on - internal cache is on by default */ /* off - Do not setup external cache */ /* Require both peers to provide certs */ wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, NULL); return TEST_SUCCESS; } static int twcase_cache_intOff_extOn(WOLFSSL_CTX* ctx) { EXPECT_DECLS; /* off - Disable internal cache */ ExpectIntEQ(wolfSSL_CTX_set_session_cache_mode(ctx, WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE), WOLFSSL_SUCCESS); #ifdef OPENSSL_EXTRA ExpectIntEQ(wolfSSL_CTX_get_session_cache_mode(ctx) & WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE, WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE); #endif /* on - Enable external cache */ wolfSSL_CTX_sess_set_new_cb(ctx, twcase_new_sessionCb); wolfSSL_CTX_sess_set_remove_cb(ctx, twcase_remove_sessionCb); wolfSSL_CTX_sess_set_get_cb(ctx, twcase_get_sessionCb); /* Require both peers to provide certs */ wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, NULL); return EXPECT_RESULT(); } static int twcase_cache_intOn_extOn(WOLFSSL_CTX* ctx) { /* on - internal cache is on by default */ /* on - Enable external cache */ wolfSSL_CTX_sess_set_new_cb(ctx, twcase_new_sessionCb); wolfSSL_CTX_sess_set_remove_cb(ctx, twcase_remove_sessionCb); wolfSSL_CTX_sess_set_get_cb(ctx, twcase_get_sessionCb); /* Require both peers to provide certs */ wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, NULL); return TEST_SUCCESS; } static int twcase_cache_intOn_extOn_noTicket(WOLFSSL_CTX* ctx) { /* on - internal cache is on by default */ /* on - Enable external cache */ wolfSSL_CTX_sess_set_new_cb(ctx, twcase_new_sessionCb); wolfSSL_CTX_sess_set_remove_cb(ctx, twcase_remove_sessionCb); wolfSSL_CTX_sess_set_get_cb(ctx, twcase_get_sessionCb); wolfSSL_CTX_set_options(ctx, WOLFSSL_OP_NO_TICKET); /* Require both peers to provide certs */ wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, NULL); return TEST_SUCCESS; } static int twcase_server_sess_ctx_pre_shutdown(WOLFSSL* ssl) { EXPECT_DECLS; WOLFSSL_SESSION** sess; if (wolfSSL_is_server(ssl)) sess = &twcase_server_first_session_ptr; else return TEST_SUCCESS; if (*sess == NULL) { ExpectNotNull(*sess = wolfSSL_get1_session(ssl)); /* Now save the session in the internal store to make it available * for lookup. For TLS 1.3, we can't save the session without * WOLFSSL_TICKET_HAVE_ID because there is no way to retrieve the * session from cache. */ if (wolfSSL_is_server(ssl) #ifndef WOLFSSL_TICKET_HAVE_ID && wolfSSL_version(ssl) != TLS1_3_VERSION && wolfSSL_version(ssl) != DTLS1_3_VERSION #endif ) { ExpectIntEQ(wolfSSL_CTX_add_session(wolfSSL_get_SSL_CTX(ssl), *sess), WOLFSSL_SUCCESS); } } /* Save CTX to be able to decrypt tickets */ if (twcase_server_current_ctx_ptr == NULL) { ExpectNotNull(twcase_server_current_ctx_ptr = wolfSSL_get_SSL_CTX(ssl)); ExpectIntEQ(wolfSSL_CTX_up_ref(wolfSSL_get_SSL_CTX(ssl)), WOLFSSL_SUCCESS); } #if defined(SESSION_CERTS) && !defined(WOLFSSL_NO_CLIENT_AUTH) #ifndef WOLFSSL_TICKET_HAVE_ID if (wolfSSL_version(ssl) != TLS1_3_VERSION && wolfSSL_session_reused(ssl)) #endif { /* With WOLFSSL_TICKET_HAVE_ID the peer certs should be available * for all connections. TLS 1.3 only has tickets so if we don't * include the session id in the ticket then the certificates * will not be available on resumption. */ #ifdef KEEP_PEER_CERT WOLFSSL_X509* peer = NULL; ExpectNotNull(peer = wolfSSL_get_peer_certificate(ssl)); wolfSSL_X509_free(peer); #endif ExpectNotNull(wolfSSL_SESSION_get_peer_chain(*sess)); } #endif return EXPECT_RESULT(); } static int twcase_client_sess_ctx_pre_shutdown(WOLFSSL* ssl) { EXPECT_DECLS; WOLFSSL_SESSION** sess; sess = &twcase_client_first_session_ptr; if (*sess == NULL) { ExpectNotNull(*sess = wolfSSL_get1_session(ssl)); } else { /* If we have a session retrieved then remaining connections should be * resuming on that session */ ExpectIntEQ(wolfSSL_session_reused(ssl), 1); } #if defined(SESSION_CERTS) && !defined(WOLFSSL_NO_CLIENT_AUTH) #ifndef WOLFSSL_TICKET_HAVE_ID if (wolfSSL_version(ssl) != TLS1_3_VERSION && wolfSSL_session_reused(ssl)) #endif { #ifdef KEEP_PEER_CERT WOLFSSL_X509* peer = wolfSSL_get_peer_certificate(ssl); ExpectNotNull(peer); wolfSSL_X509_free(peer); #endif ExpectNotNull(wolfSSL_SESSION_get_peer_chain(*sess)); #ifdef OPENSSL_EXTRA ExpectNotNull(wolfSSL_SESSION_get0_peer(*sess)); #endif } #endif return EXPECT_RESULT(); } static int twcase_client_set_sess_ssl_ready(WOLFSSL* ssl) { EXPECT_DECLS; /* Set the session to reuse for the client */ ExpectNotNull(ssl); ExpectNotNull(twcase_client_first_session_ptr); ExpectIntEQ(wolfSSL_set_session(ssl,twcase_client_first_session_ptr), WOLFSSL_SUCCESS); return EXPECT_RESULT(); } struct test_add_session_ext_params { method_provider client_meth; method_provider server_meth; const char* tls_version; }; static int test_wolfSSL_CTX_add_session_ext( struct test_add_session_ext_params* param) { EXPECT_DECLS; /* Test the default 33 sessions */ int j; /* Clear cache before starting */ wolfSSL_CTX_flush_sessions(NULL, -1); XMEMSET(&server_sessionCache, 0, sizeof(hashTable)); if (wc_InitMutex(&server_sessionCache.htLock) != 0) return BAD_MUTEX_E; server_sessionCache.capacity = SESSION_CACHE_SIZE; fprintf(stderr, "\tBegin %s\n", param->tls_version); for (j = 0; j < 5; j++) { int tls13 = XSTRSTR(param->tls_version, "TLSv1_3") != NULL; int dtls = XSTRSTR(param->tls_version, "DTLS") != NULL; test_ssl_cbf client_cb; test_ssl_cbf server_cb; (void)dtls; /* Test five cache configurations */ twcase_client_first_session_ptr = NULL; twcase_server_first_session_ptr = NULL; twcase_server_current_ctx_ptr = NULL; twcase_new_session_called = 0; twcase_remove_session_called = 0; twcase_get_session_called = 0; /* connection 1 - first connection */ fprintf(stderr, "\tconnect: %s: j=%d\n", param->tls_version, j); XMEMSET(&client_cb, 0, sizeof(client_cb)); XMEMSET(&server_cb, 0, sizeof(server_cb)); client_cb.method = param->client_meth; server_cb.method = param->server_meth; if (dtls) client_cb.doUdp = server_cb.doUdp = 1; /* Setup internal and external cache */ switch (j) { case 0: /* SSL_OP_NO_TICKET stateful ticket case */ server_cb.ctx_ready = twcase_cache_intOn_extOn_noTicket; break; case 1: server_cb.ctx_ready = twcase_cache_intOn_extOn; break; case 2: server_cb.ctx_ready = twcase_cache_intOff_extOn; break; case 3: server_cb.ctx_ready = twcase_cache_intOn_extOff; break; case 4: server_cb.ctx_ready = twcase_cache_intOff_extOff; break; } client_cb.ctx_ready = twcase_cache_intOff_extOff; /* Add session to internal cache and save SSL session for testing */ server_cb.on_result = twcase_server_sess_ctx_pre_shutdown; /* Save client SSL session for testing */ client_cb.on_result = twcase_client_sess_ctx_pre_shutdown; server_cb.ticNoInit = 1; /* Use default builtin */ /* Don't free/release ctx */ server_cb.ctx = twcase_server_current_ctx_ptr; server_cb.isSharedCtx = 1; ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&client_cb, &server_cb, NULL), TEST_SUCCESS); ExpectIntEQ(twcase_get_session_called, 0); if (EXPECT_FAIL()) { wolfSSL_SESSION_free(twcase_client_first_session_ptr); wolfSSL_SESSION_free(twcase_server_first_session_ptr); wolfSSL_CTX_free(twcase_server_current_ctx_ptr); break; } switch (j) { case 0: case 1: case 2: /* cache cannot be searched with out a connection */ /* Add a new session */ ExpectIntEQ(twcase_new_session_called, 1); /* In twcase_server_sess_ctx_pre_shutdown * wolfSSL_CTX_add_session which evicts the existing session * in cache and adds it back in */ ExpectIntLE(twcase_remove_session_called, 1); break; case 3: case 4: /* no external cache */ ExpectIntEQ(twcase_new_session_called, 0); ExpectIntEQ(twcase_remove_session_called, 0); break; } /* connection 2 - session resume */ fprintf(stderr, "\tresume: %s: j=%d\n", param->tls_version, j); twcase_new_session_called = 0; twcase_remove_session_called = 0; twcase_get_session_called = 0; server_cb.on_result = 0; client_cb.on_result = 0; server_cb.ticNoInit = 1; /* Use default builtin */ server_cb.ctx = twcase_server_current_ctx_ptr; /* try session resumption */ client_cb.ssl_ready = twcase_client_set_sess_ssl_ready; ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&client_cb, &server_cb, NULL), TEST_SUCCESS); /* Clear cache before checking */ wolfSSL_CTX_flush_sessions(NULL, -1); switch (j) { case 0: if (tls13) { /* (D)TLSv1.3 stateful case */ /* cache hit */ /* DTLS accesses cache once for stateless parsing and * once for stateful parsing */ ExpectIntEQ(twcase_get_session_called, !dtls ? 1 : 2); /* (D)TLSv1.3 creates a new ticket, * updates both internal and external cache */ ExpectIntEQ(twcase_new_session_called, 1); /* A new session ID is created for a new ticket */ ExpectIntEQ(twcase_remove_session_called, 2); } else { /* non (D)TLSv1.3 case, no update */ /* DTLS accesses cache once for stateless parsing and * once for stateful parsing */ #ifdef WOLFSSL_DTLS_NO_HVR_ON_RESUME ExpectIntEQ(twcase_get_session_called, !dtls ? 1 : 2); #else ExpectIntEQ(twcase_get_session_called, 1); #endif ExpectIntEQ(twcase_new_session_called, 0); /* Called on session added in * twcase_server_sess_ctx_pre_shutdown */ ExpectIntEQ(twcase_remove_session_called, 1); } break; case 1: if (tls13) { /* (D)TLSv1.3 case */ /* cache hit */ ExpectIntEQ(twcase_get_session_called, 1); /* (D)TLSv1.3 creates a new ticket, * updates both internal and external cache */ ExpectIntEQ(twcase_new_session_called, 1); /* Called on session added in * twcase_server_sess_ctx_pre_shutdown and by wolfSSL */ ExpectIntEQ(twcase_remove_session_called, 1); } else { /* non (D)TLSv1.3 case */ /* cache hit */ /* DTLS accesses cache once for stateless parsing and * once for stateful parsing */ #ifdef WOLFSSL_DTLS_NO_HVR_ON_RESUME ExpectIntEQ(twcase_get_session_called, !dtls ? 1 : 2); #else ExpectIntEQ(twcase_get_session_called, 1); #endif ExpectIntEQ(twcase_new_session_called, 0); /* Called on session added in * twcase_server_sess_ctx_pre_shutdown */ ExpectIntEQ(twcase_remove_session_called, 1); } break; case 2: if (tls13) { /* (D)TLSv1.3 case */ /* cache hit */ ExpectIntEQ(twcase_get_session_called, 1); /* (D)TLSv1.3 creates a new ticket, * updates both internal and external cache */ ExpectIntEQ(twcase_new_session_called, 1); /* Called on session added in * twcase_server_sess_ctx_pre_shutdown and by wolfSSL */ ExpectIntEQ(twcase_remove_session_called, 1); } else { /* non (D)TLSv1.3 case */ /* cache hit */ /* DTLS accesses cache once for stateless parsing and * once for stateful parsing */ #ifdef WOLFSSL_DTLS_NO_HVR_ON_RESUME ExpectIntEQ(twcase_get_session_called, !dtls ? 1 : 2); #else ExpectIntEQ(twcase_get_session_called, 1); #endif ExpectIntEQ(twcase_new_session_called, 0); /* Called on session added in * twcase_server_sess_ctx_pre_shutdown */ ExpectIntEQ(twcase_remove_session_called, 1); } break; case 3: case 4: /* no external cache */ ExpectIntEQ(twcase_get_session_called, 0); ExpectIntEQ(twcase_new_session_called, 0); ExpectIntEQ(twcase_remove_session_called, 0); break; } wolfSSL_SESSION_free(twcase_client_first_session_ptr); wolfSSL_SESSION_free(twcase_server_first_session_ptr); wolfSSL_CTX_free(twcase_server_current_ctx_ptr); if (EXPECT_FAIL()) break; } twcase_get_sessionCb_cleanup(); XMEMSET(&server_sessionCache.entries, 0, sizeof(server_sessionCache.entries)); fprintf(stderr, "\tEnd %s\n", param->tls_version); wc_FreeMutex(&server_sessionCache.htLock); return EXPECT_RESULT(); } #endif static int test_wolfSSL_CTX_add_session_ext_tls13(void) { EXPECT_DECLS; #if defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(HAVE_EXT_CACHE) && \ defined(WOLFSSL_TLS13) && !defined(NO_SESSION_CACHE) && \ defined(OPENSSL_EXTRA) && defined(SESSION_CERTS) && \ defined(HAVE_SESSION_TICKET) && \ !defined(TITAN_SESSION_CACHE) && \ !defined(HUGE_SESSION_CACHE) && \ !defined(BIG_SESSION_CACHE) && \ !defined(MEDIUM_SESSION_CACHE) #if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) && \ defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_TICKET_HAVE_ID) struct test_add_session_ext_params param[1] = { { wolfTLSv1_3_client_method, wolfTLSv1_3_server_method, "TLSv1_3" } }; ExpectIntEQ(test_wolfSSL_CTX_add_session_ext(param), TEST_SUCCESS); #endif #endif return EXPECT_RESULT(); } static int test_wolfSSL_CTX_add_session_ext_dtls13(void) { EXPECT_DECLS; #if defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(HAVE_EXT_CACHE) && \ defined(WOLFSSL_TLS13) && !defined(NO_SESSION_CACHE) && \ defined(OPENSSL_EXTRA) && defined(SESSION_CERTS) && \ defined(HAVE_SESSION_TICKET) && \ !defined(TITAN_SESSION_CACHE) && \ !defined(HUGE_SESSION_CACHE) && \ !defined(BIG_SESSION_CACHE) && \ !defined(MEDIUM_SESSION_CACHE) #if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) && \ defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_TICKET_HAVE_ID) #ifdef WOLFSSL_DTLS13 struct test_add_session_ext_params param[1] = { { wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method, "DTLSv1_3" } }; ExpectIntEQ(test_wolfSSL_CTX_add_session_ext(param), TEST_SUCCESS); #endif #endif #endif return EXPECT_RESULT(); } static int test_wolfSSL_CTX_add_session_ext_tls12(void) { EXPECT_DECLS; #if defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(HAVE_EXT_CACHE) && \ defined(WOLFSSL_TLS13) && !defined(NO_SESSION_CACHE) && \ defined(OPENSSL_EXTRA) && defined(SESSION_CERTS) && \ defined(HAVE_SESSION_TICKET) && \ !defined(TITAN_SESSION_CACHE) && \ !defined(HUGE_SESSION_CACHE) && \ !defined(BIG_SESSION_CACHE) && \ !defined(MEDIUM_SESSION_CACHE) #ifndef WOLFSSL_NO_TLS12 struct test_add_session_ext_params param[1] = { { wolfTLSv1_2_client_method, wolfTLSv1_2_server_method, "TLSv1_2" } }; ExpectIntEQ(test_wolfSSL_CTX_add_session_ext(param), TEST_SUCCESS); #endif #endif return EXPECT_RESULT(); } static int test_wolfSSL_CTX_add_session_ext_dtls12(void) { EXPECT_DECLS; #if defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(HAVE_EXT_CACHE) && \ defined(WOLFSSL_TLS13) && !defined(NO_SESSION_CACHE) && \ defined(OPENSSL_EXTRA) && defined(SESSION_CERTS) && \ defined(HAVE_SESSION_TICKET) && \ !defined(TITAN_SESSION_CACHE) && \ !defined(HUGE_SESSION_CACHE) && \ !defined(BIG_SESSION_CACHE) && \ !defined(MEDIUM_SESSION_CACHE) #ifndef WOLFSSL_NO_TLS12 #ifdef WOLFSSL_DTLS struct test_add_session_ext_params param[1] = { { wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method, "DTLSv1_2" } }; ExpectIntEQ(test_wolfSSL_CTX_add_session_ext(param), TEST_SUCCESS); #endif #endif #endif return EXPECT_RESULT(); } static int test_wolfSSL_CTX_add_session_ext_tls11(void) { EXPECT_DECLS; #if defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(HAVE_EXT_CACHE) && \ defined(WOLFSSL_TLS13) && !defined(NO_SESSION_CACHE) && \ defined(OPENSSL_EXTRA) && defined(SESSION_CERTS) && \ defined(HAVE_SESSION_TICKET) && \ !defined(TITAN_SESSION_CACHE) && \ !defined(HUGE_SESSION_CACHE) && \ !defined(BIG_SESSION_CACHE) && \ !defined(MEDIUM_SESSION_CACHE) #if !defined(NO_OLD_TLS) && ((!defined(NO_AES) && !defined(NO_AES_CBC)) || \ !defined(NO_DES3)) struct test_add_session_ext_params param[1] = { { wolfTLSv1_1_client_method, wolfTLSv1_1_server_method, "TLSv1_1" } }; ExpectIntEQ(test_wolfSSL_CTX_add_session_ext(param), TEST_SUCCESS); #endif #endif return EXPECT_RESULT(); } static int test_wolfSSL_CTX_add_session_ext_dtls1(void) { EXPECT_DECLS; #if defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(HAVE_EXT_CACHE) && \ defined(WOLFSSL_TLS13) && !defined(NO_SESSION_CACHE) && \ defined(OPENSSL_EXTRA) && defined(SESSION_CERTS) && \ defined(HAVE_SESSION_TICKET) && \ !defined(TITAN_SESSION_CACHE) && \ !defined(HUGE_SESSION_CACHE) && \ !defined(BIG_SESSION_CACHE) && \ !defined(MEDIUM_SESSION_CACHE) #if !defined(NO_OLD_TLS) && ((!defined(NO_AES) && !defined(NO_AES_CBC)) || \ !defined(NO_DES3)) #ifdef WOLFSSL_DTLS struct test_add_session_ext_params param[1] = { { wolfDTLSv1_client_method, wolfDTLSv1_server_method, "DTLSv1_0" } }; ExpectIntEQ(test_wolfSSL_CTX_add_session_ext(param), TEST_SUCCESS); #endif #endif #endif return EXPECT_RESULT(); } #if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SESSION_EXPORT) /* canned export of a session using older version 3 */ static unsigned char version_3[] = { 0xA5, 0xA3, 0x01, 0x88, 0x00, 0x3c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x30, 0x05, 0x09, 0x0A, 0x01, 0x01, 0x00, 0x0D, 0x05, 0xFE, 0xFD, 0x01, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x10, 0x01, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x05, 0x12, 0xCF, 0x22, 0xA1, 0x9F, 0x1C, 0x39, 0x1D, 0x31, 0x11, 0x12, 0x1D, 0x11, 0x18, 0x0D, 0x0B, 0xF3, 0xE1, 0x4D, 0xDC, 0xB1, 0xF1, 0x39, 0x98, 0x91, 0x6C, 0x48, 0xE5, 0xED, 0x11, 0x12, 0xA0, 0x00, 0xF2, 0x25, 0x4C, 0x09, 0x26, 0xD1, 0x74, 0xDF, 0x23, 0x40, 0x15, 0x6A, 0x42, 0x2A, 0x26, 0xA5, 0xAC, 0x56, 0xD5, 0x4A, 0x20, 0xB7, 0xE9, 0xEF, 0xEB, 0xAF, 0xA8, 0x1E, 0x23, 0x7C, 0x04, 0xAA, 0xA1, 0x6D, 0x92, 0x79, 0x7B, 0xFA, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0C, 0x79, 0x7B, 0xFA, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xA1, 0x6D, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x10, 0x08, 0x02, 0x05, 0x08, 0x01, 0x30, 0x28, 0x00, 0x00, 0x0F, 0x00, 0x02, 0x00, 0x09, 0x31, 0x32, 0x37, 0x2E, 0x30, 0x2E, 0x30, 0x2E, 0x31, 0xED, 0x4F }; #endif /* defined(WOLFSSL_DTLS) && defined(WOLFSSL_SESSION_EXPORT) */ static int test_wolfSSL_dtls_export(void) { EXPECT_DECLS; #if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SESSION_EXPORT) tcp_ready ready; func_args client_args; func_args server_args; THREAD_TYPE serverThread; callback_functions server_cbf; callback_functions client_cbf; #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); #endif InitTcpReady(&ready); /* set using dtls */ XMEMSET(&client_args, 0, sizeof(func_args)); XMEMSET(&server_args, 0, sizeof(func_args)); XMEMSET(&server_cbf, 0, sizeof(callback_functions)); XMEMSET(&client_cbf, 0, sizeof(callback_functions)); server_cbf.method = wolfDTLSv1_2_server_method; client_cbf.method = wolfDTLSv1_2_client_method; server_args.callbacks = &server_cbf; client_args.callbacks = &client_cbf; server_args.signal = &ready; client_args.signal = &ready; start_thread(run_wolfssl_server, &server_args, &serverThread); wait_tcp_ready(&server_args); run_wolfssl_client(&client_args); join_thread(serverThread); ExpectTrue(client_args.return_code); ExpectTrue(server_args.return_code); FreeTcpReady(&ready); #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); #endif if (EXPECT_SUCCESS()) { SOCKET_T sockfd = 0; WOLFSSL_CTX* ctx = NULL; WOLFSSL* ssl = NULL; char msg[64] = "hello wolfssl!"; char reply[1024]; int msgSz = (int)XSTRLEN(msg); byte *session, *window; unsigned int sessionSz = 0; unsigned int windowSz = 0; #ifndef TEST_IPV6 struct sockaddr_in peerAddr; #else struct sockaddr_in6 peerAddr; #endif /* TEST_IPV6 */ int i; /* Set ctx to DTLS 1.2 */ ExpectNotNull(ctx = wolfSSL_CTX_new(wolfDTLSv1_2_server_method())); ExpectNotNull(ssl = wolfSSL_new(ctx)); /* test importing version 3 */ ExpectIntGE(wolfSSL_dtls_import(ssl, version_3, sizeof(version_3)), 0); /* test importing bad length and bad version */ version_3[2]++; ExpectIntLT(wolfSSL_dtls_import(ssl, version_3, sizeof(version_3)), 0); version_3[2]--; version_3[1] = 0XA0; ExpectIntLT(wolfSSL_dtls_import(ssl, version_3, sizeof(version_3)), 0); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); /* check storing client state after connection and storing window only */ #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); #endif InitTcpReady(&ready); /* set using dtls */ XMEMSET(&server_args, 0, sizeof(func_args)); XMEMSET(&server_cbf, 0, sizeof(callback_functions)); server_cbf.method = wolfDTLSv1_2_server_method; server_cbf.doUdp = 1; server_args.callbacks = &server_cbf; server_args.argc = 3; /* set loop_count to 3 */ server_args.signal = &ready; start_thread(test_server_nofail, &server_args, &serverThread); wait_tcp_ready(&server_args); /* create and connect with client */ ExpectNotNull(ctx = wolfSSL_CTX_new(wolfDTLSv1_2_client_method())); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_use_certificate_file(ctx, cliCertFile, SSL_FILETYPE_PEM)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_use_PrivateKey_file(ctx, cliKeyFile, SSL_FILETYPE_PEM)); tcp_connect(&sockfd, wolfSSLIP, server_args.signal->port, 1, 0, NULL); ExpectNotNull(ssl = wolfSSL_new(ctx)); ExpectIntEQ(wolfSSL_set_fd(ssl, sockfd), WOLFSSL_SUCCESS); /* store server information connected too */ XMEMSET(&peerAddr, 0, sizeof(peerAddr)); #ifndef TEST_IPV6 peerAddr.sin_family = AF_INET; ExpectIntEQ(XINET_PTON(AF_INET, wolfSSLIP, &peerAddr.sin_addr),1); peerAddr.sin_port = XHTONS(server_args.signal->port); #else peerAddr.sin6_family = AF_INET6; ExpectIntEQ( XINET_PTON(AF_INET6, wolfSSLIP, &peerAddr.sin6_addr),1); peerAddr.sin6_port = XHTONS(server_args.signal->port); #endif ExpectIntEQ(wolfSSL_dtls_set_peer(ssl, &peerAddr, sizeof(peerAddr)), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_connect(ssl), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_dtls_export(ssl, NULL, &sessionSz), 0); session = (byte*)XMALLOC(sessionSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); ExpectIntGT(wolfSSL_dtls_export(ssl, session, &sessionSz), 0); ExpectIntEQ(wolfSSL_write(ssl, msg, msgSz), msgSz); ExpectIntGT(wolfSSL_read(ssl, reply, sizeof(reply)), 0); ExpectIntEQ(wolfSSL_dtls_export_state_only(ssl, NULL, &windowSz), 0); window = (byte*)XMALLOC(windowSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); ExpectIntGT(wolfSSL_dtls_export_state_only(ssl, window, &windowSz), 0); wolfSSL_free(ssl); for (i = 1; EXPECT_SUCCESS() && i < server_args.argc; i++) { /* restore state */ ExpectNotNull(ssl = wolfSSL_new(ctx)); ExpectIntGT(wolfSSL_dtls_import(ssl, session, sessionSz), 0); ExpectIntGT(wolfSSL_dtls_import(ssl, window, windowSz), 0); ExpectIntEQ(wolfSSL_set_fd(ssl, sockfd), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_dtls_set_peer(ssl, &peerAddr, sizeof(peerAddr)), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_write(ssl, msg, msgSz), msgSz); ExpectIntGE(wolfSSL_read(ssl, reply, sizeof(reply)), 0); ExpectIntGT(wolfSSL_dtls_export_state_only(ssl, window, &windowSz), 0); wolfSSL_free(ssl); } XFREE(session, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(window, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wolfSSL_CTX_free(ctx); fprintf(stderr, "done and waiting for server\n"); join_thread(serverThread); ExpectIntEQ(server_args.return_code, TEST_SUCCESS); FreeTcpReady(&ready); #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); #endif } #endif return EXPECT_RESULT(); } #if defined(WOLFSSL_SESSION_EXPORT) && !defined(WOLFSSL_NO_TLS12) #ifdef WOLFSSL_TLS13 static const byte canned_client_tls13_session_v4[] = { 0xA7, 0xA4, 0x01, 0x18, 0x00, 0x41, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x1C, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x01, 0x0A, 0x0F, 0x10, 0x01, 0x02, 0x09, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x00, 0xB7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x11, 0x01, 0x01, 0x00, 0x20, 0x84, 0x4F, 0x18, 0xD8, 0xC1, 0x24, 0xD8, 0xBB, 0x17, 0x9E, 0x31, 0xA3, 0xF8, 0xA7, 0x3C, 0xBA, 0xEC, 0xFA, 0xB4, 0x7F, 0xC5, 0x78, 0xEB, 0x6D, 0xE3, 0x2B, 0x7B, 0x94, 0xBE, 0x20, 0x11, 0x7E, 0x17, 0x10, 0xA7, 0x10, 0x19, 0xEC, 0x62, 0xCC, 0xBE, 0xF5, 0x01, 0x35, 0x3C, 0xEA, 0xEF, 0x44, 0x3C, 0x40, 0xA2, 0xBC, 0x18, 0x43, 0xA1, 0xA1, 0x65, 0x5C, 0x48, 0xE2, 0xF9, 0x38, 0xEB, 0x11, 0x10, 0x72, 0x7C, 0x78, 0x22, 0x13, 0x3B, 0x19, 0x40, 0xF0, 0x73, 0xBE, 0x96, 0x14, 0x78, 0x26, 0xB9, 0x6B, 0x2E, 0x72, 0x22, 0x0D, 0x90, 0x94, 0xDD, 0x78, 0x77, 0xFC, 0x0C, 0x2E, 0x63, 0x6E, 0xF0, 0x0C, 0x35, 0x41, 0xCD, 0xF3, 0x49, 0x31, 0x08, 0xD0, 0x6F, 0x02, 0x3D, 0xC1, 0xD3, 0xB7, 0xEE, 0x3A, 0xA0, 0x8E, 0xA1, 0x4D, 0xC3, 0x2E, 0x5E, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x35, 0x41, 0xCD, 0xF3, 0x49, 0x31, 0x08, 0xD0, 0x6F, 0x02, 0x3D, 0xC1, 0xD3, 0xB7, 0xEE, 0x3A, 0xA0, 0x8E, 0xA1, 0x4D, 0xC3, 0x2E, 0x5E, 0x06, 0x00, 0x10, 0x00, 0x10, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x10, 0x07, 0x02, 0x04, 0x00, 0x00, 0x20, 0x28, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03 }; static const byte canned_client_tls13_session_v5[] = { 0xa7, 0xa5, 0x01, 0x19, 0x00, 0x42, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x1c, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x01, 0x0a, 0x0f, 0x10, 0x01, 0x02, 0x09, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x04, 0x00, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x11, 0x01, 0x01, 0x00, 0x20, 0x84, 0x4f, 0x18, 0xd8, 0xc1, 0x24, 0xd8, 0xbb, 0x17, 0x9e, 0x31, 0xa3, 0xf8, 0xa7, 0x3c, 0xba, 0xec, 0xfa, 0xb4, 0x7f, 0xc5, 0x78, 0xeb, 0x6d, 0xe3, 0x2b, 0x7b, 0x94, 0xbe, 0x20, 0x11, 0x7e, 0x17, 0x10, 0xa7, 0x10, 0x19, 0xec, 0x62, 0xcc, 0xbe, 0xf5, 0x01, 0x35, 0x3c, 0xea, 0xef, 0x44, 0x3c, 0x40, 0xa2, 0xbc, 0x18, 0x43, 0xa1, 0xa1, 0x65, 0x5c, 0x48, 0xe2, 0xf9, 0x38, 0xeb, 0x11, 0x10, 0x72, 0x7c, 0x78, 0x22, 0x13, 0x3b, 0x19, 0x40, 0xf0, 0x73, 0xbe, 0x96, 0x14, 0x78, 0x26, 0xb9, 0x6b, 0x2e, 0x72, 0x22, 0x0d, 0x90, 0x94, 0xdd, 0x78, 0x77, 0xfc, 0x0c, 0x2e, 0x63, 0x6e, 0xf0, 0x0c, 0x35, 0x41, 0xcd, 0xf3, 0x49, 0x31, 0x08, 0xd0, 0x6f, 0x02, 0x3d, 0xc1, 0xd3, 0xb7, 0xee, 0x3a, 0xa0, 0x8e, 0xa1, 0x4d, 0xc3, 0x2e, 0x5e, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x35, 0x41, 0xcd, 0xf3, 0x49, 0x31, 0x08, 0xd0, 0x6f, 0x02, 0x3d, 0xc1, 0xd3, 0xb7, 0xee, 0x3a, 0xa0, 0x8e, 0xa1, 0x4d, 0xc3, 0x2e, 0x5e, 0x06, 0x00, 0x10, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x10, 0x07, 0x02, 0x04, 0x00, 0x00, 0x20, 0x28, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03 }; static const byte canned_server_tls13_session[] = { 0xA7, 0xA4, 0x01, 0x18, 0x00, 0x41, 0x01, 0x00, 0x01, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x1C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x01, 0x0A, 0x0F, 0x10, 0x01, 0x02, 0x00, 0x0F, 0x05, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x00, 0xB7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x11, 0x01, 0x01, 0x00, 0x20, 0x84, 0x4F, 0x18, 0xD8, 0xC1, 0x24, 0xD8, 0xBB, 0x17, 0x9E, 0x31, 0xA3, 0xF8, 0xA7, 0x3C, 0xBA, 0xEC, 0xFA, 0xB4, 0x7F, 0xC5, 0x78, 0xEB, 0x6D, 0xE3, 0x2B, 0x7B, 0x94, 0xBE, 0x20, 0x11, 0x7E, 0x17, 0x10, 0xA7, 0x10, 0x19, 0xEC, 0x62, 0xCC, 0xBE, 0xF5, 0x01, 0x35, 0x3C, 0xEA, 0xEF, 0x44, 0x3C, 0x40, 0xA2, 0xBC, 0x18, 0x43, 0xA1, 0xA1, 0x65, 0x5C, 0x48, 0xE2, 0xF9, 0x38, 0xEB, 0x11, 0x10, 0x72, 0x7C, 0x78, 0x22, 0x13, 0x3B, 0x19, 0x40, 0xF0, 0x73, 0xBE, 0x96, 0x14, 0x78, 0x26, 0xB9, 0x6B, 0x2E, 0x72, 0x22, 0x0D, 0x90, 0x94, 0xDD, 0x78, 0x77, 0xFC, 0x0C, 0x2E, 0x63, 0x6E, 0xF0, 0x0C, 0x35, 0x41, 0xCD, 0xF3, 0x49, 0x31, 0x08, 0xD0, 0x6F, 0x02, 0x3D, 0xC1, 0xD3, 0xB7, 0xEE, 0x3A, 0xA0, 0x8E, 0xA1, 0x4D, 0xC3, 0x2E, 0x5E, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xD3, 0xB7, 0xEE, 0x3A, 0xA0, 0x8E, 0xA1, 0x4D, 0xC3, 0x2E, 0x5E, 0x06, 0x35, 0x41, 0xCD, 0xF3, 0x49, 0x31, 0x08, 0xD0, 0x6F, 0x02, 0x3D, 0xC1, 0x00, 0x10, 0x00, 0x10, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x10, 0x07, 0x02, 0x04, 0x00, 0x00, 0x20, 0x28, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04 }; #endif /* WOLFSSL_TLS13 */ static const byte canned_client_session_v4[] = { 0xA7, 0xA4, 0x01, 0x40, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x27, 0x0A, 0x0D, 0x10, 0x01, 0x01, 0x0A, 0x00, 0x05, 0x00, 0x01, 0x01, 0x01, 0x03, 0x03, 0x00, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x0A, 0x01, 0x01, 0x00, 0x20, 0x69, 0x11, 0x6D, 0x97, 0x15, 0x6E, 0x52, 0x27, 0xD6, 0x1D, 0x1D, 0xF5, 0x0D, 0x59, 0xA5, 0xAC, 0x2E, 0x8C, 0x0E, 0xCB, 0x26, 0x1E, 0xE2, 0xCE, 0xBB, 0xCE, 0xE1, 0x7D, 0xD7, 0xEF, 0xA5, 0x44, 0x80, 0x2A, 0xDE, 0xBB, 0x75, 0xB0, 0x1D, 0x75, 0x17, 0x20, 0x4C, 0x08, 0x05, 0x1B, 0xBA, 0x60, 0x1F, 0x6C, 0x91, 0x8C, 0xAA, 0xBB, 0xE5, 0xA3, 0x0B, 0x12, 0x3E, 0xC0, 0x35, 0x43, 0x1D, 0xE2, 0x10, 0xE2, 0x02, 0x92, 0x4B, 0x8F, 0x05, 0xA9, 0x4B, 0xCC, 0x90, 0xC3, 0x0E, 0xC2, 0x0F, 0xE9, 0x33, 0x85, 0x9B, 0x3C, 0x19, 0x21, 0xD5, 0x62, 0xE5, 0xE1, 0x17, 0x8F, 0x8C, 0x19, 0x52, 0xD8, 0x59, 0x10, 0x2D, 0x20, 0x6F, 0xBA, 0xC1, 0x1C, 0xD1, 0x82, 0xC7, 0x32, 0x1B, 0xBB, 0xCC, 0x30, 0x03, 0xD7, 0x3A, 0xC8, 0x18, 0xED, 0x58, 0xC8, 0x11, 0xFE, 0x71, 0x9C, 0x71, 0xD8, 0x6B, 0xE0, 0x25, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x06, 0x01, 0x04, 0x08, 0x01, 0x20, 0x28, 0x00, 0x09, 0xE1, 0x50, 0x70, 0x02, 0x2F, 0x7E, 0xDA, 0xBD, 0x40, 0xC5, 0x58, 0x87, 0xCE, 0x43, 0xF3, 0xC5, 0x8F, 0xA1, 0x59, 0x93, 0xEF, 0x7E, 0xD3, 0xD0, 0xB5, 0x87, 0x1D, 0x81, 0x54, 0x14, 0x63, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03 }; static const byte canned_client_session_v5[] = { 0xa7, 0xa5, 0x01, 0x41, 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x27, 0x0a, 0x0d, 0x10, 0x01, 0x01, 0x0a, 0x00, 0x05, 0x00, 0x01, 0x01, 0x01, 0x01, 0x03, 0x03, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x01, 0x00, 0x20, 0x69, 0x11, 0x6d, 0x97, 0x15, 0x6e, 0x52, 0x27, 0xd6, 0x1d, 0x1d, 0xf5, 0x0d, 0x59, 0xa5, 0xac, 0x2e, 0x8c, 0x0e, 0xcb, 0x26, 0x1e, 0xe2, 0xce, 0xbb, 0xce, 0xe1, 0x7d, 0xd7, 0xef, 0xa5, 0x44, 0x80, 0x2a, 0xde, 0xbb, 0x75, 0xb0, 0x1d, 0x75, 0x17, 0x20, 0x4c, 0x08, 0x05, 0x1b, 0xba, 0x60, 0x1f, 0x6c, 0x91, 0x8c, 0xaa, 0xbb, 0xe5, 0xa3, 0x0b, 0x12, 0x3e, 0xc0, 0x35, 0x43, 0x1d, 0xe2, 0x10, 0xe2, 0x02, 0x92, 0x4b, 0x8f, 0x05, 0xa9, 0x4b, 0xcc, 0x90, 0xc3, 0x0e, 0xc2, 0x0f, 0xe9, 0x33, 0x85, 0x9b, 0x3c, 0x19, 0x21, 0xd5, 0x62, 0xe5, 0xe1, 0x17, 0x8f, 0x8c, 0x19, 0x52, 0xd8, 0x59, 0x10, 0x2d, 0x20, 0x6f, 0xba, 0xc1, 0x1c, 0xd1, 0x82, 0xc7, 0x32, 0x1b, 0xbb, 0xcc, 0x30, 0x03, 0xd7, 0x3a, 0xc8, 0x18, 0xed, 0x58, 0xc8, 0x11, 0xfe, 0x71, 0x9c, 0x71, 0xd8, 0x6b, 0xe0, 0x25, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x06, 0x01, 0x04, 0x08, 0x01, 0x20, 0x28, 0x00, 0x09, 0xe1, 0x50, 0x70, 0x02, 0x2f, 0x7e, 0xda, 0xbd, 0x40, 0xc5, 0x58, 0x87, 0xce, 0x43, 0xf3, 0xc5, 0x8f, 0xa1, 0x59, 0x93, 0xef, 0x7e, 0xd3, 0xd0, 0xb5, 0x87, 0x1d, 0x81, 0x54, 0x14, 0x63, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03 }; static const byte canned_server_session[] = { 0xA7, 0xA4, 0x01, 0x40, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x27, 0x08, 0x0F, 0x10, 0x01, 0x01, 0x00, 0x11, 0x05, 0x00, 0x01, 0x01, 0x01, 0x03, 0x03, 0x00, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x0A, 0x01, 0x01, 0x00, 0x20, 0x69, 0x11, 0x6D, 0x97, 0x15, 0x6E, 0x52, 0x27, 0xD6, 0x1D, 0x1D, 0xF5, 0x0D, 0x59, 0xA5, 0xAC, 0x2E, 0x8C, 0x0E, 0xCB, 0x26, 0x1E, 0xE2, 0xCE, 0xBB, 0xCE, 0xE1, 0x7D, 0xD7, 0xEF, 0xA5, 0x44, 0x80, 0x2A, 0xDE, 0xBB, 0x75, 0xB0, 0x1D, 0x75, 0x17, 0x20, 0x4C, 0x08, 0x05, 0x1B, 0xBA, 0x60, 0x1F, 0x6C, 0x91, 0x8C, 0xAA, 0xBB, 0xE5, 0xA3, 0x0B, 0x12, 0x3E, 0xC0, 0x35, 0x43, 0x1D, 0xE2, 0x10, 0xE2, 0x02, 0x92, 0x4B, 0x8F, 0x05, 0xA9, 0x4B, 0xCC, 0x90, 0xC3, 0x0E, 0xC2, 0x0F, 0xE9, 0x33, 0x85, 0x9B, 0x3C, 0x19, 0x21, 0xD5, 0x62, 0xE5, 0xE1, 0x17, 0x8F, 0x8C, 0x19, 0x52, 0xD8, 0x59, 0x10, 0x2D, 0x20, 0x6F, 0xBA, 0xC1, 0x1C, 0xD1, 0x82, 0xC7, 0x32, 0x1B, 0xBB, 0xCC, 0x30, 0x03, 0xD7, 0x3A, 0xC8, 0x18, 0xED, 0x58, 0xC8, 0x11, 0xFE, 0x71, 0x9C, 0x71, 0xD8, 0x6B, 0xE0, 0x25, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x06, 0x01, 0x04, 0x08, 0x01, 0x20, 0x28, 0x00, 0xC5, 0x8F, 0xA1, 0x59, 0x93, 0xEF, 0x7E, 0xD3, 0xD0, 0xB5, 0x87, 0x1D, 0x81, 0x54, 0x14, 0x63, 0x09, 0xE1, 0x50, 0x70, 0x02, 0x2F, 0x7E, 0xDA, 0xBD, 0x40, 0xC5, 0x58, 0x87, 0xCE, 0x43, 0xF3, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04 }; static THREAD_RETURN WOLFSSL_THREAD tls_export_server(void* args) { SOCKET_T sockfd = 0; SOCKET_T clientfd = 0; word16 port; callback_functions* cbf; WOLFSSL_CTX* ctx = 0; WOLFSSL* ssl = 0; char msg[] = "I hear you fa shizzle!"; char input[1024]; int idx; #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); #endif ((func_args*)args)->return_code = TEST_FAIL; cbf = ((func_args*)args)->callbacks; #if defined(USE_WINDOWS_API) port = ((func_args*)args)->signal->port; #elif defined(NO_MAIN_DRIVER) && !defined(WOLFSSL_SNIFFER) && \ !defined(WOLFSSL_MDK_SHELL) && !defined(WOLFSSL_TIRTOS) /* Let tcp_listen assign port */ port = 0; #else /* Use default port */ port = wolfSSLPort; #endif /* do it here to detect failure */ tcp_accept(&sockfd, &clientfd, (func_args*)args, port, 0, 0, 0, 0, 1, 0, 0); CloseSocket(sockfd); { WOLFSSL_METHOD* method = NULL; if (cbf != NULL && cbf->method != NULL) { method = cbf->method(); } else { method = wolfTLSv1_2_server_method(); } ctx = wolfSSL_CTX_new(method); } if (ctx == NULL) { goto done; } wolfSSL_CTX_set_cipher_list(ctx, "ECDHE-RSA-AES128-SHA256"); /* call ctx setup callback */ if (cbf != NULL && cbf->ctx_ready != NULL) { cbf->ctx_ready(ctx); } ssl = wolfSSL_new(ctx); if (ssl == NULL) { goto done; } wolfSSL_set_fd(ssl, clientfd); /* call ssl setup callback */ if (cbf != NULL && cbf->ssl_ready != NULL) { cbf->ssl_ready(ssl); } idx = wolfSSL_read(ssl, input, sizeof(input)-1); if (idx > 0) { input[idx] = '\0'; fprintf(stderr, "Client message export/import: %s\n", input); } else { fprintf(stderr, "ret = %d error = %d\n", idx, wolfSSL_get_error(ssl, idx)); goto done; } if (wolfSSL_write(ssl, msg, sizeof(msg)) != sizeof(msg)) { /*err_sys("SSL_write failed");*/ WOLFSSL_RETURN_FROM_THREAD(0); } #ifdef WOLFSSL_TIRTOS Task_yield(); #endif ((func_args*)args)->return_code = TEST_SUCCESS; done: wolfSSL_shutdown(ssl); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); CloseSocket(clientfd); #ifdef WOLFSSL_TIRTOS fdCloseSession(Task_self()); #endif #if defined(NO_MAIN_DRIVER) && defined(HAVE_ECC) && defined(FP_ECC) \ && defined(HAVE_THREAD_LS) wc_ecc_fp_free(); /* free per thread cache */ #endif #if defined(HAVE_SESSION_TICKET) && \ ((defined(HAVE_CHACHA) && defined(HAVE_POLY1305)) || defined(HAVE_AESGCM)) #if defined(OPENSSL_EXTRA) && defined(HAVE_AESGCM) OpenSSLTicketCleanup(); #elif defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) TicketCleanup(); #endif #endif WOLFSSL_RETURN_FROM_THREAD(0); } static void load_tls12_canned_server(WOLFSSL* ssl) { int clientfd = wolfSSL_get_fd(ssl); AssertIntEQ(wolfSSL_tls_import(ssl, canned_server_session, sizeof(canned_server_session)), sizeof(canned_server_session)); wolfSSL_set_fd(ssl, clientfd); } #ifdef WOLFSSL_TLS13 static void load_tls13_canned_server(WOLFSSL* ssl) { int clientfd = wolfSSL_get_fd(ssl); AssertIntEQ(wolfSSL_tls_import(ssl, canned_server_tls13_session, sizeof(canned_server_tls13_session)), sizeof(canned_server_tls13_session)); wolfSSL_set_fd(ssl, clientfd); } #endif /* v is for version WOLFSSL_TLSV1_2 or WOLFSSL_TLSV1_3 */ static int test_wolfSSL_tls_export_run(method_provider server_method, method_provider client_method, ssl_callback ssl_ready, const byte* clientSession, int clientSessionSz, int cmpSess) { EXPECT_DECLS; SOCKET_T sockfd = 0; WOLFSSL_CTX* ctx = 0; WOLFSSL* ssl = 0; char msg[64] = "hello wolfssl!"; char reply[1024]; word32 replySz; int msgSz = (int)XSTRLEN(msg); tcp_ready ready; func_args server_args; THREAD_TYPE serverThread; callback_functions server_cbf; #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); #endif (void)cmpSess; InitTcpReady(&ready); XMEMSET(&server_args, 0, sizeof(func_args)); XMEMSET(&server_cbf, 0, sizeof(callback_functions)); server_cbf.method = server_method; server_cbf.ssl_ready = ssl_ready; ExpectNotNull(ctx = wolfSSL_CTX_new(client_method())); server_args.callbacks = &server_cbf; server_args.signal = &ready; start_thread(tls_export_server, &server_args, &serverThread); wait_tcp_ready(&server_args); #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); #endif ExpectNotNull(ssl = wolfSSL_new(ctx)); tcp_connect(&sockfd, wolfSSLIP, ready.port, 0, 0, ssl); ExpectIntEQ(wolfSSL_tls_import(ssl, clientSession, clientSessionSz), clientSessionSz); replySz = sizeof(reply); ExpectIntGT(wolfSSL_tls_export(ssl, (byte*)reply, &replySz), 0); #if !defined(NO_PSK) && defined(HAVE_ANON) if (cmpSess) { /* index 20 has is setting if PSK was on and 49 is if anon is allowed */ ExpectIntEQ(replySz, clientSessionSz); ExpectBufEQ(reply, clientSession, replySz); } #endif wolfSSL_set_fd(ssl, sockfd); ExpectIntEQ(wolfSSL_write(ssl, msg, msgSz), msgSz); ExpectIntGT(wolfSSL_read(ssl, reply, sizeof(reply)-1), 0); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); CloseSocket(sockfd); #ifdef WOLFSSL_TIRTOS fdCloseSession(Task_self()); #endif #if defined(NO_MAIN_DRIVER) && defined(HAVE_ECC) && defined(FP_ECC) \ && defined(HAVE_THREAD_LS) wc_ecc_fp_free(); /* free per thread cache */ #endif join_thread(serverThread); ExpectIntEQ(server_args.return_code, TEST_SUCCESS); FreeTcpReady(&ready); #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); #endif return EXPECT_RESULT(); } #endif static int test_wolfSSL_tls_export(void) { EXPECT_DECLS; #if defined(WOLFSSL_SESSION_EXPORT) && !defined(WOLFSSL_NO_TLS12) EXPECT_TEST(test_wolfSSL_tls_export_run(wolfTLSv1_2_server_method, wolfTLSv1_2_client_method, load_tls12_canned_server, canned_client_session_v4, sizeof(canned_client_session_v4), 0)); EXPECT_TEST(test_wolfSSL_tls_export_run(wolfTLSv1_2_server_method, wolfTLSv1_2_client_method, load_tls12_canned_server, canned_client_session_v5, sizeof(canned_client_session_v5), 1)); #ifdef WOLFSSL_TLS13 EXPECT_TEST(test_wolfSSL_tls_export_run(wolfTLSv1_3_server_method, wolfTLSv1_3_client_method, load_tls13_canned_server, canned_client_tls13_session_v4, sizeof(canned_client_tls13_session_v4), 0)); EXPECT_TEST(test_wolfSSL_tls_export_run(wolfTLSv1_3_server_method, wolfTLSv1_3_client_method, load_tls13_canned_server, canned_client_tls13_session_v5, sizeof(canned_client_tls13_session_v5), 1)); #endif #endif return EXPECT_RESULT(); } /*----------------------------------------------------------------------------* | TLS extensions tests *----------------------------------------------------------------------------*/ #ifdef ENABLE_TLS_CALLBACK_TEST /* Connection test runner - generic */ static void test_wolfSSL_client_server(callback_functions* client_callbacks, callback_functions* server_callbacks) { tcp_ready ready; func_args client_args; func_args server_args; THREAD_TYPE serverThread; XMEMSET(&client_args, 0, sizeof(func_args)); XMEMSET(&server_args, 0, sizeof(func_args)); StartTCP(); client_args.callbacks = client_callbacks; server_args.callbacks = server_callbacks; #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); #endif /* RUN Server side */ InitTcpReady(&ready); server_args.signal = &ready; client_args.signal = &ready; start_thread(run_wolfssl_server, &server_args, &serverThread); wait_tcp_ready(&server_args); /* RUN Client side */ run_wolfssl_client(&client_args); join_thread(serverThread); FreeTcpReady(&ready); #ifdef WOLFSSL_TIRTOS fdCloseSession(Task_self()); #endif client_callbacks->return_code = client_args.return_code; server_callbacks->return_code = server_args.return_code; } #endif /* ENABLE_TLS_CALLBACK_TEST */ #ifdef HAVE_SNI static int test_wolfSSL_UseSNI_params(void) { EXPECT_DECLS; #if !defined(NO_WOLFSSL_CLIENT) WOLFSSL_CTX *ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); WOLFSSL *ssl = wolfSSL_new(ctx); ExpectNotNull(ctx); ExpectNotNull(ssl); /* invalid [ctx|ssl] */ ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_UseSNI(NULL, 0, "ctx", 3)); ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_UseSNI( NULL, 0, "ssl", 3)); /* invalid type */ ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_UseSNI(ctx, (byte)-1, "ctx", 3)); ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_UseSNI( ssl, (byte)-1, "ssl", 3)); /* invalid data */ ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_UseSNI(ctx, 0, NULL, 3)); ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_UseSNI( ssl, 0, NULL, 3)); /* success case */ ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_UseSNI(ctx, 0, "ctx", 3)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseSNI( ssl, 0, "ssl", 3)); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #endif /* !NO_WOLFSSL_CLIENT */ return EXPECT_RESULT(); } /* BEGIN of connection tests callbacks */ static void use_SNI_at_ctx(WOLFSSL_CTX* ctx) { AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_UseSNI(ctx, WOLFSSL_SNI_HOST_NAME, "www.wolfssl.com", 15)); } static void use_SNI_at_ssl(WOLFSSL* ssl) { AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME, "www.wolfssl.com", 15)); } static void different_SNI_at_ssl(WOLFSSL* ssl) { AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME, "ww2.wolfssl.com", 15)); } static void use_SNI_WITH_CONTINUE_at_ssl(WOLFSSL* ssl) { use_SNI_at_ssl(ssl); wolfSSL_SNI_SetOptions(ssl, WOLFSSL_SNI_HOST_NAME, WOLFSSL_SNI_CONTINUE_ON_MISMATCH); } static void use_SNI_WITH_FAKE_ANSWER_at_ssl(WOLFSSL* ssl) { use_SNI_at_ssl(ssl); wolfSSL_SNI_SetOptions(ssl, WOLFSSL_SNI_HOST_NAME, WOLFSSL_SNI_ANSWER_ON_MISMATCH); } static void use_MANDATORY_SNI_at_ctx(WOLFSSL_CTX* ctx) { use_SNI_at_ctx(ctx); wolfSSL_CTX_SNI_SetOptions(ctx, WOLFSSL_SNI_HOST_NAME, WOLFSSL_SNI_ABORT_ON_ABSENCE); } static void use_MANDATORY_SNI_at_ssl(WOLFSSL* ssl) { use_SNI_at_ssl(ssl); wolfSSL_SNI_SetOptions(ssl, WOLFSSL_SNI_HOST_NAME, WOLFSSL_SNI_ABORT_ON_ABSENCE); } static void use_PSEUDO_MANDATORY_SNI_at_ctx(WOLFSSL_CTX* ctx) { use_SNI_at_ctx(ctx); wolfSSL_CTX_SNI_SetOptions(ctx, WOLFSSL_SNI_HOST_NAME, WOLFSSL_SNI_ANSWER_ON_MISMATCH | WOLFSSL_SNI_ABORT_ON_ABSENCE); } static void verify_UNKNOWN_SNI_on_server(WOLFSSL* ssl) { AssertIntEQ(WC_NO_ERR_TRACE(UNKNOWN_SNI_HOST_NAME_E), wolfSSL_get_error(ssl, 0)); } static void verify_SNI_ABSENT_on_server(WOLFSSL* ssl) { AssertIntEQ(WC_NO_ERR_TRACE(SNI_ABSENT_ERROR), wolfSSL_get_error(ssl, 0)); } static void verify_SNI_no_matching(WOLFSSL* ssl) { byte type = WOLFSSL_SNI_HOST_NAME; void* request = (void*) &type; /* to be overwritten */ AssertIntEQ(WOLFSSL_SNI_NO_MATCH, wolfSSL_SNI_Status(ssl, type)); AssertNotNull(request); AssertIntEQ(0, wolfSSL_SNI_GetRequest(ssl, type, &request)); AssertNull(request); } static void verify_SNI_real_matching(WOLFSSL* ssl) { byte type = WOLFSSL_SNI_HOST_NAME; void* request = NULL; AssertIntEQ(WOLFSSL_SNI_REAL_MATCH, wolfSSL_SNI_Status(ssl, type)); AssertIntEQ(15, wolfSSL_SNI_GetRequest(ssl, type, &request)); AssertNotNull(request); AssertStrEQ("www.wolfssl.com", (char*)request); } static void verify_SNI_fake_matching(WOLFSSL* ssl) { byte type = WOLFSSL_SNI_HOST_NAME; void* request = NULL; AssertIntEQ(WOLFSSL_SNI_FAKE_MATCH, wolfSSL_SNI_Status(ssl, type)); AssertIntEQ(15, wolfSSL_SNI_GetRequest(ssl, type, &request)); AssertNotNull(request); AssertStrEQ("ww2.wolfssl.com", (char*)request); } static void verify_FATAL_ERROR_on_client(WOLFSSL* ssl) { AssertIntEQ(WC_NO_ERR_TRACE(FATAL_ERROR), wolfSSL_get_error(ssl, 0)); } /* END of connection tests callbacks */ static int test_wolfSSL_UseSNI_connection(void) { int res = TEST_SKIPPED; #if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) callback_functions client_cb; callback_functions server_cb; size_t i; #ifdef WOLFSSL_STATIC_MEMORY byte cliMem[TEST_TLS_STATIC_MEMSZ]; byte svrMem[TEST_TLS_STATIC_MEMSZ]; #endif struct { method_provider client_meth; method_provider server_meth; #ifdef WOLFSSL_STATIC_MEMORY wolfSSL_method_func client_meth_ex; wolfSSL_method_func server_meth_ex; #endif } methods[] = { #if defined(WOLFSSL_NO_TLS12) && !defined(WOLFSSL_TLS13) {wolfSSLv23_client_method, wolfSSLv23_server_method #ifdef WOLFSSL_STATIC_MEMORY ,wolfSSLv23_client_method_ex, wolfSSLv23_server_method_ex #endif }, #endif #ifndef WOLFSSL_NO_TLS12 {wolfTLSv1_2_client_method, wolfTLSv1_2_server_method #ifdef WOLFSSL_STATIC_MEMORY ,wolfTLSv1_2_client_method_ex, wolfTLSv1_2_server_method_ex #endif }, #endif #ifdef WOLFSSL_TLS13 {wolfTLSv1_3_client_method, wolfTLSv1_3_server_method #ifdef WOLFSSL_STATIC_MEMORY ,wolfTLSv1_3_client_method_ex, wolfTLSv1_3_server_method_ex #endif }, #endif }; size_t methodsSz = sizeof(methods) / sizeof(*methods); for (i = 0; i < methodsSz; i++) { XMEMSET(&client_cb, 0, sizeof(callback_functions)); XMEMSET(&server_cb, 0, sizeof(callback_functions)); client_cb.method = methods[i].client_meth; server_cb.method = methods[i].server_meth; client_cb.devId = testDevId; server_cb.devId = testDevId; #ifdef WOLFSSL_STATIC_MEMORY client_cb.method_ex = methods[i].client_meth_ex; server_cb.method_ex = methods[i].server_meth_ex; client_cb.mem = cliMem; client_cb.memSz = (word32)sizeof(cliMem); server_cb.mem = svrMem; server_cb.memSz = (word32)sizeof(svrMem);; #endif /* success case at ctx */ fprintf(stderr, "\n\tsuccess case at ctx\n"); client_cb.ctx_ready = use_SNI_at_ctx; client_cb.ssl_ready = NULL; client_cb.on_result = NULL; server_cb.ctx_ready = use_SNI_at_ctx; server_cb.ssl_ready = NULL; server_cb.on_result = verify_SNI_real_matching; test_wolfSSL_client_server(&client_cb, &server_cb); /* success case at ssl */ fprintf(stderr, "\tsuccess case at ssl\n"); client_cb.ctx_ready = NULL; client_cb.ssl_ready = use_SNI_at_ssl; client_cb.on_result = verify_SNI_real_matching; server_cb.ctx_ready = NULL; server_cb.ssl_ready = use_SNI_at_ssl; server_cb.on_result = verify_SNI_real_matching; test_wolfSSL_client_server(&client_cb, &server_cb); /* default mismatch behavior */ fprintf(stderr, "\tdefault mismatch behavior\n"); client_cb.ctx_ready = NULL; client_cb.ssl_ready = different_SNI_at_ssl; client_cb.on_result = verify_FATAL_ERROR_on_client; server_cb.ctx_ready = NULL; server_cb.ssl_ready = use_SNI_at_ssl; server_cb.on_result = verify_UNKNOWN_SNI_on_server; test_wolfSSL_client_server(&client_cb, &server_cb); /* continue on mismatch */ fprintf(stderr, "\tcontinue on mismatch\n"); client_cb.ctx_ready = NULL; client_cb.ssl_ready = different_SNI_at_ssl; client_cb.on_result = NULL; server_cb.ctx_ready = NULL; server_cb.ssl_ready = use_SNI_WITH_CONTINUE_at_ssl; server_cb.on_result = verify_SNI_no_matching; test_wolfSSL_client_server(&client_cb, &server_cb); /* fake answer on mismatch */ fprintf(stderr, "\tfake answer on mismatch\n"); client_cb.ctx_ready = NULL; client_cb.ssl_ready = different_SNI_at_ssl; client_cb.on_result = NULL; server_cb.ctx_ready = NULL; server_cb.ssl_ready = use_SNI_WITH_FAKE_ANSWER_at_ssl; server_cb.on_result = verify_SNI_fake_matching; test_wolfSSL_client_server(&client_cb, &server_cb); /* sni abort - success */ fprintf(stderr, "\tsni abort - success\n"); client_cb.ctx_ready = use_SNI_at_ctx; client_cb.ssl_ready = NULL; client_cb.on_result = NULL; server_cb.ctx_ready = use_MANDATORY_SNI_at_ctx; server_cb.ssl_ready = NULL; server_cb.on_result = verify_SNI_real_matching; test_wolfSSL_client_server(&client_cb, &server_cb); /* sni abort - abort when absent (ctx) */ fprintf(stderr, "\tsni abort - abort when absent (ctx)\n"); client_cb.ctx_ready = NULL; client_cb.ssl_ready = NULL; client_cb.on_result = verify_FATAL_ERROR_on_client; server_cb.ctx_ready = use_MANDATORY_SNI_at_ctx; server_cb.ssl_ready = NULL; server_cb.on_result = verify_SNI_ABSENT_on_server; test_wolfSSL_client_server(&client_cb, &server_cb); /* sni abort - abort when absent (ssl) */ fprintf(stderr, "\tsni abort - abort when absent (ssl)\n"); client_cb.ctx_ready = NULL; client_cb.ssl_ready = NULL; client_cb.on_result = verify_FATAL_ERROR_on_client; server_cb.ctx_ready = NULL; server_cb.ssl_ready = use_MANDATORY_SNI_at_ssl; server_cb.on_result = verify_SNI_ABSENT_on_server; test_wolfSSL_client_server(&client_cb, &server_cb); /* sni abort - success when overwritten */ fprintf(stderr, "\tsni abort - success when overwritten\n"); client_cb.ctx_ready = NULL; client_cb.ssl_ready = NULL; client_cb.on_result = NULL; server_cb.ctx_ready = use_MANDATORY_SNI_at_ctx; server_cb.ssl_ready = use_SNI_at_ssl; server_cb.on_result = verify_SNI_no_matching; test_wolfSSL_client_server(&client_cb, &server_cb); /* sni abort - success when allowing mismatches */ fprintf(stderr, "\tsni abort - success when allowing mismatches\n"); client_cb.ctx_ready = NULL; client_cb.ssl_ready = different_SNI_at_ssl; client_cb.on_result = NULL; server_cb.ctx_ready = use_PSEUDO_MANDATORY_SNI_at_ctx; server_cb.ssl_ready = NULL; server_cb.on_result = verify_SNI_fake_matching; test_wolfSSL_client_server(&client_cb, &server_cb); } res = TEST_RES_CHECK(1); #endif /* !NO_WOLFSSL_CLIENT && !NO_WOLFSSL_SERVER */ return res; } static int test_wolfSSL_SNI_GetFromBuffer(void) { EXPECT_DECLS; byte buff[] = { /* www.paypal.com */ 0x00, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x60, 0x03, 0x03, 0x5c, 0xc4, 0xb3, 0x8c, 0x87, 0xef, 0xa4, 0x09, 0xe0, 0x02, 0xab, 0x86, 0xca, 0x76, 0xf0, 0x9e, 0x01, 0x65, 0xf6, 0xa6, 0x06, 0x13, 0x1d, 0x0f, 0xa5, 0x79, 0xb0, 0xd4, 0x77, 0x22, 0xeb, 0x1a, 0x00, 0x00, 0x16, 0x00, 0x6b, 0x00, 0x67, 0x00, 0x39, 0x00, 0x33, 0x00, 0x3d, 0x00, 0x3c, 0x00, 0x35, 0x00, 0x2f, 0x00, 0x05, 0x00, 0x04, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x13, 0x00, 0x11, 0x00, 0x00, 0x0e, 0x77, 0x77, 0x77, 0x2e, 0x70, 0x61, 0x79, 0x70, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x0d, 0x00, 0x06, 0x00, 0x04, 0x04, 0x01, 0x02, 0x01 }; byte buff2[] = { /* api.textmate.org */ 0x16, 0x03, 0x01, 0x00, 0xc6, 0x01, 0x00, 0x00, 0xc2, 0x03, 0x03, 0x52, 0x8b, 0x7b, 0xca, 0x69, 0xec, 0x97, 0xd5, 0x08, 0x03, 0x50, 0xfe, 0x3b, 0x99, 0xc3, 0x20, 0xce, 0xa5, 0xf6, 0x99, 0xa5, 0x71, 0xf9, 0x57, 0x7f, 0x04, 0x38, 0xf6, 0x11, 0x0b, 0xb8, 0xd3, 0x00, 0x00, 0x5e, 0x00, 0xff, 0xc0, 0x24, 0xc0, 0x23, 0xc0, 0x0a, 0xc0, 0x09, 0xc0, 0x07, 0xc0, 0x08, 0xc0, 0x28, 0xc0, 0x27, 0xc0, 0x14, 0xc0, 0x13, 0xc0, 0x11, 0xc0, 0x12, 0xc0, 0x26, 0xc0, 0x25, 0xc0, 0x2a, 0xc0, 0x29, 0xc0, 0x05, 0xc0, 0x04, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x0f, 0xc0, 0x0e, 0xc0, 0x0c, 0xc0, 0x0d, 0x00, 0x3d, 0x00, 0x3c, 0x00, 0x2f, 0x00, 0x05, 0x00, 0x04, 0x00, 0x35, 0x00, 0x0a, 0x00, 0x67, 0x00, 0x6b, 0x00, 0x33, 0x00, 0x39, 0x00, 0x16, 0x00, 0xaf, 0x00, 0xae, 0x00, 0x8d, 0x00, 0x8c, 0x00, 0x8a, 0x00, 0x8b, 0x00, 0xb1, 0x00, 0xb0, 0x00, 0x2c, 0x00, 0x3b, 0x01, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x15, 0x00, 0x13, 0x00, 0x00, 0x10, 0x61, 0x70, 0x69, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x6d, 0x61, 0x74, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x0d, 0x00, 0x0c, 0x00, 0x0a, 0x05, 0x01, 0x04, 0x01, 0x02, 0x01, 0x04, 0x03, 0x02, 0x03 }; byte buff3[] = { /* no sni extension */ 0x16, 0x03, 0x03, 0x00, 0x4d, 0x01, 0x00, 0x00, 0x49, 0x03, 0x03, 0xea, 0xa1, 0x9f, 0x60, 0xdd, 0x52, 0x12, 0x13, 0xbd, 0x84, 0x34, 0xd5, 0x1c, 0x38, 0x25, 0xa8, 0x97, 0xd2, 0xd5, 0xc6, 0x45, 0xaf, 0x1b, 0x08, 0xe4, 0x1e, 0xbb, 0xdf, 0x9d, 0x39, 0xf0, 0x65, 0x00, 0x00, 0x16, 0x00, 0x6b, 0x00, 0x67, 0x00, 0x39, 0x00, 0x33, 0x00, 0x3d, 0x00, 0x3c, 0x00, 0x35, 0x00, 0x2f, 0x00, 0x05, 0x00, 0x04, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x06, 0x00, 0x04, 0x04, 0x01, 0x02, 0x01 }; byte buff4[] = { /* last extension has zero size */ 0x16, 0x03, 0x01, 0x00, 0xba, 0x01, 0x00, 0x00, 0xb6, 0x03, 0x03, 0x83, 0xa3, 0xe6, 0xdc, 0x16, 0xa1, 0x43, 0xe9, 0x45, 0x15, 0xbd, 0x64, 0xa9, 0xb6, 0x07, 0xb4, 0x50, 0xc6, 0xdd, 0xff, 0xc2, 0xd3, 0x0d, 0x4f, 0x36, 0xb4, 0x41, 0x51, 0x61, 0xc1, 0xa5, 0x9e, 0x00, 0x00, 0x28, 0xcc, 0x14, 0xcc, 0x13, 0xc0, 0x2b, 0xc0, 0x2f, 0x00, 0x9e, 0xc0, 0x0a, 0xc0, 0x09, 0xc0, 0x13, 0xc0, 0x14, 0xc0, 0x07, 0xc0, 0x11, 0x00, 0x33, 0x00, 0x32, 0x00, 0x39, 0x00, 0x9c, 0x00, 0x2f, 0x00, 0x35, 0x00, 0x0a, 0x00, 0x05, 0x00, 0x04, 0x01, 0x00, 0x00, 0x65, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x23, 0x00, 0x00, 0x33, 0x74, 0x00, 0x00, 0x00, 0x10, 0x00, 0x1b, 0x00, 0x19, 0x06, 0x73, 0x70, 0x64, 0x79, 0x2f, 0x33, 0x08, 0x73, 0x70, 0x64, 0x79, 0x2f, 0x33, 0x2e, 0x31, 0x08, 0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31, 0x75, 0x50, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x12, 0x00, 0x10, 0x04, 0x01, 0x05, 0x01, 0x02, 0x01, 0x04, 0x03, 0x05, 0x03, 0x02, 0x03, 0x04, 0x02, 0x02, 0x02, 0x00, 0x12, 0x00, 0x00 }; byte buff5[] = { /* SSL v2.0 client hello */ 0x00, 0x2b, 0x01, 0x03, 0x01, 0x00, 0x09, 0x00, 0x00, /* dummy bytes below, just to pass size check */ 0xb6, 0x03, 0x03, 0x83, 0xa3, 0xe6, 0xdc, 0x16, 0xa1, 0x43, 0xe9, 0x45, 0x15, 0xbd, 0x64, 0xa9, 0xb6, 0x07, 0xb4, 0x50, 0xc6, 0xdd, 0xff, 0xc2, 0xd3, 0x0d, 0x4f, 0x36, 0xb4, 0x41, 0x51, 0x61, 0xc1, 0xa5, 0x9e, 0x00, }; byte result[32] = {0}; word32 length = 32; ExpectIntEQ(0, wolfSSL_SNI_GetFromBuffer(buff4, sizeof(buff4), 0, result, &length)); ExpectIntEQ(0, wolfSSL_SNI_GetFromBuffer(buff3, sizeof(buff3), 0, result, &length)); ExpectIntEQ(0, wolfSSL_SNI_GetFromBuffer(buff2, sizeof(buff2), 1, result, &length)); ExpectIntEQ(WC_NO_ERR_TRACE(BUFFER_ERROR), wolfSSL_SNI_GetFromBuffer(buff, sizeof(buff), 0, result, &length)); buff[0] = 0x16; ExpectIntEQ(WC_NO_ERR_TRACE(BUFFER_ERROR), wolfSSL_SNI_GetFromBuffer(buff, sizeof(buff), 0, result, &length)); buff[1] = 0x03; ExpectIntEQ(WC_NO_ERR_TRACE(SNI_UNSUPPORTED), wolfSSL_SNI_GetFromBuffer(buff, sizeof(buff), 0, result, &length)); buff[2] = 0x03; ExpectIntEQ(WC_NO_ERR_TRACE(INCOMPLETE_DATA), wolfSSL_SNI_GetFromBuffer(buff, sizeof(buff), 0, result, &length)); buff[4] = 0x64; ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_SNI_GetFromBuffer(buff, sizeof(buff), 0, result, &length)); if (EXPECT_SUCCESS()) result[length] = 0; ExpectStrEQ("www.paypal.com", (const char*) result); length = 32; ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_SNI_GetFromBuffer(buff2, sizeof(buff2), 0, result, &length)); if (EXPECT_SUCCESS()) result[length] = 0; ExpectStrEQ("api.textmate.org", (const char*) result); /* SSL v2.0 tests */ ExpectIntEQ(WC_NO_ERR_TRACE(SNI_UNSUPPORTED), wolfSSL_SNI_GetFromBuffer(buff5, sizeof(buff5), 0, result, &length)); buff5[2] = 0x02; ExpectIntEQ(WC_NO_ERR_TRACE(BUFFER_ERROR), wolfSSL_SNI_GetFromBuffer(buff5, sizeof(buff5), 0, result, &length)); buff5[2] = 0x01; buff5[6] = 0x08; ExpectIntEQ(WC_NO_ERR_TRACE(BUFFER_ERROR), wolfSSL_SNI_GetFromBuffer(buff5, sizeof(buff5), 0, result, &length)); buff5[6] = 0x09; buff5[8] = 0x01; ExpectIntEQ(WC_NO_ERR_TRACE(BUFFER_ERROR), wolfSSL_SNI_GetFromBuffer(buff5, sizeof(buff5), 0, result, &length)); return EXPECT_RESULT(); } #endif /* HAVE_SNI */ #endif /* HAVE_IO_TESTS_DEPENDENCIES */ #if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SESSION_EXPORT) && \ defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) /* Dummy peer functions to satisfy the exporter/importer */ static int test_wolfSSL_dtls_export_peers_get_peer(WOLFSSL* ssl, char* ip, int* ipSz, unsigned short* port, int* fam) { (void)ssl; ip[0] = -1; *ipSz = 1; *port = 1; *fam = 2; return 1; } static int test_wolfSSL_dtls_export_peers_set_peer(WOLFSSL* ssl, char* ip, int ipSz, unsigned short port, int fam) { (void)ssl; if (ip[0] != -1 || ipSz != 1 || port != 1 || fam != 2) return 0; return 1; } static int test_wolfSSL_dtls_export_peers_on_handshake(WOLFSSL_CTX **ctx, WOLFSSL **ssl) { EXPECT_DECLS; unsigned char* sessionBuf = NULL; unsigned int sessionSz = 0; void* ioWriteCtx = wolfSSL_GetIOWriteCtx(*ssl); void* ioReadCtx = wolfSSL_GetIOReadCtx(*ssl); wolfSSL_CTX_SetIOGetPeer(*ctx, test_wolfSSL_dtls_export_peers_get_peer); wolfSSL_CTX_SetIOSetPeer(*ctx, test_wolfSSL_dtls_export_peers_set_peer); ExpectIntGE(wolfSSL_dtls_export(*ssl, NULL, &sessionSz), 0); ExpectNotNull(sessionBuf = (unsigned char*)XMALLOC(sessionSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER)); ExpectIntGE(wolfSSL_dtls_export(*ssl, sessionBuf, &sessionSz), 0); wolfSSL_free(*ssl); *ssl = NULL; ExpectNotNull(*ssl = wolfSSL_new(*ctx)); ExpectIntGE(wolfSSL_dtls_import(*ssl, sessionBuf, sessionSz), 0); wolfSSL_SetIOWriteCtx(*ssl, ioWriteCtx); wolfSSL_SetIOReadCtx(*ssl, ioReadCtx); XFREE(sessionBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); return EXPECT_RESULT(); } #endif static int test_wolfSSL_dtls_export_peers(void) { EXPECT_DECLS; #if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SESSION_EXPORT) && \ defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) test_ssl_cbf client_cbf; test_ssl_cbf server_cbf; size_t i, j; struct test_params { method_provider client_meth; method_provider server_meth; const char* dtls_version; } params[] = { #ifndef NO_OLD_TLS {wolfDTLSv1_client_method, wolfDTLSv1_server_method, "1.0"}, #endif {wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method, "1.2"}, /* TODO DTLS 1.3 exporting not supported #ifdef WOLFSSL_DTLS13 {wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method, "1.3"}, #endif */ }; for (i = 0; i < sizeof(params)/sizeof(*params); i++) { for (j = 0; j <= 3; j++) { XMEMSET(&client_cbf, 0, sizeof(client_cbf)); XMEMSET(&server_cbf, 0, sizeof(server_cbf)); printf("\n\tTesting DTLS %s connection;", params[i].dtls_version); client_cbf.method = params[i].client_meth; server_cbf.method = params[i].server_meth; if (j & 0x1) { client_cbf.on_handshake = test_wolfSSL_dtls_export_peers_on_handshake; printf(" With client export;"); } if (j & 0x2) { server_cbf.on_handshake = test_wolfSSL_dtls_export_peers_on_handshake; printf(" With server export;"); } printf("\n"); ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&client_cbf, &server_cbf, NULL), TEST_SUCCESS); if (!EXPECT_SUCCESS()) break; } } #endif return EXPECT_RESULT(); } /* Test that ImportKeyState correctly skips extra window words when importing * state from a peer compiled with a larger WOLFSSL_DTLS_WINDOW_WORDS. */ static int test_wolfSSL_dtls_import_state_extra_window_words(void) { EXPECT_DECLS; #if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SESSION_EXPORT) WOLFSSL_CTX* ctx = NULL; WOLFSSL* ssl = NULL; unsigned int stateSz = 0; byte* state = NULL; byte* modified = NULL; unsigned int modifiedSz; word16 origKeyLen; word16 origTotalLen; /* Offset from start of key state data to the first wordCount field. * Layout: 4 sequence numbers (16 bytes) + DTLS-specific fields (42 bytes) + * encryptSz(4) + padSz(4) + encryptionOn(1) + decryptedCur(1) = 68 */ const int keyStateWindowOffset = 68; /* Buffer header: 2 proto + 2 total_len + 2 key_len = 6 */ const int headerSz = 6; int idx, modIdx; int extraPerWindow = 2 * (int)sizeof(word32); /* 8 bytes extra per window */ int totalExtra = extraPerWindow * 2; /* 16 bytes extra total */ /* Create DTLS context and SSL object */ ExpectNotNull(ctx = wolfSSL_CTX_new(wolfDTLSv1_2_server_method())); ExpectNotNull(ssl = wolfSSL_new(ctx)); /* Get required buffer size and export state-only */ ExpectIntEQ(wolfSSL_dtls_export_state_only(ssl, NULL, &stateSz), 0); ExpectIntGT((int)stateSz, 0); state = (byte*)XMALLOC(stateSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); ExpectNotNull(state); ExpectIntGT(wolfSSL_dtls_export_state_only(ssl, state, &stateSz), 0); /* Build a modified buffer that simulates a peer with * WOLFSSL_DTLS_WINDOW_WORDS = WOLFSSL_DTLS_WINDOW_WORDS + 2. * Each window section gets 2 extra word32 values (8 bytes). * Two windows => 16 extra bytes total. */ modifiedSz = stateSz + totalExtra; modified = (byte*)XMALLOC(modifiedSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); ExpectNotNull(modified); if (EXPECT_SUCCESS()) { int windowWords = WOLFSSL_DTLS_WINDOW_WORDS; int windowDataSz = windowWords * (int)sizeof(word32); XMEMSET(modified, 0, modifiedSz); /* Copy protocol/version bytes (first 2 bytes) */ XMEMCPY(modified, state, 2); /* Read original total length and key state length */ ato16(state + 2, &origTotalLen); ato16(state + 4, &origKeyLen); /* Write updated total length and key state length */ c16toa((word16)(origTotalLen + totalExtra), modified + 2); c16toa((word16)(origKeyLen + totalExtra), modified + 4); /* Copy key state data up to first window section */ idx = headerSz; modIdx = headerSz; XMEMCPY(modified + modIdx, state + idx, keyStateWindowOffset); idx += keyStateWindowOffset; modIdx += keyStateWindowOffset; /* First window: write increased wordCount */ c16toa((word16)(windowWords + 2), modified + modIdx); idx += OPAQUE16_LEN; modIdx += OPAQUE16_LEN; /* Copy original window data */ XMEMCPY(modified + modIdx, state + idx, windowDataSz); idx += windowDataSz; modIdx += windowDataSz; /* Insert 2 extra word32 padding values */ XMEMSET(modified + modIdx, 0, extraPerWindow); modIdx += extraPerWindow; /* Second window (prevWindow): same transformation */ c16toa((word16)(windowWords + 2), modified + modIdx); idx += OPAQUE16_LEN; modIdx += OPAQUE16_LEN; XMEMCPY(modified + modIdx, state + idx, windowDataSz); idx += windowDataSz; modIdx += windowDataSz; XMEMSET(modified + modIdx, 0, extraPerWindow); modIdx += extraPerWindow; /* Copy remainder of key state (after both windows) */ XMEMCPY(modified + modIdx, state + idx, stateSz - idx); } /* Import the modified state - should succeed with the fix */ wolfSSL_free(ssl); ssl = NULL; ExpectNotNull(ssl = wolfSSL_new(ctx)); ExpectIntGT(wolfSSL_dtls_import(ssl, modified, modifiedSz), 0); XFREE(state, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(modified, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } static int test_wolfSSL_UseTrustedCA(void) { EXPECT_DECLS; #if defined(HAVE_TRUSTED_CA) && !defined(NO_CERTS) && !defined(NO_FILESYSTEM) \ && !defined(NO_RSA) #if !defined(NO_TLS) && \ (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) WOLFSSL_CTX *ctx = NULL; WOLFSSL *ssl = NULL; byte id[20]; #ifndef NO_WOLFSSL_SERVER ExpectNotNull((ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()))); ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile, WOLFSSL_FILETYPE_PEM)); ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, WOLFSSL_FILETYPE_PEM)); #else ExpectNotNull((ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()))); #endif ExpectNotNull((ssl = wolfSSL_new(ctx))); XMEMSET(id, 0, sizeof(id)); /* error cases */ ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_UseTrustedCA(NULL, 0, NULL, 0)); ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_UseTrustedCA(ssl, WOLFSSL_TRUSTED_CA_CERT_SHA1+1, NULL, 0)); ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_UseTrustedCA(ssl, WOLFSSL_TRUSTED_CA_CERT_SHA1, NULL, 0)); ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_UseTrustedCA(ssl, WOLFSSL_TRUSTED_CA_CERT_SHA1, id, 5)); #ifdef NO_SHA ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_UseTrustedCA(ssl, WOLFSSL_TRUSTED_CA_KEY_SHA1, id, sizeof(id))); #endif ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_UseTrustedCA(ssl, WOLFSSL_TRUSTED_CA_X509_NAME, id, 0)); /* success cases */ ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseTrustedCA(ssl, WOLFSSL_TRUSTED_CA_PRE_AGREED, NULL, 0)); #ifndef NO_SHA ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseTrustedCA(ssl, WOLFSSL_TRUSTED_CA_KEY_SHA1, id, sizeof(id))); #endif ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseTrustedCA(ssl, WOLFSSL_TRUSTED_CA_X509_NAME, id, 5)); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #endif /* !NO_TLS && (!NO_WOLFSSL_CLIENT || !NO_WOLFSSL_SERVER) */ #endif /* HAVE_TRUSTED_CA */ return EXPECT_RESULT(); } static int test_wolfSSL_UseMaxFragment(void) { EXPECT_DECLS; #if defined(HAVE_MAX_FRAGMENT) && !defined(NO_CERTS) && \ !defined(NO_FILESYSTEM) && !defined(NO_RSA) && !defined(NO_WOLFSSL_CLIENT) #if !defined(NO_TLS) #ifndef NO_WOLFSSL_SERVER WOLFSSL_CTX* ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()); #else WOLFSSL_CTX* ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); #endif WOLFSSL *ssl = NULL; #ifdef OPENSSL_EXTRA int (*UseMaxFragment)(SSL *s, unsigned char mode); int (*CTX_UseMaxFragment)(SSL_CTX *c, unsigned char mode); #else int (*UseMaxFragment)(WOLFSSL *s, unsigned char mode); int (*CTX_UseMaxFragment)(WOLFSSL_CTX *c, unsigned char mode); #endif #ifndef NO_WOLFSSL_SERVER ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile, WOLFSSL_FILETYPE_PEM)); ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, WOLFSSL_FILETYPE_PEM)); #endif ExpectNotNull(ctx); ExpectNotNull(ssl = wolfSSL_new(ctx)); #ifdef OPENSSL_EXTRA CTX_UseMaxFragment = SSL_CTX_set_tlsext_max_fragment_length; UseMaxFragment = SSL_set_tlsext_max_fragment_length; #else UseMaxFragment = wolfSSL_UseMaxFragment; CTX_UseMaxFragment = wolfSSL_CTX_UseMaxFragment; #endif /* error cases */ ExpectIntNE(WOLFSSL_SUCCESS, CTX_UseMaxFragment(NULL, WOLFSSL_MFL_2_9)); ExpectIntNE(WOLFSSL_SUCCESS, UseMaxFragment( NULL, WOLFSSL_MFL_2_9)); ExpectIntNE(WOLFSSL_SUCCESS, CTX_UseMaxFragment(ctx, WOLFSSL_MFL_MIN-1)); ExpectIntNE(WOLFSSL_SUCCESS, CTX_UseMaxFragment(ctx, WOLFSSL_MFL_MAX+1)); ExpectIntNE(WOLFSSL_SUCCESS, UseMaxFragment(ssl, WOLFSSL_MFL_MIN-1)); ExpectIntNE(WOLFSSL_SUCCESS, UseMaxFragment(ssl, WOLFSSL_MFL_MAX+1)); /* success case */ #ifdef OPENSSL_EXTRA ExpectIntEQ(WC_NO_ERR_TRACE(BAD_FUNC_ARG), CTX_UseMaxFragment(ctx, WOLFSSL_MFL_2_8)); #else ExpectIntEQ(WOLFSSL_SUCCESS, CTX_UseMaxFragment(ctx, WOLFSSL_MFL_2_8)); #endif ExpectIntEQ(WOLFSSL_SUCCESS, CTX_UseMaxFragment(ctx, WOLFSSL_MFL_2_9)); ExpectIntEQ(WOLFSSL_SUCCESS, CTX_UseMaxFragment(ctx, WOLFSSL_MFL_2_10)); ExpectIntEQ(WOLFSSL_SUCCESS, CTX_UseMaxFragment(ctx, WOLFSSL_MFL_2_11)); ExpectIntEQ(WOLFSSL_SUCCESS, CTX_UseMaxFragment(ctx, WOLFSSL_MFL_2_12)); #ifdef OPENSSL_EXTRA ExpectIntEQ(WC_NO_ERR_TRACE(BAD_FUNC_ARG), CTX_UseMaxFragment(ctx, WOLFSSL_MFL_2_13)); ExpectIntEQ(WC_NO_ERR_TRACE(BAD_FUNC_ARG), UseMaxFragment( ssl, WOLFSSL_MFL_2_8)); #else ExpectIntEQ(WOLFSSL_SUCCESS, CTX_UseMaxFragment(ctx, WOLFSSL_MFL_2_13)); ExpectIntEQ(WOLFSSL_SUCCESS, UseMaxFragment( ssl, WOLFSSL_MFL_2_8)); #endif ExpectIntEQ(WOLFSSL_SUCCESS, UseMaxFragment( ssl, WOLFSSL_MFL_2_9)); ExpectIntEQ(WOLFSSL_SUCCESS, UseMaxFragment( ssl, WOLFSSL_MFL_2_10)); ExpectIntEQ(WOLFSSL_SUCCESS, UseMaxFragment( ssl, WOLFSSL_MFL_2_11)); ExpectIntEQ(WOLFSSL_SUCCESS, UseMaxFragment( ssl, WOLFSSL_MFL_2_12)); #ifdef OPENSSL_EXTRA ExpectIntEQ(WC_NO_ERR_TRACE(BAD_FUNC_ARG), UseMaxFragment( ssl, WOLFSSL_MFL_2_13)); #else ExpectIntEQ(WOLFSSL_SUCCESS, UseMaxFragment( ssl, WOLFSSL_MFL_2_13)); #endif wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #if defined(OPENSSL_EXTRA) && defined(HAVE_MAX_FRAGMENT) && \ defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) /* check negotiated max fragment size */ { WOLFSSL *ssl_c = NULL; WOLFSSL *ssl_s = NULL; struct test_memio_ctx test_ctx; WOLFSSL_CTX *ctx_c = NULL; WOLFSSL_CTX *ctx_s = NULL; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, wolfTLSv1_2_client_method, wolfTLSv1_2_server_method), 0); ExpectIntEQ(wolfSSL_UseMaxFragment(ssl_c, WOLFSSL_MFL_2_8), WOLFSSL_SUCCESS); ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); #ifndef NO_SESSION_CACHE ExpectIntEQ(SSL_SESSION_get_max_fragment_length( wolfSSL_get_session(ssl_c)), WOLFSSL_MFL_2_8); #endif wolfSSL_free(ssl_c); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_c); wolfSSL_CTX_free(ctx_s); } #endif #endif /* !NO_TLS && (!NO_WOLFSSL_CLIENT || !NO_WOLFSSL_SERVER) */ #endif return EXPECT_RESULT(); } static int test_wolfSSL_UseTruncatedHMAC(void) { EXPECT_DECLS; #if defined(HAVE_TRUNCATED_HMAC) && !defined(NO_CERTS) && !defined(NO_TLS) && \ !defined(NO_FILESYSTEM) && !defined(NO_RSA) #if !defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER) #ifndef NO_WOLFSSL_SERVER WOLFSSL_CTX* ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()); #else WOLFSSL_CTX* ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); #endif WOLFSSL *ssl = NULL; ExpectNotNull(ctx); #ifndef NO_WOLFSSL_SERVER ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile, WOLFSSL_FILETYPE_PEM)); ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, WOLFSSL_FILETYPE_PEM)); #endif ExpectNotNull(ssl = wolfSSL_new(ctx)); #ifndef NO_WOLFSSL_CLIENT /* error cases */ ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_UseTruncatedHMAC(NULL)); ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_UseTruncatedHMAC(NULL)); /* success case */ ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_UseTruncatedHMAC(ctx)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseTruncatedHMAC(ssl)); #endif wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #endif /* !NO_WOLFSSL_CLIENT || !NO_WOLFSSL_SERVER */ #endif return EXPECT_RESULT(); } static int test_wolfSSL_UseSupportedCurve(void) { EXPECT_DECLS; #if defined(HAVE_SUPPORTED_CURVES) && !defined(NO_WOLFSSL_CLIENT) && \ !defined(NO_TLS) WOLFSSL_CTX* ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); WOLFSSL *ssl = wolfSSL_new(ctx); ExpectNotNull(ctx); ExpectNotNull(ssl); /* error cases */ ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_UseSupportedCurve(NULL, WOLFSSL_ECC_SECP256R1)); ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_UseSupportedCurve(ctx, 0)); ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_UseSupportedCurve(NULL, WOLFSSL_ECC_SECP256R1)); ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_UseSupportedCurve(ssl, 0)); /* success case */ ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_UseSupportedCurve(ctx, WOLFSSL_ECC_SECP256R1)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseSupportedCurve(ssl, WOLFSSL_ECC_SECP256R1)); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } #if defined(HAVE_ALPN) && defined(HAVE_IO_TESTS_DEPENDENCIES) static void verify_ALPN_FATAL_ERROR_on_client(WOLFSSL* ssl) { AssertIntEQ(WC_NO_ERR_TRACE(UNKNOWN_ALPN_PROTOCOL_NAME_E), wolfSSL_get_error(ssl, 0)); } static void use_ALPN_all(WOLFSSL* ssl) { /* http/1.1,spdy/1,spdy/2,spdy/3 */ char alpn_list[] = {0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31, 0x2c, 0x73, 0x70, 0x64, 0x79, 0x2f, 0x31, 0x2c, 0x73, 0x70, 0x64, 0x79, 0x2f, 0x32, 0x2c, 0x73, 0x70, 0x64, 0x79, 0x2f, 0x33}; AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseALPN(ssl, alpn_list, sizeof(alpn_list), WOLFSSL_ALPN_FAILED_ON_MISMATCH)); } static void use_ALPN_all_continue(WOLFSSL* ssl) { /* http/1.1,spdy/1,spdy/2,spdy/3 */ char alpn_list[] = {0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31, 0x2c, 0x73, 0x70, 0x64, 0x79, 0x2f, 0x31, 0x2c, 0x73, 0x70, 0x64, 0x79, 0x2f, 0x32, 0x2c, 0x73, 0x70, 0x64, 0x79, 0x2f, 0x33}; AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseALPN(ssl, alpn_list, sizeof(alpn_list), WOLFSSL_ALPN_CONTINUE_ON_MISMATCH)); } static void use_ALPN_one(WOLFSSL* ssl) { /* spdy/2 */ char proto[] = {0x73, 0x70, 0x64, 0x79, 0x2f, 0x32}; AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseALPN(ssl, proto, sizeof(proto), WOLFSSL_ALPN_FAILED_ON_MISMATCH)); } static void use_ALPN_unknown(WOLFSSL* ssl) { /* http/2.0 */ char proto[] = {0x68, 0x74, 0x74, 0x70, 0x2f, 0x32, 0x2e, 0x30}; AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseALPN(ssl, proto, sizeof(proto), WOLFSSL_ALPN_FAILED_ON_MISMATCH)); } static void use_ALPN_unknown_continue(WOLFSSL* ssl) { /* http/2.0 */ char proto[] = {0x68, 0x74, 0x74, 0x70, 0x2f, 0x32, 0x2e, 0x30}; AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseALPN(ssl, proto, sizeof(proto), WOLFSSL_ALPN_CONTINUE_ON_MISMATCH)); } static void verify_ALPN_not_matching_spdy3(WOLFSSL* ssl) { /* spdy/3 */ char nego_proto[] = {0x73, 0x70, 0x64, 0x79, 0x2f, 0x33}; char *proto = NULL; word16 protoSz = 0; AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_ALPN_GetProtocol(ssl, &proto, &protoSz)); /* check value */ AssertIntNE(1, sizeof(nego_proto) == protoSz); if (proto) { AssertIntNE(0, XMEMCMP(nego_proto, proto, sizeof(nego_proto))); } } static void verify_ALPN_not_matching_continue(WOLFSSL* ssl) { char *proto = NULL; word16 protoSz = 0; AssertIntEQ(WC_NO_ERR_TRACE(WOLFSSL_ALPN_NOT_FOUND), wolfSSL_ALPN_GetProtocol(ssl, &proto, &protoSz)); /* check value */ AssertIntEQ(1, (0 == protoSz)); AssertIntEQ(1, (NULL == proto)); } static void verify_ALPN_matching_http1(WOLFSSL* ssl) { /* http/1.1 */ char nego_proto[] = {0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31}; char *proto; word16 protoSz = 0; AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_ALPN_GetProtocol(ssl, &proto, &protoSz)); /* check value */ AssertIntEQ(1, sizeof(nego_proto) == protoSz); AssertIntEQ(0, XMEMCMP(nego_proto, proto, protoSz)); } static void verify_ALPN_matching_spdy2(WOLFSSL* ssl) { /* spdy/2 */ char nego_proto[] = {0x73, 0x70, 0x64, 0x79, 0x2f, 0x32}; char *proto; word16 protoSz = 0; AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_ALPN_GetProtocol(ssl, &proto, &protoSz)); /* check value */ AssertIntEQ(1, sizeof(nego_proto) == protoSz); AssertIntEQ(0, XMEMCMP(nego_proto, proto, protoSz)); } static void verify_ALPN_client_list(WOLFSSL* ssl) { /* http/1.1,spdy/1,spdy/2,spdy/3 */ char alpn_list[] = {0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31, 0x2c, 0x73, 0x70, 0x64, 0x79, 0x2f, 0x31, 0x2c, 0x73, 0x70, 0x64, 0x79, 0x2f, 0x32, 0x2c, 0x73, 0x70, 0x64, 0x79, 0x2f, 0x33}; char *clist = NULL; word16 clistSz = 0; AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_ALPN_GetPeerProtocol(ssl, &clist, &clistSz)); /* check value */ AssertIntEQ(1, sizeof(alpn_list) == clistSz); AssertIntEQ(0, XMEMCMP(alpn_list, clist, clistSz)); AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_ALPN_FreePeerProtocol(ssl, &clist)); } #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || \ defined(WOLFSSL_HAPROXY) || defined(HAVE_LIGHTY) /* ALPN select callback, success with spdy/2 */ static int select_ALPN_spdy2(WOLFSSL *ssl, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg) { /* spdy/2 */ const char proto[] = {0x73, 0x70, 0x64, 0x79, 0x2f, 0x32}; (void)ssl; (void)arg; /* adding +1 since LEN byte comes first */ if (inlen < sizeof(proto) + 1) { return SSL_TLSEXT_ERR_ALERT_FATAL; } if (XMEMCMP(in + 1, proto, sizeof(proto)) == 0) { *out = in + 1; *outlen = (unsigned char)sizeof(proto); return SSL_TLSEXT_ERR_OK; } return SSL_TLSEXT_ERR_ALERT_FATAL; } /* ALPN select callback, force failure */ static int select_ALPN_failure(WOLFSSL *ssl, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg) { (void)ssl; (void)out; (void)outlen; (void)in; (void)inlen; (void)arg; return SSL_TLSEXT_ERR_ALERT_FATAL; } static void use_ALPN_spdy2_callback(WOLFSSL* ssl) { wolfSSL_set_alpn_select_cb(ssl, select_ALPN_spdy2, NULL); } static void use_ALPN_failure_callback(WOLFSSL* ssl) { wolfSSL_set_alpn_select_cb(ssl, select_ALPN_failure, NULL); } #endif /* OPENSSL_ALL | NGINX | HAPROXY | LIGHTY | QUIC */ static int test_wolfSSL_UseALPN_connection(void) { int res = TEST_SKIPPED; #if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) callback_functions client_cb; callback_functions server_cb; XMEMSET(&client_cb, 0, sizeof(callback_functions)); XMEMSET(&server_cb, 0, sizeof(callback_functions)); client_cb.method = wolfSSLv23_client_method; server_cb.method = wolfSSLv23_server_method; client_cb.devId = testDevId; server_cb.devId = testDevId; /* success case same list */ client_cb.ctx_ready = NULL; client_cb.ssl_ready = use_ALPN_all; client_cb.on_result = NULL; server_cb.ctx_ready = NULL; server_cb.ssl_ready = use_ALPN_all; server_cb.on_result = verify_ALPN_matching_http1; test_wolfSSL_client_server(&client_cb, &server_cb); /* success case only one for server */ client_cb.ctx_ready = NULL; client_cb.ssl_ready = use_ALPN_all; client_cb.on_result = NULL; server_cb.ctx_ready = NULL; server_cb.ssl_ready = use_ALPN_one; server_cb.on_result = verify_ALPN_matching_spdy2; test_wolfSSL_client_server(&client_cb, &server_cb); /* success case only one for client */ client_cb.ctx_ready = NULL; client_cb.ssl_ready = use_ALPN_one; client_cb.on_result = NULL; server_cb.ctx_ready = NULL; server_cb.ssl_ready = use_ALPN_all; server_cb.on_result = verify_ALPN_matching_spdy2; test_wolfSSL_client_server(&client_cb, &server_cb); /* success case none for client */ client_cb.ctx_ready = NULL; client_cb.ssl_ready = NULL; client_cb.on_result = NULL; server_cb.ctx_ready = NULL; server_cb.ssl_ready = use_ALPN_all; server_cb.on_result = NULL; test_wolfSSL_client_server(&client_cb, &server_cb); /* success case mismatch behavior but option 'continue' set */ client_cb.ctx_ready = NULL; client_cb.ssl_ready = use_ALPN_all_continue; client_cb.on_result = verify_ALPN_not_matching_continue; server_cb.ctx_ready = NULL; server_cb.ssl_ready = use_ALPN_unknown_continue; server_cb.on_result = NULL; test_wolfSSL_client_server(&client_cb, &server_cb); /* success case read protocol send by client */ client_cb.ctx_ready = NULL; client_cb.ssl_ready = use_ALPN_all; client_cb.on_result = NULL; server_cb.ctx_ready = NULL; server_cb.ssl_ready = use_ALPN_one; server_cb.on_result = verify_ALPN_client_list; test_wolfSSL_client_server(&client_cb, &server_cb); /* mismatch behavior with same list * the first and only this one must be taken */ client_cb.ctx_ready = NULL; client_cb.ssl_ready = use_ALPN_all; client_cb.on_result = NULL; server_cb.ctx_ready = NULL; server_cb.ssl_ready = use_ALPN_all; server_cb.on_result = verify_ALPN_not_matching_spdy3; test_wolfSSL_client_server(&client_cb, &server_cb); /* default mismatch behavior */ client_cb.ctx_ready = NULL; client_cb.ssl_ready = use_ALPN_all; client_cb.on_result = NULL; server_cb.ctx_ready = NULL; server_cb.ssl_ready = use_ALPN_unknown; server_cb.on_result = verify_ALPN_FATAL_ERROR_on_client; test_wolfSSL_client_server(&client_cb, &server_cb); #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || \ defined(WOLFSSL_HAPROXY) || defined(HAVE_LIGHTY) /* WOLFSSL-level ALPN select callback tests */ /* Callback: success (one protocol, spdy/2) */ client_cb.ctx_ready = NULL; client_cb.ssl_ready = use_ALPN_one; client_cb.on_result = verify_ALPN_matching_spdy2; server_cb.ctx_ready = NULL; server_cb.ssl_ready = use_ALPN_spdy2_callback; server_cb.on_result = verify_ALPN_matching_spdy2; test_wolfSSL_client_server(&client_cb, &server_cb); /* Callback: failure (one client protocol, spdy/2) */ client_cb.ctx_ready = NULL; client_cb.ssl_ready = use_ALPN_one; client_cb.on_result = NULL; server_cb.ctx_ready = NULL; server_cb.ssl_ready = use_ALPN_failure_callback; server_cb.on_result = verify_ALPN_FATAL_ERROR_on_client; test_wolfSSL_client_server(&client_cb, &server_cb); #endif /* OPENSSL_ALL | NGINX | HAPROXY | LIGHTY */ res = TEST_RES_CHECK(1); #endif /* !NO_WOLFSSL_CLIENT && !NO_WOLFSSL_SERVER */ return res; } static int test_wolfSSL_UseALPN_params(void) { EXPECT_DECLS; #ifndef NO_WOLFSSL_CLIENT /* "http/1.1" */ char http1[] = {0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31}; /* "spdy/1" */ char spdy1[] = {0x73, 0x70, 0x64, 0x79, 0x2f, 0x31}; /* "spdy/2" */ char spdy2[] = {0x73, 0x70, 0x64, 0x79, 0x2f, 0x32}; /* "spdy/3" */ char spdy3[] = {0x73, 0x70, 0x64, 0x79, 0x2f, 0x33}; char buff[256]; word32 idx; WOLFSSL_CTX *ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); WOLFSSL *ssl = wolfSSL_new(ctx); ExpectNotNull(ctx); ExpectNotNull(ssl); /* error cases */ ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_UseALPN(NULL, http1, sizeof(http1), WOLFSSL_ALPN_FAILED_ON_MISMATCH)); ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_UseALPN(ssl, NULL, 0, WOLFSSL_ALPN_FAILED_ON_MISMATCH)); /* success case */ /* http1 only */ ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseALPN(ssl, http1, sizeof(http1), WOLFSSL_ALPN_FAILED_ON_MISMATCH)); /* http1, spdy1 */ XMEMCPY(buff, http1, sizeof(http1)); idx = sizeof(http1); buff[idx++] = ','; XMEMCPY(buff+idx, spdy1, sizeof(spdy1)); idx += sizeof(spdy1); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseALPN(ssl, buff, idx, WOLFSSL_ALPN_FAILED_ON_MISMATCH)); /* http1, spdy2, spdy1 */ XMEMCPY(buff, http1, sizeof(http1)); idx = sizeof(http1); buff[idx++] = ','; XMEMCPY(buff+idx, spdy2, sizeof(spdy2)); idx += sizeof(spdy2); buff[idx++] = ','; XMEMCPY(buff+idx, spdy1, sizeof(spdy1)); idx += sizeof(spdy1); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseALPN(ssl, buff, idx, WOLFSSL_ALPN_FAILED_ON_MISMATCH)); /* spdy3, http1, spdy2, spdy1 */ XMEMCPY(buff, spdy3, sizeof(spdy3)); idx = sizeof(spdy3); buff[idx++] = ','; XMEMCPY(buff+idx, http1, sizeof(http1)); idx += sizeof(http1); buff[idx++] = ','; XMEMCPY(buff+idx, spdy2, sizeof(spdy2)); idx += sizeof(spdy2); buff[idx++] = ','; XMEMCPY(buff+idx, spdy1, sizeof(spdy1)); idx += sizeof(spdy1); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseALPN(ssl, buff, idx, WOLFSSL_ALPN_CONTINUE_ON_MISMATCH)); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } #endif /* HAVE_ALPN */ #ifdef HAVE_ALPN_PROTOS_SUPPORT static void CTX_set_alpn_protos(SSL_CTX *ctx) { unsigned char p[] = { 8, 'h', 't', 't', 'p', '/', '1', '.', '1', 6, 's', 'p', 'd', 'y', '/', '2', 6, 's', 'p', 'd', 'y', '/', '1', }; unsigned char p_len = sizeof(p); int ret; ret = SSL_CTX_set_alpn_protos(ctx, p, p_len); #ifdef WOLFSSL_ERROR_CODE_OPENSSL AssertIntEQ(ret, 0); #else AssertIntEQ(ret, SSL_SUCCESS); #endif } static void set_alpn_protos(SSL* ssl) { unsigned char p[] = { 6, 's', 'p', 'd', 'y', '/', '3', 8, 'h', 't', 't', 'p', '/', '1', '.', '1', 6, 's', 'p', 'd', 'y', '/', '2', 6, 's', 'p', 'd', 'y', '/', '1', }; unsigned char p_len = sizeof(p); int ret; ret = SSL_set_alpn_protos(ssl, p, p_len); #ifdef WOLFSSL_ERROR_CODE_OPENSSL AssertIntEQ(ret, 0); #else AssertIntEQ(ret, SSL_SUCCESS); #endif } static void verify_alpn_matching_spdy3(WOLFSSL* ssl) { /* "spdy/3" */ char nego_proto[] = {0x73, 0x70, 0x64, 0x79, 0x2f, 0x33}; const unsigned char *proto; unsigned int protoSz = 0; SSL_get0_alpn_selected(ssl, &proto, &protoSz); /* check value */ AssertIntEQ(1, sizeof(nego_proto) == protoSz); AssertIntEQ(0, XMEMCMP(nego_proto, proto, protoSz)); } static void verify_alpn_matching_http1(WOLFSSL* ssl) { /* "http/1.1" */ char nego_proto[] = {0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31}; const unsigned char *proto; unsigned int protoSz = 0; SSL_get0_alpn_selected(ssl, &proto, &protoSz); /* check value */ AssertIntEQ(1, sizeof(nego_proto) == protoSz); AssertIntEQ(0, XMEMCMP(nego_proto, proto, protoSz)); } static int test_wolfSSL_set_alpn_protos(void) { int res = TEST_SKIPPED; #if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) callback_functions client_cb; callback_functions server_cb; XMEMSET(&client_cb, 0, sizeof(callback_functions)); XMEMSET(&server_cb, 0, sizeof(callback_functions)); client_cb.method = wolfSSLv23_client_method; server_cb.method = wolfSSLv23_server_method; client_cb.devId = testDevId; server_cb.devId = testDevId; /* use CTX_alpn_protos */ client_cb.ctx_ready = CTX_set_alpn_protos; client_cb.ssl_ready = NULL; client_cb.on_result = NULL; server_cb.ctx_ready = CTX_set_alpn_protos; server_cb.ssl_ready = NULL; server_cb.on_result = verify_alpn_matching_http1; test_wolfSSL_client_server(&client_cb, &server_cb); /* use set_alpn_protos */ client_cb.ctx_ready = NULL; client_cb.ssl_ready = set_alpn_protos; client_cb.on_result = NULL; server_cb.ctx_ready = NULL; server_cb.ssl_ready = set_alpn_protos; server_cb.on_result = verify_alpn_matching_spdy3; test_wolfSSL_client_server(&client_cb, &server_cb); res = TEST_SUCCESS; #endif /* !NO_WOLFSSL_CLIENT && !NO_WOLFSSL_SERVER */ return res; } static int test_wolfSSL_select_next_proto(void) { EXPECT_DECLS; unsigned char *out = NULL; unsigned char outLen = 0; int ret; /* Wire format: length-prefixed protocol names */ unsigned char serverList[] = { 8, 'h','t','t','p','/','1','.','1', 6, 's','p','d','y','/','2' }; unsigned int serverLen = sizeof(serverList); unsigned char clientList[] = { 6, 's','p','d','y','/','2' }; unsigned int clientLen = sizeof(clientList); unsigned char clientListHttp[] = { 8, 'h','t','t','p','/','1','.','1' }; unsigned int clientListHttpLen = sizeof(clientListHttp); unsigned char clientListNoMatch[] = { 6, 's','p','d','y','/','3' }; unsigned int clientListNoMatchLen = sizeof(clientListNoMatch); /* Test 1: NULL parameters return UNSUPPORTED */ ExpectIntEQ(wolfSSL_select_next_proto(NULL, &outLen, serverList, serverLen, clientList, clientLen), WOLFSSL_NPN_UNSUPPORTED); ExpectIntEQ(wolfSSL_select_next_proto(&out, NULL, serverList, serverLen, clientList, clientLen), WOLFSSL_NPN_UNSUPPORTED); ExpectIntEQ(wolfSSL_select_next_proto(&out, &outLen, NULL, serverLen, clientList, clientLen), WOLFSSL_NPN_UNSUPPORTED); ExpectIntEQ(wolfSSL_select_next_proto(&out, &outLen, serverList, serverLen, NULL, clientLen), WOLFSSL_NPN_UNSUPPORTED); /* Test 2: Normal match - client wants "spdy/2", server offers it */ out = NULL; outLen = 0; ret = wolfSSL_select_next_proto(&out, &outLen, serverList, serverLen, clientList, clientLen); ExpectIntEQ(ret, WOLFSSL_NPN_NEGOTIATED); ExpectIntEQ(outLen, 6); ExpectNotNull(out); ExpectIntEQ(XMEMCMP(out, "spdy/2", 6), 0); /* Test 3: No overlap - server offers "http/1.1,spdy/2", client wants * "spdy/3". Falls back to first client protocol. */ out = NULL; outLen = 0; ret = wolfSSL_select_next_proto(&out, &outLen, serverList, serverLen, clientListNoMatch, clientListNoMatchLen); ExpectIntEQ(ret, WOLFSSL_NPN_NO_OVERLAP); ExpectIntEQ(outLen, 6); ExpectNotNull(out); ExpectIntEQ(XMEMCMP(out, "spdy/3", 6), 0); /* Test 4: Malformed server list - length byte overruns buffer. * Must NOT crash (heap over-read). */ { unsigned char malformedServer[] = { 200, 'h','t','t','p' }; out = NULL; outLen = 0; ret = wolfSSL_select_next_proto(&out, &outLen, malformedServer, sizeof(malformedServer), clientList, clientLen); ExpectIntEQ(ret, WOLFSSL_NPN_NO_OVERLAP); } /* Test 5: Malformed client list - length byte overruns buffer. * Must NOT crash. */ { unsigned char malformedClient[] = { 200, 's','p','d','y' }; out = NULL; outLen = 0; ret = wolfSSL_select_next_proto(&out, &outLen, serverList, serverLen, malformedClient, sizeof(malformedClient)); ExpectIntEQ(ret, WOLFSSL_NPN_NO_OVERLAP); } /* Test 6: Zero-length entry in server list - must NOT infinite loop */ { unsigned char zeroLenServer[] = { 0, 6, 's','p','d','y','/','2' }; out = NULL; outLen = 0; ret = wolfSSL_select_next_proto(&out, &outLen, zeroLenServer, sizeof(zeroLenServer), clientList, clientLen); /* Zero-length entry causes break, so no match found */ ExpectIntEQ(ret, WOLFSSL_NPN_NO_OVERLAP); } /* Test 7: Empty client list (clientLen == 0) - must NOT dereference * clientNames[0]. */ { unsigned char emptyClient[] = { 0 }; out = NULL; outLen = 0; ret = wolfSSL_select_next_proto(&out, &outLen, serverList, serverLen, emptyClient, 0); ExpectIntEQ(ret, WOLFSSL_NPN_NO_OVERLAP); ExpectIntEQ(outLen, 0); } /* Test 8: First protocol match - both start with "http/1.1" */ out = NULL; outLen = 0; ret = wolfSSL_select_next_proto(&out, &outLen, serverList, serverLen, clientListHttp, clientListHttpLen); ExpectIntEQ(ret, WOLFSSL_NPN_NEGOTIATED); ExpectIntEQ(outLen, 8); ExpectNotNull(out); ExpectIntEQ(XMEMCMP(out, "http/1.1", 8), 0); return EXPECT_RESULT(); } #endif /* HAVE_ALPN_PROTOS_SUPPORT */ static int test_wolfSSL_wolfSSL_UseSecureRenegotiation(void) { EXPECT_DECLS; #if defined(HAVE_SECURE_RENEGOTIATION) && !defined(NO_WOLFSSL_CLIENT) && \ !defined(NO_TLS) WOLFSSL_CTX *ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); WOLFSSL *ssl = wolfSSL_new(ctx); ExpectNotNull(ctx); ExpectNotNull(ssl); /* error cases */ ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_UseSecureRenegotiation(NULL)); ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_UseSecureRenegotiation(NULL)); /* success cases */ ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_UseSecureRenegotiation(ctx)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseSecureRenegotiation(ssl)); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } /* TLSX_FreeAll frees the SecureRenegotiation struct but the cached pointer * ssl->secure_renegotiation was not cleared, causing a use-after-free when * queried after wolfSSL_clear(). */ static int test_wolfSSL_clear_secure_renegotiation(void) { EXPECT_DECLS; #if (defined(HAVE_SECURE_RENEGOTIATION) || \ defined(HAVE_SERVER_RENEGOTIATION_INFO)) && \ (defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)) && \ !defined(NO_WOLFSSL_CLIENT) && !defined(NO_TLS) WOLFSSL_CTX *ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); WOLFSSL *ssl = wolfSSL_new(ctx); long support; ExpectNotNull(ctx); ExpectNotNull(ssl); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseSecureRenegotiation(ssl)); ExpectNotNull(ssl->secure_renegotiation); if (EXPECT_SUCCESS()) { if (ssl->secure_renegotiation != NULL) ssl->secure_renegotiation->enabled = 1; } ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_clear(ssl)); if (EXPECT_SUCCESS()) { support = wolfSSL_SSL_get_secure_renegotiation_support(ssl); ExpectNull(ssl->secure_renegotiation); ExpectIntEQ(WOLFSSL_FAILURE, support); } wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } /* Test reconnecting with a different ciphersuite after a renegotiation. */ static int test_wolfSSL_SCR_Reconnect(void) { EXPECT_DECLS; #if defined(HAVE_SECURE_RENEGOTIATION) && \ defined(BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) && \ defined(BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256) && \ defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) struct test_memio_ctx test_ctx; WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL; WOLFSSL *ssl_c = NULL, *ssl_s = NULL; byte data; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); test_ctx.c_ciphers = "ECDHE-RSA-AES256-GCM-SHA384"; test_ctx.s_ciphers = "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-CHACHA20-POLY1305"; ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, wolfTLSv1_2_client_method, wolfTLSv1_2_server_method), 0); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_UseSecureRenegotiation(ctx_c)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_UseSecureRenegotiation(ctx_s)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseSecureRenegotiation(ssl_c)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseSecureRenegotiation(ssl_s)); ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); /* WOLFSSL_FATAL_ERROR since it will block */ ExpectIntEQ(wolfSSL_Rehandshake(ssl_s), WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)); ExpectIntEQ(wolfSSL_get_error(ssl_s, WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)), WOLFSSL_ERROR_WANT_READ); ExpectIntEQ(wolfSSL_read(ssl_c, &data, 1), WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)); ExpectIntEQ(wolfSSL_get_error(ssl_s, WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)), WOLFSSL_ERROR_WANT_READ); ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); wolfSSL_free(ssl_c); ssl_c = NULL; wolfSSL_free(ssl_s); ssl_s = NULL; wolfSSL_CTX_free(ctx_c); ctx_c = NULL; test_ctx.c_ciphers = "ECDHE-RSA-CHACHA20-POLY1305"; ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, wolfTLSv1_2_client_method, wolfTLSv1_2_server_method), 0); ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); wolfSSL_free(ssl_s); wolfSSL_free(ssl_c); wolfSSL_CTX_free(ctx_s); wolfSSL_CTX_free(ctx_c); #endif return EXPECT_RESULT(); } /* Test SCR check when server doesn't reply to secure_renegotiation. */ #if !defined(NO_WOLFSSL_CLIENT) && !defined(WOLFSSL_NO_TLS12) && \ defined(WOLFSSL_HARDEN_TLS) && !defined(WOLFSSL_HARDEN_TLS_NO_SCR_CHECK) && \ defined(HAVE_SECURE_RENEGOTIATION) && \ defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) /* IO callback to remove secure renegotiation extension from ServerHello */ static int test_SCR_check_remove_ext_io_cb(WOLFSSL *ssl, char *buf, int sz, void *ctx) { static int sentServerHello = FALSE; if (!sentServerHello) { /* Look for secure renegotiation extension: 0xFF 0x01 (extension type) */ byte renegExt[] = { 0xFF, 0x01 }; size_t i; if (sz < (int)sizeof(renegExt)) return test_memio_write_cb(ssl, buf, sz, ctx); /* Search for the extension in the buffer */ for (i = 0; i < (size_t)sz - sizeof(renegExt); i++) { if (XMEMCMP(buf + i, renegExt, sizeof(renegExt)) == 0) { /* Found the extension. Remove it by changing the type to something * unrecognized so it won't be parsed as secure renegotiation. */ buf[i+1] = 0x11; break; } } sentServerHello = TRUE; } /* Call the original test_memio_write_cb */ return test_memio_write_cb(ssl, buf, sz, ctx); } #endif static int test_wolfSSL_SCR_check_enabled(void) { EXPECT_DECLS; #if !defined(NO_WOLFSSL_CLIENT) && !defined(WOLFSSL_NO_TLS12) && \ defined(WOLFSSL_HARDEN_TLS) && !defined(WOLFSSL_HARDEN_TLS_NO_SCR_CHECK) && \ defined(HAVE_SECURE_RENEGOTIATION) && \ defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) struct test_memio_ctx test_ctx; WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL; WOLFSSL *ssl_c = NULL, *ssl_s = NULL; int ret; int enabled; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); /* Set up client and server */ ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, wolfTLSv1_2_client_method, wolfTLSv1_2_server_method), 0); /* Enable secure renegotiation on client (so it sends the extension) */ ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_UseSecureRenegotiation(ctx_c)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseSecureRenegotiation(ssl_c)); /* Set up IO callback on server to remove the extension from ServerHello */ wolfSSL_SSLSetIOSend(ssl_s, test_SCR_check_remove_ext_io_cb); /* Try to connect - should fail with SECURE_RENEGOTIATION_E */ ret = test_memio_do_handshake(ssl_c, ssl_s, 10, NULL); ExpectIntNE(0, ret); /* Handshake should fail */ ret = wolfSSL_get_error(ssl_c, 0); ExpectIntEQ(WC_NO_ERR_TRACE(SECURE_RENEGOTIATION_E), ret); /* Clean up for next attempt */ wolfSSL_free(ssl_c); ssl_c = NULL; wolfSSL_free(ssl_s); ssl_s = NULL; test_memio_clear_buffer(&test_ctx, 1); test_memio_clear_buffer(&test_ctx, 0); /* Set up new client and server */ ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, wolfTLSv1_2_client_method, wolfTLSv1_2_server_method), 0); /* Enable secure renegotiation on client */ ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_UseSecureRenegotiation(ctx_c)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseSecureRenegotiation(ssl_c)); /* Set up IO callback on server to remove the extension from ServerHello */ wolfSSL_SSLSetIOSend(ssl_s, test_SCR_check_remove_ext_io_cb); /* Disable the SCR check */ ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_set_scr_check_enabled(ssl_c, 0)); /* Verify the state is 0 */ enabled = wolfSSL_get_scr_check_enabled(ssl_c); ExpectIntEQ(0, enabled); /* Now connection should succeed */ ExpectIntEQ(0, test_memio_do_handshake(ssl_c, ssl_s, 10, NULL)); /* Cleanup */ wolfSSL_free(ssl_c); ssl_c = NULL; wolfSSL_free(ssl_s); ssl_s = NULL; wolfSSL_CTX_free(ctx_c); ctx_c = NULL; wolfSSL_CTX_free(ctx_s); ctx_s = NULL; #endif return EXPECT_RESULT(); } /* F-2922: wolfSSL_TicketKeyCb must reject a session ticket whose HMAC * does not match its encrypted contents. */ static int test_wolfSSL_ticket_keycb_bad_hmac(void) { EXPECT_DECLS; #if defined(HAVE_SESSION_TICKET) && !defined(WOLFSSL_NO_TLS12) && \ defined(OPENSSL_EXTRA) && defined(HAVE_AES_CBC) && \ defined(WOLFSSL_AES_256) && \ defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \ !defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) struct test_memio_ctx test_ctx; WOLFSSL_CTX *ctx_c = NULL; WOLFSSL_CTX *ctx_s = NULL; WOLFSSL *ssl_c = NULL; WOLFSSL *ssl_s = NULL; WOLFSSL_SESSION *session = NULL; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, wolfTLSv1_2_client_method, wolfTLSv1_2_server_method), 0); ExpectIntEQ(OpenSSLTicketInit(), 0); ExpectIntEQ(wolfSSL_CTX_set_tlsext_ticket_key_cb(ctx_s, myTicketEncCbOpenSSL), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_UseSessionTicket(ssl_c), WOLFSSL_SUCCESS); ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); ExpectNotNull(session = wolfSSL_get1_session(ssl_c)); ExpectIntGT(session->ticketLen, 0); /* Corrupt a byte of the ticket HMAC so the server's HMAC * verification rejects it. */ if (session != NULL && session->ticket != NULL && session->ticketLen > 0) session->ticket[session->ticketLen - 1] ^= 0xFF; wolfSSL_free(ssl_c); ssl_c = NULL; wolfSSL_free(ssl_s); ssl_s = NULL; test_memio_clear_buffer(&test_ctx, 0); test_memio_clear_buffer(&test_ctx, 1); ExpectNotNull(ssl_c = wolfSSL_new(ctx_c)); ExpectNotNull(ssl_s = wolfSSL_new(ctx_s)); wolfSSL_SetIOReadCtx(ssl_c, &test_ctx); wolfSSL_SetIOWriteCtx(ssl_c, &test_ctx); wolfSSL_SetIOReadCtx(ssl_s, &test_ctx); wolfSSL_SetIOWriteCtx(ssl_s, &test_ctx); ExpectIntEQ(wolfSSL_set_session(ssl_c, session), WOLFSSL_SUCCESS); /* Disable the process-global session cache lookup on the server so that * the ticket is the only resumption path - with WOLFSSL_TICKET_HAVE_ID * the server could otherwise resume by session ID. */ if (ssl_s != NULL) ssl_s->options.sessionCacheOff = 1; /* Corrupted ticket bytes fail the HMAC check in * wolfSSL_TicketKeyCb; the session must not resume. */ ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); ExpectIntEQ(wolfSSL_session_reused(ssl_c), 0); wolfSSL_SESSION_free(session); wolfSSL_free(ssl_c); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_c); wolfSSL_CTX_free(ctx_s); OpenSSLTicketCleanup(); #endif return EXPECT_RESULT(); } #if !defined(NO_WOLFSSL_SERVER) && !defined(NO_TLS) && \ !defined(NO_FILESYSTEM) && (!defined(NO_RSA) || defined(HAVE_ECC)) /* Called when writing. */ static int DummySend(WOLFSSL* ssl, char* buf, int sz, void* ctx) { (void)ssl; (void)buf; (void)sz; (void)ctx; /* Force error return from wolfSSL_accept_TLSv13(). */ return WANT_WRITE; } /* Called when reading. */ static int BufferInfoRecv(WOLFSSL* ssl, char* buf, int sz, void* ctx) { WOLFSSL_BUFFER_INFO* msg = (WOLFSSL_BUFFER_INFO*)ctx; int len = (int)msg->length; (void)ssl; (void)sz; /* Pass back as much of message as will fit in buffer. */ if (len > sz) len = sz; XMEMCPY(buf, msg->buffer, len); /* Move over returned data. */ msg->buffer += len; msg->length -= (word32)len; /* Amount actually copied. */ return len; } #endif /* Test the detection of duplicate known TLS extensions. * Specifically in a ClientHello. */ static int test_tls_ext_duplicate(void) { EXPECT_DECLS; #if !defined(NO_WOLFSSL_SERVER) && !defined(NO_TLS) && \ !defined(NO_FILESYSTEM) && (!defined(NO_RSA) || defined(HAVE_ECC)) const unsigned char clientHelloDupTlsExt[] = { 0x16, 0x03, 0x03, 0x00, 0x6a, 0x01, 0x00, 0x00, 0x66, 0x03, 0x03, 0xf4, 0x65, 0xbd, 0x22, 0xfe, 0x6e, 0xab, 0x66, 0xdd, 0xcf, 0xe9, 0x65, 0x55, 0xe8, 0xdf, 0xc3, 0x8e, 0x4b, 0x00, 0xbc, 0xf8, 0x23, 0x57, 0x1b, 0xa0, 0xc8, 0xa9, 0xe2, 0x8c, 0x91, 0x6e, 0xf9, 0x20, 0xf7, 0x5c, 0xc5, 0x5b, 0x75, 0x8c, 0x47, 0x0a, 0x0e, 0xc4, 0x1a, 0xda, 0xef, 0x75, 0xe5, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x13, 0x01, 0x00, 0x9e, 0x01, 0x00, /* Extensions - duplicate signature algorithms. */ 0x00, 0x19, 0x00, 0x0d, 0x00, 0x04, 0x00, 0x02, 0x04, 0x01, 0x00, 0x0d, 0x00, 0x04, 0x00, 0x02, 0x04, 0x01, /* Supported Versions extension for TLS 1.3. */ 0x00, 0x2b, 0x00, 0x05, 0x04, 0x03, 0x04, 0x03, 0x03 }; WOLFSSL_BUFFER_INFO msg; const char* testCertFile; const char* testKeyFile; WOLFSSL_CTX *ctx = NULL; WOLFSSL *ssl = NULL; #ifndef NO_RSA testCertFile = svrCertFile; testKeyFile = svrKeyFile; #elif defined(HAVE_ECC) testCertFile = eccCertFile; testKeyFile = eccKeyFile; #endif ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx, testCertFile, CERT_FILETYPE)); ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, testKeyFile, CERT_FILETYPE)); /* Read from 'msg'. */ wolfSSL_SetIORecv(ctx, BufferInfoRecv); /* No where to send to - dummy sender. */ wolfSSL_SetIOSend(ctx, DummySend); ssl = wolfSSL_new(ctx); ExpectNotNull(ssl); msg.buffer = (unsigned char*)clientHelloDupTlsExt; msg.length = (unsigned int)sizeof(clientHelloDupTlsExt); wolfSSL_SetIOReadCtx(ssl, &msg); ExpectIntNE(wolfSSL_accept(ssl), WOLFSSL_SUCCESS); /* can return duplicate ext error or socket error if the peer closed down * while sending alert */ if (wolfSSL_get_error(ssl, 0) != WC_NO_ERR_TRACE(SOCKET_ERROR_E)) { ExpectIntEQ(wolfSSL_get_error(ssl, 0), WC_NO_ERR_TRACE(DUPLICATE_TLS_EXT_E)); } wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } /* Regression test: TLSX extension size accumulation must not silently wrap * the internal word16 accumulator. Prior to the fix, a single extension * whose size (plus the 4-byte header) pushes the running total past 0xFFFF * caused TLSX_GetSize / TLSX_Write to return a truncated length, which * in turn led to undersized buffer writes. The on-wire extensions block * length is a 2-byte field per RFC 8446 Section 4.2, so the correct * behavior is to return BUFFER_E rather than wrap. */ static int test_tls_ext_word16_overflow(void) { EXPECT_DECLS; #if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_CLIENT) && \ !defined(NO_TLS) WOLFSSL_CTX* ctx = NULL; WOLFSSL* ssl = NULL; SessionTicket* ticket = NULL; byte* big = NULL; /* Size chosen so that 4 (ext header) + size > 0xFFFF. */ const word16 bigSz = 0xFFFE; word32 length = 0; big = (byte*)XMALLOC(bigSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); ExpectNotNull(big); if (big != NULL) XMEMSET(big, 0xA5, bigSz); ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); ExpectNotNull(ssl = wolfSSL_new(ctx)); /* Build an oversized SessionTicket extension directly on the ssl * extension list. Going via the public API is not enough here because * wolfSSL_set_SessionTicket clamps to word16 without creating the * TLSX entry; the TLSX path is what exercises the accumulator. */ if (EXPECT_SUCCESS()) { ticket = TLSX_SessionTicket_Create(0, big, bigSz, ssl->heap); ExpectNotNull(ticket); } if (EXPECT_SUCCESS()) { ExpectIntEQ(TLSX_UseSessionTicket(&ssl->extensions, ticket, ssl->heap), WOLFSSL_SUCCESS); /* TLSX_UseSessionTicket takes ownership on success. */ if (EXPECT_SUCCESS()) ticket = NULL; } /* TLSX_GetRequestSize must refuse to encode: 4-byte ext header + * 0xFFFE payload + 2-byte block length prefix = 0x10004, which does * not fit in a word16 wire length. Expect BUFFER_E, not a silently * wrapped small value. */ if (EXPECT_SUCCESS()) { int ret = TLSX_GetRequestSize(ssl, client_hello, &length); ExpectIntEQ(ret, BUFFER_E); } if (ticket != NULL) TLSX_SessionTicket_Free(ticket, ssl->heap); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); XFREE(big, NULL, DYNAMIC_TYPE_TMP_BUFFER); ssl = NULL; ctx = NULL; big = NULL; /* Boundary case: construct a SessionTicket extension sized so that the * total extensions length in TLSX_GetRequestSize is exactly * WOLFSSL_MAX_16BIT - OPAQUE16_LEN (0xFFFD) *before* the OPAQUE16_LEN * block-prefix adjustment, which must succeed. This pins the `>` * comparison in the overflow check -- mutating it to `>=` would * incorrectly reject this valid case and fail this test. */ { WOLFSSL_CTX* ctx2 = NULL; WOLFSSL* ssl2 = NULL; SessionTicket* ticket2 = NULL; byte* buf = NULL; word32 baseLen = 0; word32 baseInternal = 0; word32 tickSz = 0; /* TLSX_GetRequestSize rejects when internal sum > 0xFFFD. */ const word32 target = (word32)WOLFSSL_MAX_16BIT - (word32)OPAQUE16_LEN; /* Session ticket extension contributes: type (2) + len (2) + size. */ const word32 extHdr = (word32)HELLO_EXT_TYPE_SZ + (word32)OPAQUE16_LEN; int ret; ExpectNotNull(ctx2 = wolfSSL_CTX_new(wolfSSLv23_client_method())); ExpectNotNull(ssl2 = wolfSSL_new(ctx2)); /* Measure baseline length with no session ticket extension. The * returned value already includes the 2-byte block-length prefix * when nonzero; strip it to get the raw internal sum. */ if (EXPECT_SUCCESS()) { baseLen = 0; ret = TLSX_GetRequestSize(ssl2, client_hello, &baseLen); ExpectIntEQ(ret, 0); baseInternal = (baseLen > 0) ? baseLen - (word32)OPAQUE16_LEN : 0; } /* Target: baseInternal + extHdr + tickSz == 0xFFFD. */ if (EXPECT_SUCCESS() && baseInternal + extHdr < target) { tickSz = target - baseInternal - extHdr; } if (EXPECT_SUCCESS() && tickSz > 0 && tickSz <= WOLFSSL_MAX_16BIT) { buf = (byte*)XMALLOC(tickSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); ExpectNotNull(buf); if (buf != NULL) XMEMSET(buf, 0x5A, tickSz); } if (EXPECT_SUCCESS() && buf != NULL) { ticket2 = TLSX_SessionTicket_Create(0, buf, (word16)tickSz, ssl2->heap); ExpectNotNull(ticket2); } if (EXPECT_SUCCESS() && ticket2 != NULL) { ExpectIntEQ(TLSX_UseSessionTicket(&ssl2->extensions, ticket2, ssl2->heap), WOLFSSL_SUCCESS); if (EXPECT_SUCCESS()) ticket2 = NULL; } /* Exact boundary: internal sum == 0xFFFD must succeed, and the * final returned length is 0xFFFD + OPAQUE16_LEN == 0xFFFF. */ if (EXPECT_SUCCESS()) { word32 lenBoundary = 0; ret = TLSX_GetRequestSize(ssl2, client_hello, &lenBoundary); ExpectIntEQ(ret, 0); ExpectIntEQ(lenBoundary, (word32)WOLFSSL_MAX_16BIT); } if (ticket2 != NULL) TLSX_SessionTicket_Free(ticket2, ssl2->heap); wolfSSL_free(ssl2); wolfSSL_CTX_free(ctx2); XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); } #endif return EXPECT_RESULT(); } /* Test TLS connection abort when legacy version field indicates TLS 1.3 or * higher. Based on test_tls_ext_duplicate() but with legacy version modified * to 0x0304. */ static int test_tls_bad_legacy_version(void) { EXPECT_DECLS; #if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_ALLOW_BAD_TLS_LEGACY_VERSION) #if !defined(NO_WOLFSSL_SERVER) && !defined(NO_TLS) && \ !defined(NO_FILESYSTEM) && (!defined(NO_RSA) || defined(HAVE_ECC)) /* This buffer (prior to Extensions) is exactly the same as the buffer in * test_tls_ext_duplicate() except the 11th byte is set to 0x04. That * change means the legacy protocol version field is invalid. That will be * caught before the dulplicate signature algorithms extension. */ const unsigned char clientHelloBadLegacyVersion[] = { 0x16, 0x03, 0x03, 0x00, 0x6a, 0x01, 0x00, 0x00, 0x66, 0x03, 0x04, 0xf4, 0x65, 0xbd, 0x22, 0xfe, 0x6e, 0xab, 0x66, 0xdd, 0xcf, 0xe9, 0x65, 0x55, 0xe8, 0xdf, 0xc3, 0x8e, 0x4b, 0x00, 0xbc, 0xf8, 0x23, 0x57, 0x1b, 0xa0, 0xc8, 0xa9, 0xe2, 0x8c, 0x91, 0x6e, 0xf9, 0x20, 0xf7, 0x5c, 0xc5, 0x5b, 0x75, 0x8c, 0x47, 0x0a, 0x0e, 0xc4, 0x1a, 0xda, 0xef, 0x75, 0xe5, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x13, 0x01, 0x00, 0x9e, 0x01, 0x00, /* Extensions */ 0x00, 0x19, 0x00, 0x0d, 0x00, 0x04, 0x00, 0x02, 0x04, 0x01, 0x00, 0x15, 0x00, 0x04, 0x00, 0x02, 0x04, 0x01, /* Supported Versions extension for TLS 1.3. */ 0x00, 0x2b, 0x00, 0x05, 0x04, 0x03, 0x04, 0x03, 0x03 }; WOLFSSL_BUFFER_INFO msg; const char* testCertFile; const char* testKeyFile; WOLFSSL_CTX *ctx = NULL; WOLFSSL *ssl = NULL; #ifndef NO_RSA testCertFile = svrCertFile; testKeyFile = svrKeyFile; #elif defined(HAVE_ECC) testCertFile = eccCertFile; testKeyFile = eccKeyFile; #endif ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx, testCertFile, CERT_FILETYPE)); ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, testKeyFile, CERT_FILETYPE)); /* Read from 'msg'. */ wolfSSL_SetIORecv(ctx, BufferInfoRecv); /* No where to send to - dummy sender. */ wolfSSL_SetIOSend(ctx, DummySend); ssl = wolfSSL_new(ctx); ExpectNotNull(ssl); msg.buffer = (unsigned char*)clientHelloBadLegacyVersion; msg.length = (unsigned int)sizeof(clientHelloBadLegacyVersion); wolfSSL_SetIOReadCtx(ssl, &msg); ExpectIntNE(wolfSSL_accept(ssl), WOLFSSL_SUCCESS); /* Connection should fail due to bad legacy version field. When that * happens the return code is VERSION_ERROR but that gets transformed into * SOCKET_ERROR_E. */ ExpectIntEQ(wolfSSL_get_error(ssl, 0), WC_NO_ERR_TRACE(SOCKET_ERROR_E)); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #endif #endif return EXPECT_RESULT(); } /*----------------------------------------------------------------------------* | X509 Tests *----------------------------------------------------------------------------*/ #if !defined(NO_FILESYSTEM) && !defined(NO_ASN) && defined(HAVE_PKCS8) && \ defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_DES3) && !defined(NO_PWDBASED) && \ (!defined(NO_RSA) || defined(HAVE_ECC)) && !defined(NO_MD5) #define TEST_PKCS8_ENC #endif #if !defined(NO_FILESYSTEM) && !defined(NO_ASN) && defined(HAVE_PKCS8) && \ defined(HAVE_ECC) && defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_TLS) /* used to keep track if FailTestCallback was called */ static int failTestCallbackCalled = 0; static WC_INLINE int FailTestCallBack(char* passwd, int sz, int rw, void* userdata) { (void)passwd; (void)sz; (void)rw; (void)userdata; /* mark called, test_wolfSSL_no_password_cb() will check and fail if set */ failTestCallbackCalled = 1; return -1; } #endif static int test_wolfSSL_no_password_cb(void) { EXPECT_DECLS; #if !defined(NO_FILESYSTEM) && !defined(NO_ASN) && defined(HAVE_PKCS8) && \ defined(HAVE_ECC) && defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_TLS) WOLFSSL_CTX* ctx = NULL; byte buff[FOURK_BUF]; const char eccPkcs8PrivKeyDerFile[] = "./certs/ecc-privkeyPkcs8.der"; const char eccPkcs8PrivKeyPemFile[] = "./certs/ecc-privkeyPkcs8.pem"; XFILE f = XBADFILE; int bytes = 0; #ifndef NO_WOLFSSL_CLIENT ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLS_client_method())); #else ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLS_server_method())); #endif wolfSSL_CTX_set_default_passwd_cb(ctx, FailTestCallBack); ExpectTrue((f = XFOPEN(eccPkcs8PrivKeyDerFile, "rb")) != XBADFILE); ExpectIntGT(bytes = (int)XFREAD(buff, 1, sizeof(buff), f), 0); if (f != XBADFILE) { XFCLOSE(f); f = XBADFILE; } ExpectIntLE(bytes, sizeof(buff)); ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buff, bytes, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); ExpectTrue((f = XFOPEN(eccPkcs8PrivKeyPemFile, "rb")) != XBADFILE); ExpectIntGT(bytes = (int)XFREAD(buff, 1, sizeof(buff), f), 0); if (f != XBADFILE) XFCLOSE(f); ExpectIntLE(bytes, sizeof(buff)); ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buff, bytes, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); wolfSSL_CTX_free(ctx); /* Password callback should not be called by default */ ExpectIntEQ(failTestCallbackCalled, 0); #endif return EXPECT_RESULT(); } #if defined(TEST_PKCS8_ENC) && !defined(NO_TLS) /* for PKCS8 test case */ static int PKCS8TestCallBack(char* passwd, int sz, int rw, void* userdata) { int flag = 0; (void)rw; if (userdata != NULL) { flag = *((int*)userdata); /* user set data */ } switch (flag) { case 1: /* flag set for specific WOLFSSL_CTX structure, note userdata * can be anything the user wishes to be passed to the callback * associated with the WOLFSSL_CTX */ XSTRNCPY(passwd, "yassl123", sz); return 8; default: return BAD_FUNC_ARG; } } #endif /* TEST_PKCS8_ENC && !NO_TLS */ /* Testing functions dealing with PKCS8 */ static int test_wolfSSL_PKCS8(void) { EXPECT_DECLS; #if !defined(NO_FILESYSTEM) && !defined(NO_ASN) && defined(HAVE_PKCS8) && \ !defined(WOLFCRYPT_ONLY) && !defined(NO_TLS) && \ (!defined(WOLFSSL_NO_TLS12) || defined(WOLFSSL_TLS13)) #if !defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER) byte buff[FOURK_BUF]; byte der[FOURK_BUF]; #ifndef NO_RSA #ifdef WOLFSSL_PEM_TO_DER const char serverKeyPkcs8PemFile[] = "./certs/server-keyPkcs8.pem"; #endif const char serverKeyPkcs8DerFile[] = "./certs/server-keyPkcs8.der"; #endif #ifdef WOLFSSL_PEM_TO_DER const char eccPkcs8PrivKeyPemFile[] = "./certs/ecc-privkeyPkcs8.pem"; #endif #ifdef HAVE_ECC const char eccPkcs8PrivKeyDerFile[] = "./certs/ecc-privkeyPkcs8.der"; #endif XFILE f = XBADFILE; int bytes = 0; WOLFSSL_CTX* ctx = NULL; #if defined(HAVE_ECC) && !defined(NO_CODING) && !defined(WOLFSSL_NO_PEM) int ret; ecc_key key; word32 x = 0; #endif #ifdef TEST_PKCS8_ENC #if !defined(NO_RSA) && !defined(NO_SHA) const char serverKeyPkcs8EncPemFile[] = "./certs/server-keyPkcs8Enc.pem"; const char serverKeyPkcs8EncDerFile[] = "./certs/server-keyPkcs8Enc.der"; #endif #if defined(HAVE_ECC) && !defined(NO_SHA) const char eccPkcs8EncPrivKeyPemFile[] = "./certs/ecc-keyPkcs8Enc.pem"; const char eccPkcs8EncPrivKeyDerFile[] = "./certs/ecc-keyPkcs8Enc.der"; #endif int flag; #endif (void)der; #ifndef NO_WOLFSSL_CLIENT #ifndef WOLFSSL_NO_TLS12 ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method())); #else ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method())); #endif #else #ifndef WOLFSSL_NO_TLS12 ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_2_server_method())); #else ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method())); #endif #endif #ifdef TEST_PKCS8_ENC wolfSSL_CTX_set_default_passwd_cb(ctx, PKCS8TestCallBack); wolfSSL_CTX_set_default_passwd_cb_userdata(ctx, (void*)&flag); flag = 1; /* used by password callback as return code */ #if !defined(NO_RSA) && !defined(NO_SHA) #if defined(WOLFSSL_PEM_TO_DER) /* test loading PEM PKCS8 encrypted file */ ExpectTrue((f = XFOPEN(serverKeyPkcs8EncPemFile, "rb")) != XBADFILE); ExpectIntGT(bytes = (int)XFREAD(buff, 1, sizeof(buff), f), 0); if (f != XBADFILE) { XFCLOSE(f); f = XBADFILE; } ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buff, bytes, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); /* this next case should fail because of password callback return code */ flag = 0; /* used by password callback as return code */ ExpectIntNE(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buff, bytes, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); /* decrypt PKCS8 PEM to key in DER format with not using WOLFSSL_CTX */ ExpectIntGT(wc_KeyPemToDer(buff, bytes, der, (word32)sizeof(der), "yassl123"), 0); /* test that error value is returned with a bad password */ ExpectIntLT(wc_KeyPemToDer(buff, bytes, der, (word32)sizeof(der), "bad"), 0); #endif /* test loading PEM PKCS8 encrypted file */ ExpectTrue((f = XFOPEN(serverKeyPkcs8EncDerFile, "rb")) != XBADFILE); ExpectIntGT(bytes = (int)XFREAD(buff, 1, sizeof(buff), f), 0); if (f != XBADFILE) { XFCLOSE(f); f = XBADFILE; } flag = 1; /* used by password callback as return code */ ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buff, bytes, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); /* this next case should fail because of password callback return code */ flag = 0; /* used by password callback as return code */ ExpectIntNE(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buff, bytes, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); #endif /* !NO_RSA && !NO_SHA */ #if defined(HAVE_ECC) && !defined(NO_SHA) #if defined(WOLFSSL_PEM_TO_DER) /* test loading PEM PKCS8 encrypted ECC Key file */ ExpectTrue((f = XFOPEN(eccPkcs8EncPrivKeyPemFile, "rb")) != XBADFILE); ExpectIntGT(bytes = (int)XFREAD(buff, 1, sizeof(buff), f), 0); if (f != XBADFILE) { XFCLOSE(f); f = XBADFILE; } flag = 1; /* used by password callback as return code */ ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buff, bytes, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); /* this next case should fail because of password callback return code */ flag = 0; /* used by password callback as return code */ ExpectIntNE(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buff, bytes, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); /* decrypt PKCS8 PEM to key in DER format with not using WOLFSSL_CTX */ ExpectIntGT(wc_KeyPemToDer(buff, bytes, der, (word32)sizeof(der), "yassl123"), 0); /* test that error value is returned with a bad password */ ExpectIntLT(wc_KeyPemToDer(buff, bytes, der, (word32)sizeof(der), "bad"), 0); #endif /* test loading DER PKCS8 encrypted ECC Key file */ ExpectTrue((f = XFOPEN(eccPkcs8EncPrivKeyDerFile, "rb")) != XBADFILE); ExpectIntGT(bytes = (int)XFREAD(buff, 1, sizeof(buff), f), 0); if (f != XBADFILE) { XFCLOSE(f); f = XBADFILE; } flag = 1; /* used by password callback as return code */ ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buff, bytes, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); /* this next case should fail because of password callback return code */ flag = 0; /* used by password callback as return code */ ExpectIntNE(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buff, bytes, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); /* leave flag as "okay" */ flag = 1; #endif /* HAVE_ECC && !NO_SHA */ #endif /* TEST_PKCS8_ENC */ #ifndef NO_RSA /* test loading ASN.1 (DER) PKCS8 private key file (not encrypted) */ ExpectTrue((f = XFOPEN(serverKeyPkcs8DerFile, "rb")) != XBADFILE); ExpectIntGT(bytes = (int)XFREAD(buff, 1, sizeof(buff), f), 0); if (f != XBADFILE) { XFCLOSE(f); f = XBADFILE; } ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buff, bytes, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); #ifdef WOLFSSL_PEM_TO_DER /* test loading PEM PKCS8 private key file (not encrypted) */ ExpectTrue((f = XFOPEN(serverKeyPkcs8PemFile, "rb")) != XBADFILE); ExpectIntGT(bytes = (int)XFREAD(buff, 1, sizeof(buff), f), 0); if (f != XBADFILE) { XFCLOSE(f); f = XBADFILE; } ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buff, bytes, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); #endif #endif /* !NO_RSA */ #ifdef WOLFSSL_PEM_TO_DER /* Test PKCS8 PEM ECC key no crypt */ ExpectTrue((f = XFOPEN(eccPkcs8PrivKeyPemFile, "rb")) != XBADFILE); ExpectIntGT(bytes = (int)XFREAD(buff, 1, sizeof(buff), f), 0); if (f != XBADFILE) { XFCLOSE(f); f = XBADFILE; } #endif #ifdef HAVE_ECC #ifdef WOLFSSL_PEM_TO_DER /* Test PKCS8 PEM ECC key no crypt */ ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buff, bytes, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); /* decrypt PKCS8 PEM to key in DER format */ ExpectIntGT((bytes = wc_KeyPemToDer(buff, bytes, der, (word32)sizeof(der), NULL)), 0); ret = wc_ecc_init(&key); if (ret == 0) { ret = wc_EccPrivateKeyDecode(der, &x, &key, (word32)bytes); wc_ecc_free(&key); } ExpectIntEQ(ret, 0); #endif /* Test PKCS8 DER ECC key no crypt */ ExpectTrue((f = XFOPEN(eccPkcs8PrivKeyDerFile, "rb")) != XBADFILE); ExpectIntGT(bytes = (int)XFREAD(buff, 1, sizeof(buff), f), 0); if (f != XBADFILE) XFCLOSE(f); /* Test using a PKCS8 ECC PEM */ ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, buff, bytes, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); #else #ifdef WOLFSSL_PEM_TO_DER /* if HAVE_ECC is not defined then BEGIN EC PRIVATE KEY is not found */ ExpectIntEQ((bytes = wc_KeyPemToDer(buff, bytes, der, (word32)sizeof(der), NULL)), WC_NO_ERR_TRACE(ASN_NO_PEM_HEADER)); #endif #endif /* HAVE_ECC */ wolfSSL_CTX_free(ctx); #endif /* !NO_WOLFSSL_CLIENT || !NO_WOLFSSL_SERVER */ #endif /* !NO_FILESYSTEM && !NO_ASN && HAVE_PKCS8 */ return EXPECT_RESULT(); } static int test_wolfSSL_PKCS8_ED25519(void) { EXPECT_DECLS; #if !defined(NO_ASN) && defined(HAVE_PKCS8) && defined(HAVE_AES_CBC) && \ defined(WOLFSSL_AES_256) && \ defined(WOLFSSL_ENCRYPTED_KEYS) && defined(HAVE_ED25519) && \ defined(HAVE_ED25519_KEY_IMPORT) const byte encPrivKey[] = \ "-----BEGIN ENCRYPTED PRIVATE KEY-----\n" "MIGbMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAheCGLmWGh7+AICCAAw\n" "DAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEC4L5P6GappsTyhOOoQfvh8EQJMX\n" "OAdlsYKCOcFo4djg6AI1lRdeBRwVFWkha7gBdoCJOzS8wDvTbYcJMPvANu5ft3nl\n" "2L9W4v7swXkV+X+a1ww=\n" "-----END ENCRYPTED PRIVATE KEY-----\n"; const char password[] = "abcdefghijklmnopqrstuvwxyz"; byte der[FOURK_BUF]; #if !defined(NO_TLS) && \ (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) WOLFSSL_CTX* ctx = NULL; #endif int bytes; XMEMSET(der, 0, sizeof(der)); ExpectIntGT((bytes = wc_KeyPemToDer(encPrivKey, sizeof(encPrivKey), der, (word32)sizeof(der), password)), 0); #if !defined(NO_TLS) && \ (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) #ifndef NO_WOLFSSL_SERVER ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); #else ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); #endif ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, der, bytes, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); wolfSSL_CTX_free(ctx); #endif /* !NO_TLS && (!NO_WOLFSSL_CLIENT || !NO_WOLFSSL_SERVER) */ #endif return EXPECT_RESULT(); } static int test_wolfSSL_PKCS8_ED448(void) { EXPECT_DECLS; #if !defined(NO_ASN) && defined(HAVE_PKCS8) && defined(HAVE_AES_CBC) && \ defined(WOLFSSL_AES_256) && \ defined(WOLFSSL_ENCRYPTED_KEYS) && defined(HAVE_ED448) && \ defined(HAVE_ED448_KEY_IMPORT) const byte encPrivKey[] = \ "-----BEGIN ENCRYPTED PRIVATE KEY-----\n" "MIGrMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAjSbZKnG4EPggICCAAw\n" "DAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEFvCFWBBHBlJBsYleBJlJWcEUNC7\n" "Tf5pZviT5Btar4D/MNg6BsQHSDf5KW4ix871EsgDY2Zz+euaoWspiMntz7gU+PQu\n" "T/JJcbD2Ly8BbE3l5WHMifAQqNLxJBfXrHkfYtAo\n" "-----END ENCRYPTED PRIVATE KEY-----\n"; const char password[] = "abcdefghijklmnopqrstuvwxyz"; byte der[FOURK_BUF]; #if !defined(NO_TLS) && \ (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) WOLFSSL_CTX* ctx = NULL; #endif int bytes; XMEMSET(der, 0, sizeof(der)); ExpectIntGT((bytes = wc_KeyPemToDer(encPrivKey, sizeof(encPrivKey), der, (word32)sizeof(der), password)), 0); #if !defined(NO_TLS) && \ (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) #ifndef NO_WOLFSSL_SERVER ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); #else ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); #endif ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_buffer(ctx, der, bytes, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); wolfSSL_CTX_free(ctx); #endif /* !NO_TLS && (!NO_WOLFSSL_CLIENT || !NO_WOLFSSL_SERVER) */ #endif return EXPECT_RESULT(); } /* Testing functions dealing with PKCS5 */ static int test_wolfSSL_PKCS5(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_SHA) && !defined(NO_PWDBASED) #ifdef HAVE_FIPS /* Password minimum length is 14 (112-bit) in FIPS MODE */ const char* passwd = "myfipsPa$$W0rd"; #else const char *passwd = "pass1234"; #endif const unsigned char *salt = (unsigned char *)"salt1234"; unsigned char *out = (unsigned char *)XMALLOC(WC_SHA_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); int ret = 0; ExpectNotNull(out); ExpectIntEQ(ret = PKCS5_PBKDF2_HMAC_SHA1(passwd,(int)XSTRLEN(passwd), salt, (int)XSTRLEN((const char *) salt), 10, WC_SHA_DIGEST_SIZE,out), WOLFSSL_SUCCESS); #ifdef WOLFSSL_SHA512 ExpectIntEQ(ret = PKCS5_PBKDF2_HMAC(passwd,(int)XSTRLEN(passwd), salt, (int)XSTRLEN((const char *) salt), 10, wolfSSL_EVP_sha512(), WC_SHA_DIGEST_SIZE, out), SSL_SUCCESS); #endif XFREE(out, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif /* defined(OPENSSL_EXTRA) && !defined(NO_SHA) */ return EXPECT_RESULT(); } /* test parsing URI from certificate */ static int test_wolfSSL_URI(void) { EXPECT_DECLS; #if !defined(NO_CERTS) && !defined(NO_RSA) && !defined(NO_FILESYSTEM) \ && (defined(KEEP_PEER_CERT) || defined(SESSION_CERTS) || \ defined(OPENSSL_EXTRA)) WOLFSSL_X509* x509 = NULL; const char uri[] = "./certs/client-uri-cert.pem"; const char urn[] = "./certs/client-absolute-urn.pem"; const char badUri[] = "./certs/client-relative-uri.pem"; ExpectNotNull(x509 = wolfSSL_X509_load_certificate_file(uri, WOLFSSL_FILETYPE_PEM)); wolfSSL_FreeX509(x509); x509 = NULL; ExpectNotNull(x509 = wolfSSL_X509_load_certificate_file(urn, WOLFSSL_FILETYPE_PEM)); wolfSSL_FreeX509(x509); x509 = NULL; #if !defined(IGNORE_NAME_CONSTRAINTS) && !defined(WOLFSSL_NO_ASN_STRICT) \ && !defined(WOLFSSL_FPKI) ExpectNull(x509 = wolfSSL_X509_load_certificate_file(badUri, WOLFSSL_FILETYPE_PEM)); #else ExpectNotNull(x509 = wolfSSL_X509_load_certificate_file(badUri, WOLFSSL_FILETYPE_PEM)); #endif wolfSSL_FreeX509(x509); #endif return EXPECT_RESULT(); } #if !defined(NO_DH) && !defined(NO_AES) && defined(WOLFSSL_CERT_GEN) && \ defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && \ defined(OPENSSL_EXTRA) && !defined(NO_ASN_TIME) /* create certificate with version 2 */ static int test_set_x509_badversion(WOLFSSL_CTX* ctx) { EXPECT_DECLS; WOLFSSL_X509 *x509 = NULL, *x509v2 = NULL; WOLFSSL_EVP_PKEY *priv = NULL, *pub = NULL; unsigned char *der = NULL, *key = NULL, *pt; char *header = NULL, *name = NULL; int derSz; long keySz; XFILE fp = XBADFILE; WOLFSSL_ASN1_TIME *notBefore = NULL, *notAfter = NULL; time_t t; ExpectNotNull(x509 = wolfSSL_X509_load_certificate_file(cliCertFile, WOLFSSL_FILETYPE_PEM)); ExpectTrue((fp = XFOPEN(cliKeyFile, "rb")) != XBADFILE); ExpectIntEQ(wolfSSL_PEM_read(fp, &name, &header, &key, &keySz), WOLFSSL_SUCCESS); if (fp != XBADFILE) XFCLOSE(fp); pt = key; ExpectNotNull(priv = wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, NULL, (const unsigned char**)&pt, keySz)); /* create the version 2 certificate */ ExpectNotNull(x509v2 = X509_new()); ExpectIntEQ(wolfSSL_X509_set_version(x509v2, 1), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_X509_set_subject_name(x509v2, wolfSSL_X509_get_subject_name(x509)), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_X509_set_issuer_name(x509v2, wolfSSL_X509_get_issuer_name(x509)), WOLFSSL_SUCCESS); ExpectNotNull(pub = wolfSSL_X509_get_pubkey(x509)); ExpectIntEQ(X509_set_pubkey(x509v2, pub), WOLFSSL_SUCCESS); t = time(NULL); ExpectNotNull(notBefore = wolfSSL_ASN1_TIME_adj(NULL, t, 0, 0)); ExpectNotNull(notAfter = wolfSSL_ASN1_TIME_adj(NULL, t, 365, 0)); ExpectTrue(wolfSSL_X509_set_notBefore(x509v2, notBefore)); ExpectTrue(wolfSSL_X509_set_notAfter(x509v2, notAfter)); ExpectIntGT(wolfSSL_X509_sign(x509v2, priv, EVP_sha256()), 0); derSz = wolfSSL_i2d_X509(x509v2, &der); ExpectIntGT(derSz, 0); ExpectIntEQ(wolfSSL_CTX_use_certificate_buffer(ctx, der, derSz, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); /* TODO: Replace with API call */ XFREE(der, HEAP_HINT, DYNAMIC_TYPE_OPENSSL); XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(name, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(header, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wolfSSL_X509_free(x509); wolfSSL_X509_free(x509v2); wolfSSL_EVP_PKEY_free(priv); wolfSSL_EVP_PKEY_free(pub); wolfSSL_ASN1_TIME_free(notBefore); wolfSSL_ASN1_TIME_free(notAfter); return EXPECT_RESULT(); } /* override certificate version error */ static int test_override_x509(int preverify, WOLFSSL_X509_STORE_CTX* store) { EXPECT_DECLS; #ifndef OPENSSL_COMPATIBLE_DEFAULTS ExpectIntEQ(store->error, WC_NO_ERR_TRACE(ASN_VERSION_E)); #else ExpectIntEQ(store->error, 0); #endif ExpectIntEQ((int)wolfSSL_X509_get_version(store->current_cert), 1); (void)preverify; return EXPECT_RESULT() == TEST_SUCCESS; } /* set verify callback that will override bad certificate version */ static int test_set_override_x509(WOLFSSL_CTX* ctx) { wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, test_override_x509); return TEST_SUCCESS; } #endif static int test_wolfSSL_X509_TLS_version_test_1(void) { EXPECT_DECLS; #if !defined(NO_DH) && !defined(NO_AES) && defined(WOLFSSL_CERT_GEN) && \ defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && \ defined(OPENSSL_EXTRA) && !defined(NO_ASN_TIME) test_ssl_cbf func_cb_client; test_ssl_cbf func_cb_server; /* test server rejects a client certificate that is not version 3 */ XMEMSET(&func_cb_client, 0, sizeof(func_cb_client)); XMEMSET(&func_cb_server, 0, sizeof(func_cb_server)); func_cb_client.ctx_ready = &test_set_x509_badversion; #ifndef WOLFSSL_NO_TLS12 func_cb_client.method = wolfTLSv1_2_client_method; #else func_cb_client.method = wolfTLSv1_3_client_method; #endif #ifndef WOLFSSL_NO_TLS12 func_cb_server.method = wolfTLSv1_2_server_method; #else func_cb_server.method = wolfTLSv1_3_server_method; #endif #ifndef OPENSSL_COMPATIBLE_DEFAULTS ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&func_cb_client, &func_cb_server, NULL), -1001); #else ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&func_cb_client, &func_cb_server, NULL), TEST_SUCCESS); #endif #endif return EXPECT_RESULT(); } static int test_wolfSSL_X509_TLS_version_test_2(void) { EXPECT_DECLS; #if !defined(NO_DH) && !defined(NO_AES) && defined(WOLFSSL_CERT_GEN) && \ defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && \ defined(OPENSSL_EXTRA) && !defined(NO_ASN_TIME) test_ssl_cbf func_cb_client; test_ssl_cbf func_cb_server; XMEMSET(&func_cb_client, 0, sizeof(func_cb_client)); XMEMSET(&func_cb_server, 0, sizeof(func_cb_server)); func_cb_client.ctx_ready = &test_set_x509_badversion; func_cb_server.ctx_ready = &test_set_override_x509; #ifndef WOLFSSL_NO_TLS12 func_cb_client.method = wolfTLSv1_2_client_method; #else func_cb_client.method = wolfTLSv1_3_client_method; #endif #ifndef WOLFSSL_NO_TLS12 func_cb_server.method = wolfTLSv1_2_server_method; #else func_cb_server.method = wolfTLSv1_3_server_method; #endif ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&func_cb_client, &func_cb_server, NULL), TEST_SUCCESS); #endif return EXPECT_RESULT(); } /* Testing function wolfSSL_CTX_SetMinVersion; sets the minimum downgrade * version allowed. * POST: 1 on success. */ static int test_wolfSSL_CTX_SetMinVersion(void) { int res = TEST_SKIPPED; #if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_TLS) int failFlag = WOLFSSL_SUCCESS; WOLFSSL_CTX* ctx; int itr; #ifndef NO_OLD_TLS const int versions[] = { #ifdef WOLFSSL_ALLOW_TLSV10 WOLFSSL_TLSV1, #endif WOLFSSL_TLSV1_1, WOLFSSL_TLSV1_2 }; #elif !defined(WOLFSSL_NO_TLS12) const int versions[] = { WOLFSSL_TLSV1_2 }; #elif defined(WOLFSSL_TLS13) const int versions[] = { WOLFSSL_TLSV1_3 }; #else const int versions[0]; #endif ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); for (itr = 0; itr < (int)(sizeof(versions)/sizeof(int)); itr++) { if (wolfSSL_CTX_SetMinVersion(ctx, *(versions + itr)) != WOLFSSL_SUCCESS) { failFlag = WOLFSSL_FAILURE; } } wolfSSL_CTX_free(ctx); res = TEST_RES_CHECK(failFlag == WOLFSSL_SUCCESS); #endif return res; } /* END test_wolfSSL_CTX_SetMinVersion */ /*----------------------------------------------------------------------------* | OCSP Stapling *----------------------------------------------------------------------------*/ /* Testing wolfSSL_UseOCSPStapling function. OCSP stapling eliminates the need * need to contact the CA, lowering the cost of cert revocation checking. * PRE: HAVE_OCSP and HAVE_CERTIFICATE_STATUS_REQUEST * POST: 1 returned for success. */ static int test_wolfSSL_UseOCSPStapling(void) { EXPECT_DECLS; #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) && defined(HAVE_OCSP) && \ !defined(NO_TLS) && !defined(NO_WOLFSSL_CLIENT) WOLFSSL_CTX* ctx = NULL; WOLFSSL* ssl = NULL; #ifndef NO_WOLFSSL_CLIENT #ifndef WOLFSSL_NO_TLS12 ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method())); #else ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method())); #endif #else #ifndef WOLFSSL_NO_TLS12 ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_2_server_method())); #else ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method())); #endif #endif ExpectNotNull(ssl = wolfSSL_new(ctx)); ExpectIntEQ(wolfSSL_UseOCSPStapling(NULL, WOLFSSL_CSR2_OCSP, WOLFSSL_CSR2_OCSP_USE_NONCE), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); #ifndef NO_WOLFSSL_CLIENT ExpectIntEQ(wolfSSL_UseOCSPStapling(ssl, WOLFSSL_CSR2_OCSP, WOLFSSL_CSR2_OCSP_USE_NONCE), 1); #else ExpectIntEQ(wolfSSL_UseOCSPStapling(ssl, WOLFSSL_CSR2_OCSP, WOLFSSL_CSR2_OCSP_USE_NONCE), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); #endif wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } /* END test_wolfSSL_UseOCSPStapling */ /* Testing OCSP stapling version 2, wolfSSL_UseOCSPStaplingV2 function. OCSP * stapling eliminates the need to contact the CA and lowers cert revocation * check. * PRE: HAVE_CERTIFICATE_STATUS_REQUEST_V2 and HAVE_OCSP defined. */ static int test_wolfSSL_UseOCSPStaplingV2(void) { EXPECT_DECLS; #if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) && defined(HAVE_OCSP) && \ !defined(NO_TLS) && !defined(NO_WOLFSSL_CLIENT) WOLFSSL_CTX* ctx = NULL; WOLFSSL* ssl = NULL; #ifndef NO_WOLFSSL_CLIENT #ifndef WOLFSSL_NO_TLS12 ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method())); #else ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method())); #endif #else #ifndef WOLFSSL_NO_TLS12 ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_2_server_method())); #else ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method())); #endif #endif ExpectNotNull(ssl = wolfSSL_new(ctx)); ExpectIntEQ(wolfSSL_UseOCSPStaplingV2(NULL, WOLFSSL_CSR2_OCSP, WOLFSSL_CSR2_OCSP_USE_NONCE), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); #ifndef NO_WOLFSSL_CLIENT ExpectIntEQ(wolfSSL_UseOCSPStaplingV2(ssl, WOLFSSL_CSR2_OCSP, WOLFSSL_CSR2_OCSP_USE_NONCE), 1); #else ExpectIntEQ(wolfSSL_UseOCSPStaplingV2(ssl, WOLFSSL_CSR2_OCSP, WOLFSSL_CSR2_OCSP_USE_NONCE), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); #endif wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } /* END test_wolfSSL_UseOCSPStaplingV2 */ /*----------------------------------------------------------------------------* | Multicast Tests *----------------------------------------------------------------------------*/ static int test_wolfSSL_mcast(void) { EXPECT_DECLS; #if defined(WOLFSSL_DTLS) && defined(WOLFSSL_MULTICAST) && \ (defined(WOLFSSL_TLS13) || defined(WOLFSSL_SNIFFER)) && \ !defined(NO_WOLFSSL_CLIENT) WOLFSSL_CTX* ctx = NULL; WOLFSSL* ssl = NULL; byte preMasterSecret[512]; byte clientRandom[32]; byte serverRandom[32]; byte suite[2] = {0, 0xfe}; /* WDM_WITH_NULL_SHA256 */ byte buf[256]; word16 newId; ExpectNotNull(ctx = wolfSSL_CTX_new(wolfDTLSv1_2_client_method())); ExpectIntEQ(wolfSSL_CTX_mcast_set_member_id(ctx, 0), WOLFSSL_SUCCESS); ExpectNotNull(ssl = wolfSSL_new(ctx)); XMEMSET(preMasterSecret, 0x23, sizeof(preMasterSecret)); XMEMSET(clientRandom, 0xA5, sizeof(clientRandom)); XMEMSET(serverRandom, 0x5A, sizeof(serverRandom)); ExpectIntEQ(wolfSSL_set_secret(ssl, 23, preMasterSecret, sizeof(preMasterSecret), clientRandom, serverRandom, suite), WOLFSSL_SUCCESS); ExpectIntLE(wolfSSL_mcast_read(ssl, &newId, buf, sizeof(buf)), 0); ExpectIntLE(newId, 100); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #endif /* WOLFSSL_DTLS && WOLFSSL_MULTICAST && (WOLFSSL_TLS13 || * WOLFSSL_SNIFFER) */ return EXPECT_RESULT(); } /*----------------------------------------------------------------------------* | Wolfcrypt *----------------------------------------------------------------------------*/ /* * Testing wc_SetAcmeIdentifierExt() round-trip - the RFC 8737 * id-pe-acmeIdentifier (1.3.6.1.5.5.7.1.31) extension used by * TLS-ALPN-01 ACME challenge certs. */ static int test_wc_SetAcmeIdentifierExt(void) { EXPECT_DECLS; #if defined(WOLFSSL_ACME_OID) && defined(WOLFSSL_CERT_GEN) && \ defined(HAVE_ECC) && !defined(NO_SHA256) && !defined(NO_ASN_TIME) && \ !defined(WC_NO_RNG) && !defined(NO_RSA) Cert cert; DecodedCert decoded; WC_RNG rng; ecc_key key; byte der[TWOK_BUF]; int derSz = 0; int rngInited = 0, keyInited = 0; const char* keyAuth = "evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA" ".kZdq0qaDcXNVxKBkP_uiKvw2Yg5sRJ8KBfQa9Ru13nE"; word32 keyAuthSz = (word32)XSTRLEN(keyAuth); byte expected[WC_SHA256_DIGEST_SIZE]; XMEMSET(&cert, 0, sizeof(cert)); XMEMSET(&decoded, 0, sizeof(decoded)); XMEMSET(&rng, 0, sizeof(rng)); XMEMSET(&key, 0, sizeof(key)); XMEMSET(der, 0, sizeof(der)); /* Compute the expected digest */ ExpectIntEQ(wc_Sha256Hash((const byte*)keyAuth, keyAuthSz, expected), 0); /* Input validation. */ ExpectIntEQ(wc_SetAcmeIdentifierExt(NULL, (const byte*)keyAuth, keyAuthSz), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wc_SetAcmeIdentifierExt(&cert, NULL, keyAuthSz), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wc_SetAcmeIdentifierExt(&cert, (const byte*)keyAuth, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* Build a P-256 keypair to sign the cert. */ ExpectIntEQ(wc_InitRng(&rng), 0); rngInited = 1; ExpectIntEQ(wc_ecc_init(&key), 0); keyInited = 1; ExpectIntEQ(wc_ecc_make_key_ex(&rng, KEY32, &key, ECC_SECP256R1), 0); /* Build a minimal self-signed cert template carrying the extension. */ ExpectIntEQ(wc_InitCert(&cert), 0); cert.sigType = CTC_SHA256wECDSA; cert.daysValid = 1; cert.isCA = 0; XSTRNCPY(cert.subject.commonName, "acme-test.example", CTC_NAME_SIZE); ExpectIntEQ(wc_SetAcmeIdentifierExt(&cert, (const byte*)keyAuth, keyAuthSz), 0); ExpectIntEQ(cert.acmeIdentifierSz, WC_SHA256_DIGEST_SIZE); ExpectIntEQ(XMEMCMP(cert.acmeIdentifier, expected, WC_SHA256_DIGEST_SIZE), 0); /* MakeCert + SignCert. ECC_TYPE selects the ECDSA signing path. */ ExpectIntGT(derSz = wc_MakeCert_ex(&cert, der, sizeof(der), ECC_TYPE, &key, &rng), 0); ExpectIntGT(derSz = wc_SignCert_ex(cert.bodySz, cert.sigType, der, sizeof(der), ECC_TYPE, &key, &rng), 0); /* Parse the cert back and verify the extension survives the * round-trip via DecodeAcmeId. */ wc_InitDecodedCert(&decoded, der, derSz, NULL); ExpectIntEQ(wc_ParseCert(&decoded, CERT_TYPE, NO_VERIFY, NULL), 0); ExpectIntEQ(decoded.extAcmeIdentifierSet, 1); ExpectIntEQ(decoded.extAcmeIdentifierCrit, 1); ExpectIntEQ(decoded.acmeIdentifierSz, WC_SHA256_DIGEST_SIZE); ExpectIntEQ(XMEMCMP(decoded.acmeIdentifier, expected, WC_SHA256_DIGEST_SIZE), 0); wc_FreeDecodedCert(&decoded); if (keyInited) wc_ecc_free(&key); if (rngInited) wc_FreeRng(&rng); #endif return EXPECT_RESULT(); } /* END test_wc_SetAcmeIdentifierExt */ /* * Testing wc_SetKeyUsage() */ static int test_wc_SetKeyUsage(void) { EXPECT_DECLS; #if !defined(NO_RSA) && defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CERT_GEN) && !defined(HAVE_FIPS) Cert myCert; ExpectIntEQ(wc_InitCert(&myCert), 0); ExpectIntEQ(wc_SetKeyUsage(&myCert, "keyEncipherment,keyAgreement"), 0); ExpectIntEQ(wc_SetKeyUsage(&myCert, "digitalSignature,nonRepudiation"), 0); ExpectIntEQ(wc_SetKeyUsage(&myCert, "contentCommitment,encipherOnly"), 0); ExpectIntEQ(wc_SetKeyUsage(&myCert, "decipherOnly"), 0); ExpectIntEQ(wc_SetKeyUsage(&myCert, "cRLSign,keyCertSign"), 0); /* Test bad args. */ ExpectIntEQ(wc_SetKeyUsage(NULL, "decipherOnly"), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wc_SetKeyUsage(&myCert, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wc_SetKeyUsage(&myCert, ""), WC_NO_ERR_TRACE(KEYUSAGE_E)); ExpectIntEQ(wc_SetKeyUsage(&myCert, ","), WC_NO_ERR_TRACE(KEYUSAGE_E)); ExpectIntEQ(wc_SetKeyUsage(&myCert, "digitalSignature, cRLSign"), WC_NO_ERR_TRACE(KEYUSAGE_E)); #endif return EXPECT_RESULT(); } /* END test_wc_SetKeyUsage */ #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) static void sample_mutex_cb (int flag, int type, const char* file, int line) { (void)flag; (void)type; (void)file; (void)line; } #endif /* * Testing wc_LockMutex_ex */ static int test_wc_LockMutex_ex(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) int flag = CRYPTO_LOCK; int type = 0; const char* file = "./test-LockMutex_ex.txt"; int line = 0; /* without SetMutexCb */ ExpectIntEQ(wc_LockMutex_ex(flag, type, file, line), WC_NO_ERR_TRACE(BAD_STATE_E)); /* with SetMutexCb */ ExpectIntEQ(wc_SetMutexCb(sample_mutex_cb), 0); ExpectIntEQ(wc_LockMutex_ex(flag, type, file, line), 0); ExpectIntEQ(wc_SetMutexCb(NULL), 0); #endif return EXPECT_RESULT(); } /* End test_wc_LockMutex_ex*/ /* * Testing wc_SetMutexCb */ static int test_wc_SetMutexCb(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) ExpectIntEQ(wc_SetMutexCb(sample_mutex_cb), 0); ExpectIntEQ(wc_SetMutexCb(NULL), 0); #endif return EXPECT_RESULT(); } /* End test_wc_SetMutexCb*/ /* * Testing ToTraditional */ static int test_ToTraditional(void) { EXPECT_DECLS; #if !defined(NO_ASN) && (defined(HAVE_PKCS8) || defined(HAVE_PKCS12)) && \ (defined(WOLFSSL_TEST_CERT) || defined(OPENSSL_EXTRA) || \ defined(OPENSSL_EXTRA_X509_SMALL)) && !defined(NO_FILESYSTEM) XFILE f = XBADFILE; byte input[TWOK_BUF]; word32 sz = 0; ExpectTrue((f = XFOPEN("./certs/server-keyPkcs8.der", "rb")) != XBADFILE); ExpectTrue((sz = (word32)XFREAD(input, 1, sizeof(input), f)) > 0); if (f != XBADFILE) XFCLOSE(f); /* Good case */ ExpectIntGT(ToTraditional(input, sz), 0); /* Bad cases */ ExpectIntEQ(ToTraditional(NULL, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(ToTraditional(NULL, sz), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); #ifdef WOLFSSL_ASN_TEMPLATE ExpectIntEQ(ToTraditional(input, 0), WC_NO_ERR_TRACE(BUFFER_E)); #else ExpectIntEQ(ToTraditional(input, 0), WC_NO_ERR_TRACE(ASN_PARSE_E)); #endif #endif return EXPECT_RESULT(); } /* End test_ToTraditional*/ /* * Testing wc_SetSubjectBuffer */ static int test_wc_SetSubjectBuffer(void) { EXPECT_DECLS; #if defined(WOLFSSL_CERT_GEN) && !defined(NO_RSA) && !defined(NO_FILESYSTEM) Cert cert; XFILE file = XBADFILE; byte* der = NULL; word32 derSz; derSz = FOURK_BUF; ExpectNotNull(der = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER)); ExpectTrue((file = XFOPEN("./certs/ca-cert.der", "rb")) != XBADFILE); ExpectTrue((derSz = (word32)XFREAD(der, 1, FOURK_BUF, file)) > 0); if (file != XBADFILE) XFCLOSE(file); ExpectIntEQ(wc_InitCert(&cert), 0); ExpectIntEQ(wc_SetSubjectBuffer(&cert, der, (int)derSz), 0); ExpectIntEQ(wc_SetSubjectBuffer(NULL, der, (int)derSz), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); #endif return EXPECT_RESULT(); } /* End test_wc_SetSubjectBuffer*/ /* * Testing wc_SetSubjectKeyIdFromPublicKey_ex */ static int test_wc_SetSubjectKeyIdFromPublicKey_ex(void) { EXPECT_DECLS; #if defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CERT_GEN) WC_RNG rng; Cert cert; #if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) RsaKey rsaKey; int bits = 2048; #endif #if defined(HAVE_ECC) ecc_key eccKey; int ret; #endif #if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_EXPORT) ed25519_key ed25519Key; #endif #if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_EXPORT) ed448_key ed448Key; #endif #ifndef HAVE_FIPS ExpectIntEQ(wc_InitRng_ex(&rng, HEAP_HINT, testDevId), 0); #else ExpectIntEQ(wc_InitRng(&rng), 0); #endif ExpectIntEQ(wc_InitCert(&cert), 0); #if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) /* RSA */ XMEMSET(&rsaKey, 0, sizeof(RsaKey)); ExpectIntEQ(wc_InitRsaKey(&rsaKey, HEAP_HINT), 0); ExpectIntEQ(MAKE_RSA_KEY(&rsaKey, bits, WC_RSA_EXPONENT, &rng), 0); ExpectIntEQ(wc_SetSubjectKeyIdFromPublicKey_ex(&cert, RSA_TYPE, &rsaKey), 0); DoExpectIntEQ(wc_FreeRsaKey(&rsaKey), 0); #endif #if defined(HAVE_ECC) /* ECC */ XMEMSET(&eccKey, 0, sizeof(ecc_key)); ExpectIntEQ(wc_ecc_init(&eccKey), 0); ret = wc_ecc_make_key(&rng, KEY14, &eccKey); #if defined(WOLFSSL_ASYNC_CRYPT) ret = wc_AsyncWait(ret, &eccKey.asyncDev, WC_ASYNC_FLAG_NONE); #endif ExpectIntEQ(ret, 0); ExpectIntEQ(wc_SetSubjectKeyIdFromPublicKey_ex(&cert, ECC_TYPE, &eccKey), 0); DoExpectIntEQ(wc_ecc_free(&eccKey), 0); #endif #if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_EXPORT) /* ED25519 */ XMEMSET(&ed25519Key, 0, sizeof(ed25519_key)); ExpectIntEQ(wc_ed25519_init(&ed25519Key), 0); ExpectIntEQ(wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, &ed25519Key), 0); ExpectIntEQ(wc_SetSubjectKeyIdFromPublicKey_ex(&cert, ED25519_TYPE, &ed25519Key), 0); wc_ed25519_free(&ed25519Key); #endif #if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_EXPORT) /* ED448 */ XMEMSET(&ed448Key, 0, sizeof(ed448_key)); ExpectIntEQ(wc_ed448_init(&ed448Key), 0); ExpectIntEQ(wc_ed448_make_key(&rng, ED448_KEY_SIZE, &ed448Key), 0); ExpectIntEQ(wc_SetSubjectKeyIdFromPublicKey_ex(&cert, ED448_TYPE, &ed448Key), 0); wc_ed448_free(&ed448Key); #endif wc_FreeRng(&rng); DoExpectIntEQ(wc_FreeRng(&rng), 0); #endif /* WOLFSSL_CERT_EXT && WOLFSSL_CERT_GEN */ return EXPECT_RESULT(); } /* End test_wc_SetSubjectKeyIdFromPublicKey_ex*/ /* * Testing wc_SetAuthKeyIdFromPublicKey_ex */ static int test_wc_SetAuthKeyIdFromPublicKey_ex(void) { EXPECT_DECLS; #if defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CERT_GEN) WC_RNG rng; Cert cert; #if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) RsaKey rsaKey; int bits = 2048; #endif #if defined(HAVE_ECC) ecc_key eccKey; int ret; #endif #if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_EXPORT) ed25519_key ed25519Key; #endif #if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_EXPORT) ed448_key ed448Key; #endif #ifndef HAVE_FIPS ExpectIntEQ(wc_InitRng_ex(&rng, HEAP_HINT, testDevId), 0); #else ExpectIntEQ(wc_InitRng(&rng), 0); #endif ExpectIntEQ(wc_InitCert(&cert), 0); #if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) /* RSA */ XMEMSET(&rsaKey, 0, sizeof(RsaKey)); ExpectIntEQ(wc_InitRsaKey(&rsaKey, HEAP_HINT), 0); ExpectIntEQ(MAKE_RSA_KEY(&rsaKey, bits, WC_RSA_EXPONENT, &rng), 0); ExpectIntEQ(wc_SetAuthKeyIdFromPublicKey_ex(&cert, RSA_TYPE, &rsaKey), 0); DoExpectIntEQ(wc_FreeRsaKey(&rsaKey), 0); #endif #if defined(HAVE_ECC) /* ECC */ XMEMSET(&eccKey, 0, sizeof(ecc_key)); ExpectIntEQ(wc_ecc_init(&eccKey), 0); ret = wc_ecc_make_key(&rng, KEY14, &eccKey); #if defined(WOLFSSL_ASYNC_CRYPT) ret = wc_AsyncWait(ret, &eccKey.asyncDev, WC_ASYNC_FLAG_NONE); #endif ExpectIntEQ(ret, 0); ExpectIntEQ(wc_SetAuthKeyIdFromPublicKey_ex(&cert, ECC_TYPE, &eccKey), 0); DoExpectIntEQ(wc_ecc_free(&eccKey), 0); #endif #if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_EXPORT) /* ED25519 */ XMEMSET(&ed25519Key, 0, sizeof(ed25519_key)); ExpectIntEQ(wc_ed25519_init(&ed25519Key), 0); ExpectIntEQ(wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, &ed25519Key), 0); ExpectIntEQ(wc_SetAuthKeyIdFromPublicKey_ex(&cert, ED25519_TYPE, &ed25519Key), 0); wc_ed25519_free(&ed25519Key); #endif #if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_EXPORT) /* ED448 */ XMEMSET(&ed448Key, 0, sizeof(ed448_key)); ExpectIntEQ(wc_ed448_init(&ed448Key), 0); ExpectIntEQ(wc_ed448_make_key(&rng, ED448_KEY_SIZE, &ed448Key), 0); ExpectIntEQ(wc_SetAuthKeyIdFromPublicKey_ex(&cert, ED448_TYPE, &ed448Key), 0); wc_ed448_free(&ed448Key); #endif DoExpectIntEQ(wc_FreeRng(&rng), 0); #endif /* defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CERT_GEN)*/ return EXPECT_RESULT(); } /* End test_wc_SetAuthKeyIdFromPublicKey_ex*/ static int test_wolfSSL_lhash(void) { EXPECT_DECLS; #ifdef OPENSSL_ALL const char testStr[] = "Like a true nature's child\n" "We were born\n" "Born to be wild"; #ifdef NO_SHA ExpectIntEQ(lh_strhash(testStr), 0xf9dc8a43); #else ExpectIntEQ(lh_strhash(testStr), 0x5b7541dc); #endif #endif return EXPECT_RESULT(); } static int test_wc_PemToDer(void) { EXPECT_DECLS; #if !defined(NO_CERTS) && defined(WOLFSSL_PEM_TO_DER) && !defined(NO_FILESYSTEM) int ret; DerBuffer* pDer = NULL; const char* ca_cert = "./certs/server-cert.pem"; const char* trusted_cert = "./certs/test/ossl-trusted-cert.pem"; byte* cert_buf = NULL; size_t cert_sz = 0; int eccKey = 0; EncryptedInfo info; XMEMSET(&info, 0, sizeof(info)); ExpectIntEQ(ret = load_file(ca_cert, &cert_buf, &cert_sz), 0); ExpectIntEQ(ret = wc_PemToDer(cert_buf, (long int)cert_sz, CERT_TYPE, &pDer, NULL, &info, &eccKey), 0); wc_FreeDer(&pDer); pDer = NULL; if (cert_buf != NULL) { XFREE(cert_buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); cert_buf = NULL; } /* Test that -----BEGIN TRUSTED CERTIFICATE----- banner parses OK */ ExpectIntEQ(ret = load_file(trusted_cert, &cert_buf, &cert_sz), 0); ExpectIntEQ(ret = wc_PemToDer(cert_buf, (long int)cert_sz, TRUSTED_CERT_TYPE, &pDer, NULL, &info, &eccKey), 0); wc_FreeDer(&pDer); pDer = NULL; if (cert_buf != NULL) { XFREE(cert_buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); cert_buf = NULL; } #ifdef HAVE_ECC { const char* ecc_private_key = "./certs/ecc-privOnlyKey.pem"; byte key_buf[256] = {0}; /* Test fail of loading a key with cert type */ ExpectIntEQ(load_file(ecc_private_key, &cert_buf, &cert_sz), 0); key_buf[0] = '\n'; ExpectNotNull(XMEMCPY(key_buf + 1, cert_buf, cert_sz)); ExpectIntNE((ret = wc_PemToDer(key_buf, (long int)cert_sz + 1, CERT_TYPE, &pDer, NULL, &info, &eccKey)), 0); #ifdef OPENSSL_EXTRA ExpectIntEQ((ret = wc_PemToDer(key_buf, cert_sz + 1, PRIVATEKEY_TYPE, &pDer, NULL, &info, &eccKey)), 0); #endif wc_FreeDer(&pDer); if (cert_buf != NULL) XFREE(cert_buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); } #endif /* NULL buff, zero size, and negative size must be rejected up front. The * pre-fix code cast longSz to word32, so a negative value drove an * over-read inside PemToDer. */ { const byte stub[] = "x"; DerBuffer* badDer = NULL; ExpectIntEQ(wc_PemToDer(NULL, 100, CERT_TYPE, &badDer, NULL, &info, &eccKey), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wc_PemToDer(stub, 0, CERT_TYPE, &badDer, NULL, &info, &eccKey), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wc_PemToDer(stub, -1, CERT_TYPE, &badDer, NULL, &info, &eccKey), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); } #endif return EXPECT_RESULT(); } static int test_wc_AllocDer(void) { EXPECT_DECLS; #if !defined(NO_CERTS) DerBuffer* pDer = NULL; word32 testSize = 1024; ExpectIntEQ(wc_AllocDer(NULL, testSize, CERT_TYPE, HEAP_HINT), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wc_AllocDer(&pDer, testSize, CERT_TYPE, HEAP_HINT), 0); ExpectNotNull(pDer); wc_FreeDer(&pDer); #endif return EXPECT_RESULT(); } static int test_wc_CertPemToDer(void) { EXPECT_DECLS; #if !defined(NO_CERTS) && defined(WOLFSSL_PEM_TO_DER) && !defined(NO_FILESYSTEM) const char* ca_cert = "./certs/ca-cert.pem"; byte* cert_buf = NULL; size_t cert_sz = 0; size_t cert_dersz = 0; byte* cert_der = NULL; ExpectIntEQ(load_file(ca_cert, &cert_buf, &cert_sz), 0); cert_dersz = cert_sz; /* DER will be smaller than PEM */ ExpectNotNull(cert_der = (byte*)malloc(cert_dersz)); ExpectIntGE(wc_CertPemToDer(cert_buf, (int)cert_sz, cert_der, (int)cert_dersz, CERT_TYPE), 0); ExpectIntEQ(wc_CertPemToDer(NULL, (int)cert_sz, NULL, -1, CERT_TYPE), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wc_CertPemToDer(cert_buf, (int)cert_sz, NULL, -1, CERT_TYPE), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wc_CertPemToDer(NULL, (int)cert_sz, cert_der, -1, CERT_TYPE), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wc_CertPemToDer(NULL, (int)cert_sz, NULL, (int)cert_dersz, CERT_TYPE), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wc_CertPemToDer(NULL, (int)cert_sz, cert_der, (int)cert_dersz, CERT_TYPE), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wc_CertPemToDer(cert_buf, (int)cert_sz, NULL, (int)cert_dersz, CERT_TYPE), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wc_CertPemToDer(cert_buf, (int)cert_sz, cert_der, -1, CERT_TYPE), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wc_CertPemToDer(cert_buf, -1, cert_der, (int)cert_dersz, CERT_TYPE), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wc_CertPemToDer(cert_buf, 0, cert_der, (int)cert_dersz, CERT_TYPE), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); if (cert_der != NULL) free(cert_der); if (cert_buf != NULL) XFREE(cert_buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return EXPECT_RESULT(); } static int test_wc_KeyPemToDer(void) { EXPECT_DECLS; #if defined(WOLFSSL_PEM_TO_DER) && !defined(NO_FILESYSTEM) && !defined(NO_RSA) int ret = 0; const byte cert_buf[] = \ "-----BEGIN PRIVATE KEY-----\n" "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDMG5KgWxP002pA\n" "QJIdA4H5N0oM1Wf0LrHcos5RYUlrHDkC2b5p2BUpVRPmgDAFD2+8leim98x0BvcB\n" "k48TNzrVynuwyVEY664+iQyzEBO5v27HPRydOddprbLCvRO036XINGIjauy1jHFi\n" "HaDVx3bexSwgp9aefUGAszFXi4q1J4GacV7Cr2b/wBqUHqWv4ZXPu6R9/UYngTkD\n" "UDJL5gLlLfcLzNyyodKPHPCIAKdWn6mSVdcHk8XVpK4y9lgz4E7YDWA6ohKZgWgG\n" "2RDha8CMilFMDgYa0G0SiS9g3PQx0qh3AMXJJsKSVhScFCZufAE0kV6KvjP7jAqP\n" "XBiSkRGPAgMBAAECggEAW7hmRyY2jRX2UMJThrM9VIs6fRLnYI0dQ0tsEJj536ay\n" "nevQjArc05KWW0Yujg+WRDZPcry3RUqd9Djlmhp/F3Si6dpF1b+PMS3wJYVrf9Sd\n" "SO5W7faArU4vnyBNe0HnY1Ta5xSVI65lg1RSIs88RTZwsooJwXYDGf0shq0/21CE\n" "V8HOb27DDYNcEnm35lzaONjFnMqQQT2Vs9anRrPiSEXNleEvTgLVXZtGTyCGTz6v\n" "x86Y8eSWL9YNHvPE1I+mDPuocfSR7eRNgRu7SK3mn94W5mqd7Ns072YKX/2XN1mO\n" "66+ZFHO6v4dK1u7cSjuwrU1EhLHpUsgDz6Bna5InyQKBgQDv5l8RPy8UneKSADaf\n" "M5L/5675I/5t4nqVjvbnQje00YveLTAEjlJBNR93Biln3sYgnvNamYDCxyEuUZ/I\n" "S/vmBL9PoxfGZow4FcsIBOEbIn3E0SYJgCBNWthquUvGpKsYDnThJuhO+1cVmxAJ\n" "BUOjLFnJYHM0a+Vmk9GexT2OBwKBgQDZzkUBOK7Im3eiYytFocUJyhqMH30d49X9\n" "ujC7kGw4UWAqVe7YCSvlBa8nzWpRWK2kRpu3M0272RU0V4geyWqT+nr/SvRRPtNP\n" "F5dY8l3yR7hjtSejqqjOfBcZT6ETJxI4tiG0+Nl5BlfM5M+0nxnkWpRcHuOR3j79\n" "YUFERyN+OQKBgQCjlOKeUAc6d65W/+4/AFvsQ378Q57qLtSHxsR1TKHPmlNVXFqx\n" "wJo1/JNIBduWCEHxXHF0BdfW+RGXE/FwEt/hKLuLAhrkHmjelX2sKieU6R/5ZOQa\n" "9lMQbDHGFDOncAF6leD85hriQGBRSzrT69MDIOrYdfwYcroqCAGX0cb3YQKBgQC8\n" "iIFQylj5SyHmjcMSNjKSA8CxFDzAV8yPIdE3Oo+CvGXqn5HsrRuy1hXE9VmXapR8\n" "A6ackSszdHiXY0FvrNe1mfdH7wDHJwPQjdIzazCJHS3uGQxj7sDKY7226ie6pXJv\n" "ZrCMr2/IBAaSVGm6ppHKCeIsT4ybYm7R85KEYLPHeQKBgBeJOMBinXQfWN/1jT9b\n" "6Ywrutvp2zP8hVxQGSZJ0WG4iewZyFLsPUlbWRXOSYNPElHmdD0ZomdLVm+lSpAA\n" "XSH5FJ/IFCwqq7Eft6Gf8NFRV+NjPMUny+PnjHe4oFP8YK/Ek22K3ttNG8Hw69Aw\n" "AQue5o6oVfhgLiJzMdo/77gw\n" "-----END PRIVATE KEY-----\n"; const int cert_sz = sizeof(cert_buf); const char cert_pw[] = "password"; int cert_dersz = 0; byte* cert_der = NULL; /* Bad arg: Cert buffer is NULL */ ExpectIntEQ(wc_KeyPemToDer(NULL, cert_sz, cert_der, cert_dersz, ""), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* Bad arg: Cert DER buffer non-NULL but size zero (or less) */ ExpectIntEQ(wc_KeyPemToDer(cert_buf, cert_sz, (byte*)&cert_der, 0, ""), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* Bad arg: negative or zero pemSz */ ExpectIntEQ(wc_KeyPemToDer(cert_buf, -1, (byte*)&cert_der, cert_sz, ""), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wc_KeyPemToDer(cert_buf, 0, (byte*)&cert_der, cert_sz, ""), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* Test normal operation */ cert_dersz = cert_sz; /* DER will be smaller than PEM */ ExpectNotNull(cert_der = (byte*)malloc((size_t)cert_dersz)); ExpectIntGE(ret = wc_KeyPemToDer(cert_buf, cert_sz, cert_der, cert_dersz, cert_pw), 0); ExpectIntLE(ret, cert_sz); if (cert_der != NULL) { free(cert_der); cert_der = NULL; } /* Test NULL for DER buffer to return needed DER buffer size */ ExpectIntGT(ret = wc_KeyPemToDer(cert_buf, cert_sz, NULL, 0, ""), 0); ExpectIntLE(ret, cert_sz); if (EXPECT_SUCCESS()) cert_dersz = ret; ExpectNotNull(cert_der = (byte*)malloc((size_t)cert_dersz)); ExpectIntGE(ret = wc_KeyPemToDer(cert_buf, cert_sz, cert_der, cert_dersz, cert_pw), 0); ExpectIntLE(ret, cert_sz); if (cert_der != NULL) free(cert_der); #endif return EXPECT_RESULT(); } static int test_wc_PubKeyPemToDer(void) { EXPECT_DECLS; #if defined(WOLFSSL_PEM_TO_DER) && !defined(NO_FILESYSTEM) && \ (defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_PUB_PEM_TO_DER)) int ret = 0; const char* key = "./certs/ecc-client-keyPub.pem"; byte* cert_buf = NULL; size_t cert_sz = 0, cert_dersz = 0; byte* cert_der = NULL; ExpectIntEQ(wc_PubKeyPemToDer(cert_buf, (int)cert_sz, cert_der, (int)cert_dersz), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(load_file(key, &cert_buf, &cert_sz), 0); cert_dersz = cert_sz; /* DER will be smaller than PEM */ ExpectNotNull(cert_der = (byte*)malloc(cert_dersz)); ExpectIntEQ(wc_PubKeyPemToDer(cert_buf, -1, cert_der, (int)cert_dersz), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wc_PubKeyPemToDer(cert_buf, 0, cert_der, (int)cert_dersz), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntGE(wc_PubKeyPemToDer(cert_buf, (int)cert_sz, cert_der, (int)cert_dersz), 0); if (cert_der != NULL) { free(cert_der); cert_der = NULL; } /* Test NULL for DER buffer to return needed DER buffer size */ ExpectIntGT(ret = wc_PubKeyPemToDer(cert_buf, (int)cert_sz, NULL, 0), 0); ExpectIntLE(ret, cert_sz); cert_dersz = (size_t)ret; ExpectNotNull(cert_der = (byte*)malloc(cert_dersz)); ExpectIntGE(wc_PubKeyPemToDer(cert_buf, (int)cert_sz, cert_der, (int)cert_dersz), 0); if (cert_der != NULL) { free(cert_der); } if (cert_buf != NULL) { XFREE(cert_buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); } #endif return EXPECT_RESULT(); } static int test_wc_PemPubKeyToDer(void) { EXPECT_DECLS; #if !defined(NO_FILESYSTEM) && \ (defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_PUB_PEM_TO_DER)) const char* key = "./certs/ecc-client-keyPub.pem"; size_t cert_dersz = 1024; byte* cert_der = NULL; ExpectIntGE(wc_PemPubKeyToDer(NULL, cert_der, (int)cert_dersz), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectNotNull(cert_der = (byte*)malloc(cert_dersz)); ExpectIntGE(wc_PemPubKeyToDer(key, cert_der, (int)cert_dersz), 0); if (cert_der != NULL) { free(cert_der); } #endif return EXPECT_RESULT(); } static int test_wc_GetPubKeyDerFromCert(void) { EXPECT_DECLS; #if !defined(NO_RSA) || defined(HAVE_ECC) int ret; word32 idx = 0; byte keyDer[TWOK_BUF]; /* large enough for up to RSA 2048 */ word32 keyDerSz = (word32)sizeof(keyDer); DecodedCert decoded; #if !defined(NO_RSA) && defined(WOLFSSL_CERT_REQ) && !defined(NO_FILESYSTEM) byte certBuf[6000]; /* for PEM and CSR, client-cert.pem is 5-6kB */ word32 certBufSz = sizeof(certBuf); #endif #if ((!defined(USE_CERT_BUFFERS_2048) && !defined(USE_CERT_BUFFERS_1024)) || \ defined(WOLFSSL_CERT_REQ)) && !defined(NO_RSA) && !defined(NO_FILESYSTEM) XFILE fp = XBADFILE; #endif #ifndef NO_RSA RsaKey rsaKey; #if defined(USE_CERT_BUFFERS_2048) byte* rsaCertDer = (byte*)client_cert_der_2048; word32 rsaCertDerSz = sizeof_client_cert_der_2048; #elif defined(USE_CERT_BUFFERS_1024) byte* rsaCertDer = (byte*)client_cert_der_1024; word32 rsaCertDerSz = sizeof_client_cert_der_1024; #else unsigned char rsaCertDer[TWOK_BUF]; word32 rsaCertDerSz; #endif #endif #ifdef HAVE_ECC ecc_key eccKey; #if defined(USE_CERT_BUFFERS_256) byte* eccCert = (byte*)cliecc_cert_der_256; word32 eccCertSz = sizeof_cliecc_cert_der_256; #else unsigned char eccCert[ONEK_BUF]; word32 eccCertSz; XFILE fp2 = XBADFILE; #endif #endif #ifndef NO_RSA #if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) ExpectTrue((fp = XFOPEN("./certs/1024/client-cert.der", "rb")) != XBADFILE); ExpectIntGT(rsaCertDerSz = (word32)XFREAD(rsaCertDer, 1, sizeof(rsaCertDer), fp), 0); if (fp != XBADFILE) { XFCLOSE(fp); fp = XBADFILE; } #endif /* good test case - RSA DER cert */ wc_InitDecodedCert(&decoded, rsaCertDer, rsaCertDerSz, NULL); ExpectIntEQ(wc_ParseCert(&decoded, CERT_TYPE, NO_VERIFY, NULL), 0); ExpectIntEQ(wc_GetPubKeyDerFromCert(&decoded, keyDer, &keyDerSz), 0); ExpectIntGT(keyDerSz, 0); /* sanity check, verify we can import DER public key */ ret = wc_InitRsaKey(&rsaKey, HEAP_HINT); ExpectIntEQ(ret, 0); ExpectIntEQ(wc_RsaPublicKeyDecode(keyDer, &idx, &rsaKey, keyDerSz), 0); if (ret == 0) { wc_FreeRsaKey(&rsaKey); } /* test LENGTH_ONLY_E case */ keyDerSz = 0; ExpectIntEQ(wc_GetPubKeyDerFromCert(&decoded, NULL, &keyDerSz), WC_NO_ERR_TRACE(LENGTH_ONLY_E)); ExpectIntGT(keyDerSz, 0); /* bad args: DecodedCert NULL */ ExpectIntEQ(wc_GetPubKeyDerFromCert(NULL, keyDer, &keyDerSz), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* bad args: output key buff size */ ExpectIntEQ(wc_GetPubKeyDerFromCert(&decoded, keyDer, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* bad args: zero size output key buffer */ keyDerSz = 0; ExpectIntEQ(ret = wc_GetPubKeyDerFromCert(&decoded, keyDer, &keyDerSz), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); wc_FreeDecodedCert(&decoded); /* Certificate Request Tests */ #if defined(WOLFSSL_CERT_REQ) && !defined(NO_FILESYSTEM) { XMEMSET(certBuf, 0, sizeof(certBuf)); ExpectTrue((fp = XFOPEN("./certs/csr.signed.der", "rb")) != XBADFILE); ExpectIntGT(certBufSz = (word32)XFREAD(certBuf, 1, certBufSz, fp), 0); if (fp != XBADFILE) { XFCLOSE(fp); } wc_InitDecodedCert(&decoded, certBuf, certBufSz, NULL); ExpectIntEQ(wc_ParseCert(&decoded, CERTREQ_TYPE, VERIFY, NULL), 0); /* good test case - RSA DER certificate request */ keyDerSz = sizeof(keyDer); ExpectIntEQ(ret = wc_GetPubKeyDerFromCert(&decoded, keyDer, &keyDerSz), 0); ExpectIntGT(keyDerSz, 0); /* sanity check, verify we can import DER public key */ ret = wc_InitRsaKey(&rsaKey, HEAP_HINT); ExpectIntEQ(ret, 0); idx = 0; ExpectIntEQ(wc_RsaPublicKeyDecode(keyDer, &idx, &rsaKey, keyDerSz), 0); if (ret == 0) { wc_FreeRsaKey(&rsaKey); } wc_FreeDecodedCert(&decoded); } #endif /* WOLFSSL_CERT_REQ */ #endif /* NO_RSA */ #ifdef HAVE_ECC #ifndef USE_CERT_BUFFERS_256 ExpectTrue((fp2 = XFOPEN("./certs/client-ecc-cert.der", "rb")) != XBADFILE); ExpectIntGT(eccCertSz = (word32)XFREAD(eccCert, 1, ONEK_BUF, fp2), 0); if (fp2 != XBADFILE) { XFCLOSE(fp2); } #endif wc_InitDecodedCert(&decoded, eccCert, eccCertSz, NULL); ExpectIntEQ(wc_ParseCert(&decoded, CERT_TYPE, NO_VERIFY, NULL), 0); /* good test case - ECC */ XMEMSET(keyDer, 0, sizeof(keyDer)); keyDerSz = sizeof(keyDer); ExpectIntEQ(wc_GetPubKeyDerFromCert(&decoded, keyDer, &keyDerSz), 0); ExpectIntGT(keyDerSz, 0); /* sanity check, verify we can import DER public key */ ret = wc_ecc_init(&eccKey); ExpectIntEQ(ret, 0); idx = 0; /* reset idx to 0, used above in RSA case */ ExpectIntEQ(wc_EccPublicKeyDecode(keyDer, &idx, &eccKey, keyDerSz), 0); if (ret == 0) { wc_ecc_free(&eccKey); } /* test LENGTH_ONLY_E case */ keyDerSz = 0; ExpectIntEQ(wc_GetPubKeyDerFromCert(&decoded, NULL, &keyDerSz), WC_NO_ERR_TRACE(LENGTH_ONLY_E)); ExpectIntGT(keyDerSz, 0); wc_FreeDecodedCert(&decoded); #endif #endif /* !NO_RSA || HAVE_ECC */ return EXPECT_RESULT(); } static int test_wc_GetSubjectPubKeyInfoDerFromCert(void) { EXPECT_DECLS; #if !defined(NO_RSA) || defined(HAVE_ECC) int ret; word32 idx = 0; byte keyDer[TWOK_BUF]; /* large enough for up to RSA 2048 */ word32 keyDerSz = (word32)sizeof(keyDer); #if !defined(NO_RSA) && defined(WOLFSSL_CERT_REQ) && !defined(NO_FILESYSTEM) byte certBuf[6000]; /* for PEM and CSR, client-cert.pem is 5-6kB */ word32 certBufSz = sizeof(certBuf); #endif #if ((!defined(USE_CERT_BUFFERS_2048) && !defined(USE_CERT_BUFFERS_1024)) || \ defined(WOLFSSL_CERT_REQ)) && !defined(NO_RSA) && !defined(NO_FILESYSTEM) XFILE fp = XBADFILE; #endif #ifndef NO_RSA RsaKey rsaKey; #if defined(USE_CERT_BUFFERS_2048) byte* rsaCertDer = (byte*)client_cert_der_2048; word32 rsaCertDerSz = sizeof_client_cert_der_2048; #elif defined(USE_CERT_BUFFERS_1024) byte* rsaCertDer = (byte*)client_cert_der_1024; word32 rsaCertDerSz = sizeof_client_cert_der_1024; #else unsigned char rsaCertDer[TWOK_BUF]; word32 rsaCertDerSz; #endif #endif #ifdef HAVE_ECC ecc_key eccKey; #if defined(USE_CERT_BUFFERS_256) byte* eccCert = (byte*)cliecc_cert_der_256; word32 eccCertSz = sizeof_cliecc_cert_der_256; #else unsigned char eccCert[ONEK_BUF]; word32 eccCertSz; XFILE fp2 = XBADFILE; #endif #endif #ifndef NO_RSA #if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) ExpectTrue((fp = XFOPEN("./certs/1024/client-cert.der", "rb")) != XBADFILE); ExpectIntGT(rsaCertDerSz = (word32)XFREAD(rsaCertDer, 1, sizeof(rsaCertDer), fp), 0); if (fp != XBADFILE) { XFCLOSE(fp); fp = XBADFILE; } #endif /* good test case - RSA DER cert */ ExpectIntEQ(wc_GetSubjectPubKeyInfoDerFromCert(rsaCertDer, rsaCertDerSz, keyDer, &keyDerSz), 0); ExpectIntGT(keyDerSz, 0); /* sanity check, verify we can import DER public key */ ret = wc_InitRsaKey(&rsaKey, HEAP_HINT); ExpectIntEQ(ret, 0); ExpectIntEQ(wc_RsaPublicKeyDecode(keyDer, &idx, &rsaKey, keyDerSz), 0); if (ret == 0) { wc_FreeRsaKey(&rsaKey); } /* bad args: certDer */ keyDerSz = (word32)sizeof(keyDer); ExpectIntEQ(wc_GetSubjectPubKeyInfoDerFromCert(NULL, rsaCertDerSz, keyDer, &keyDerSz), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* bad args: 0 sized certSz */ keyDerSz = (word32)sizeof(keyDer); ExpectIntEQ(wc_GetSubjectPubKeyInfoDerFromCert(rsaCertDer, 0, keyDer, &keyDerSz), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* bad args: NULL inout size */ ExpectIntEQ(ret = wc_GetSubjectPubKeyInfoDerFromCert(rsaCertDer, rsaCertDerSz, keyDer, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* Certificate Request Tests */ #if defined(WOLFSSL_CERT_REQ) && !defined(NO_FILESYSTEM) { XMEMSET(certBuf, 0, sizeof(certBuf)); ExpectTrue((fp = XFOPEN("./certs/csr.signed.der", "rb")) != XBADFILE); ExpectIntGT(certBufSz = (word32)XFREAD(certBuf, 1, certBufSz, fp), 0); if (fp != XBADFILE) { XFCLOSE(fp); } /* good test case - RSA DER certificate request */ keyDerSz = sizeof(keyDer); ExpectIntEQ(ret = wc_GetSubjectPubKeyInfoDerFromCert(rsaCertDer, rsaCertDerSz, keyDer, &keyDerSz), 0); ExpectIntGT(keyDerSz, 0); /* sanity check, verify we can import DER public key */ ret = wc_InitRsaKey(&rsaKey, HEAP_HINT); ExpectIntEQ(ret, 0); idx = 0; ExpectIntEQ(wc_RsaPublicKeyDecode(keyDer, &idx, &rsaKey, keyDerSz), 0); if (ret == 0) { wc_FreeRsaKey(&rsaKey); } } #endif /* WOLFSSL_CERT_REQ */ #endif /* NO_RSA */ #ifdef HAVE_ECC #ifndef USE_CERT_BUFFERS_256 ExpectTrue((fp2 = XFOPEN("./certs/client-ecc-cert.der", "rb")) != XBADFILE); ExpectIntGT(eccCertSz = (word32)XFREAD(eccCert, 1, ONEK_BUF, fp2), 0); if (fp2 != XBADFILE) { XFCLOSE(fp2); } #endif /* good test case - ECC */ XMEMSET(keyDer, 0, sizeof(keyDer)); keyDerSz = sizeof(keyDer); ExpectIntEQ(wc_GetSubjectPubKeyInfoDerFromCert(eccCert, eccCertSz, keyDer, &keyDerSz), 0); ExpectIntGT(keyDerSz, 0); /* sanity check, verify we can import DER public key */ ret = wc_ecc_init(&eccKey); ExpectIntEQ(ret, 0); idx = 0; /* reset idx to 0, used above in RSA case */ ExpectIntEQ(wc_EccPublicKeyDecode(keyDer, &idx, &eccKey, keyDerSz), 0); if (ret == 0) { wc_ecc_free(&eccKey); } #endif #endif /* !NO_RSA || HAVE_ECC */ return EXPECT_RESULT(); } static int test_wc_CheckCertSigPubKey(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && !defined(NO_FILESYSTEM) && \ !defined(NO_RSA) && defined(WOLFSSL_PEM_TO_DER) && defined(HAVE_ECC) int ret = 0; const char* ca_cert = "./certs/ca-cert.pem"; byte* cert_buf = NULL; size_t cert_sz = 0; byte* cert_der = NULL; word32 cert_dersz = 0; byte keyDer[TWOK_BUF]; /* large enough for up to RSA 2048 */ word32 keyDerSz = (word32)sizeof(keyDer); DecodedCert decoded; ExpectIntEQ(load_file(ca_cert, &cert_buf, &cert_sz), 0); cert_dersz = (word32)cert_sz; /* DER will be smaller than PEM */ ExpectNotNull(cert_der = (byte*)malloc(cert_dersz)); ExpectIntGE(ret = wc_CertPemToDer(cert_buf, (int)cert_sz, cert_der, (int)cert_dersz, CERT_TYPE), 0); wc_InitDecodedCert(&decoded, cert_der, cert_dersz, NULL); ExpectIntEQ(wc_ParseCert(&decoded, CERT_TYPE, NO_VERIFY, NULL), 0); ExpectIntEQ(wc_GetPubKeyDerFromCert(&decoded, keyDer, &keyDerSz), 0); ExpectIntGT(keyDerSz, 0); /* Good test case. */ ExpectIntEQ(wc_CheckCertSigPubKey(cert_der, cert_dersz, NULL, keyDer, keyDerSz, RSAk), 0); /* No certificate. */ ExpectIntEQ(wc_CheckCertSigPubKey(NULL, cert_dersz, NULL, keyDer, keyDerSz, ECDSAk), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* Bad cert size. */ ExpectIntNE(ret = wc_CheckCertSigPubKey(cert_der, 0, NULL, keyDer, keyDerSz, RSAk), 0); ExpectTrue(ret == WC_NO_ERR_TRACE(ASN_PARSE_E) || ret == WC_NO_ERR_TRACE(BUFFER_E)); /* No public key. */ ExpectIntEQ(wc_CheckCertSigPubKey(cert_der, cert_dersz, NULL, NULL, keyDerSz, RSAk), WC_NO_ERR_TRACE(ASN_NO_SIGNER_E)); /* Bad public key size. */ ExpectIntEQ(wc_CheckCertSigPubKey(cert_der, cert_dersz, NULL, keyDer, 0, RSAk), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* Wrong algo. */ ExpectIntEQ(wc_CheckCertSigPubKey(cert_der, cert_dersz, NULL, keyDer, keyDerSz, ECDSAk), WC_NO_ERR_TRACE(ASN_SIG_OID_E)); wc_FreeDecodedCert(&decoded); if (cert_der != NULL) free(cert_der); if (cert_buf != NULL) XFREE(cert_buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return EXPECT_RESULT(); } static int test_wolfSSL_X509_ext_d2i(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) X509* x509 = NULL; ExpectNotNull(x509 = wolfSSL_X509_new()); ExpectNull(wolfSSL_X509_get_ext_d2i(x509, NID_basic_constraints, NULL, NULL)); ExpectNull(wolfSSL_X509_get_ext_d2i(x509, NID_subject_alt_name, NULL, NULL)); ExpectNull(wolfSSL_X509_get_ext_d2i(x509, NID_authority_key_identifier, NULL, NULL)); ExpectNull(wolfSSL_X509_get_ext_d2i(x509, NID_subject_key_identifier, NULL, NULL)); ExpectNull(wolfSSL_X509_get_ext_d2i(x509, NID_key_usage, NULL, NULL)); ExpectNull(wolfSSL_X509_get_ext_d2i(x509, NID_crl_distribution_points, NULL, NULL)); ExpectNull(wolfSSL_X509_get_ext_d2i(x509, NID_ext_key_usage, NULL, NULL)); ExpectNull(wolfSSL_X509_get_ext_d2i(x509, NID_info_access, NULL, NULL)); ExpectNull(wolfSSL_X509_get_ext_d2i(x509, NID_certificate_policies, NULL, NULL)); /* Invalid NID for an extension. */ ExpectNull(wolfSSL_X509_get_ext_d2i(x509, NID_description, NULL, NULL)); wolfSSL_X509_free(x509); #endif return EXPECT_RESULT(); } static int test_wolfSSL_certs(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && !defined(NO_FILESYSTEM) && \ !defined(NO_TLS) && !defined(NO_RSA) X509* x509ext = NULL; X509* x509 = NULL; #ifdef OPENSSL_ALL WOLFSSL_X509_EXTENSION* ext = NULL; ASN1_OBJECT* obj = NULL; #endif WOLFSSL* ssl = NULL; WOLFSSL_CTX* ctx = NULL; STACK_OF(ASN1_OBJECT)* sk = NULL; ASN1_STRING* asn1_str = NULL; AUTHORITY_KEYID* akey = NULL; WOLFSSL_STACK* skid = NULL; BASIC_CONSTRAINTS* bc = NULL; int crit = 0; #ifndef NO_WOLFSSL_SERVER ExpectNotNull(ctx = SSL_CTX_new(SSLv23_server_method())); #else ExpectNotNull(ctx = SSL_CTX_new(SSLv23_client_method())); #endif ExpectTrue(SSL_CTX_use_certificate_file(ctx, svrCertFile, SSL_FILETYPE_PEM)); ExpectTrue(SSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, SSL_FILETYPE_PEM)); ExpectTrue(SSL_CTX_use_PrivateKey_file(ctx, cliKeyFile, SSL_FILETYPE_PEM)); #if !defined(NO_CHECK_PRIVATE_KEY) ExpectIntEQ(SSL_CTX_check_private_key(ctx), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); #endif ExpectTrue(SSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, SSL_FILETYPE_PEM)); #if !defined(NO_CHECK_PRIVATE_KEY) ExpectIntEQ(SSL_CTX_check_private_key(ctx), SSL_SUCCESS); #endif ExpectNotNull(ssl = SSL_new(ctx)); /* Invalid parameters. */ ExpectIntEQ(SSL_use_certificate_file(NULL, NULL, WOLFSSL_FILETYPE_PEM), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(SSL_use_certificate_file(ssl, NULL, WOLFSSL_FILETYPE_PEM), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(SSL_use_certificate_file(NULL, "./certs/server-cert.pem", WOLFSSL_FILETYPE_PEM), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); #if !defined(NO_CHECK_PRIVATE_KEY) ExpectIntEQ(wolfSSL_check_private_key(ssl), WOLFSSL_SUCCESS); #endif #ifdef HAVE_PK_CALLBACKS ExpectIntEQ((int)SSL_set_tlsext_debug_arg(ssl, NULL), WOLFSSL_SUCCESS); #endif /* HAVE_PK_CALLBACKS */ /* Invalid parameters. */ ExpectNotNull(x509 = wolfSSL_X509_new()); ExpectIntEQ(SSL_use_certificate(NULL, NULL), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(SSL_use_certificate(ssl, NULL), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(SSL_use_certificate(NULL, x509), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); /* No data in certificate. */ ExpectIntEQ(SSL_use_certificate(ssl, x509), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); wolfSSL_X509_free(x509); x509 = NULL; /* create and use x509 */ ExpectNull(wolfSSL_X509_load_certificate_file(cliCertFileExt, -1)); ExpectNull(wolfSSL_X509_load_certificate_file("/tmp/badfile", WOLFSSL_FILETYPE_PEM)); ExpectNull(wolfSSL_X509_load_certificate_file(NULL, WOLFSSL_FILETYPE_PEM)); ExpectNull(wolfSSL_X509_load_certificate_file(cliCertFileExt, WOLFSSL_FILETYPE_ASN1)); #ifdef OPENSSL_ALL ExpectNotNull(x509 = wolfSSL_X509_load_certificate_file(cliCertFile, WOLFSSL_FILETYPE_PEM)); #endif ExpectNotNull(x509ext = wolfSSL_X509_load_certificate_file(cliCertFileExt, WOLFSSL_FILETYPE_PEM)); ExpectIntEQ(SSL_use_certificate(ssl, x509ext), WOLFSSL_SUCCESS); #if !defined(NO_CHECK_PRIVATE_KEY) /* with loading in a new cert the check on private key should now fail */ ExpectIntNE(wolfSSL_check_private_key(ssl), WOLFSSL_SUCCESS); #endif #if defined(USE_CERT_BUFFERS_2048) /* Invalid parameters. */ ExpectIntEQ(SSL_use_certificate_ASN1(NULL, NULL, 0), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(SSL_use_certificate_ASN1(ssl, NULL, 0), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(SSL_use_certificate_ASN1(NULL, (unsigned char*)server_cert_der_2048, 0), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); /* No data. */ ExpectIntEQ(SSL_use_certificate_ASN1(ssl, (unsigned char*)server_cert_der_2048, 0), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(SSL_use_certificate_ASN1(ssl, (unsigned char*)server_cert_der_2048, sizeof_server_cert_der_2048), WOLFSSL_SUCCESS); #endif #if !defined(NO_SHA) && !defined(NO_SHA256) && !defined(NO_PWDBASED) /************* Get Digest of Certificate ******************/ { byte digest[64]; /* max digest size */ word32 digestSz; X509* x509Empty = NULL; XMEMSET(digest, 0, sizeof(digest)); ExpectIntEQ(X509_digest(NULL, wolfSSL_EVP_sha1(), digest, &digestSz), WOLFSSL_FAILURE); ExpectIntEQ(X509_digest(x509ext, NULL, digest, &digestSz), WOLFSSL_FAILURE); ExpectIntEQ(X509_digest(x509ext, wolfSSL_EVP_sha1(), NULL, &digestSz), WOLFSSL_FAILURE); ExpectIntEQ(X509_digest(x509ext, wolfSSL_EVP_sha1(), digest, NULL), WOLFSSL_SUCCESS); ExpectIntEQ(X509_digest(x509ext, wolfSSL_EVP_sha1(), digest, &digestSz), WOLFSSL_SUCCESS); ExpectIntEQ(X509_digest(x509ext, wolfSSL_EVP_sha256(), digest, &digestSz), WOLFSSL_SUCCESS); ExpectNotNull(x509Empty = wolfSSL_X509_new()); ExpectIntEQ(X509_digest(x509Empty, wolfSSL_EVP_sha256(), digest, &digestSz), WOLFSSL_FAILURE); wolfSSL_X509_free(x509Empty); } #endif /* !NO_SHA && !NO_SHA256 && !NO_PWDBASED */ #if !defined(NO_SHA) && !defined(NO_SHA256) && !defined(NO_PWDBASED) /************* Get Digest of Certificate ******************/ { byte digest[64]; /* max digest size */ word32 digestSz; X509* x509Empty = NULL; XMEMSET(digest, 0, sizeof(digest)); ExpectIntEQ(X509_pubkey_digest(NULL, wolfSSL_EVP_sha1(), digest, &digestSz), WOLFSSL_FAILURE); ExpectIntEQ(X509_pubkey_digest(x509ext, NULL, digest, &digestSz), WOLFSSL_FAILURE); ExpectIntEQ(X509_pubkey_digest(x509ext, wolfSSL_EVP_sha1(), NULL, &digestSz), WOLFSSL_FAILURE); ExpectIntEQ(X509_pubkey_digest(x509ext, wolfSSL_EVP_sha1(), digest, NULL), WOLFSSL_SUCCESS); ExpectIntEQ(X509_pubkey_digest(x509ext, wolfSSL_EVP_sha1(), digest, &digestSz), WOLFSSL_SUCCESS); ExpectIntEQ(X509_pubkey_digest(x509ext, wolfSSL_EVP_sha256(), digest, &digestSz), WOLFSSL_SUCCESS); ExpectNotNull(x509Empty = wolfSSL_X509_new()); ExpectIntEQ(X509_pubkey_digest(x509Empty, wolfSSL_EVP_sha256(), digest, &digestSz), WOLFSSL_FAILURE); wolfSSL_X509_free(x509Empty); } #endif /* !NO_SHA && !NO_SHA256 && !NO_PWDBASED */ /* test and checkout X509 extensions */ ExpectNotNull(bc = (BASIC_CONSTRAINTS*)X509_get_ext_d2i(x509ext, NID_basic_constraints, NULL, NULL)); BASIC_CONSTRAINTS_free(bc); bc = NULL; ExpectNotNull(bc = (BASIC_CONSTRAINTS*)X509_get_ext_d2i(x509ext, NID_basic_constraints, &crit, NULL)); ExpectIntEQ(crit, 0); #ifdef OPENSSL_ALL ExpectNull(X509V3_EXT_i2d(NID_basic_constraints, crit, NULL)); { int i; int unsupportedNid[] = { 0, NID_inhibit_any_policy, NID_certificate_policies, NID_policy_mappings, NID_name_constraints, NID_policy_constraints, NID_crl_distribution_points }; int unsupportedNidCnt = (int)(sizeof(unsupportedNid) / sizeof(*unsupportedNid)); for (i = 0; i < unsupportedNidCnt; i++) { ExpectNotNull(ext = X509V3_EXT_i2d(unsupportedNid[i], crit, bc)); X509_EXTENSION_free(ext); ext = NULL; } } ExpectNotNull(ext = X509V3_EXT_i2d(NID_basic_constraints, crit, bc)); X509_EXTENSION_free(ext); ext = NULL; ExpectNotNull(ext = X509_EXTENSION_new()); ExpectIntEQ(X509_EXTENSION_set_critical(NULL, 1), WOLFSSL_FAILURE); ExpectIntEQ(X509_EXTENSION_set_critical(ext, 1), WOLFSSL_SUCCESS); ExpectNotNull(obj = OBJ_nid2obj(NID_basic_constraints)); ExpectIntEQ(X509_EXTENSION_set_object(NULL, NULL), SSL_FAILURE); ExpectIntEQ(X509_EXTENSION_set_object(NULL, obj), SSL_FAILURE); ExpectIntEQ(X509_EXTENSION_set_object(ext, NULL), SSL_SUCCESS); ExpectIntEQ(X509_EXTENSION_set_object(ext, obj), SSL_SUCCESS); /* Check old object is being freed. */ ExpectIntEQ(X509_EXTENSION_set_object(ext, obj), SSL_SUCCESS); ASN1_OBJECT_free(obj); obj = NULL; X509_EXTENSION_free(ext); ext = NULL; ExpectNotNull(ext = X509_EXTENSION_new()); ExpectIntEQ(X509_EXTENSION_set_critical(ext, 0), WOLFSSL_SUCCESS); ExpectIntEQ(X509_EXTENSION_set_data(ext, NULL), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectNotNull(asn1_str = (ASN1_STRING*)X509_get_ext_d2i(x509ext, NID_key_usage, NULL, NULL)); ASN1_STRING_free(asn1_str); asn1_str = NULL; ExpectNotNull(asn1_str = (ASN1_STRING*)X509_get_ext_d2i(x509ext, NID_key_usage, &crit, NULL)); ExpectIntEQ(X509_EXTENSION_set_data(ext, asn1_str), SSL_SUCCESS); ExpectIntEQ(X509_EXTENSION_set_data(ext, asn1_str), SSL_SUCCESS); ASN1_STRING_free(asn1_str); /* X509_EXTENSION_set_data has made a copy * and X509_get_ext_d2i has created new */ asn1_str = NULL; X509_EXTENSION_free(ext); ext = NULL; #endif BASIC_CONSTRAINTS_free(NULL); BASIC_CONSTRAINTS_free(bc); bc = NULL; ExpectNotNull(asn1_str = (ASN1_STRING*)X509_get_ext_d2i(x509ext, NID_key_usage, NULL, NULL)); ASN1_STRING_free(asn1_str); asn1_str = NULL; ExpectNotNull(asn1_str = (ASN1_STRING*)X509_get_ext_d2i(x509ext, NID_key_usage, &crit, NULL)); ExpectIntEQ(crit, 1); ExpectIntEQ(asn1_str->type, NID_key_usage); #ifdef OPENSSL_ALL ExpectNotNull(ext = X509V3_EXT_i2d(NID_key_usage, crit, asn1_str)); X509_EXTENSION_free(ext); ext = NULL; #endif ASN1_STRING_free(asn1_str); asn1_str = NULL; #ifdef OPENSSL_ALL ExpectNotNull(sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_ext_key_usage, NULL, NULL)); EXTENDED_KEY_USAGE_free(NULL); EXTENDED_KEY_USAGE_free(sk); sk = NULL; ExpectNotNull(sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_ext_key_usage, &crit, NULL)); ExpectNotNull(ext = X509V3_EXT_i2d(NID_ext_key_usage, crit, sk)); X509_EXTENSION_free(ext); ext = NULL; EXTENDED_KEY_USAGE_free(sk); sk = NULL; #else sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509ext, NID_ext_key_usage, &crit, NULL); ExpectNull(sk); #endif ExpectNotNull(akey = (AUTHORITY_KEYID*)X509_get_ext_d2i(x509ext, NID_authority_key_identifier, NULL, NULL)); wolfSSL_AUTHORITY_KEYID_free(NULL); wolfSSL_AUTHORITY_KEYID_free(akey); akey = NULL; ExpectNotNull(akey = (AUTHORITY_KEYID*)X509_get_ext_d2i(x509ext, NID_authority_key_identifier, &crit, NULL)); #ifdef OPENSSL_ALL ExpectNotNull(ext = X509V3_EXT_i2d(NID_authority_key_identifier, crit, akey)); X509_EXTENSION_free(ext); ext = NULL; #endif wolfSSL_AUTHORITY_KEYID_free(akey); akey = NULL; ExpectNotNull(skid = (WOLFSSL_STACK*)X509_get_ext_d2i(x509ext, NID_subject_key_identifier, NULL, NULL)); wolfSSL_sk_ASN1_OBJECT_pop_free(skid, wolfSSL_ASN1_OBJECT_free); skid = NULL; ExpectNotNull(skid = (WOLFSSL_STACK*)X509_get_ext_d2i(x509ext, NID_subject_key_identifier, &crit, NULL)); #ifdef OPENSSL_ALL ExpectNotNull(ext = X509V3_EXT_i2d(NID_subject_key_identifier, crit, skid)); X509_EXTENSION_free(ext); ext = NULL; #endif wolfSSL_sk_ASN1_OBJECT_pop_free(skid, wolfSSL_ASN1_OBJECT_free); skid = NULL; /* NID not yet supported */ ExpectNull(sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509ext, NID_private_key_usage_period, &crit, NULL)); ExpectIntEQ(crit, -1); sk_ASN1_OBJECT_free(sk); sk = NULL; ExpectNotNull(sk = (STACK_OF(GENERAL_NAME)*)X509_get_ext_d2i(x509ext, NID_subject_alt_name, NULL, NULL)); sk_GENERAL_NAME_free(sk); sk = NULL; ExpectNotNull(sk = (STACK_OF(GENERAL_NAME)*)X509_get_ext_d2i(x509ext, NID_subject_alt_name, &crit, NULL)); { int i; for (i = 0; i < sk_GENERAL_NAME_num(sk); i++) { GENERAL_NAME* gen = sk_GENERAL_NAME_value(sk, i); ExpectIntEQ(gen->type, GEN_DNS); ExpectIntEQ(gen->d.dNSName->type, V_ASN1_IA5STRING); } } sk_GENERAL_NAME_free(sk); sk = NULL; /* NID not yet supported */ ExpectNull(sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509ext, NID_issuer_alt_name, &crit, NULL)); ExpectIntEQ(crit, -1); sk_ASN1_OBJECT_free(sk); sk = NULL; /* NID not yet supported */ ExpectNull(sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509ext, NID_info_access, &crit, NULL)); sk_ASN1_OBJECT_free(sk); sk = NULL; /* NID not yet supported */ ExpectNull(sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509ext, NID_sinfo_access, &crit, NULL)); ExpectIntEQ(crit, -1); sk_ASN1_OBJECT_free(sk); sk = NULL; /* NID not yet supported */ ExpectNull(sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509ext, NID_name_constraints, &crit, NULL)); ExpectIntEQ(crit, -1); sk_ASN1_OBJECT_free(sk); sk = NULL; /* no cert policy set */ ExpectNull(sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509ext, NID_certificate_policies, &crit, NULL)); sk_ASN1_OBJECT_free(sk); sk = NULL; /* NID not yet supported */ ExpectNull(sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509ext, NID_policy_mappings, &crit, NULL)); ExpectIntEQ(crit, -1); sk_ASN1_OBJECT_free(sk); sk = NULL; /* NID not yet supported */ ExpectNull(sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509ext, NID_policy_constraints, &crit, NULL)); ExpectIntEQ(crit, -1); sk_ASN1_OBJECT_free(sk); sk = NULL; /* NID not yet supported */ ExpectNull(sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509ext, NID_inhibit_any_policy, &crit, NULL)); ExpectIntEQ(crit, -1); sk_ASN1_OBJECT_free(sk); sk = NULL; /* NID not yet supported */ ExpectNull(sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509ext, NID_tlsfeature, &crit, NULL)); ExpectIntEQ(crit, -1); sk_ASN1_OBJECT_free(sk); sk = NULL; /* test invalid cases */ crit = 0; ExpectNull(sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509ext, -1, &crit, NULL)); ExpectIntEQ(crit, -1); /* NULL passed for criticality. */ ExpectNull(sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(NULL, NID_tlsfeature, NULL, NULL)); ExpectIntEQ(SSL_get_hit(ssl), 0); #ifdef OPENSSL_ALL X509_free(x509); #endif X509_free(x509ext); SSL_free(ssl); SSL_CTX_free(ctx); #endif /* OPENSSL_EXTRA && !NO_CERTS */ return EXPECT_RESULT(); } static int test_wolfSSL_private_keys(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && !defined(NO_TLS) && \ !defined(NO_FILESYSTEM) #if !defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER) WOLFSSL* ssl = NULL; WOLFSSL_CTX* ctx = NULL; EVP_PKEY* pkey = NULL; OpenSSL_add_all_digests(); OpenSSL_add_all_algorithms(); #ifndef NO_RSA #ifndef NO_WOLFSSL_SERVER ExpectNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); #else ExpectNotNull(ctx = SSL_CTX_new(wolfSSLv23_client_method())); #endif ExpectTrue(SSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, WOLFSSL_FILETYPE_PEM)); /* Have to load a cert before you can check the private key against that * certificates public key! */ #if !defined(NO_CHECK_PRIVATE_KEY) ExpectIntEQ(wolfSSL_CTX_check_private_key(ctx), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); #endif ExpectTrue(SSL_CTX_use_certificate_file(ctx, svrCertFile, WOLFSSL_FILETYPE_PEM)); #if !defined(NO_CHECK_PRIVATE_KEY) ExpectIntEQ(wolfSSL_CTX_check_private_key(ctx), WOLFSSL_SUCCESS); #endif ExpectNotNull(ssl = SSL_new(ctx)); #if !defined(NO_CHECK_PRIVATE_KEY) ExpectIntEQ(wolfSSL_check_private_key(ssl), WOLFSSL_SUCCESS); #endif /* Invalid parameters. */ ExpectIntEQ(SSL_use_PrivateKey_file(NULL, NULL, WOLFSSL_FILETYPE_PEM), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(SSL_use_PrivateKey_file(NULL, svrKeyFile, WOLFSSL_FILETYPE_PEM), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(SSL_use_PrivateKey_file(ssl, NULL, WOLFSSL_FILETYPE_PEM), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); #ifdef USE_CERT_BUFFERS_2048 { const unsigned char* server_key = (const unsigned char*)server_key_der_2048; unsigned char buf[FOURK_BUF]; word32 bufSz; /* Invalid parameters. */ ExpectIntEQ(SSL_use_RSAPrivateKey_ASN1(NULL, NULL, 0), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(SSL_use_RSAPrivateKey_ASN1(ssl, NULL, 0), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(SSL_use_RSAPrivateKey_ASN1(NULL, (unsigned char*)client_key_der_2048, 0), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(SSL_use_PrivateKey_ASN1(0, NULL, NULL, 0), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(SSL_use_PrivateKey_ASN1(0, ssl, NULL, 0), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(SSL_use_PrivateKey_ASN1(0, NULL, (unsigned char*)server_key, 0), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(SSL_CTX_use_PrivateKey_ASN1(0, NULL, NULL, 0), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(SSL_CTX_use_PrivateKey_ASN1(0, ctx, NULL, 0), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(SSL_CTX_use_PrivateKey_ASN1(0, NULL, (unsigned char*)server_key, 0), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(SSL_use_RSAPrivateKey_ASN1(ssl, (unsigned char*)client_key_der_2048, sizeof_client_key_der_2048), WOLFSSL_SUCCESS); #if !defined(NO_CHECK_PRIVATE_KEY) /* Should mismatch now that a different private key loaded */ ExpectIntNE(wolfSSL_check_private_key(ssl), WOLFSSL_SUCCESS); #endif ExpectIntEQ(SSL_use_PrivateKey_ASN1(0, ssl, (unsigned char*)server_key, sizeof_server_key_der_2048), WOLFSSL_SUCCESS); #if !defined(NO_CHECK_PRIVATE_KEY) /* After loading back in DER format of original key, should match */ ExpectIntEQ(wolfSSL_check_private_key(ssl), WOLFSSL_SUCCESS); #endif /* test loading private key to the WOLFSSL_CTX */ ExpectIntEQ(SSL_CTX_use_PrivateKey_ASN1(0, ctx, (unsigned char*)client_key_der_2048, sizeof_client_key_der_2048), WOLFSSL_SUCCESS); #if !defined(NO_CHECK_PRIVATE_KEY) /* Should mismatch now that a different private key loaded */ ExpectIntNE(wolfSSL_CTX_check_private_key(ctx), WOLFSSL_SUCCESS); #endif ExpectIntEQ(SSL_CTX_use_PrivateKey_ASN1(0, ctx, (unsigned char*)server_key, sizeof_server_key_der_2048), WOLFSSL_SUCCESS); #if !defined(NO_CHECK_PRIVATE_KEY) /* After loading back in DER format of original key, should match */ ExpectIntEQ(wolfSSL_CTX_check_private_key(ctx), WOLFSSL_SUCCESS); #endif /* Invalid parameters. */ ExpectNotNull(pkey = wolfSSL_EVP_PKEY_new()); ExpectIntEQ(SSL_use_PrivateKey(NULL, NULL), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(SSL_use_PrivateKey(ssl, NULL), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(SSL_use_PrivateKey(NULL, pkey), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); /* pkey is empty - no key data to use. */ ExpectIntEQ(SSL_use_PrivateKey(ssl, pkey), WC_NO_ERR_TRACE(ASN_PARSE_E)); wolfSSL_EVP_PKEY_free(pkey); pkey = NULL; /* set PKEY and test again */ ExpectNotNull(wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, &pkey, &server_key, (long)sizeof_server_key_der_2048)); ExpectIntEQ(SSL_use_PrivateKey(ssl, pkey), WOLFSSL_SUCCESS); /* reuse PKEY structure and test * this should be checked with a memory management sanity checker */ ExpectFalse(server_key == (const unsigned char*)server_key_der_2048); server_key = (const unsigned char*)server_key_der_2048; ExpectNotNull(wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, &pkey, &server_key, (long)sizeof_server_key_der_2048)); ExpectIntEQ(SSL_use_PrivateKey(ssl, pkey), WOLFSSL_SUCCESS); /* check striping PKCS8 header with wolfSSL_d2i_PrivateKey */ bufSz = FOURK_BUF; ExpectIntGT((bufSz = (word32)wc_CreatePKCS8Key(buf, &bufSz, (byte*)server_key_der_2048, sizeof_server_key_der_2048, RSAk, NULL, 0)), 0); server_key = (const unsigned char*)buf; ExpectNotNull(wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, &pkey, &server_key, (long)bufSz)); } #endif EVP_PKEY_free(pkey); pkey = NULL; SSL_free(ssl); /* frees x509 also since loaded into ssl */ ssl = NULL; SSL_CTX_free(ctx); ctx = NULL; #endif /* end of RSA private key match tests */ #ifdef HAVE_ECC #ifndef NO_WOLFSSL_SERVER ExpectNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); #else ExpectNotNull(ctx = SSL_CTX_new(wolfSSLv23_client_method())); #endif ExpectTrue(SSL_CTX_use_certificate_file(ctx, eccCertFile, WOLFSSL_FILETYPE_PEM)); ExpectTrue(SSL_CTX_use_PrivateKey_file(ctx, eccKeyFile, WOLFSSL_FILETYPE_PEM)); ExpectNotNull(ssl = SSL_new(ctx)); #if !defined(NO_CHECK_PRIVATE_KEY) ExpectIntEQ(wolfSSL_check_private_key(ssl), WOLFSSL_SUCCESS); #endif SSL_free(ssl); ssl = NULL; ExpectTrue(SSL_CTX_use_PrivateKey_file(ctx, cliEccKeyFile, WOLFSSL_FILETYPE_PEM)); ExpectNotNull(ssl = SSL_new(ctx)); #ifdef WOLFSSL_VALIDATE_ECC_IMPORT ExpectIntNE(wolfSSL_check_private_key(ssl), WOLFSSL_SUCCESS); #endif SSL_free(ssl); ssl = NULL; SSL_CTX_free(ctx); ctx = NULL; #endif /* end of ECC private key match tests */ #if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_IMPORT) #ifndef NO_WOLFSSL_SERVER ExpectNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); #else ExpectNotNull(ctx = SSL_CTX_new(wolfSSLv23_client_method())); #endif ExpectTrue(SSL_CTX_use_certificate_file(ctx, edCertFile, WOLFSSL_FILETYPE_PEM)); ExpectTrue(SSL_CTX_use_PrivateKey_file(ctx, edKeyFile, WOLFSSL_FILETYPE_PEM)); ExpectNotNull(ssl = SSL_new(ctx)); #if !defined(NO_CHECK_PRIVATE_KEY) ExpectIntEQ(wolfSSL_check_private_key(ssl), WOLFSSL_SUCCESS); #endif SSL_free(ssl); ssl = NULL; ExpectTrue(SSL_CTX_use_PrivateKey_file(ctx, cliEdKeyFile, WOLFSSL_FILETYPE_PEM)); ExpectNotNull(ssl = SSL_new(ctx)); #if !defined(NO_CHECK_PRIVATE_KEY) #ifdef HAVE_ED25519_MAKE_KEY ExpectIntNE(wolfSSL_check_private_key(ssl), WOLFSSL_SUCCESS); #else ExpectIntEQ(wolfSSL_check_private_key(ssl), WOLFSSL_SUCCESS); #endif #endif SSL_free(ssl); ssl = NULL; SSL_CTX_free(ctx); ctx = NULL; #endif /* end of Ed25519 private key match tests */ #if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_IMPORT) #ifndef NO_WOLFSSL_SERVER ExpectNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); #else ExpectNotNull(ctx = SSL_CTX_new(wolfSSLv23_client_method())); #endif ExpectTrue(SSL_CTX_use_certificate_file(ctx, ed448CertFile, WOLFSSL_FILETYPE_PEM)); ExpectTrue(SSL_CTX_use_PrivateKey_file(ctx, ed448KeyFile, WOLFSSL_FILETYPE_PEM)); ExpectNotNull(ssl = SSL_new(ctx)); #if !defined(NO_CHECK_PRIVATE_KEY) ExpectIntEQ(wolfSSL_check_private_key(ssl), WOLFSSL_SUCCESS); #endif SSL_free(ssl); ssl = NULL; ExpectTrue(SSL_CTX_use_PrivateKey_file(ctx, cliEd448KeyFile, WOLFSSL_FILETYPE_PEM)); ExpectNotNull(ssl = SSL_new(ctx)); #if !defined(NO_CHECK_PRIVATE_KEY) ExpectIntNE(wolfSSL_check_private_key(ssl), WOLFSSL_SUCCESS); #endif SSL_free(ssl); ssl = NULL; SSL_CTX_free(ctx); ctx = NULL; #endif /* end of Ed448 private key match tests */ EVP_cleanup(); /* test existence of no-op macros in wolfssl/openssl/ssl.h */ CONF_modules_free(); ENGINE_cleanup(); CONF_modules_unload(); (void)ssl; (void)ctx; (void)pkey; #endif /* !NO_WOLFSSL_CLIENT || !NO_WOLFSSL_SERVER */ #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) */ return EXPECT_RESULT(); } static int test_wolfSSL_tmp_dh(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && !defined(NO_FILESYSTEM) && \ !defined(NO_RSA) && !defined(NO_DH) && !defined(NO_BIO) && \ !defined(NO_TLS) && \ (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) byte buff[6000]; static const unsigned char p[] = { 0xb0, 0xa1, 0x08, 0x06, 0x9c, 0x08, 0x13, 0xba, 0x59, 0x06, 0x3c, 0xbc, 0x30, 0xd5, 0xf5, 0x00, 0xc1, 0x4f, 0x44, 0xa7, 0xd6, 0xef, 0x4a, 0xc6, 0x25, 0x27, 0x1c, 0xe8, 0xd2, 0x96, 0x53, 0x0a, 0x5c, 0x91, 0xdd, 0xa2, 0xc2, 0x94, 0x84, 0xbf, 0x7d, 0xb2, 0x44, 0x9f, 0x9b, 0xd2, 0xc1, 0x8a, 0xc5, 0xbe, 0x72, 0x5c, 0xa7, 0xe7, 0x91, 0xe6, 0xd4, 0x9f, 0x73, 0x07, 0x85, 0x5b, 0x66, 0x48, 0xc7, 0x70, 0xfa, 0xb4, 0xee, 0x02, 0xc9, 0x3d, 0x9a, 0x4a, 0xda, 0x3d, 0xc1, 0x46, 0x3e, 0x19, 0x69, 0xd1, 0x17, 0x46, 0x07, 0xa3, 0x4d, 0x9f, 0x2b, 0x96, 0x17, 0x39, 0x6d, 0x30, 0x8d, 0x2a, 0xf3, 0x94, 0xd3, 0x75, 0xcf, 0xa0, 0x75, 0xe6, 0xf2, 0x92, 0x1f, 0x1a, 0x70, 0x05, 0xaa, 0x04, 0x83, 0x57, 0x30, 0xfb, 0xda, 0x76, 0x93, 0x38, 0x50, 0xe8, 0x27, 0xfd, 0x63, 0xee, 0x3c, 0xe5, 0xb7, 0xc8, 0x09, 0xae, 0x6f, 0x50, 0x35, 0x8e, 0x84, 0xce, 0x4a, 0x00, 0xe9, 0x12, 0x7e, 0x5a, 0x31, 0xd7, 0x33, 0xfc, 0x21, 0x13, 0x76, 0xcc, 0x16, 0x30, 0xdb, 0x0c, 0xfc, 0xc5, 0x62, 0xa7, 0x35, 0xb8, 0xef, 0xb7, 0xb0, 0xac, 0xc0, 0x36, 0xf6, 0xd9, 0xc9, 0x46, 0x48, 0xf9, 0x40, 0x90, 0x00, 0x2b, 0x1b, 0xaa, 0x6c, 0xe3, 0x1a, 0xc3, 0x0b, 0x03, 0x9e, 0x1b, 0xc2, 0x46, 0xe4, 0x48, 0x4e, 0x22, 0x73, 0x6f, 0xc3, 0x5f, 0xd4, 0x9a, 0xd6, 0x30, 0x07, 0x48, 0xd6, 0x8c, 0x90, 0xab, 0xd4, 0xf6, 0xf1, 0xe3, 0x48, 0xd3, 0x58, 0x4b, 0xa6, 0xb9, 0xcd, 0x29, 0xbf, 0x68, 0x1f, 0x08, 0x4b, 0x63, 0x86, 0x2f, 0x5c, 0x6b, 0xd6, 0xb6, 0x06, 0x65, 0xf7, 0xa6, 0xdc, 0x00, 0x67, 0x6b, 0xbb, 0xc3, 0xa9, 0x41, 0x83, 0xfb, 0xc7, 0xfa, 0xc8, 0xe2, 0x1e, 0x7e, 0xaf, 0x00, 0x3f, 0x93 }; int pSz = (int)sizeof(p); #if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \ !defined(HAVE_SELFTEST) static const unsigned char bad_p[] = { 0xb0, 0xa1, 0x08, 0x06, 0x9c, 0x08, 0x13, 0xba, 0x59, 0x06, 0x3c, 0xbc, 0x30, 0xd5, 0xf5, 0x00, 0xc1, 0x4f, 0x44, 0xa7, 0xd6, 0xef, 0x4a, 0xc6, 0x25, 0x27, 0x1c, 0xe8, 0xd2, 0x96, 0x53, 0x0a, 0x5c, 0x91, 0xdd, 0xa2, 0xc2, 0x94, 0x84, 0xbf, 0x7d, 0xb2, 0x44, 0x9f, 0x9b, 0xd2, 0xc1, 0x8a, 0xc5, 0xbe, 0x72, 0x5c, 0xa7, 0xe7, 0x91, 0xe6, 0xd4, 0x9f, 0x73, 0x07, 0x85, 0x5b, 0x66, 0x48, 0xc7, 0x70, 0xfa, 0xb4, 0xee, 0x02, 0xc9, 0x3d, 0x9a, 0x4a, 0xda, 0x3d, 0xc1, 0x46, 0x3e, 0x19, 0x69, 0xd1, 0x17, 0x46, 0x07, 0xa3, 0x4d, 0x9f, 0x2b, 0x96, 0x17, 0x39, 0x6d, 0x30, 0x8d, 0x2a, 0xf3, 0x94, 0xd3, 0x75, 0xcf, 0xa0, 0x75, 0xe6, 0xf2, 0x92, 0x1f, 0x1a, 0x70, 0x05, 0xaa, 0x04, 0x83, 0x57, 0x30, 0xfb, 0xda, 0x76, 0x93, 0x38, 0x50, 0xe8, 0x27, 0xfd, 0x63, 0xee, 0x3c, 0xe5, 0xb7, 0xc8, 0x09, 0xae, 0x6f, 0x50, 0x35, 0x8e, 0x84, 0xce, 0x4a, 0x00, 0xe9, 0x12, 0x7e, 0x5a, 0x31, 0xd7, 0x33, 0xfc, 0x21, 0x13, 0x76, 0xcc, 0x16, 0x30, 0xdb, 0x0c, 0xfc, 0xc5, 0x62, 0xa7, 0x35, 0xb8, 0xef, 0xb7, 0xb0, 0xac, 0xc0, 0x36, 0xf6, 0xd9, 0xc9, 0x46, 0x48, 0xf9, 0x40, 0x90, 0x00, 0x2b, 0x1b, 0xaa, 0x6c, 0xe3, 0x1a, 0xc3, 0x0b, 0x03, 0x9e, 0x1b, 0xc2, 0x46, 0xe4, 0x48, 0x4e, 0x22, 0x73, 0x6f, 0xc3, 0x5f, 0xd4, 0x9a, 0xd6, 0x30, 0x07, 0x48, 0xd6, 0x8c, 0x90, 0xab, 0xd4, 0xf6, 0xf1, 0xe3, 0x48, 0xd3, 0x58, 0x4b, 0xa6, 0xb9, 0xcd, 0x29, 0xbf, 0x68, 0x1f, 0x08, 0x4b, 0x63, 0x86, 0x2f, 0x5c, 0x6b, 0xd6, 0xb6, 0x06, 0x65, 0xf7, 0xa6, 0xdc, 0x00, 0x67, 0x6b, 0xbb, 0xc3, 0xa9, 0x41, 0x83, 0xfb, 0xc7, 0xfa, 0xc8, 0xe2, 0x1e, 0x7e, 0xaf, 0x00, 0x3f, 0x91 }; #endif static const unsigned char g[] = { 0x02 }; int gSz = (int)sizeof(g); #if !defined(NO_DSA) char file[] = "./certs/dsaparams.pem"; DSA* dsa = NULL; #else char file[] = "./certs/dh2048.pem"; #endif XFILE f = XBADFILE; int bytes = 0; DH* dh = NULL; DH* dh2 = NULL; BIO* bio = NULL; SSL* ssl = NULL; SSL_CTX* ctx = NULL; #ifndef NO_WOLFSSL_CLIENT SSL* ssl_c = NULL; SSL_CTX* ctx_c = NULL; #endif #ifndef NO_WOLFSSL_SERVER ExpectNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); ExpectTrue(SSL_CTX_use_certificate_file(ctx, svrCertFile, WOLFSSL_FILETYPE_PEM)); ExpectTrue(SSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, WOLFSSL_FILETYPE_PEM)); ExpectNotNull(ssl = SSL_new(ctx)); #endif #ifndef NO_WOLFSSL_CLIENT ExpectNotNull(ctx_c = SSL_CTX_new(wolfSSLv23_client_method())); ExpectTrue(SSL_CTX_use_certificate_file(ctx_c, svrCertFile, WOLFSSL_FILETYPE_PEM)); ExpectTrue(SSL_CTX_use_PrivateKey_file(ctx_c, svrKeyFile, WOLFSSL_FILETYPE_PEM)); ExpectNotNull(ssl_c = SSL_new(ctx_c)); #ifdef NO_WOLFSSL_SERVER ctx = ctx_c; ssl = ssl_c; #endif #endif XMEMSET(buff, 0, sizeof(buff)); ExpectTrue((f = XFOPEN(file, "rb")) != XBADFILE); ExpectIntGT(bytes = (int)XFREAD(buff, 1, sizeof(buff), f), 0); if (f != XBADFILE) XFCLOSE(f); ExpectNotNull(bio = BIO_new_mem_buf((void*)buff, bytes)); #if !defined(NO_DSA) dsa = wolfSSL_PEM_read_bio_DSAparams(bio, NULL, NULL, NULL); ExpectNotNull(dsa); dh = wolfSSL_DSA_dup_DH(dsa); #else dh = wolfSSL_PEM_read_bio_DHparams(bio, NULL, NULL, NULL); #endif ExpectNotNull(dh); #if defined(WOLFSSL_DH_EXTRA) && \ (defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(WOLFSSL_OPENSSH)) ExpectNotNull(dh2 = wolfSSL_DH_dup(dh)); DH_free(dh2); dh2 = NULL; #endif /* Failure cases */ ExpectIntEQ((int)wolfSSL_CTX_SetTmpDH(NULL, NULL, 0, NULL, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ((int)wolfSSL_CTX_SetTmpDH(ctx , NULL, 0, NULL, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ((int)wolfSSL_CTX_SetTmpDH(NULL, p , 0, NULL, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ((int)wolfSSL_CTX_SetTmpDH(NULL, NULL, 0, g , 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ((int)wolfSSL_CTX_SetTmpDH(ctx , p , 0, NULL, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ((int)wolfSSL_CTX_SetTmpDH(ctx , NULL, 0, g , 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ((int)wolfSSL_CTX_SetTmpDH(NULL, p , 0, g , 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ((int)wolfSSL_CTX_SetTmpDH(ctx , p , 1, g , 1), WC_NO_ERR_TRACE(DH_KEY_SIZE_E)); ExpectIntEQ((int)wolfSSL_CTX_SetTmpDH(ctx , buff, 6000, g , 1), WC_NO_ERR_TRACE(DH_KEY_SIZE_E)); #if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \ !defined(HAVE_SELFTEST) ExpectIntEQ((int)wolfSSL_CTX_SetTmpDH(ctx, bad_p, pSz, g, gSz), WC_NO_ERR_TRACE(DH_CHECK_PUB_E)); #endif ExpectIntEQ((int)wolfSSL_SetTmpDH(NULL, NULL, 0, NULL, 0), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ((int)wolfSSL_SetTmpDH(ssl , NULL, 0, NULL, 0), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ((int)wolfSSL_SetTmpDH(NULL, p , 0, NULL, 0), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ((int)wolfSSL_SetTmpDH(NULL, NULL, 0, g , 0), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ((int)wolfSSL_SetTmpDH(ssl , p , 0, NULL, 0), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ((int)wolfSSL_SetTmpDH(ssl , NULL, 0, g , 0), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ((int)wolfSSL_SetTmpDH(NULL, p , 0, g , 0), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ((int)wolfSSL_SetTmpDH(ssl , p , 1, g , 1), WC_NO_ERR_TRACE(DH_KEY_SIZE_E)); ExpectIntEQ((int)wolfSSL_SetTmpDH(ssl , buff, 6000, g , 1), WC_NO_ERR_TRACE(DH_KEY_SIZE_E)); #if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \ !defined(HAVE_SELFTEST) #ifndef NO_WOLFSSL_SERVER /* Parameters will be tested later so it passes now. */ ExpectIntEQ((int)wolfSSL_SetTmpDH(ssl, bad_p, pSz, g, gSz), WOLFSSL_SUCCESS); #endif #endif #ifndef NO_WOLFSSL_CLIENT ExpectIntEQ((int)wolfSSL_SetTmpDH(ssl_c, p, pSz, g, gSz), WC_NO_ERR_TRACE(SIDE_ERROR)); #endif ExpectIntEQ((int)SSL_CTX_set_tmp_dh(NULL, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ((int)SSL_CTX_set_tmp_dh(ctx , NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ((int)SSL_CTX_set_tmp_dh(NULL, dh ), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ((int)SSL_set_tmp_dh(NULL, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ((int)SSL_set_tmp_dh(ssl , NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ((int)SSL_set_tmp_dh(NULL, dh ), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* No p/g to use. */ dh2 = wolfSSL_DH_new(); ExpectIntEQ((int)SSL_CTX_set_tmp_dh(ctx , dh2 ), WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)); ExpectIntEQ((int)SSL_set_tmp_dh(ssl , dh2 ), WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)); DH_free(dh2); dh2 = NULL; ExpectIntEQ((int)wolfSSL_CTX_SetTmpDH(ctx, p, pSz, g, gSz), WOLFSSL_SUCCESS); ExpectIntEQ((int)SSL_CTX_set_tmp_dh(ctx, dh), WOLFSSL_SUCCESS); #ifndef NO_WOLFSSL_SERVER ExpectIntEQ((int)SSL_set_tmp_dh(ssl, dh), WOLFSSL_SUCCESS); #else ExpectIntEQ((int)SSL_set_tmp_dh(ssl, dh), WC_NO_ERR_TRACE(SIDE_ERROR)); #endif BIO_free(bio); #if !defined(NO_DSA) DSA_free(dsa); #endif DH_free(dh); dh = NULL; #ifndef NO_WOLFSSL_CLIENT if (ssl != ssl_c) { SSL_free(ssl_c); } #endif SSL_free(ssl); #ifndef NO_WOLFSSL_CLIENT if (ctx != ctx_c) { SSL_CTX_free(ctx_c); } #endif SSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } /* Tests SSL_CTX_set_tmp_dh with single-operand failure (p set, g missing) * and wolfSSL_CTX_SetTmpDH_buffer with WOLFSSL_FILETYPE_ASN1 DER input. */ static int test_wolfSSL_tmp_dh_regression(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_DH) && !defined(NO_CERTS) && \ !defined(NO_FILESYSTEM) && !defined(NO_RSA) && !defined(NO_TLS) && \ !defined(NO_WOLFSSL_SERVER) SSL_CTX* ctx = NULL; ExpectNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); ExpectTrue(SSL_CTX_use_certificate_file(ctx, svrCertFile, WOLFSSL_FILETYPE_PEM)); ExpectTrue(SSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, WOLFSSL_FILETYPE_PEM)); #if defined(OPENSSL_ALL) || \ (defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L) { /* Test single-operand failure: DH with p but no g. */ DH* dh = NULL; WOLFSSL_BIGNUM* p_bn = NULL; ExpectNotNull(dh = wolfSSL_DH_new()); ExpectNotNull(p_bn = wolfSSL_BN_new()); ExpectIntEQ(wolfSSL_BN_set_word(p_bn, 0xFFFF), 1); if (dh != NULL && p_bn != NULL) { if (wolfSSL_DH_set0_pqg(dh, p_bn, NULL, NULL) == 1) { p_bn = NULL; /* ownership transferred on success */ } } ExpectIntEQ((int)SSL_CTX_set_tmp_dh(ctx, dh), WOLFSSL_FATAL_ERROR); DH_free(dh); wolfSSL_BN_free(p_bn); } #endif /* Test ASN1/DER path through wolfSSL_CTX_SetTmpDH_buffer. */ { byte derBuf[4096]; XFILE f = XBADFILE; int derSz = 0; ExpectTrue((f = XFOPEN("./certs/dh2048.der", "rb")) != XBADFILE); if (f != XBADFILE) { derSz = (int)XFREAD(derBuf, 1, sizeof(derBuf), f); XFCLOSE(f); } ExpectIntGT(derSz, 0); ExpectIntEQ(wolfSSL_CTX_SetTmpDH_buffer(ctx, derBuf, (long)derSz, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); } SSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } static int test_wolfSSL_ctrl(void) { EXPECT_DECLS; #if defined (OPENSSL_EXTRA) && !defined(NO_BIO) byte buff[6000]; BIO* bio = NULL; int bytes; BUF_MEM* ptr = NULL; XMEMSET(buff, 0, sizeof(buff)); bytes = sizeof(buff); ExpectNotNull(bio = BIO_new_mem_buf((void*)buff, bytes)); ExpectNotNull(BIO_s_socket()); ExpectIntEQ((int)wolfSSL_BIO_get_mem_ptr(bio, &ptr), WOLFSSL_SUCCESS); /* needs tested after stubs filled out @TODO SSL_ctrl SSL_CTX_ctrl */ BIO_free(bio); #endif /* defined(OPENSSL_EXTRA) && !defined(NO_BIO) */ return EXPECT_RESULT(); } static int test_wolfSSL_CTX_add_extra_chain_cert(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && !defined(NO_TLS) && \ !defined(NO_FILESYSTEM) && !defined(NO_RSA) && !defined(NO_BIO) #if !defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER) char caFile[] = "./certs/client-ca.pem"; char clientFile[] = "./certs/client-cert.pem"; SSL_CTX* ctx = NULL; X509* x509 = NULL; BIO *bio = NULL; X509 *cert = NULL; X509 *ca = NULL; STACK_OF(X509) *chain = NULL; STACK_OF(X509) *chain2 = NULL; #ifndef NO_WOLFSSL_SERVER ExpectNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); #else ExpectNotNull(ctx = SSL_CTX_new(wolfSSLv23_client_method())); #endif ExpectNotNull(x509 = wolfSSL_X509_load_certificate_file(caFile, WOLFSSL_FILETYPE_PEM)); /* Negative tests. */ ExpectIntEQ((int)SSL_CTX_add_extra_chain_cert(NULL, NULL), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ((int)SSL_CTX_add_extra_chain_cert(ctx, NULL), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ((int)SSL_CTX_add_extra_chain_cert(NULL, x509), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ((int)SSL_CTX_add_extra_chain_cert(ctx, x509), WOLFSSL_SUCCESS); ExpectNotNull(x509 = wolfSSL_X509_new()); /* Empty certificate. */ ExpectIntEQ((int)SSL_CTX_add_extra_chain_cert(ctx, x509), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); wolfSSL_X509_free(x509); x509 = NULL; ExpectNotNull(x509 = wolfSSL_X509_load_certificate_file(clientFile, WOLFSSL_FILETYPE_PEM)); /* additional test of getting EVP_PKEY key size from X509 * Do not run with user RSA because wolfSSL_RSA_size is not currently * allowed with user RSA */ { EVP_PKEY* pkey = NULL; #if defined(HAVE_ECC) X509* ecX509 = NULL; #endif /* HAVE_ECC */ ExpectNotNull(pkey = X509_get_pubkey(x509)); /* current RSA key is 2048 bit (256 bytes) */ ExpectIntEQ(EVP_PKEY_size(pkey), 256); EVP_PKEY_free(pkey); pkey = NULL; #if defined(HAVE_ECC) #if defined(USE_CERT_BUFFERS_256) ExpectNotNull(ecX509 = wolfSSL_X509_load_certificate_buffer( cliecc_cert_der_256, sizeof_cliecc_cert_der_256, SSL_FILETYPE_ASN1)); #else ExpectNotNull(ecX509 = wolfSSL_X509_load_certificate_file( cliEccCertFile, SSL_FILETYPE_PEM)); #endif pkey = X509_get_pubkey(ecX509); ExpectNotNull(pkey); /* current ECC key is 256 bit (32 bytes) */ ExpectIntGE(EVP_PKEY_size(pkey), 72); X509_free(ecX509); ecX509 = NULL; EVP_PKEY_free(pkey); pkey = NULL; #endif /* HAVE_ECC */ } ExpectIntEQ((int)SSL_CTX_add_extra_chain_cert(ctx, x509), SSL_SUCCESS); if (EXPECT_SUCCESS()) { x509 = NULL; } #ifdef WOLFSSL_ENCRYPTED_KEYS ExpectNull(SSL_CTX_get_default_passwd_cb(ctx)); ExpectNull(SSL_CTX_get_default_passwd_cb_userdata(ctx)); #endif SSL_CTX_free(ctx); ctx = NULL; #ifndef NO_WOLFSSL_SERVER ExpectNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); #else ExpectNotNull(ctx = SSL_CTX_new(wolfSSLv23_client_method())); #endif /* Test haproxy use case */ ExpectNotNull(bio = BIO_new_file(svrCertFile, "r")); /* Read Certificate */ ExpectNotNull(cert = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL)); ExpectNotNull(ca = PEM_read_bio_X509(bio, NULL, NULL, NULL)); ExpectNotNull(chain = sk_X509_new_null()); ExpectIntEQ(sk_X509_push(chain, ca), 1); if (EXPECT_SUCCESS()) { ca = NULL; } ExpectNotNull(chain2 = X509_chain_up_ref(chain)); ExpectNotNull(ca = sk_X509_shift(chain2)); ExpectIntEQ(SSL_CTX_use_certificate(ctx, cert), 1); ExpectIntEQ(SSL_CTX_add_extra_chain_cert(ctx, ca), 1); if (EXPECT_SUCCESS()) { ca = NULL; } BIO_free(bio); X509_free(cert); X509_free(ca); X509_free(x509); sk_X509_pop_free(chain, X509_free); sk_X509_pop_free(chain2, X509_free); SSL_CTX_free(ctx); #endif /* !NO_WOLFSSL_CLIENT || !NO_WOLFSSL_SERVER */ #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ !defined(NO_FILESYSTEM) && !defined(NO_RSA) && !defined (NO_BIO) */ return EXPECT_RESULT(); } #if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) static int test_wolfSSL_ERR_peek_last_error_line(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ !defined(NO_FILESYSTEM) && defined(DEBUG_WOLFSSL) && \ !defined(NO_OLD_TLS) && !defined(WOLFSSL_NO_TLS12) && \ defined(HAVE_IO_TESTS_DEPENDENCIES) && !defined(NO_ERROR_QUEUE) callback_functions client_cb; callback_functions server_cb; int line = 0; int flag = ERR_TXT_STRING; const char* file = NULL; const char* data = NULL; /* create a failed connection and inspect the error */ XMEMSET(&client_cb, 0, sizeof(callback_functions)); XMEMSET(&server_cb, 0, sizeof(callback_functions)); client_cb.method = wolfTLSv1_1_client_method; server_cb.method = wolfTLSv1_2_server_method; test_wolfSSL_client_server_nofail(&client_cb, &server_cb); ExpectIntGT(ERR_get_error_line_data(NULL, NULL, &data, &flag), 0); ExpectNotNull(data); /* check clearing error state */ ERR_remove_state(0); ExpectIntEQ((int)ERR_peek_last_error_line(NULL, NULL), 0); ERR_peek_last_error_line(NULL, &line); ExpectIntEQ(line, 0); ERR_peek_last_error_line(&file, NULL); ExpectNull(file); /* retry connection to fill error queue */ XMEMSET(&client_cb, 0, sizeof(callback_functions)); XMEMSET(&server_cb, 0, sizeof(callback_functions)); client_cb.method = wolfTLSv1_1_client_method; server_cb.method = wolfTLSv1_2_server_method; test_wolfSSL_client_server_nofail(&client_cb, &server_cb); /* check that error code was stored */ ExpectIntNE((int)ERR_peek_last_error_line(NULL, NULL), 0); ERR_peek_last_error_line(NULL, &line); ExpectIntNE(line, 0); ERR_peek_last_error_line(&file, NULL); ExpectNotNull(file); fprintf(stderr, "\nTesting error print out\n"); ERR_print_errors_fp(stderr); fprintf(stderr, "Done testing print out\n\n"); #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && * !defined(NO_FILESYSTEM) && !defined(DEBUG_WOLFSSL) */ return EXPECT_RESULT(); } #endif /* !NO_WOLFSSL_CLIENT && !NO_WOLFSSL_SERVER */ static int test_wolfSSL_CTX_get0_set1_param(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) #if !defined(NO_TLS) && \ (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) SSL_CTX* ctx = NULL; WOLFSSL_X509_VERIFY_PARAM* pParam = NULL; WOLFSSL_X509_VERIFY_PARAM* pvpm = NULL; char testIPv4[] = "127.0.0.1"; char testhostName[] = "foo.hoge.com"; #ifndef NO_WOLFSSL_SERVER ExpectNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); #else ExpectNotNull(ctx = SSL_CTX_new(wolfSSLv23_client_method())); #endif ExpectNull(SSL_CTX_get0_param(NULL)); ExpectNotNull(pParam = SSL_CTX_get0_param(ctx)); ExpectNotNull(pvpm = (WOLFSSL_X509_VERIFY_PARAM *)XMALLOC( sizeof(WOLFSSL_X509_VERIFY_PARAM), NULL, DYNAMIC_TYPE_OPENSSL)); ExpectNotNull(XMEMSET(pvpm, 0, sizeof(WOLFSSL_X509_VERIFY_PARAM))); ExpectIntEQ(wolfSSL_X509_VERIFY_PARAM_set1_host(pvpm, testhostName, (int)XSTRLEN(testhostName)), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_X509_VERIFY_PARAM_set1_ip_asc(pvpm, testIPv4), WOLFSSL_SUCCESS); wolfSSL_X509_VERIFY_PARAM_set_hostflags(pvpm, 0x01); ExpectIntEQ(SSL_CTX_set1_param(ctx, pvpm), 1); ExpectIntEQ(0, XSTRNCMP(pParam->hostName, testhostName, (int)XSTRLEN(testhostName))); ExpectIntEQ(0x01, pParam->hostFlags); ExpectIntEQ(0, XSTRNCMP(pParam->ipasc, testIPv4, WOLFSSL_MAX_IPSTR)); /* test for incorrect parameter */ ExpectIntEQ(1,SSL_CTX_set1_param(ctx, NULL)); ExpectIntEQ(1,SSL_CTX_set1_param(NULL, pvpm)); ExpectIntEQ(1,SSL_CTX_set1_param(NULL, NULL)); SSL_CTX_free(ctx); XFREE(pvpm, NULL, DYNAMIC_TYPE_OPENSSL); #endif /* !NO_WOLFSSL_CLIENT || !NO_WOLFSSL_SERVER */ #endif /* OPENSSL_EXTRA && !defined(NO_RSA)*/ return EXPECT_RESULT(); } static int test_wolfSSL_get0_param(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_TLS) && \ (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) && \ !defined(NO_FILESYSTEM) SSL_CTX* ctx = NULL; SSL* ssl = NULL; #ifndef NO_WOLFSSL_SERVER ExpectNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); #else ExpectNotNull(ctx = SSL_CTX_new(wolfSSLv23_client_method())); #endif ExpectTrue(SSL_CTX_use_certificate_file(ctx, svrCertFile, SSL_FILETYPE_PEM)); ExpectTrue(SSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, SSL_FILETYPE_PEM)); ExpectNotNull(ssl = SSL_new(ctx)); ExpectNotNull(SSL_get0_param(ssl)); SSL_free(ssl); SSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } static int test_wolfSSL_set1_host(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_TLS) && \ (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) && \ !defined(NO_FILESYSTEM) const char host[] = "www.test_wolfSSL_set1_host.com"; const char emptyStr[] = ""; SSL_CTX* ctx = NULL; SSL* ssl = NULL; WOLFSSL_X509_VERIFY_PARAM* pParam = NULL; #ifndef NO_WOLFSSL_SERVER ExpectNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); #else ExpectNotNull(ctx = SSL_CTX_new(wolfSSLv23_client_method())); #endif ExpectTrue(SSL_CTX_use_certificate_file(ctx, svrCertFile, SSL_FILETYPE_PEM)); ExpectTrue(SSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, SSL_FILETYPE_PEM)); ExpectNotNull(ssl = SSL_new(ctx)); pParam = SSL_get0_param(ssl); /* we should get back host string */ ExpectIntEQ(SSL_set1_host(ssl, host), WOLFSSL_SUCCESS); ExpectIntEQ(XMEMCMP(pParam->hostName, host, sizeof(host)), 0); /* we should get back empty string */ ExpectIntEQ(SSL_set1_host(ssl, emptyStr), WOLFSSL_SUCCESS); ExpectIntEQ(XMEMCMP(pParam->hostName, emptyStr, sizeof(emptyStr)), 0); /* we should get back host string */ ExpectIntEQ(SSL_set1_host(ssl, host), WOLFSSL_SUCCESS); ExpectIntEQ(XMEMCMP(pParam->hostName, host, sizeof(host)), 0); /* we should get back empty string */ ExpectIntEQ(SSL_set1_host(ssl, NULL), WOLFSSL_SUCCESS); ExpectIntEQ(XMEMCMP(pParam->hostName, emptyStr, sizeof(emptyStr)), 0); SSL_free(ssl); SSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } #if defined(OPENSSL_ALL) && !defined(NO_RSA) && !defined(NO_CERTS) && \ !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) && \ defined(HAVE_ECC) && !defined(NO_TLS) && defined(HAVE_AESGCM) static int test_wolfSSL_get_client_ciphers_ctx_ready(WOLFSSL_CTX* ctx) { EXPECT_DECLS; ExpectTrue(wolfSSL_CTX_set_cipher_list(ctx, "ECDHE-RSA-AES128-GCM-SHA256")); return EXPECT_RESULT(); } static int test_wolfSSL_get_client_ciphers_on_result(WOLFSSL* ssl) { EXPECT_DECLS; WOLF_STACK_OF(WOLFSSL_CIPHER)* ciphers; ciphers = SSL_get_client_ciphers(ssl); if (wolfSSL_is_server(ssl) == 0) { ExpectNull(ciphers); } else { WOLFSSL_CIPHER* current; /* client should have only sent over one cipher suite */ ExpectNotNull(ciphers); ExpectIntEQ(sk_SSL_CIPHER_num(ciphers), 1); current = sk_SSL_CIPHER_value(ciphers, 0); ExpectNotNull(current); #if !defined(WOLFSSL_CIPHER_INTERNALNAME) && !defined(NO_ERROR_STRINGS) && \ !defined(WOLFSSL_QT) ExpectStrEQ("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", SSL_CIPHER_get_name(current)); #else ExpectStrEQ("ECDHE-RSA-AES128-GCM-SHA256", SSL_CIPHER_get_name(current)); #endif } return EXPECT_RESULT(); } #endif static int test_wolfSSL_get_client_ciphers(void) { EXPECT_DECLS; #if defined(OPENSSL_ALL) && !defined(NO_RSA) && !defined(NO_CERTS) && \ !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) && \ defined(HAVE_ECC) && !defined(NO_TLS) && defined(HAVE_AESGCM) test_ssl_cbf server_cb; test_ssl_cbf client_cb; XMEMSET(&client_cb, 0, sizeof(test_ssl_cbf)); XMEMSET(&server_cb, 0, sizeof(test_ssl_cbf)); client_cb.method = wolfTLSv1_2_client_method; server_cb.method = wolfTLSv1_2_server_method; client_cb.devId = testDevId; server_cb.devId = testDevId; client_cb.ctx_ready = test_wolfSSL_get_client_ciphers_ctx_ready; client_cb.on_result = test_wolfSSL_get_client_ciphers_on_result; server_cb.on_result = test_wolfSSL_get_client_ciphers_on_result; ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&client_cb, &server_cb, NULL), TEST_SUCCESS); #endif return EXPECT_RESULT(); } static int test_wolfSSL_CTX_set_client_CA_list(void) { EXPECT_DECLS; #if defined(OPENSSL_ALL) && !defined(NO_RSA) && !defined(NO_CERTS) && \ !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) && \ !defined(NO_BIO) && !defined(NO_TLS) WOLFSSL_CTX* ctx = NULL; WOLFSSL* ssl = NULL; X509_NAME* name = NULL; STACK_OF(X509_NAME)* names = NULL; STACK_OF(X509_NAME)* ca_list = NULL; int names_len = 0; int i; ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); /* Send two X501 names in cert request */ names = SSL_load_client_CA_file(cliCertFile); ExpectNotNull(names); ca_list = SSL_load_client_CA_file(caCertFile); ExpectNotNull(ca_list); ExpectNotNull(name = sk_X509_NAME_value(ca_list, 0)); ExpectIntEQ(sk_X509_NAME_push(names, name), 2); if (EXPECT_FAIL()) { wolfSSL_X509_NAME_free(name); name = NULL; } SSL_CTX_set_client_CA_list(ctx, names); /* This should only free the stack structure */ sk_X509_NAME_free(ca_list); ca_list = NULL; ExpectNotNull(ca_list = SSL_CTX_get_client_CA_list(ctx)); ExpectIntEQ(sk_X509_NAME_num(ca_list), sk_X509_NAME_num(names)); ExpectIntEQ(sk_X509_NAME_find(NULL, name), BAD_FUNC_ARG); ExpectIntEQ(sk_X509_NAME_find(names, NULL), WOLFSSL_FATAL_ERROR); ExpectIntGT((names_len = sk_X509_NAME_num(names)), 0); for (i = 0; i < names_len; i++) { ExpectNotNull(name = sk_X509_NAME_value(names, i)); ExpectIntEQ(sk_X509_NAME_find(names, name), i); } /* Needed to be able to create ssl object */ ExpectTrue(SSL_CTX_use_certificate_file(ctx, svrCertFile, SSL_FILETYPE_PEM)); ExpectTrue(SSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, SSL_FILETYPE_PEM)); ExpectNotNull(ssl = wolfSSL_new(ctx)); /* load again as old names are responsibility of ctx to free*/ names = SSL_load_client_CA_file(cliCertFile); ExpectNotNull(names); SSL_set_client_CA_list(ssl, names); ExpectNotNull(ca_list = SSL_get_client_CA_list(ssl)); ExpectIntEQ(sk_X509_NAME_num(ca_list), sk_X509_NAME_num(names)); ExpectIntGT((names_len = sk_X509_NAME_num(names)), 0); for (i = 0; i < names_len; i++) { ExpectNotNull(name = sk_X509_NAME_value(names, i)); ExpectIntEQ(sk_X509_NAME_find(names, name), i); } #if !defined(SINGLE_THREADED) && defined(SESSION_CERTS) { tcp_ready ready; func_args server_args; callback_functions server_cb; THREAD_TYPE serverThread; WOLFSSL* ssl_client = NULL; WOLFSSL_CTX* ctx_client = NULL; SOCKET_T sockfd = 0; /* wolfSSL_get_client_CA_list() with handshake */ StartTCP(); InitTcpReady(&ready); XMEMSET(&server_args, 0, sizeof(func_args)); XMEMSET(&server_cb, 0, sizeof(callback_functions)); server_args.signal = &ready; server_args.callbacks = &server_cb; /* we are responsible for free'ing WOLFSSL_CTX */ server_cb.ctx = ctx; server_cb.isSharedCtx = 1; ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_load_verify_locations(ctx, cliCertFile, 0)); start_thread(test_server_nofail, &server_args, &serverThread); wait_tcp_ready(&server_args); tcp_connect(&sockfd, wolfSSLIP, server_args.signal->port, 0, 0, NULL); ExpectNotNull(ctx_client = wolfSSL_CTX_new(wolfTLSv1_2_client_method())); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_load_verify_locations( ctx_client, caCertFile, 0)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_use_certificate_file( ctx_client, cliCertFile, SSL_FILETYPE_PEM)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_use_PrivateKey_file( ctx_client, cliKeyFile, SSL_FILETYPE_PEM)); ExpectNotNull(ssl_client = wolfSSL_new(ctx_client)); ExpectIntEQ(wolfSSL_set_fd(ssl_client, sockfd), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_connect(ssl_client), WOLFSSL_SUCCESS); ExpectNotNull(ca_list = SSL_get_client_CA_list(ssl_client)); /* We are expecting two cert names to be sent */ ExpectIntEQ(sk_X509_NAME_num(ca_list), 2); ExpectNotNull(names = SSL_CTX_get_client_CA_list(ctx)); for (i=0; icallbacks; WOLFSSL_CTX* ctx = callbacks->ctx; WOLFSSL* ssl = NULL; SOCKET_T sfd = 0; SOCKET_T cfd = 0; word16 port; char input[1024]; int idx; int ret, err = 0; const char* privateName = "ech-private-name.com"; int privateNameLen = (int)XSTRLEN(privateName); ((func_args*)args)->return_code = TEST_FAIL; port = ((func_args*)args)->signal->port; AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_load_verify_locations(ctx, cliCertFile, 0)); AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_use_certificate_file(ctx, svrCertFile, WOLFSSL_FILETYPE_PEM)); AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, WOLFSSL_FILETYPE_PEM)); if (callbacks->ctx_ready) callbacks->ctx_ready(ctx); ssl = wolfSSL_new(ctx); AssertNotNull(ssl); /* set the sni for the server */ AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME, privateName, privateNameLen)); tcp_accept(&sfd, &cfd, (func_args*)args, port, 0, 0, 0, 0, 1, NULL, NULL); CloseSocket(sfd); AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_set_fd(ssl, cfd)); if (callbacks->ssl_ready) callbacks->ssl_ready(ssl); do { err = 0; /* Reset error */ ret = wolfSSL_accept(ssl); if (ret != WOLFSSL_SUCCESS) { err = wolfSSL_get_error(ssl, 0); } } while (ret != WOLFSSL_SUCCESS && err == WC_NO_ERR_TRACE(WC_PENDING_E)); if (ret != WOLFSSL_SUCCESS) { char buff[WOLFSSL_MAX_ERROR_SZ]; fprintf(stderr, "error = %d, %s\n", err, wolfSSL_ERR_error_string(err, buff)); } else { if (0 < (idx = wolfSSL_read(ssl, input, sizeof(input)-1))) { input[idx] = 0; fprintf(stderr, "Client message: %s\n", input); } AssertIntEQ(privateNameLen, wolfSSL_write(ssl, privateName, privateNameLen)); ((func_args*)args)->return_code = TEST_SUCCESS; } if (callbacks->on_result) callbacks->on_result(ssl); wolfSSL_shutdown(ssl); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); CloseSocket(cfd); #ifdef FP_ECC wc_ecc_fp_free(); #endif WOLFSSL_RETURN_FROM_THREAD(0); } #endif /* HAVE_ECH && WOLFSSL_TLS13 */ #if defined(OPENSSL_EXTRA) && defined(HAVE_SECRET_CALLBACK) static void keyLog_callback(const WOLFSSL* ssl, const char* line) { XFILE fp; const byte lf = '\n'; AssertNotNull(ssl); AssertNotNull(line); fp = XFOPEN("./MyKeyLog.txt", "a"); XFWRITE(line, 1, XSTRLEN(line), fp); XFWRITE((void*)&lf, 1, 1, fp); XFFLUSH(fp); XFCLOSE(fp); } #endif /* OPENSSL_EXTRA && HAVE_SECRET_CALLBACK */ static int test_wolfSSL_CTX_set_keylog_callback(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && defined(HAVE_SECRET_CALLBACK) && \ !defined(NO_WOLFSSL_CLIENT) SSL_CTX* ctx = NULL; ExpectNotNull(ctx = SSL_CTX_new(wolfSSLv23_client_method())); SSL_CTX_set_keylog_callback(ctx, keyLog_callback ); SSL_CTX_free(ctx); SSL_CTX_set_keylog_callback(NULL, NULL); #endif /* OPENSSL_EXTRA && HAVE_SECRET_CALLBACK && !NO_WOLFSSL_CLIENT */ return EXPECT_RESULT(); } static int test_wolfSSL_CTX_get_keylog_callback(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && defined(HAVE_SECRET_CALLBACK) && \ !defined(NO_WOLFSSL_CLIENT) SSL_CTX* ctx = NULL; ExpectNotNull(ctx = SSL_CTX_new(wolfSSLv23_client_method())); ExpectPtrEq(SSL_CTX_get_keylog_callback(ctx),NULL); SSL_CTX_set_keylog_callback(ctx, keyLog_callback ); ExpectPtrEq(SSL_CTX_get_keylog_callback(ctx),keyLog_callback); SSL_CTX_set_keylog_callback(ctx, NULL ); ExpectPtrEq(SSL_CTX_get_keylog_callback(ctx),NULL); SSL_CTX_free(ctx); #endif /* OPENSSL_EXTRA && HAVE_SECRET_CALLBACK && !NO_WOLFSSL_CLIENT */ return EXPECT_RESULT(); } #if defined(OPENSSL_EXTRA) && defined(HAVE_SECRET_CALLBACK) static int test_wolfSSL_Tls12_Key_Logging_client_ctx_ready(WOLFSSL_CTX* ctx) { /* set keylog callback */ wolfSSL_CTX_set_keylog_callback(ctx, keyLog_callback); return TEST_SUCCESS; } #endif static int test_wolfSSL_Tls12_Key_Logging_test(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && defined(HAVE_SECRET_CALLBACK) /* This test is intended for checking whether keylog callback is called * in client during TLS handshake between the client and a server. */ test_ssl_cbf server_cbf; test_ssl_cbf client_cbf; XFILE fp = XBADFILE; char buff[500]; int found = 0; XMEMSET(&server_cbf, 0, sizeof(test_ssl_cbf)); XMEMSET(&client_cbf, 0, sizeof(test_ssl_cbf)); server_cbf.method = wolfTLSv1_2_server_method; client_cbf.ctx_ready = &test_wolfSSL_Tls12_Key_Logging_client_ctx_ready; /* clean up keylog file */ ExpectTrue((fp = XFOPEN("./MyKeyLog.txt", "w")) != XBADFILE); if (fp != XBADFILE) { XFFLUSH(fp); XFCLOSE(fp); fp = XBADFILE; } ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&client_cbf, &server_cbf, NULL), TEST_SUCCESS); /* check if the keylog file exists */ ExpectTrue((fp = XFOPEN("./MyKeyLog.txt", "rb")) != XBADFILE); XFFLUSH(fp); /* Just to make sure any buffers get flushed */ XMEMSET(buff, 0, sizeof(buff)); while (EXPECT_SUCCESS() && XFGETS(buff, (int)sizeof(buff), fp) != NULL) { if (0 == strncmp(buff,"CLIENT_RANDOM ", sizeof("CLIENT_RANDOM ")-1)) { found = 1; break; } } if (fp != XBADFILE) { XFCLOSE(fp); } /* a log starting with "CLIENT_RANDOM " should exit in the file */ ExpectIntEQ(found, 1); /* clean up */ ExpectIntEQ(rem_file("./MyKeyLog.txt"), 0); #endif /* OPENSSL_EXTRA && HAVE_SECRET_CALLBACK */ return EXPECT_RESULT(); } #if defined(WOLFSSL_TLS13) && defined(OPENSSL_EXTRA) && \ defined(HAVE_SECRET_CALLBACK) static int test_wolfSSL_Tls13_Key_Logging_client_ctx_ready(WOLFSSL_CTX* ctx) { /* set keylog callback */ wolfSSL_CTX_set_keylog_callback(ctx, keyLog_callback); return TEST_SUCCESS; } #endif static int test_wolfSSL_Tls13_Key_Logging_test(void) { EXPECT_DECLS; #if defined(WOLFSSL_TLS13) && defined(OPENSSL_EXTRA) && \ defined(HAVE_SECRET_CALLBACK) /* This test is intended for checking whether keylog callback is called * in client during TLS handshake between the client and a server. */ test_ssl_cbf server_cbf; test_ssl_cbf client_cbf; XFILE fp = XBADFILE; XMEMSET(&server_cbf, 0, sizeof(test_ssl_cbf)); XMEMSET(&client_cbf, 0, sizeof(test_ssl_cbf)); server_cbf.method = wolfTLSv1_3_server_method; /* TLS1.3 */ client_cbf.ctx_ready = &test_wolfSSL_Tls13_Key_Logging_client_ctx_ready; /* clean up keylog file */ ExpectTrue((fp = XFOPEN("./MyKeyLog.txt", "w")) != XBADFILE); if (fp != XBADFILE) { XFCLOSE(fp); fp = XBADFILE; } ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&client_cbf, &server_cbf, NULL), TEST_SUCCESS); /* check if the keylog file exists */ { char buff[300] = {0}; int found[4] = {0}; int numfnd = 0; int i; ExpectTrue((fp = XFOPEN("./MyKeyLog.txt", "rb")) != XBADFILE); while (EXPECT_SUCCESS() && XFGETS(buff, (int)sizeof(buff), fp) != NULL) { if (0 == strncmp(buff, "CLIENT_HANDSHAKE_TRAFFIC_SECRET ", sizeof("CLIENT_HANDSHAKE_TRAFFIC_SECRET ")-1)) { found[0] = 1; continue; } else if (0 == strncmp(buff, "SERVER_HANDSHAKE_TRAFFIC_SECRET ", sizeof("SERVER_HANDSHAKE_TRAFFIC_SECRET ")-1)) { found[1] = 1; continue; } else if (0 == strncmp(buff, "CLIENT_TRAFFIC_SECRET_0 ", sizeof("CLIENT_TRAFFIC_SECRET_0 ")-1)) { found[2] = 1; continue; } else if (0 == strncmp(buff, "SERVER_TRAFFIC_SECRET_0 ", sizeof("SERVER_TRAFFIC_SECRET_0 ")-1)) { found[3] = 1; continue; } } if (fp != XBADFILE) XFCLOSE(fp); for (i = 0; i < 4; i++) { if (found[i] != 0) numfnd++; } ExpectIntEQ(numfnd, 4); } #endif /* OPENSSL_EXTRA && HAVE_SECRET_CALLBACK && WOLFSSL_TLS13 */ return EXPECT_RESULT(); } #if defined(WOLFSSL_TLS13) && defined(HAVE_ECH) #if defined(HAVE_IO_TESTS_DEPENDENCIES) static int test_wolfSSL_Tls13_ECH_params(void) { EXPECT_DECLS; #if !defined(NO_WOLFSSL_CLIENT) byte testBuf[256]; word32 outputLen = sizeof(testBuf); word16 tmpLen = 0; WOLFSSL_CTX* ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method()); WOLFSSL* ssl = wolfSSL_new(ctx); ExpectNotNull(ctx); ExpectNotNull(ssl); /* generation errors */ /* invalid ctx */ ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_GenerateEchConfig(NULL, "ech-public-name.com", 0, 0, 0)); /* invalid public name */ ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_GenerateEchConfig(ctx, NULL, 0, 0, 0)); /* invalid algorithms */ ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_GenerateEchConfig(ctx, "ech-public-name.com", 1000, 0, 0)); ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_GenerateEchConfig(ctx, "ech-public-name.com", 0, 1000, 0)); ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_GenerateEchConfig(ctx, "ech-public-name.com", 0, 0, 1000)); /* bad function calls */ /* NULL ctx */ ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_SetEchConfigs(NULL, testBuf, sizeof(testBuf))); ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_SetEchConfigs(NULL, testBuf, sizeof(testBuf))); /* NULL configs */ ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_SetEchConfigs(ctx, NULL, sizeof(testBuf))); ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_SetEchConfigs(ssl, NULL, sizeof(testBuf))); /* 0 length */ ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_SetEchConfigs(ctx, testBuf, 0)); ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_SetEchConfigs(ssl, testBuf, 0)); /* stateful errors */ /* actually generate configs */ ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_GenerateEchConfig(ctx, "ech-public-name.com", 0, 0, 0)); /* bad get: NULL ctx, NULL output len, short output len */ ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_GetEchConfigs(NULL, testBuf, &outputLen)); ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_GetEchConfigs(ctx, testBuf, NULL)); outputLen = 5; ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_GetEchConfigs(ctx, testBuf, &outputLen)); /* should be able to retrieve length with NULL buffer... */ ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_GetEchConfigs(ctx, NULL, &outputLen)); ExpectIntGE(sizeof(testBuf), outputLen); /* and the get should work with this length */ ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_GetEchConfigs(ctx, testBuf, &outputLen)); /* reject config with invalid total length */ if (EXPECT_SUCCESS()) { ato16(testBuf, &tmpLen); testBuf[0] = 0xFF; testBuf[1] = 0xFF; } ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_SetEchConfigs(ctx, testBuf, outputLen)); ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_SetEchConfigs(ssl, testBuf, outputLen)); if (EXPECT_SUCCESS()) { c16toa(tmpLen, testBuf); } /* reject config with invalid version */ if (EXPECT_SUCCESS()) { testBuf[2] ^= 0x01; } ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_SetEchConfigs(ctx, testBuf, outputLen)); ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_SetEchConfigs(ssl, testBuf, outputLen)); if (EXPECT_SUCCESS()) { testBuf[2] ^= 0x01; } /* reject config with bad length */ if (EXPECT_SUCCESS()) { ato16(testBuf + 4, &tmpLen); testBuf[4] = 0xFF; testBuf[5] = 0xFF; } ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_SetEchConfigs(ctx, testBuf, outputLen)); ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_SetEchConfigs(ssl, testBuf, outputLen)); if (EXPECT_SUCCESS()) { c16toa(tmpLen, testBuf + 4); } /* set valid configs */ ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_SetEchConfigs(ctx, testBuf, outputLen)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_SetEchConfigs(ssl, testBuf, outputLen)); /* NULL ssl, NULL buffer, NULL output len */ ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_GetEchConfigs(NULL, testBuf, &outputLen)); ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_GetEchConfigs(ssl, NULL, &outputLen)); ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_GetEchConfigs(ssl, testBuf, NULL)); /* reject setting configs when ssl already has them */ ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_SetEchConfigs(ssl, testBuf, outputLen)); /* unable to get configs from ssl with no configs (because of disable) */ wolfSSL_SetEchEnable(ssl, 0); outputLen = sizeof(testBuf); ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_GetEchConfigs(ssl, testBuf, &outputLen)); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #endif /* !NO_WOLFSSL_CLIENT */ return EXPECT_RESULT(); } static int test_wolfSSL_Tls13_ECH_params_b64(void) { EXPECT_DECLS; #if !defined(NO_WOLFSSL_CLIENT) /* base64 ech configs from cloudflare-ech.com (these are good configs) */ const char* b64Valid = "AEX+DQBBFAAgACBuAoQI8+liEVYQbXKBDeVgTmF2rfXuKO2knhwrN7jgTgAEAAEAAQASY2xvdWRmbGFyZS1lY2guY29tAAA="; /* ech configs with bad version */ const char* b64BadVers = "AEX+/gBBFAAgACBuAoQI8+liEVYQbXKBDeVgTmF2rfXuKO2knhwrN7jgTgAEAAEAAQASY2xvdWRmbGFyZS1lY2guY29tAAA="; /* ech configs with bad/unsupported algorithm */ const char* b64BadAlgo = "AEX+DQBBFP7+ACBuAoQI8+liEVYQbXKBDeVgTmF2rfXuKO2knhwrN7jgTgAEAAEAAQASY2xvdWRmbGFyZS1lY2guY29tAAA="; /* ech configs with 0 length algorithm */ const char* b64BadAlgo0 = "ACX+DQAhFAAgAAAABAABAAEAEmNsb3VkZmxhcmUtZWNoLmNvbQAA"; /* ech configs with long algorithm */ const char* b64BadAlgo33 = "AEb+DQBCFAAgACEBbgKECPPpYhFWEG1ygQ3lYE5hdq317ijtpJ4cKze44E4ABAABAAEAEmNsb3VkZmxhcmUtZWNoLmNvbQAA"; /* ech configs with bad/unsupported ciphersuite */ const char* b64BadCiph = "AEX+DQBBFAAgACBuAoQI8+liEVYQbXKBDeVgTmF2rfXuKO2knhwrN7jgTgAE/v4AAQASY2xvdWRmbGFyZS1lY2guY29tAAA="; /* ech configs with unrecognized mandatory extension */ const char* b64Mandatory = "AEn+DQBFFAAgACBuAoQI8+liEVYQbXKBDeVgTmF2rfXuKO2knhwrN7jgTgAEAAEAAQASY2xvdWRmbGFyZS1lY2guY29tAAT6+gAA"; /* ech configs with bad version first */ const char* b64BadVers1 = "AIz+HQBCAQAgACCjR6+Qn9UYkMaWdXZzsby88vXFhPHJ2tWCDHQJLvMkEgAEAAEAAQATZWNoLXB1YmxpYy1uYW1lLmNvbQAA/g0AQgIAIAAgMM6vLrTbOfsfA6fTbJY/Iu0Lj2xeHEPGUJeUwQGAYF4ABAABAAEAE2VjaC1wdWJsaWMtbmFtZS5jb20AAA=="; /* ech configs with bad version second */ const char* b64BadVers2 = "AIz+DQBCAQAgACCjR6+Qn9UYkMaWdXZzsby88vXFhPHJ2tWCDHQJLvMkEgAEAAEAAQATZWNoLXB1YmxpYy1uYW1lLmNvbQAA/h0AQgIAIAAgMM6vLrTbOfsfA6fTbJY/Iu0Lj2xeHEPGUJeUwQGAYF4ABAABAAEAE2VjaC1wdWJsaWMtbmFtZS5jb20AAA=="; byte testBuf[256]; word32 outputLen; WOLFSSL_CTX* ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method()); WOLFSSL* ssl = wolfSSL_new(ctx); ExpectNotNull(ctx); ExpectNotNull(ssl); /* NULL ctx/ssl, short public key */ ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_SetEchConfigsBase64(NULL, b64Valid, (word32)XSTRLEN(b64Valid))); ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_SetEchConfigsBase64(NULL, b64Valid, (word32)XSTRLEN(b64Valid))); /* NULL configs */ ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_SetEchConfigsBase64(ctx, NULL, (word32)XSTRLEN(b64Valid))); ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_SetEchConfigsBase64(ssl, NULL, (word32)XSTRLEN(b64Valid))); /* 0 length */ ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_SetEchConfigsBase64(ctx, b64Valid, 0)); ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_SetEchConfigsBase64(ssl, b64Valid, 0)); /* bad version */ ExpectIntEQ(UNSUPPORTED_PROTO_VERSION, wolfSSL_CTX_SetEchConfigsBase64(ctx, b64BadVers, (word32)XSTRLEN(b64BadVers))); ExpectIntEQ(UNSUPPORTED_PROTO_VERSION, wolfSSL_SetEchConfigsBase64(ssl, b64BadVers, (word32)XSTRLEN(b64BadVers))); /* bad algorithm */ ExpectIntEQ(UNSUPPORTED_SUITE, wolfSSL_CTX_SetEchConfigsBase64(ctx, b64BadAlgo, (word32)XSTRLEN(b64BadAlgo))); ExpectIntEQ(UNSUPPORTED_SUITE, wolfSSL_SetEchConfigsBase64(ssl, b64BadAlgo, (word32)XSTRLEN(b64BadAlgo))); /* bad algorithm with 0 length key */ ExpectIntEQ(BUFFER_E, wolfSSL_CTX_SetEchConfigsBase64(ctx, b64BadAlgo0, (word32)XSTRLEN(b64BadAlgo0))); ExpectIntEQ(BUFFER_E, wolfSSL_SetEchConfigsBase64(ssl, b64BadAlgo0, (word32)XSTRLEN(b64BadAlgo0))); /* bad algorithm with long key */ ExpectIntEQ(BUFFER_E, wolfSSL_CTX_SetEchConfigsBase64(ctx, b64BadAlgo33, (word32)XSTRLEN(b64BadAlgo33))); ExpectIntEQ(BUFFER_E, wolfSSL_SetEchConfigsBase64(ssl, b64BadAlgo33, (word32)XSTRLEN(b64BadAlgo33))); /* bad ciphersuite */ ExpectIntEQ(UNSUPPORTED_SUITE, wolfSSL_CTX_SetEchConfigsBase64(ctx, b64BadCiph, (word32)XSTRLEN(b64BadCiph))); ExpectIntEQ(UNSUPPORTED_SUITE, wolfSSL_SetEchConfigsBase64(ssl, b64BadCiph, (word32)XSTRLEN(b64BadCiph))); /* unrecognized mandatory extension */ ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_SetEchConfigsBase64(ctx, b64Mandatory, (word32)XSTRLEN(b64Mandatory))); ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_SetEchConfigsBase64(ssl, b64Mandatory, (word32)XSTRLEN(b64Mandatory))); /* bad version first, should only have config 2 set */ ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_SetEchConfigsBase64(ctx, b64BadVers1, (word32)XSTRLEN(b64BadVers1))); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_SetEchConfigsBase64(ssl, b64BadVers1, (word32)XSTRLEN(b64BadVers1))); ExpectIntEQ(2, ctx->echConfigs->configId); ExpectIntEQ(2, ssl->echConfigs->configId); /* clear configs */ wolfSSL_CTX_SetEchEnable(ctx, 0); wolfSSL_CTX_SetEchEnable(ctx, 1); wolfSSL_SetEchEnable(ssl, 0); wolfSSL_SetEchEnable(ssl, 1); /* bad version second, should only have config 1 set */ ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_SetEchConfigsBase64(ctx, b64BadVers2, (word32)XSTRLEN(b64BadVers2))); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_SetEchConfigsBase64(ssl, b64BadVers2, (word32)XSTRLEN(b64BadVers2))); ExpectIntEQ(1, ctx->echConfigs->configId); ExpectIntEQ(1, ssl->echConfigs->configId); /* clear configs */ wolfSSL_CTX_SetEchEnable(ctx, 0); wolfSSL_CTX_SetEchEnable(ctx, 1); wolfSSL_SetEchEnable(ssl, 0); wolfSSL_SetEchEnable(ssl, 1); /* base64 tests */ /* set base64 configs */ ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_SetEchConfigsBase64(ctx, b64Valid, (word32)XSTRLEN(b64Valid))); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_SetEchConfigsBase64(ssl, b64Valid, (word32)XSTRLEN(b64Valid))); /* disable and check ctx has no configs */ wolfSSL_CTX_SetEchEnable(ctx, 0); outputLen = sizeof(testBuf); ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_GetEchConfigs(ctx, testBuf, &outputLen)); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #endif /* !NO_WOLFSSL_CLIENT */ return EXPECT_RESULT(); } static int test_wolfSSL_ECH_conn_ex(method_provider serverMeth, method_provider clientMeth, int hrr) { EXPECT_DECLS; tcp_ready ready; func_args client_args; func_args server_args; THREAD_TYPE serverThread; callback_functions server_cbf; callback_functions client_cbf; SOCKET_T sockfd = 0; WOLFSSL_CTX* ctx = NULL; WOLFSSL* ssl = NULL; const char* publicName = "ech-public-name.com"; const char* privateName = "ech-private-name.com"; int privateNameLen = 20; char reply[1024]; int replyLen = 0; byte rawEchConfig[128]; word32 rawEchConfigLen = sizeof(rawEchConfig); InitTcpReady(&ready); ready.port = 22222; XMEMSET(&client_args, 0, sizeof(func_args)); XMEMSET(&server_args, 0, sizeof(func_args)); XMEMSET(&server_cbf, 0, sizeof(callback_functions)); XMEMSET(&client_cbf, 0, sizeof(callback_functions)); server_cbf.method = serverMeth; /* create the server context here so we can get the ech config */ ExpectNotNull(server_cbf.ctx = wolfSSL_CTX_new(serverMeth())); /* generate ech config */ ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_GenerateEchConfig(server_cbf.ctx, publicName, 0, 0, 0)); /* get the config for the client to use */ ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_GetEchConfigs(server_cbf.ctx, rawEchConfig, &rawEchConfigLen)); server_args.callbacks = &server_cbf; server_args.signal = &ready; /* start server task */ start_thread(server_task_ech, &server_args, &serverThread); wait_tcp_ready(&server_args); /* set the client TLS version and run */ ExpectNotNull(ctx = wolfSSL_CTX_new(clientMeth())); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_use_certificate_file(ctx, cliCertFile, SSL_FILETYPE_PEM)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_use_PrivateKey_file(ctx, cliKeyFile, SSL_FILETYPE_PEM)); tcp_connect(&sockfd, wolfSSLIP, server_args.signal->port, 0, 0, NULL); /* get connected the server task */ ExpectNotNull(ssl = wolfSSL_new(ctx)); /* set the ech configs for the client */ ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_SetEchConfigs(ssl, rawEchConfig, rawEchConfigLen)); /* set the sni for the client */ ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME, privateName, privateNameLen)); /* force hello retry request */ if (hrr) ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_NoKeyShares(ssl)); /* connect like normal */ ExpectIntEQ(wolfSSL_set_fd(ssl, sockfd), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_connect(ssl), WOLFSSL_SUCCESS); ExpectIntEQ(ssl->options.echAccepted, 1); ExpectIntEQ(wolfSSL_write(ssl, privateName, privateNameLen), privateNameLen); ExpectIntGT((replyLen = wolfSSL_read(ssl, reply, sizeof(reply))), 0); /* add the null terminator for string compare */ reply[replyLen] = '\0'; /* check that the server replied with the private name */ ExpectStrEQ(privateName, reply); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); CloseSocket(sockfd); join_thread(serverThread); FreeTcpReady(&ready); return EXPECT_RESULT(); } static int test_wolfSSL_Tls13_ECH(void) { return test_wolfSSL_ECH_conn_ex(wolfTLSv1_3_server_method, wolfTLSv1_3_client_method, 0); } static int test_wolfSSL_Tls13_ECH_HRR(void) { return test_wolfSSL_ECH_conn_ex(wolfTLSv1_3_server_method, wolfTLSv1_3_client_method, 1); } static int test_wolfSSL_SubTls13_ECH(void) { EXPECT_DECLS; #ifndef WOLFSSL_NO_TLS12 ExpectIntNE(test_wolfSSL_ECH_conn_ex(wolfTLSv1_3_server_method, wolfTLSv1_2_client_method, 0), WOLFSSL_SUCCESS); ExpectIntNE(test_wolfSSL_ECH_conn_ex(wolfTLSv1_2_server_method, wolfTLSv1_3_client_method, 0), WOLFSSL_SUCCESS); ExpectIntNE(test_wolfSSL_ECH_conn_ex(wolfSSLv23_server_method, wolfTLSv1_2_client_method, 0), WOLFSSL_SUCCESS); #endif return EXPECT_RESULT(); } #endif /* HAVE_IO_TESTS_DEPENDENCIES */ #ifdef HAVE_SSL_MEMIO_TESTS_DEPENDENCIES /* Static storage for passing ECH config between server and client callbacks */ static byte echCbTestConfigs[512]; static word32 echCbTestConfigsLen; static const char* echCbTestPublicName = "example.com"; static const char* echCbTestPrivateName = "ech-private-name.com"; static word16 echCbTestKemID = 0; static word16 echCbTestKdfID = 0; static word16 echCbTestAeadID = 0; /* the arg is whether the client has ech enabled or not */ static int test_ech_server_sni_callback(WOLFSSL* ssl, int* ad, void* arg) { const char* name; if (!wolfSSL_SNI_GetRequest(ssl, WOLFSSL_SNI_HOST_NAME, (void**)&name)) { *ad = WOLFSSL_AD_UNRECOGNIZED_NAME; return fatal_return; } /* reached by *_disable_conn test: expect name to be the public SNI when * client has ECH enabled, otherwise it should be the private SNI */ if (arg != NULL && *(int*)arg == 1 && XSTRCMP(name, echCbTestPublicName) == 0) { return 0; } else if (XSTRCMP(name, echCbTestPrivateName) == 0) { return 0; } else { *ad = WOLFSSL_AD_UNRECOGNIZED_NAME; return fatal_return; } } /* Server ctx_ready callback: generate ECH config */ static int test_ech_server_ctx_ready(WOLFSSL_CTX* ctx) { int ret; /* +20 for this isn't significant, it just exercises the padding code */ ret = wolfSSL_CTX_GenerateEchConfigEx(ctx, echCbTestPublicName, echCbTestKemID, echCbTestKdfID, echCbTestAeadID, XSTRLEN(echCbTestPublicName) + 20); if (ret != WOLFSSL_SUCCESS) return TEST_FAIL; echCbTestConfigsLen = sizeof(echCbTestConfigs); ret = wolfSSL_CTX_GetEchConfigs(ctx, echCbTestConfigs, &echCbTestConfigsLen); if (ret != WOLFSSL_SUCCESS) return TEST_FAIL; return TEST_SUCCESS; } /* Server ssl_ready callback: set SNI */ static int test_ech_server_ssl_ready(WOLFSSL* ssl) { int ret; ret = wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME, echCbTestPrivateName, (word16)XSTRLEN(echCbTestPrivateName)); if (ret != WOLFSSL_SUCCESS) return TEST_FAIL; return TEST_SUCCESS; } /* Client ssl_ready callback: set ECH configs and SNI */ static int test_ech_client_ssl_ready(WOLFSSL* ssl) { int ret; ret = wolfSSL_SetEchConfigs(ssl, echCbTestConfigs, echCbTestConfigsLen); if (ret != WOLFSSL_SUCCESS) return TEST_FAIL; ret = wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME, echCbTestPrivateName, (word16)XSTRLEN(echCbTestPrivateName)); if (ret != WOLFSSL_SUCCESS) return TEST_FAIL; return TEST_SUCCESS; } static int test_wolfSSL_Tls13_ECH_all_algos_ex(void) { EXPECT_DECLS; struct test_ssl_memio_ctx test_ctx; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); test_ctx.s_cb.method = wolfTLSv1_3_server_method; test_ctx.c_cb.method = wolfTLSv1_3_client_method; test_ctx.s_cb.ctx_ready = test_ech_server_ctx_ready; test_ctx.s_cb.ssl_ready = test_ech_server_ssl_ready; test_ctx.c_cb.ssl_ready = test_ech_client_ssl_ready; ExpectIntEQ(test_ssl_memio_setup(&test_ctx), TEST_SUCCESS); ExpectIntEQ(test_ssl_memio_do_handshake(&test_ctx, 10, NULL), TEST_SUCCESS); ExpectIntEQ(test_ctx.c_ssl->options.echAccepted, 1); if (echCbTestKemID != 0 && echCbTestKdfID != 0 && echCbTestAeadID != 0) { TLSX* echX = TLSX_Find(test_ctx.c_ssl->extensions, TLSX_ECH); ExpectNotNull(echX); if (echX != NULL) { WOLFSSL_ECH* ech = (WOLFSSL_ECH*)echX->data; ExpectNotNull(ech); if (ech != NULL) { /* verify that the ech extension has the correct algos */ ExpectIntEQ(ech->kemId, echCbTestKemID); ExpectIntEQ(ech->cipherSuite.kdfId, echCbTestKdfID); ExpectIntEQ(ech->cipherSuite.aeadId, echCbTestAeadID); if (ech->hpke != NULL) { /* and that hpke was initialized with these algos */ ExpectIntEQ(ech->hpke->kem, echCbTestKemID); ExpectIntEQ(ech->hpke->kdf, echCbTestKdfID); ExpectIntEQ(ech->hpke->aead, echCbTestAeadID); } if (ech->echConfig != NULL) { ExpectIntEQ(ech->echConfig->kemId, echCbTestKemID); } } } } test_ssl_memio_cleanup(&test_ctx); return EXPECT_RESULT(); } static int test_wolfSSL_Tls13_ECH_all_algos(void) { EXPECT_DECLS; int i; int j; int k; static const word16 kems[] = { #if defined(HAVE_ECC) #if (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && !defined(NO_SHA256) DHKEM_P256_HKDF_SHA256, #endif #if (defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)) && \ defined(WOLFSSL_SHA384) DHKEM_P384_HKDF_SHA384, #endif #if (defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)) && \ defined(WOLFSSL_SHA512) DHKEM_P521_HKDF_SHA512, #endif #endif /* HAVE_ECC */ #if defined(HAVE_CURVE25519) && !defined(NO_SHA256) DHKEM_X25519_HKDF_SHA256, #endif }; static const word16 kdfs[] = { #if !defined(NO_SHA256) HKDF_SHA256, #endif #ifdef WOLFSSL_SHA384 HKDF_SHA384, #endif #ifdef WOLFSSL_SHA512 HKDF_SHA512, #endif }; static const word16 aeads[] = { #ifdef WOLFSSL_AES_128 HPKE_AES_128_GCM, #endif #ifdef WOLFSSL_AES_256 HPKE_AES_256_GCM, #endif }; for (i = 0; i < (int)(sizeof(kems) / sizeof(*kems)); i++) { echCbTestKemID = kems[i]; for (j = 0; j < (int)(sizeof(kdfs) / sizeof(*kdfs)); j++) { echCbTestKdfID = kdfs[j]; for (k = 0; k < (int)(sizeof(aeads) / sizeof(*aeads)); k++) { echCbTestAeadID = aeads[k]; ExpectIntEQ(test_wolfSSL_Tls13_ECH_all_algos_ex(), TEST_SUCCESS); } } } echCbTestKemID = 0; echCbTestKdfID = 0; echCbTestAeadID = 0; return EXPECT_RESULT(); } /* Test ECH when no private SNI is set */ static int test_wolfSSL_Tls13_ECH_no_private_name(void) { EXPECT_DECLS; struct test_ssl_memio_ctx test_ctx; /* client sends private SNI, server does not have one set */ XMEMSET(&test_ctx, 0, sizeof(test_ctx)); test_ctx.s_cb.method = wolfTLSv1_3_server_method; test_ctx.c_cb.method = wolfTLSv1_3_client_method; test_ctx.s_cb.ctx_ready = test_ech_server_ctx_ready; test_ctx.c_cb.ssl_ready = test_ech_client_ssl_ready; ExpectIntEQ(test_ssl_memio_setup(&test_ctx), TEST_SUCCESS); ExpectIntEQ(test_ssl_memio_do_handshake(&test_ctx, 10, NULL), TEST_SUCCESS); ExpectIntEQ(test_ctx.c_ssl->options.echAccepted, 1); test_ssl_memio_cleanup(&test_ctx); /* client does not send private SNI, server has one set */ XMEMSET(&test_ctx, 0, sizeof(test_ctx)); test_ctx.s_cb.method = wolfTLSv1_3_server_method; test_ctx.c_cb.method = wolfTLSv1_3_client_method; test_ctx.s_cb.ctx_ready = test_ech_server_ctx_ready; test_ctx.s_cb.ssl_ready = test_ech_server_ssl_ready; ExpectIntEQ(test_ssl_memio_setup(&test_ctx), TEST_SUCCESS); ExpectIntEQ(wolfSSL_SetEchConfigs(test_ctx.c_ssl, echCbTestConfigs, echCbTestConfigsLen), WOLFSSL_SUCCESS); ExpectIntNE(test_ssl_memio_do_handshake(&test_ctx, 10, NULL), TEST_SUCCESS); ExpectIntEQ(test_ctx.c_ssl->options.echAccepted, 0); test_ssl_memio_cleanup(&test_ctx); /* client does not send private SNI, server does not have one set */ XMEMSET(&test_ctx, 0, sizeof(test_ctx)); test_ctx.s_cb.method = wolfTLSv1_3_server_method; test_ctx.c_cb.method = wolfTLSv1_3_client_method; test_ctx.s_cb.ctx_ready = test_ech_server_ctx_ready; ExpectIntEQ(test_ssl_memio_setup(&test_ctx), TEST_SUCCESS); ExpectIntEQ(wolfSSL_SetEchConfigs(test_ctx.c_ssl, echCbTestConfigs, echCbTestConfigsLen), WOLFSSL_SUCCESS); ExpectIntNE(test_ssl_memio_do_handshake(&test_ctx, 10, NULL), TEST_SUCCESS); ExpectIntEQ(test_ctx.c_ssl->options.echAccepted, 0); test_ssl_memio_cleanup(&test_ctx); return EXPECT_RESULT(); } /* Test ECH rejection when configs don't match */ static int test_wolfSSL_Tls13_ECH_bad_configs_ex(int hrr, int sniCb) { EXPECT_DECLS; struct test_ssl_memio_ctx test_ctx; WOLFSSL_CTX* tempCtx = NULL; const char* badPrivateName = "ech-bad-private-name.com"; byte badPublicConfig[128]; word32 badPublicConfigLen = sizeof(badPublicConfig); /* verify with bad public SNI / config */ XMEMSET(&test_ctx, 0, sizeof(test_ctx)); test_ctx.s_cb.method = wolfTLSv1_3_server_method; test_ctx.c_cb.method = wolfTLSv1_3_client_method; /* server generates its own ECH config */ test_ctx.s_cb.ctx_ready = test_ech_server_ctx_ready; test_ctx.s_cb.ssl_ready = test_ech_server_ssl_ready; ExpectIntEQ(test_ssl_memio_setup(&test_ctx), TEST_SUCCESS); /* generate throwaway ECH config for client to use */ ExpectNotNull(tempCtx = wolfSSL_CTX_new(wolfTLSv1_3_server_method())); ExpectIntEQ(wolfSSL_CTX_GenerateEchConfig(tempCtx, echCbTestPublicName, 0, 0, 0), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_GetEchConfigs(tempCtx, badPublicConfig, &badPublicConfigLen), WOLFSSL_SUCCESS); wolfSSL_CTX_free(tempCtx); tempCtx = NULL; /* set bad public config on client */ ExpectIntEQ(wolfSSL_SetEchConfigs(test_ctx.c_ssl, badPublicConfig, badPublicConfigLen), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_UseSNI(test_ctx.c_ssl, WOLFSSL_SNI_HOST_NAME, echCbTestPrivateName, (word16)XSTRLEN(echCbTestPrivateName)), WOLFSSL_SUCCESS); /* client will send empty cert on rejection, so server should not ask for * cert */ wolfSSL_set_verify(test_ctx.s_ssl, WOLFSSL_VERIFY_NONE, NULL); if (hrr) { ExpectIntEQ(wolfSSL_NoKeyShares(test_ctx.c_ssl), WOLFSSL_SUCCESS); } if (sniCb) { wolfSSL_CTX_set_servername_callback(test_ctx.s_ctx, test_ech_server_sni_callback); } ExpectIntNE(test_ssl_memio_do_handshake(&test_ctx, 10, NULL), TEST_SUCCESS); ExpectIntEQ(test_ctx.c_ssl->options.echAccepted, 0); test_ssl_memio_cleanup(&test_ctx); /* verify with bad private SNI */ XMEMSET(&test_ctx, 0, sizeof(test_ctx)); test_ctx.s_cb.method = wolfTLSv1_3_server_method; test_ctx.c_cb.method = wolfTLSv1_3_client_method; test_ctx.s_cb.ctx_ready = test_ech_server_ctx_ready; test_ctx.s_cb.ssl_ready = test_ech_server_ssl_ready; ExpectIntEQ(test_ssl_memio_setup(&test_ctx), TEST_SUCCESS); /* set bad private SNI on client */ ExpectIntEQ(wolfSSL_SetEchConfigs(test_ctx.c_ssl, echCbTestConfigs, echCbTestConfigsLen), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_UseSNI(test_ctx.c_ssl, WOLFSSL_SNI_HOST_NAME, badPrivateName, (word16)XSTRLEN(badPrivateName)), WOLFSSL_SUCCESS); /* client will send empty cert on rejection, so server should not ask for * cert */ wolfSSL_set_verify(test_ctx.s_ssl, WOLFSSL_VERIFY_NONE, NULL); if (hrr) { ExpectIntEQ(wolfSSL_NoKeyShares(test_ctx.c_ssl), WOLFSSL_SUCCESS); } if (sniCb) { wolfSSL_CTX_set_servername_callback(test_ctx.s_ctx, test_ech_server_sni_callback); } ExpectIntNE(test_ssl_memio_do_handshake(&test_ctx, 10, NULL), TEST_SUCCESS); ExpectIntEQ(test_ctx.c_ssl->options.echAccepted, 0); test_ssl_memio_cleanup(&test_ctx); return EXPECT_RESULT(); } static int test_wolfSSL_Tls13_ECH_bad_configs(void) { EXPECT_DECLS; ExpectIntEQ(test_wolfSSL_Tls13_ECH_bad_configs_ex(0, 0), WOLFSSL_SUCCESS); ExpectIntEQ(test_wolfSSL_Tls13_ECH_bad_configs_ex(0, 1), WOLFSSL_SUCCESS); ExpectIntEQ(test_wolfSSL_Tls13_ECH_bad_configs_ex(1, 0), WOLFSSL_SUCCESS); ExpectIntEQ(test_wolfSSL_Tls13_ECH_bad_configs_ex(1, 1), WOLFSSL_SUCCESS); return EXPECT_RESULT(); } /* Test retry configs are returned after ECH rejection and are usable */ static int test_wolfSSL_Tls13_ECH_retry_configs_ex(int hrr) { EXPECT_DECLS; test_ssl_memio_ctx test_ctx; WOLFSSL_CTX* tempCtx = NULL; byte badConfigs[256]; word32 badConfigsLen = sizeof(badConfigs); byte retryConfigs[256]; word32 retryConfigsLen = sizeof(retryConfigs); WOLFSSL_CTX* savedSCtx; /* --- first attempt: wrong ECH config -> ECH rejected --- */ XMEMSET(&test_ctx, 0, sizeof(test_ctx)); test_ctx.s_cb.method = wolfTLSv1_3_server_method; test_ctx.c_cb.method = wolfTLSv1_3_client_method; test_ctx.s_cb.ctx_ready = test_ech_server_ctx_ready; test_ctx.s_cb.ssl_ready = test_ech_server_ssl_ready; ExpectIntEQ(test_ssl_memio_setup(&test_ctx), TEST_SUCCESS); /* throwaway ECH config the server won't recognise */ ExpectNotNull(tempCtx = wolfSSL_CTX_new(wolfTLSv1_3_server_method())); ExpectIntEQ(wolfSSL_CTX_GenerateEchConfig(tempCtx, echCbTestPublicName, 0, 0, 0), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_GetEchConfigs(tempCtx, badConfigs, &badConfigsLen), WOLFSSL_SUCCESS); wolfSSL_CTX_free(tempCtx); tempCtx = NULL; ExpectIntEQ(wolfSSL_SetEchConfigs(test_ctx.c_ssl, badConfigs, badConfigsLen), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_UseSNI(test_ctx.c_ssl, WOLFSSL_SNI_HOST_NAME, echCbTestPrivateName, (word16)XSTRLEN(echCbTestPrivateName)), WOLFSSL_SUCCESS); if (hrr) ExpectIntEQ(wolfSSL_NoKeyShares(test_ctx.c_ssl), WOLFSSL_SUCCESS); /* ECH must fail and retry configs must be present */ ExpectIntNE(test_ssl_memio_do_handshake(&test_ctx, 10, NULL), TEST_SUCCESS); ExpectIntEQ(test_ctx.c_ssl->options.echAccepted, 0); ExpectIntEQ(wolfSSL_get_error(test_ctx.c_ssl, 0), WC_NO_ERR_TRACE(ECH_REQUIRED_E)); /* capture retry configs */ ExpectIntEQ(wolfSSL_GetEchRetryConfigs(test_ctx.c_ssl, retryConfigs, &retryConfigsLen), WOLFSSL_SUCCESS); ExpectIntEQ(test_ctx.c_ssl->error, ECH_REQUIRED_E); ExpectIntGT(retryConfigsLen, 0); if (EXPECT_SUCCESS()){ /* keep server CTX so second attempt uses the same ECH keys */ savedSCtx = test_ctx.s_ctx; test_ctx.s_cb.isSharedCtx = 1; test_ssl_memio_cleanup(&test_ctx); /* --- second attempt: same server CTX, retry configs -> accepted --- */ XMEMSET(&test_ctx, 0, sizeof(test_ctx)); test_ctx.s_cb.method = wolfTLSv1_3_server_method; test_ctx.c_cb.method = wolfTLSv1_3_client_method; test_ctx.s_cb.ssl_ready = test_ech_server_ssl_ready; /* restore server CTX; ctx_ready left NULL to skip ECH key regen */ test_ctx.s_ctx = savedSCtx; test_ctx.s_cb.isSharedCtx = 1; ExpectIntEQ(test_ssl_memio_setup(&test_ctx), TEST_SUCCESS); ExpectIntEQ(wolfSSL_SetEchConfigs(test_ctx.c_ssl, retryConfigs, retryConfigsLen), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_UseSNI(test_ctx.c_ssl, WOLFSSL_SNI_HOST_NAME, echCbTestPrivateName, (word16)XSTRLEN(echCbTestPrivateName)), WOLFSSL_SUCCESS); if (hrr) ExpectIntEQ(wolfSSL_NoKeyShares(test_ctx.c_ssl), WOLFSSL_SUCCESS); ExpectIntEQ(test_ssl_memio_do_handshake(&test_ctx, 10, NULL), TEST_SUCCESS); ExpectIntEQ(test_ctx.c_ssl->options.echAccepted, 1); wolfSSL_CTX_free(test_ctx.s_ctx); test_ctx.s_ctx = NULL; } test_ssl_memio_cleanup(&test_ctx); return EXPECT_RESULT(); } static int test_wolfSSL_Tls13_ECH_retry_configs(void) { EXPECT_DECLS; ExpectIntEQ(test_wolfSSL_Tls13_ECH_retry_configs_ex(0), TEST_SUCCESS); ExpectIntEQ(test_wolfSSL_Tls13_ECH_retry_configs_ex(1), TEST_SUCCESS); return EXPECT_RESULT(); } /* Test retry configs are cleared when authentication fails */ static int test_wolfSSL_Tls13_ECH_retry_configs_auth_fail_ex(int hrr) { EXPECT_DECLS; test_ssl_memio_ctx test_ctx; WOLFSSL_CTX* tempCtx = NULL; byte badConfigs[256]; word32 badConfigsLen = sizeof(badConfigs); word32 retryConfigsLen = sizeof(badConfigs); const char* badPublicName = "ech-public-name.com"; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); test_ctx.s_cb.method = wolfTLSv1_3_server_method; test_ctx.c_cb.method = wolfTLSv1_3_client_method; test_ctx.s_cb.ctx_ready = test_ech_server_ctx_ready; ExpectIntEQ(test_ssl_memio_setup(&test_ctx), TEST_SUCCESS); /* generate mismatched ECH configs so retry_configs are sent * and use a bad public name so auth fails in outer hello */ ExpectNotNull(tempCtx = wolfSSL_CTX_new(wolfTLSv1_3_server_method())); ExpectIntEQ(wolfSSL_CTX_GenerateEchConfig(tempCtx, badPublicName, 0, 0, 0), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_GetEchConfigs(tempCtx, badConfigs, &badConfigsLen), WOLFSSL_SUCCESS); wolfSSL_CTX_free(tempCtx); tempCtx = NULL; ExpectIntEQ(wolfSSL_SetEchConfigs(test_ctx.c_ssl, badConfigs, badConfigsLen), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_UseSNI(test_ctx.c_ssl, WOLFSSL_SNI_HOST_NAME, echCbTestPrivateName, (word16)XSTRLEN(echCbTestPrivateName)), WOLFSSL_SUCCESS); /* Do not require client cert on server so it does not send * CertificateRequest */ wolfSSL_set_verify(test_ctx.s_ssl, WOLFSSL_VERIFY_NONE, NULL); wolfSSL_set_verify(test_ctx.c_ssl, WOLFSSL_VERIFY_PEER, NULL); /* use badPublicName so ECH public name matches */ ExpectIntEQ(wolfSSL_UseSNI(test_ctx.s_ssl, WOLFSSL_SNI_HOST_NAME, badPublicName, (word16)XSTRLEN(badPublicName)), WOLFSSL_SUCCESS); if (hrr) ExpectIntEQ(wolfSSL_NoKeyShares(test_ctx.c_ssl), WOLFSSL_SUCCESS); /* auth failure in outer handshake, not ech_required */ ExpectIntNE(test_ssl_memio_do_handshake(&test_ctx, 10, NULL), TEST_SUCCESS); ExpectIntEQ(wolfSSL_get_error(test_ctx.c_ssl, 0), WC_NO_ERR_TRACE(DOMAIN_NAME_MISMATCH)); /* retry configs must not be accessible */ ExpectIntNE(wolfSSL_GetEchRetryConfigs(test_ctx.c_ssl, NULL, &retryConfigsLen), WOLFSSL_SUCCESS); test_ssl_memio_cleanup(&test_ctx); return EXPECT_RESULT(); } static int test_wolfSSL_Tls13_ECH_retry_configs_auth_fail(void) { EXPECT_DECLS; ExpectIntEQ(test_wolfSSL_Tls13_ECH_retry_configs_auth_fail_ex(0), TEST_SUCCESS); ExpectIntEQ(test_wolfSSL_Tls13_ECH_retry_configs_auth_fail_ex(1), TEST_SUCCESS); return EXPECT_RESULT(); } /* Test that bad retry configs (unsupported cipher suite) from the server are * ignored rather than propagating an error */ static int test_wolfSSL_Tls13_ECH_retry_configs_bad(void) { EXPECT_DECLS; test_ssl_memio_ctx test_ctx; word32 retryConfigsLen = sizeof(echCbTestConfigs); XMEMSET(&test_ctx, 0, sizeof(test_ctx)); test_ctx.s_cb.method = wolfTLSv1_3_server_method; test_ctx.c_cb.method = wolfTLSv1_3_client_method; test_ctx.s_cb.ctx_ready = test_ech_server_ctx_ready; test_ctx.s_cb.ssl_ready = test_ech_server_ssl_ready; test_ctx.c_cb.ssl_ready = test_ech_client_ssl_ready; ExpectIntEQ(test_ssl_memio_setup(&test_ctx), TEST_SUCCESS); /* corrupt the server's cipher suite -> ECH decrypt will fail, and retry * configs will have an unsupported KDF/AEAD pair. * This will trigger the UNSUPPORTED_SUITE path in TLSX_ECH_Parse */ if (EXPECT_SUCCESS() && test_ctx.s_ctx->echConfigs != NULL && test_ctx.s_ctx->echConfigs->cipherSuites != NULL) { test_ctx.s_ctx->echConfigs->cipherSuites[0].aeadId = 0xFEFE; } /* bad retry configs are discarded - failure must be ECH_REQUIRED_E, * not a retry-config parse error */ ExpectIntNE(test_ssl_memio_do_handshake(&test_ctx, 10, NULL), TEST_SUCCESS); ExpectIntEQ(test_ctx.c_ssl->options.echAccepted, 0); ExpectIntEQ(wolfSSL_get_error(test_ctx.c_ssl, 0), WC_NO_ERR_TRACE(ECH_REQUIRED_E)); /* no retry configs should be stored since they were all unsupported */ ExpectIntNE(wolfSSL_GetEchRetryConfigs(test_ctx.c_ssl, NULL, &retryConfigsLen), WOLFSSL_SUCCESS); test_ssl_memio_cleanup(&test_ctx); return EXPECT_RESULT(); } /* Test that client info can be successfully decoded from one of multiple server * ECH configs * In this case the server is expected to try it's first config, fail, then try * its second config and succeed */ static int test_wolfSSL_Tls13_ECH_new_config(void) { EXPECT_DECLS; test_ssl_memio_ctx test_ctx; byte altConfig[512]; word32 altConfigLen = sizeof(altConfig); byte combinedConfigs[512]; word32 combinedConfigsLen = sizeof(combinedConfigs); word16 firstConfigLen = 0; word16 secondConfigOffset = 0; word16 secondConfigLen = 0; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); test_ctx.s_cb.method = wolfTLSv1_3_server_method; test_ctx.c_cb.method = wolfTLSv1_3_client_method; /* server generates its own ECH config */ test_ctx.s_cb.ctx_ready = test_ech_server_ctx_ready; test_ctx.s_cb.ssl_ready = test_ech_server_ssl_ready; ExpectIntEQ(test_ssl_memio_setup(&test_ctx), TEST_SUCCESS); /* generate a second ECH config for the server */ ExpectIntEQ(wolfSSL_CTX_GenerateEchConfig(test_ctx.s_ctx, echCbTestPrivateName, 0, 0, 0), WOLFSSL_SUCCESS); ExpectNotNull(test_ctx.s_ctx->echConfigs->next); /* capture the second ECH config in the list for the client to use */ ExpectIntEQ(wolfSSL_CTX_GetEchConfigs(test_ctx.s_ctx, combinedConfigs, &combinedConfigsLen), WOLFSSL_SUCCESS); /* ECHConfigList: [2 byte list len] [ECHConfig]... * ECHConfig: [2 byte version] [2 byte config len] [config data] */ ExpectIntGE(combinedConfigsLen, OPAQUE16_LEN * 3); if (EXPECT_SUCCESS()) { ato16(combinedConfigs + OPAQUE16_LEN + OPAQUE16_LEN, &firstConfigLen); secondConfigOffset = OPAQUE16_LEN + OPAQUE16_LEN + OPAQUE16_LEN + firstConfigLen; ExpectIntGE(combinedConfigsLen, secondConfigOffset + OPAQUE16_LEN + OPAQUE16_LEN); } if (EXPECT_SUCCESS()) { ato16(combinedConfigs + secondConfigOffset + OPAQUE16_LEN, &secondConfigLen); secondConfigLen += OPAQUE16_LEN + OPAQUE16_LEN; ExpectIntGE(combinedConfigsLen, secondConfigOffset + secondConfigLen); } if (EXPECT_SUCCESS()) { /* build the ECHConfigList */ c16toa(secondConfigLen, altConfig); ExpectIntLE(OPAQUE16_LEN + secondConfigLen, (word16)sizeof(altConfig)); if (EXPECT_SUCCESS()) { XMEMCPY(altConfig + OPAQUE16_LEN, combinedConfigs + secondConfigOffset, secondConfigLen); altConfigLen = OPAQUE16_LEN + secondConfigLen; } } /* Set client configs - server should try both and succeed with second * Or seek the correct one immediately through the configId */ ExpectIntEQ(wolfSSL_SetEchConfigs(test_ctx.c_ssl, altConfig, altConfigLen), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_UseSNI(test_ctx.c_ssl, WOLFSSL_SNI_HOST_NAME, echCbTestPrivateName, (word16)XSTRLEN(echCbTestPrivateName)), WOLFSSL_SUCCESS); ExpectIntEQ(test_ssl_memio_do_handshake(&test_ctx, 10, NULL), TEST_SUCCESS); ExpectIntEQ(test_ctx.c_ssl->options.echAccepted, 1); test_ssl_memio_cleanup(&test_ctx); return EXPECT_RESULT(); } /* Test GREASE ECH: * 1. client sends GREASE ECH extension but server has no ECH configs so it * ignores it, handshake succeeds normally * 2. client sends GREASE ECH extensions and server has ECH configs, handshake * succeeds * configs should never be received */ static int test_wolfSSL_Tls13_ECH_GREASE(void) { EXPECT_DECLS; test_ssl_memio_ctx test_ctx; word32 retryConfigsLen = sizeof(test_ctx); /* GREASE when server has no ECH configs */ XMEMSET(&test_ctx, 0, sizeof(test_ctx)); test_ctx.s_cb.method = wolfTLSv1_3_server_method; test_ctx.c_cb.method = wolfTLSv1_3_client_method; ExpectIntEQ(test_ssl_memio_setup(&test_ctx), TEST_SUCCESS); ExpectIntEQ(wolfSSL_UseSNI(test_ctx.c_ssl, WOLFSSL_SNI_HOST_NAME, echCbTestPrivateName, (word16)XSTRLEN(echCbTestPrivateName)), WOLFSSL_SUCCESS); /* verify ECH is enabled on the client and server */ ExpectIntEQ(test_ctx.s_ssl->options.disableECH, 0); ExpectIntEQ(test_ctx.c_ssl->options.disableECH, 0); /* verify no ECH configs are set */ ExpectNull(test_ctx.s_ctx->echConfigs); ExpectNull(test_ctx.c_ssl->echConfigs); /* handshake should succeed - server ignores the GREASE ECH extension */ ExpectIntEQ(test_ssl_memio_do_handshake(&test_ctx, 10, NULL), TEST_SUCCESS); /* ECH should NOT be accepted since this was GREASE */ ExpectIntEQ(test_ctx.s_ssl->options.echAccepted, 0); ExpectIntEQ(test_ctx.c_ssl->options.echAccepted, 0); /* verify no ECH configs are received */ ExpectNull(test_ctx.c_ssl->echConfigs); /* retry configs must not be saved */ ExpectIntNE(wolfSSL_GetEchRetryConfigs(test_ctx.c_ssl, NULL, &retryConfigsLen), WOLFSSL_SUCCESS); test_ssl_memio_cleanup(&test_ctx); /* GREASE when server has ECH configs */ XMEMSET(&test_ctx, 0, sizeof(test_ctx)); test_ctx.s_cb.method = wolfTLSv1_3_server_method; test_ctx.c_cb.method = wolfTLSv1_3_client_method; /* generate ECH configs */ test_ctx.s_cb.ctx_ready = test_ech_server_ctx_ready; test_ctx.s_cb.ssl_ready = test_ech_server_ssl_ready; ExpectIntEQ(test_ssl_memio_setup(&test_ctx), TEST_SUCCESS); ExpectIntEQ(wolfSSL_UseSNI(test_ctx.c_ssl, WOLFSSL_SNI_HOST_NAME, echCbTestPrivateName, (word16)XSTRLEN(echCbTestPrivateName)), WOLFSSL_SUCCESS); /* verify ECH is enabled on the client and server */ ExpectIntEQ(test_ctx.s_ssl->options.disableECH, 0); ExpectIntEQ(test_ctx.c_ssl->options.disableECH, 0); /* verify ECH configs are set on server */ ExpectNotNull(test_ctx.s_ctx->echConfigs); ExpectNull(test_ctx.c_ssl->echConfigs); /* handshake should succeed - server responds to the GREASE ECH extension */ ExpectIntEQ(test_ssl_memio_do_handshake(&test_ctx, 10, NULL), TEST_SUCCESS); /* ECH should NOT be accepted since this was GREASE */ ExpectIntEQ(test_ctx.s_ssl->options.echAccepted, 0); ExpectIntEQ(test_ctx.c_ssl->options.echAccepted, 0); /* verify no ECH configs are received */ ExpectNull(test_ctx.c_ssl->echConfigs); /* retry configs must not be saved */ ExpectIntNE(wolfSSL_GetEchRetryConfigs(test_ctx.c_ssl, NULL, &retryConfigsLen), WOLFSSL_SUCCESS); test_ssl_memio_cleanup(&test_ctx); return EXPECT_RESULT(); } static int test_wolfSSL_Tls13_ECH_disable_conn_ex(int enableServer, int enableClient) { EXPECT_DECLS; test_ssl_memio_ctx test_ctx; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); test_ctx.s_cb.method = wolfTLSv1_3_server_method; test_ctx.c_cb.method = wolfTLSv1_3_client_method; /* both server and client will be setup to use ECH */ test_ctx.s_cb.ctx_ready = test_ech_server_ctx_ready; test_ctx.s_cb.ssl_ready = test_ech_server_ssl_ready; test_ctx.c_cb.ssl_ready = test_ech_client_ssl_ready; ExpectIntEQ(test_ssl_memio_setup(&test_ctx), TEST_SUCCESS); /* this callback will ensure that the correct SNI is being held */ wolfSSL_CTX_set_servername_callback(test_ctx.s_ctx, test_ech_server_sni_callback); ExpectIntEQ(wolfSSL_CTX_set_servername_arg(test_ctx.s_ctx, &enableClient), WOLFSSL_SUCCESS); /* disable ECH on the appropriate side(s) */ wolfSSL_SetEchEnable(test_ctx.s_ssl, enableServer); wolfSSL_SetEchEnable(test_ctx.c_ssl, enableClient); if (!enableClient) { /* client ECH disabled: no ECH extension sent, handshake succeeds * normally but ECH is not accepted */ ExpectIntEQ(test_ssl_memio_do_handshake(&test_ctx, 10, NULL), TEST_SUCCESS); } else if (!enableServer) { /* client sends ECH but server can't process it: server has no ECH * keys so it processes the outer ClientHello, client detects ECH * rejection and aborts the handshake */ ExpectIntNE(test_ssl_memio_do_handshake(&test_ctx, 10, NULL), TEST_SUCCESS); } ExpectIntEQ(test_ctx.c_ssl->options.echAccepted, 0); test_ssl_memio_cleanup(&test_ctx); return EXPECT_RESULT(); } /* setup a server and client with ECH then disable on one, the other, or both. * Verifies that disabling ECH prevents ECH from being used and that the * public/private SNI's are verified correctly */ static int test_wolfSSL_Tls13_ECH_disable_conn(void) { EXPECT_DECLS; ExpectIntEQ(test_wolfSSL_Tls13_ECH_disable_conn_ex(0, 1), TEST_SUCCESS); ExpectIntEQ(test_wolfSSL_Tls13_ECH_disable_conn_ex(1, 0), TEST_SUCCESS); ExpectIntEQ(test_wolfSSL_Tls13_ECH_disable_conn_ex(0, 0), TEST_SUCCESS); return EXPECT_RESULT(); } /* Regression test: an inner SNI hostname >= MAX_PUBLIC_NAME_SZ (256) bytes * must not cause a stack-buffer-overflow in TLSX_EchRestoreSNI. Before the * fix, the truncated copy omitted the NUL terminator and XSTRLEN read past * the buffer. */ static int test_wolfSSL_Tls13_ECH_long_SNI(void) { EXPECT_DECLS; #if !defined(NO_WOLFSSL_CLIENT) test_ssl_memio_ctx test_ctx; /* 300 chars > MAX_PUBLIC_NAME_SZ (256) to exercise truncation */ char longName[300]; XMEMSET(longName, 'a', sizeof(longName) - 1); longName[sizeof(longName) - 1] = '\0'; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); test_ctx.s_cb.method = wolfTLSv1_3_server_method; test_ctx.c_cb.method = wolfTLSv1_3_client_method; test_ctx.s_cb.ctx_ready = test_ech_server_ctx_ready; test_ctx.s_cb.ssl_ready = test_ech_server_ssl_ready; ExpectIntEQ(test_ssl_memio_setup(&test_ctx), TEST_SUCCESS); /* Set ECH configs on the client */ ExpectIntEQ(wolfSSL_SetEchConfigs(test_ctx.c_ssl, echCbTestConfigs, echCbTestConfigsLen), WOLFSSL_SUCCESS); /* Try to set the over-long SNI as the inner hostname -- after the fix, this * is expected to fail. */ ExpectIntEQ(wolfSSL_UseSNI(test_ctx.c_ssl, WOLFSSL_SNI_HOST_NAME, longName, (word16)XSTRLEN(longName)), BAD_LENGTH_E); /* Before the fix, the handshake would trigger TLSX_EchChangeSNI / * TLSX_EchRestoreSNI, which would then stack-buffer-overflow in XSTRLEN. */ (void)test_ssl_memio_do_handshake(&test_ctx, 10, NULL); test_ssl_memio_cleanup(&test_ctx); #endif /* !NO_WOLFSSL_CLIENT */ return EXPECT_RESULT(); } /* Test the HRR ECH rejection fallback path: * client offers ECH, HRR is triggered, server sends HRR without ECH extension, * client falls back to the outer transcript, then aborts with ech_required. */ static int test_wolfSSL_Tls13_ECH_HRR_rejection(void) { EXPECT_DECLS; test_ssl_memio_ctx test_ctx; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); test_ctx.s_cb.method = wolfTLSv1_3_server_method; test_ctx.c_cb.method = wolfTLSv1_3_client_method; /* Server generates ECH config with good public name */ test_ctx.s_cb.ctx_ready = test_ech_server_ctx_ready; /* Client sets the correct ECH config and private SNI */ test_ctx.c_cb.ssl_ready = test_ech_client_ssl_ready; ExpectIntEQ(test_ssl_memio_setup(&test_ctx), TEST_SUCCESS); /* Server must not require a client certificate */ wolfSSL_set_verify(test_ctx.s_ssl, WOLFSSL_VERIFY_NONE, NULL); wolfSSL_set_verify(test_ctx.c_ssl, WOLFSSL_VERIFY_PEER, NULL); /* Disable ECH on the server SSL object: the server ignores ECH in CH1 and * sends HRR without an ECH extension (confBuf stays NULL on the client) */ wolfSSL_SetEchEnable(test_ctx.s_ssl, 0); ExpectIntEQ(wolfSSL_UseSNI(test_ctx.s_ssl, WOLFSSL_SNI_HOST_NAME, echCbTestPublicName, (word16)XSTRLEN(echCbTestPublicName)), WOLFSSL_SUCCESS); /* Force HRR so client receives HRR with no ECH extension, * detects confBuf == NULL and frees hsHashesEch, falling back to the * outer transcript */ ExpectIntEQ(wolfSSL_NoKeyShares(test_ctx.c_ssl), WOLFSSL_SUCCESS); /* Handshake must fail: client aborts with ech_required */ ExpectIntNE(test_ssl_memio_do_handshake(&test_ctx, 10, NULL), TEST_SUCCESS); ExpectIntEQ(test_ctx.c_ssl->options.echAccepted, 0); /* hsHashesEch must have been freed by the HRR rejection code path */ ExpectNull(test_ctx.c_ssl->hsHashesEch); ExpectIntEQ(wolfSSL_get_error(test_ctx.c_ssl, 0), WC_NO_ERR_TRACE(ECH_REQUIRED_E)); test_ssl_memio_cleanup(&test_ctx); return EXPECT_RESULT(); } /* verify the server aborts if CH2 omits the ECH extension after the server * accepted ECH in the HRR round */ static int test_wolfSSL_Tls13_ECH_ch2_no_ech(void) { EXPECT_DECLS; test_ssl_memio_ctx test_ctx; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); test_ctx.s_cb.method = wolfTLSv1_3_server_method; test_ctx.c_cb.method = wolfTLSv1_3_client_method; test_ctx.s_cb.ctx_ready = test_ech_server_ctx_ready; test_ctx.s_cb.ssl_ready = test_ech_server_ssl_ready; test_ctx.c_cb.ssl_ready = test_ech_client_ssl_ready; ExpectIntEQ(test_ssl_memio_setup(&test_ctx), TEST_SUCCESS); /* withhold key shares from CH1 so the server is forced to send HRR */ ExpectIntEQ(wolfSSL_NoKeyShares(test_ctx.c_ssl), WOLFSSL_SUCCESS); /* one round: client sends CH1, server processes it and sends HRR */ (void)test_ssl_memio_do_handshake(&test_ctx, 1, NULL); /* server must have committed to ECH acceptance in the HRR */ ExpectIntEQ(test_ctx.s_ssl->options.serverState, SERVER_HELLO_RETRY_REQUEST_COMPLETE); ExpectIntEQ(test_ctx.s_ssl->options.echAccepted, 1); /* disable ECH on the client so CH2 omits the ECH extension entirely */ wolfSSL_SetEchEnable(test_ctx.c_ssl, 0); /* rest of handshake must fail */ ExpectIntNE(test_ssl_memio_do_handshake(&test_ctx, 10, NULL), TEST_SUCCESS); ExpectIntEQ(wolfSSL_get_error(test_ctx.s_ssl, 0), WC_NO_ERR_TRACE(INCOMPLETE_DATA)); test_ssl_memio_cleanup(&test_ctx); return EXPECT_RESULT(); } /* verify that a decryption failure in CH2 is caught * this also verifies that HPKE context is correctly reused */ static int test_wolfSSL_Tls13_ECH_ch2_decrypt_error(void) { EXPECT_DECLS; test_ssl_memio_ctx test_ctx; int i; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); test_ctx.s_cb.method = wolfTLSv1_3_server_method; test_ctx.c_cb.method = wolfTLSv1_3_client_method; test_ctx.s_cb.ctx_ready = test_ech_server_ctx_ready; test_ctx.s_cb.ssl_ready = test_ech_server_ssl_ready; test_ctx.c_cb.ssl_ready = test_ech_client_ssl_ready; ExpectIntEQ(test_ssl_memio_setup(&test_ctx), TEST_SUCCESS); /* Withhold key shares so the server is forced to send HRR */ ExpectIntEQ(wolfSSL_NoKeyShares(test_ctx.c_ssl), WOLFSSL_SUCCESS); /* One round: client sends CH1, server processes it and sends HRR */ (void)test_ssl_memio_do_handshake(&test_ctx, 1, NULL); ExpectIntEQ(test_ctx.s_ssl->options.serverState, SERVER_HELLO_RETRY_REQUEST_COMPLETE); ExpectIntEQ(test_ctx.s_ssl->options.echAccepted, 1); if (EXPECT_SUCCESS()) { /* Client reads HRR and writes CH2 into s_buff */ (void)wolfSSL_connect(test_ctx.c_ssl); /* Corrupt one byte of the ECH ciphertext in the CH2 record in s_buff. * ECH outer extension layout after the 0xFE0D type marker: * extLen(2) + outerType(1) + kdfId(2) + aeadId(2) + configId(1) * + encLen(2, always 0 in CH2) + payloadLen(2) = 12 bytes, so the * ciphertext starts 14 bytes past the first 0xFE byte. */ for (i = 0; i < test_ctx.s_len - 1; i++) { if (test_ctx.s_buff[i] == 0xFE && test_ctx.s_buff[i + 1] == 0x0D) { if (i + 14 < test_ctx.s_len) test_ctx.s_buff[i + 14] ^= 0xFF; break; } } /* Server processes the corrupted CH2. * hpkeContext is preserved, TLSX_ECH_Parse correctly identifies the CH2 * round and sends decrypt_error. */ (void)wolfSSL_accept(test_ctx.s_ssl); ExpectIntEQ(wolfSSL_get_error(test_ctx.s_ssl, 0), WC_NO_ERR_TRACE(DECRYPT_ERROR)); } test_ssl_memio_cleanup(&test_ctx); return EXPECT_RESULT(); } /* when ECH is rejected the certificate must match the public name of the chosen * ech config * the cert check should pass and the client aborts with ech_required */ static int test_wolfSSL_Tls13_ECH_rejected_cert_valid_ex(const char* publicName, int validName) { EXPECT_DECLS; test_ssl_memio_ctx test_ctx; byte echConfigs[512]; word32 echConfigsLen = sizeof(echConfigs); XMEMSET(&test_ctx, 0, sizeof(test_ctx)); test_ctx.s_cb.method = wolfTLSv1_3_server_method; test_ctx.c_cb.method = wolfTLSv1_3_client_method; ExpectIntEQ(test_ssl_memio_setup(&test_ctx), TEST_SUCCESS); /* Generate ECH config with given public_name */ ExpectIntEQ(wolfSSL_CTX_GenerateEchConfig(test_ctx.s_ctx, publicName, 0, 0, 0), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_GetEchConfigs(test_ctx.s_ctx, echConfigs, &echConfigsLen), WOLFSSL_SUCCESS); /* Client loads ECH configs and sets a private SNI */ ExpectIntEQ(wolfSSL_SetEchConfigs(test_ctx.c_ssl, echConfigs, echConfigsLen), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_UseSNI(test_ctx.c_ssl, WOLFSSL_SNI_HOST_NAME, "ech-private.com", (word16)XSTRLEN("ech-private.com")), WOLFSSL_SUCCESS); /* Do not require client cert on server so it does not send * CertificateRequest */ wolfSSL_set_verify(test_ctx.s_ssl, WOLFSSL_VERIFY_NONE, NULL); wolfSSL_set_verify(test_ctx.c_ssl, WOLFSSL_VERIFY_PEER, NULL); /* Disable ECH on the server side so ECH is rejected */ wolfSSL_SetEchEnable(test_ctx.s_ssl, 0); /* Match the server SNI to the ECH public_name */ ExpectIntEQ(wolfSSL_UseSNI(test_ctx.s_ssl, WOLFSSL_SNI_HOST_NAME, publicName, (word16)XSTRLEN(publicName)), WOLFSSL_SUCCESS); /* client sends ECH but server can't process it, however it is possible to * fall back to the outer handshake */ ExpectIntNE(test_ssl_memio_do_handshake(&test_ctx, 10, NULL), TEST_SUCCESS); ExpectIntEQ(test_ctx.c_ssl->options.echAccepted, 0); if (validName) { /* the server should see the handshake as successful * the client should abort because the server did not use ECH */ ExpectIntEQ(wolfSSL_get_error(test_ctx.s_ssl, 0), WC_NO_ERR_TRACE(WOLFSSL_ERROR_NONE)); ExpectIntEQ(wolfSSL_get_error(test_ctx.c_ssl, 0), WC_NO_ERR_TRACE(ECH_REQUIRED_E)); } else { /* the client should abort with cert mismatch * the server error is then dependent on whether that cert mismatch * results in an abort */ ExpectIntEQ(wolfSSL_get_error(test_ctx.c_ssl, 0), WC_NO_ERR_TRACE(DOMAIN_NAME_MISMATCH)); } test_ssl_memio_cleanup(&test_ctx); return EXPECT_RESULT(); } static int test_wolfSSL_Tls13_ECH_rejected_cert_valid(void) { EXPECT_DECLS; /* "example.com" appears in the SAN of certs/server-cert.pem */ ExpectIntEQ(test_wolfSSL_Tls13_ECH_rejected_cert_valid_ex("example.com", 1), TEST_SUCCESS); ExpectIntEQ(test_wolfSSL_Tls13_ECH_rejected_cert_valid_ex("badname.com", 0), TEST_SUCCESS); return EXPECT_RESULT(); } /* when ECH is rejected and the server requests a client certificate the client * must respond with an empty cert */ static int test_wolfSSL_Tls13_ECH_rejected_empty_client_cert(void) { EXPECT_DECLS; test_ssl_memio_ctx test_ctx; byte echConfigs[512]; word32 echConfigsLen = sizeof(echConfigs); const char* publicName = "example.com"; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); test_ctx.s_cb.method = wolfTLSv1_3_server_method; test_ctx.c_cb.method = wolfTLSv1_3_client_method; ExpectIntEQ(test_ssl_memio_setup(&test_ctx), TEST_SUCCESS); /* Generate ECH config with public_name matching the server cert SAN */ ExpectIntEQ(wolfSSL_CTX_GenerateEchConfig(test_ctx.s_ctx, publicName, 0, 0, 0), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_GetEchConfigs(test_ctx.s_ctx, echConfigs, &echConfigsLen), WOLFSSL_SUCCESS); /* Client loads ECH configs and sets a private SNI */ ExpectIntEQ(wolfSSL_SetEchConfigs(test_ctx.c_ssl, echConfigs, echConfigsLen), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_UseSNI(test_ctx.c_ssl, WOLFSSL_SNI_HOST_NAME, "ech-private.com", (word16)XSTRLEN("ech-private.com")), WOLFSSL_SUCCESS); wolfSSL_set_verify(test_ctx.s_ssl, WOLFSSL_VERIFY_PEER | WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); wolfSSL_set_verify(test_ctx.c_ssl, WOLFSSL_VERIFY_PEER, NULL); /* Disable ECH on the server so ECH is rejected */ wolfSSL_SetEchEnable(test_ctx.s_ssl, 0); /* Match the Server SNI to the ECH public_name */ ExpectIntEQ(wolfSSL_UseSNI(test_ctx.s_ssl, WOLFSSL_SNI_HOST_NAME, publicName, (word16)XSTRLEN(publicName)), WOLFSSL_SUCCESS); ExpectIntNE(test_ssl_memio_do_handshake(&test_ctx, 10, NULL), TEST_SUCCESS); ExpectIntEQ(test_ctx.c_ssl->options.echAccepted, 0); /* Server cert is valid for public_name, cert check passes, ech_required * is sent on the client side. */ ExpectIntEQ(wolfSSL_get_error(test_ctx.c_ssl, 0), WC_NO_ERR_TRACE(ECH_REQUIRED_E)); /* The server received an empty Certificate from the client. * With FAIL_IF_NO_PEER_CERT set, the server aborts with NO_PEER_CERT. */ ExpectIntEQ(wolfSSL_get_error(test_ctx.s_ssl, 0), WC_NO_ERR_TRACE(NO_PEER_CERT)); test_ssl_memio_cleanup(&test_ctx); return EXPECT_RESULT(); } #endif /* HAVE_SSL_MEMIO_TESTS_DEPENDENCIES */ /* verify that ECH can be enabled/disabled without issue */ static int test_wolfSSL_Tls13_ECH_enable_disable(void) { EXPECT_DECLS; #if !defined(NO_WOLFSSL_CLIENT) WOLFSSL_CTX* ctx = NULL; WOLFSSL* ssl = NULL; byte echConfigs[128]; word32 echConfigsLen = sizeof(echConfigs); /* NULL ctx, NULL ssl should not crash */ wolfSSL_SetEchEnable(ssl, 0); wolfSSL_CTX_SetEchEnable(ctx, 0); /* test CTX level enable/disable */ ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method())); ExpectIntEQ(wolfSSL_CTX_GenerateEchConfig(ctx, "public.com", 0, 0, 0), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_GetEchConfigs(ctx, echConfigs, &echConfigsLen), WOLFSSL_SUCCESS); /* disable ECH at CTX level */ wolfSSL_CTX_SetEchEnable(ctx, 0); ExpectIntEQ(ctx->disableECH, 1); ExpectNull(ctx->echConfigs); wolfSSL_CTX_SetEchEnable(ctx, 1); ExpectIntEQ(ctx->disableECH, 0); /* test SSL level enable/disable */ ExpectNotNull(ssl = wolfSSL_new(ctx)); ExpectIntEQ(wolfSSL_SetEchConfigs(ssl, echConfigs, echConfigsLen), WOLFSSL_SUCCESS); /* disable ECH at SSL level */ wolfSSL_SetEchEnable(ssl, 0); ExpectIntEQ(ssl->options.disableECH, 1); ExpectNull(ssl->echConfigs); wolfSSL_SetEchEnable(ssl, 1); ExpectIntEQ(ssl->options.disableECH, 0); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #endif /* !NO_WOLFSSL_CLIENT */ return EXPECT_RESULT(); } #if defined(WOLFSSL_TLS13) && defined(HAVE_ECH) && \ defined(WOLFSSL_TEST_ECH) && defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && \ !defined(WOLFSSL_NO_TLS12) static int ech_tamper_seek_extension(byte* innerCh, word16* innerExtLen) { word16 idx; byte sessionIdLen; word16 cipherSuitesLen; byte compressionLen; idx = OPAQUE16_LEN + RAN_LEN; sessionIdLen = innerCh[idx++]; idx += sessionIdLen; ato16(innerCh + idx, &cipherSuitesLen); idx += OPAQUE16_LEN + cipherSuitesLen; compressionLen = innerCh[idx++]; idx += compressionLen; ato16(innerCh + idx, innerExtLen); idx += OPAQUE16_LEN; return idx; } static int ech_tamper_find_extension(byte* innerCh, word16* idx_p, word16 extType) { word16 idx; word16 innerExtIdx; word16 innerExtLen; idx = innerExtIdx = ech_tamper_seek_extension(innerCh, &innerExtLen); while (idx - innerExtIdx < innerExtLen) { word16 type; word16 len; ato16(innerCh + idx, &type); if (type == extType) { *idx_p = idx; return 0; } idx += OPAQUE16_LEN; ato16(innerCh + idx, &len); idx += OPAQUE16_LEN + len; } return BAD_FUNC_ARG; } static int ech_tamper_downgrade(byte* innerCh, word32 innerChLen) { int ret; word16 idx; (void)innerChLen; ret = ech_tamper_find_extension(innerCh, &idx, TLSXT_SUPPORTED_VERSIONS); if (ret == 0) { /* change extension type to something unknown */ innerCh[idx] = 0xFA; innerCh[idx + 1] = 0xFA; return 0; } else { return ret; } } static int ech_tamper_padding(byte* innerCh, word32 innerChLen) { word16 idx; word16 innerExtLen; /* get the unpadded length */ idx = ech_tamper_seek_extension(innerCh, &innerExtLen); idx += innerExtLen; /* no padding, but the test would fail if the message is not incorrect... * so fail the callback */ if (idx == innerChLen) { return BAD_FUNC_ARG; } else { innerCh[idx] = '\x01'; return 0; } } static int ech_tamper_type(byte* innerCh, word32 innerChLen) { int ret; word16 idx; (void)innerChLen; ret = ech_tamper_find_extension(innerCh, &idx, TLSXT_ECH); if (ret == 0) { /* change type to outer */ innerCh[idx + 4] = ECH_TYPE_OUTER; return 0; } else { return ret; } } static int ech_tamper_key_share(byte* innerCh, word32 innerChLen) { int ret; word16 idx; word16 len; (void)innerChLen; ret = ech_tamper_find_extension(innerCh, &idx, TLSXT_KEY_SHARE); if (ret == 0) { ato16(innerCh + idx + 8, &len); if (len == 0) { return BAD_FUNC_ARG; } else { /* tamper with public key data */ innerCh[idx + 10] ^= 0xFF; return 0; } } else { return ret; } } static int ech_tamper_ciphersuite(byte* innerCh, word32 innerChLen) { word16 idx; byte sessionIdLen; word16 cipherSuitesLen; (void)innerChLen; idx = OPAQUE16_LEN + RAN_LEN; sessionIdLen = innerCh[idx++]; idx += sessionIdLen; ato16(innerCh + idx, &cipherSuitesLen); idx += OPAQUE16_LEN; if (cipherSuitesLen < 2) { return BAD_FUNC_ARG; } else { /* change all ciphersuites to unknown value */ while (cipherSuitesLen > 0) { innerCh[idx] = '\xFA'; innerCh[idx + 1] = '\xFA'; idx += OPAQUE16_LEN; cipherSuitesLen -= OPAQUE16_LEN; } return 0; } } static int test_wolfSSL_Tls13_ECH_tamper_ex(struct test_ssl_memio_ctx* test_ctx) { EXPECT_DECLS; test_ssl_memio_cleanup(test_ctx); XMEMSET(test_ctx, 0, sizeof(struct test_ssl_memio_ctx)); test_ctx->s_cb.method = wolfTLSv1_3_server_method; test_ctx->c_cb.method = wolfTLSv1_3_client_method; test_ctx->s_cb.ctx_ready = test_ech_server_ctx_ready; test_ctx->s_cb.ssl_ready = test_ech_server_ssl_ready; test_ctx->c_cb.ssl_ready = test_ech_client_ssl_ready; ExpectIntEQ(test_ssl_memio_setup(test_ctx), TEST_SUCCESS); return EXPECT_RESULT(); } static int test_wolfSSL_Tls13_ECH_tamper_client(void) { EXPECT_DECLS; int err; struct test_ssl_memio_ctx test_ctx; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); /* try to downgrade to TLS 1.2 in the inner hello */ test_ctx.s_cb.method = wolfSSLv23_server_method; test_ctx.c_cb.method = wolfSSLv23_client_method; test_ctx.s_cb.ctx_ready = test_ech_server_ctx_ready; test_ctx.s_cb.ssl_ready = test_ech_server_ssl_ready; test_ctx.c_cb.ssl_ready = test_ech_client_ssl_ready; ExpectIntEQ(test_ssl_memio_setup(&test_ctx), TEST_SUCCESS); /* change supported_versions extension type to 0xFAFA: this will encourage a * downgrade to TLS 1.2 */ test_ctx.c_ssl->echInnerHelloCb = ech_tamper_downgrade; /* the server MUST reject an inner ClientHello that tries to negotiate * TLS 1.2 or below */ ExpectIntNE(test_ssl_memio_do_handshake(&test_ctx, 10, NULL), TEST_SUCCESS); ExpectIntEQ(wolfSSL_get_error(test_ctx.s_ssl, 0), WC_NO_ERR_TRACE(INVALID_PARAMETER)); ExpectIntEQ(wolfSSL_get_error(test_ctx.c_ssl, 0), WC_NO_ERR_TRACE(FATAL_ERROR)); /* non-zero padding byte */ ExpectIntEQ(test_wolfSSL_Tls13_ECH_tamper_ex(&test_ctx), TEST_SUCCESS); test_ctx.c_ssl->echInnerHelloCb = ech_tamper_padding; ExpectIntNE(test_ssl_memio_do_handshake(&test_ctx, 10, NULL), TEST_SUCCESS); if (EXPECT_SUCCESS()) { /* padding may have a length of zero which is not an error but the * callback will treat it as such (thus the BAD_FUNC_ARG) */ err = wolfSSL_get_error(test_ctx.s_ssl, 0); ExpectTrue(err == WC_NO_ERR_TRACE(INVALID_PARAMETER) || err == WC_NO_ERR_TRACE(BAD_FUNC_ARG)); } ExpectIntEQ(wolfSSL_get_error(test_ctx.c_ssl, 0), WC_NO_ERR_TRACE(FATAL_ERROR)); /* bad ECH type */ ExpectIntEQ(test_wolfSSL_Tls13_ECH_tamper_ex(&test_ctx), TEST_SUCCESS); test_ctx.c_ssl->echInnerHelloCb = ech_tamper_type; ExpectIntNE(test_ssl_memio_do_handshake(&test_ctx, 10, NULL), TEST_SUCCESS); ExpectIntEQ(wolfSSL_get_error(test_ctx.s_ssl, 0), WC_NO_ERR_TRACE(INVALID_PARAMETER)); ExpectIntEQ(wolfSSL_get_error(test_ctx.c_ssl, 0), WC_NO_ERR_TRACE(FATAL_ERROR)); /* corrupted key share */ ExpectIntEQ(test_wolfSSL_Tls13_ECH_tamper_ex(&test_ctx), TEST_SUCCESS); test_ctx.c_ssl->echInnerHelloCb = ech_tamper_key_share; ExpectIntNE(test_ssl_memio_do_handshake(&test_ctx, 10, NULL), TEST_SUCCESS); /* bad ciphersuite */ ExpectIntEQ(test_wolfSSL_Tls13_ECH_tamper_ex(&test_ctx), TEST_SUCCESS); test_ctx.c_ssl->echInnerHelloCb = ech_tamper_ciphersuite; ExpectIntNE(test_ssl_memio_do_handshake(&test_ctx, 10, NULL), TEST_SUCCESS); test_ssl_memio_cleanup(&test_ctx); return EXPECT_RESULT(); } #endif /* WOLFSSL_TLS13 && HAVE_ECH && WOLFSSL_TEST_ECH && * HAVE_SSL_MEMIO_TESTS_DEPENDENCIES && !WOLFSSL_NO_TLS12 */ #endif /* HAVE_ECH && WOLFSSL_TLS13 */ #if defined(HAVE_IO_TESTS_DEPENDENCIES) && \ defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) static int post_auth_version_cb(WOLFSSL* ssl) { EXPECT_DECLS; /* do handshake and then test version error */ ExpectIntEQ(wolfSSL_accept(ssl), WOLFSSL_SUCCESS); ExpectStrEQ("TLSv1.2", wolfSSL_get_version(ssl)); return EXPECT_RESULT(); } static int post_auth_version_client_cb(WOLFSSL* ssl) { EXPECT_DECLS; /* do handshake and then test version error */ ExpectIntEQ(wolfSSL_connect(ssl), WOLFSSL_SUCCESS); ExpectStrEQ("TLSv1.2", wolfSSL_get_version(ssl)); ExpectIntEQ(wolfSSL_verify_client_post_handshake(ssl), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); #if defined(OPENSSL_ALL) && !defined(NO_ERROR_QUEUE) /* check was added to error queue */ ExpectIntEQ(wolfSSL_ERR_get_error(), -WC_NO_ERR_TRACE(UNSUPPORTED_PROTO_VERSION)); /* check the string matches expected string */ #ifndef NO_ERROR_STRINGS ExpectStrEQ(wolfSSL_ERR_error_string(-WC_NO_ERR_TRACE(UNSUPPORTED_PROTO_VERSION), NULL), "WRONG_SSL_VERSION"); #endif #endif return EXPECT_RESULT(); } static int post_auth_cb(WOLFSSL* ssl) { EXPECT_DECLS; WOLFSSL_X509* x509 = NULL; /* do handshake and then test version error */ ExpectIntEQ(wolfSSL_accept(ssl), WOLFSSL_SUCCESS); ExpectStrEQ("TLSv1.3", wolfSSL_get_version(ssl)); ExpectNull(x509 = wolfSSL_get_peer_certificate(ssl)); wolfSSL_X509_free(x509); ExpectIntEQ(wolfSSL_verify_client_post_handshake(ssl), WOLFSSL_SUCCESS); return EXPECT_RESULT(); } static int set_post_auth_cb(WOLFSSL* ssl) { if (!wolfSSL_is_server(ssl)) { EXPECT_DECLS; ExpectIntEQ(wolfSSL_allow_post_handshake_auth(ssl), 0); return EXPECT_RESULT(); } wolfSSL_set_verify(ssl, WOLFSSL_VERIFY_POST_HANDSHAKE, NULL); return TEST_SUCCESS; } #endif static int test_wolfSSL_Tls13_postauth(void) { EXPECT_DECLS; #if defined(HAVE_IO_TESTS_DEPENDENCIES) && \ defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) test_ssl_cbf server_cbf; test_ssl_cbf client_cbf; /* test version failure doing post auth with TLS 1.2 connection */ XMEMSET(&server_cbf, 0, sizeof(server_cbf)); XMEMSET(&client_cbf, 0, sizeof(client_cbf)); server_cbf.method = wolfTLSv1_2_server_method; server_cbf.ssl_ready = set_post_auth_cb; server_cbf.on_result = post_auth_version_cb; client_cbf.ssl_ready = set_post_auth_cb; client_cbf.on_result = post_auth_version_client_cb; ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&client_cbf, &server_cbf, NULL), TEST_SUCCESS); /* tests on post auth with TLS 1.3 */ XMEMSET(&server_cbf, 0, sizeof(server_cbf)); XMEMSET(&client_cbf, 0, sizeof(client_cbf)); server_cbf.method = wolfTLSv1_3_server_method; server_cbf.ssl_ready = set_post_auth_cb; client_cbf.ssl_ready = set_post_auth_cb; server_cbf.on_result = post_auth_cb; client_cbf.on_result = NULL; ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&client_cbf, &server_cbf, NULL), TEST_SUCCESS); #endif return EXPECT_RESULT(); } static int test_wolfSSL_CTX_set_srp_username(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) && \ !defined(NO_SHA256) && !defined(WC_NO_RNG) && !defined(NO_TLS) && \ !defined(NO_WOLFSSL_CLIENT) WOLFSSL_CTX* ctx = NULL; WOLFSSL* ssl = NULL; const char *username = "TESTUSER"; const char *password = "TESTPASSWORD"; ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); ExpectIntEQ(wolfSSL_CTX_set_srp_username(ctx, (char *)username), SSL_SUCCESS); wolfSSL_CTX_free(ctx); ctx = NULL; ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); ExpectIntEQ(wolfSSL_CTX_set_srp_password(ctx, (char *)password), SSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_set_srp_username(ctx, (char *)username), SSL_SUCCESS); ExpectNotNull(ssl = SSL_new(ctx)); ExpectNotNull(SSL_get_srp_username(ssl)); ExpectStrEQ(SSL_get_srp_username(ssl), username); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #endif /* OPENSSL_EXTRA && WOLFCRYPT_HAVE_SRP */ /* && !NO_SHA256 && !WC_NO_RNG && !NO_WOLFSSL_CLIENT */ return EXPECT_RESULT(); } static int test_wolfSSL_CTX_set_srp_password(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) && \ !defined(NO_SHA256) && !defined(WC_NO_RNG) && !defined(NO_TLS) && \ !defined(NO_WOLFSSL_CLIENT) WOLFSSL_CTX* ctx = NULL; const char *username = "TESTUSER"; const char *password = "TESTPASSWORD"; ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); ExpectIntEQ(wolfSSL_CTX_set_srp_password(ctx, (char *)password), SSL_SUCCESS); wolfSSL_CTX_free(ctx); ctx = NULL; ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); ExpectIntEQ(wolfSSL_CTX_set_srp_username(ctx, (char *)username), SSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_set_srp_password(ctx, (char *)password), SSL_SUCCESS); wolfSSL_CTX_free(ctx); #endif /* OPENSSL_EXTRA && WOLFCRYPT_HAVE_SRP */ /* && !NO_SHA256 && !WC_NO_RNG && !NO_WOLFSSL_CLIENT */ return EXPECT_RESULT(); } #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && !defined(NO_TLS) && \ !defined(NO_FILESYSTEM) && !defined(NO_RSA) #define TEST_ARG 0x1234 static void msg_cb(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg) { (void)write_p; (void)version; (void)content_type; (void)buf; (void)len; (void)ssl; AssertTrue(arg == (void*)TEST_ARG); } #endif #if defined(OPENSSL_EXTRA) && defined(DEBUG_WOLFSSL) && \ defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) #if defined(SESSION_CERTS) #include "wolfssl/internal.h" #endif static int msgSrvCb(SSL_CTX *ctx, SSL *ssl) { EXPECT_DECLS; #if defined(OPENSSL_ALL) && defined(SESSION_CERTS) && !defined(NO_BIO) STACK_OF(X509)* sk = NULL; X509* x509 = NULL; int i, num; BIO* bio = NULL; #endif ExpectNotNull(ctx); ExpectNotNull(ssl); fprintf(stderr, "\n===== msgSrvCb called ====\n"); #if defined(SESSION_CERTS) && defined(TEST_PEER_CERT_CHAIN) ExpectTrue(SSL_get_peer_cert_chain(ssl) != NULL); ExpectIntEQ(((WOLFSSL_X509_CHAIN *)SSL_get_peer_cert_chain(ssl))->count, 2); ExpectNotNull(SSL_get0_verified_chain(ssl)); #endif #if defined(OPENSSL_ALL) && defined(SESSION_CERTS) && !defined(NO_BIO) #ifdef KEEP_PEER_CERT { WOLFSSL_X509* peer = NULL; ExpectNotNull(peer= wolfSSL_get_peer_certificate(ssl)); ExpectNotNull(bio = BIO_new_fp(stderr, BIO_NOCLOSE)); fprintf(stderr, "Peer Certificate = :\n"); X509_print(bio, peer); X509_free(peer); } #endif ExpectNotNull(sk = SSL_get_peer_cert_chain(ssl)); if (sk == NULL) { BIO_free(bio); return TEST_FAIL; } num = sk_X509_num(sk); ExpectTrue(num > 0); for (i = 0; i < num; i++) { ExpectNotNull(x509 = sk_X509_value(sk,i)); if (x509 == NULL) break; fprintf(stderr, "Certificate at index [%d] = :\n",i); X509_print(bio,x509); fprintf(stderr, "\n\n"); } BIO_free(bio); #endif return EXPECT_RESULT(); } static int msgCb(SSL_CTX *ctx, SSL *ssl) { EXPECT_DECLS; #if defined(OPENSSL_ALL) && defined(SESSION_CERTS) && !defined(NO_BIO) STACK_OF(X509)* sk = NULL; X509* x509 = NULL; int i, num; BIO* bio = NULL; #endif ExpectNotNull(ctx); ExpectNotNull(ssl); fprintf(stderr, "\n===== msgcb called ====\n"); #if defined(SESSION_CERTS) && defined(TEST_PEER_CERT_CHAIN) ExpectTrue(SSL_get_peer_cert_chain(ssl) != NULL); ExpectIntEQ(((WOLFSSL_X509_CHAIN *)SSL_get_peer_cert_chain(ssl))->count, 2); ExpectNotNull(SSL_get0_verified_chain(ssl)); #endif #if defined(OPENSSL_ALL) && defined(SESSION_CERTS) && !defined(NO_BIO) ExpectNotNull(bio = BIO_new_fp(stderr, BIO_NOCLOSE)); ExpectNotNull(sk = SSL_get_peer_cert_chain(ssl)); if (sk == NULL) { BIO_free(bio); return TEST_FAIL; } num = sk_X509_num(sk); ExpectTrue(num > 0); for (i = 0; i < num; i++) { ExpectNotNull(x509 = sk_X509_value(sk,i)); if (x509 == NULL) break; fprintf(stderr, "Certificate at index [%d] = :\n",i); X509_print(bio,x509); fprintf(stderr, "\n\n"); } BIO_free(bio); #endif return EXPECT_RESULT(); } #endif static int test_wolfSSL_msgCb(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && defined(DEBUG_WOLFSSL) && \ defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) test_ssl_cbf client_cb; test_ssl_cbf server_cb; XMEMSET(&client_cb, 0, sizeof(client_cb)); XMEMSET(&server_cb, 0, sizeof(server_cb)); #ifndef WOLFSSL_NO_TLS12 client_cb.method = wolfTLSv1_2_client_method; server_cb.method = wolfTLSv1_2_server_method; #else client_cb.method = wolfTLSv1_3_client_method; server_cb.method = wolfTLSv1_3_server_method; #endif server_cb.caPemFile = caCertFile; client_cb.certPemFile = "./certs/intermediate/client-chain.pem"; ExpectIntEQ(test_wolfSSL_client_server_nofail_memio_ex(&client_cb, &server_cb, msgCb, msgSrvCb), TEST_SUCCESS); #endif return EXPECT_RESULT(); } static int test_wolfSSL_either_side(void) { EXPECT_DECLS; #if (defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE)) && \ defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) test_ssl_cbf client_cb; test_ssl_cbf server_cb; XMEMSET(&client_cb, 0, sizeof(client_cb)); XMEMSET(&server_cb, 0, sizeof(server_cb)); /* Use different CTX for client and server */ client_cb.ctx = wolfSSL_CTX_new(wolfSSLv23_method()); ExpectNotNull(client_cb.ctx); server_cb.ctx = wolfSSL_CTX_new(wolfSSLv23_method()); ExpectNotNull(server_cb.ctx); /* we are responsible for free'ing WOLFSSL_CTX */ server_cb.isSharedCtx = client_cb.isSharedCtx = 1; ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&client_cb, &server_cb, NULL), TEST_SUCCESS); wolfSSL_CTX_free(client_cb.ctx); wolfSSL_CTX_free(server_cb.ctx); #endif return EXPECT_RESULT(); } static int test_wolfSSL_DTLS_either_side(void) { EXPECT_DECLS; #if (defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE)) && \ defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS) test_ssl_cbf client_cb; test_ssl_cbf server_cb; XMEMSET(&client_cb, 0, sizeof(client_cb)); XMEMSET(&server_cb, 0, sizeof(server_cb)); /* Use different CTX for client and server */ client_cb.ctx = wolfSSL_CTX_new(wolfDTLS_method()); ExpectNotNull(client_cb.ctx); server_cb.ctx = wolfSSL_CTX_new(wolfDTLS_method()); ExpectNotNull(server_cb.ctx); /* we are responsible for free'ing WOLFSSL_CTX */ server_cb.isSharedCtx = client_cb.isSharedCtx = 1; ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&client_cb, &server_cb, NULL), TEST_SUCCESS); wolfSSL_CTX_free(client_cb.ctx); wolfSSL_CTX_free(server_cb.ctx); #endif return EXPECT_RESULT(); } static int test_generate_cookie(void) { EXPECT_DECLS; #if defined(WOLFSSL_DTLS) && defined(OPENSSL_EXTRA) && defined(USE_WOLFSSL_IO) SSL_CTX* ctx = NULL; SSL* ssl = NULL; byte buf[FOURK_BUF] = {0}; ExpectNotNull(ctx = wolfSSL_CTX_new(wolfDTLS_method())); ExpectNotNull(ssl = SSL_new(ctx)); /* Test unconnected */ ExpectIntEQ(EmbedGenerateCookie(ssl, buf, FOURK_BUF, NULL), WC_NO_ERR_TRACE(GEN_COOKIE_E)); wolfSSL_CTX_SetGenCookie(ctx, EmbedGenerateCookie); wolfSSL_SetCookieCtx(ssl, ctx); ExpectNotNull(wolfSSL_GetCookieCtx(ssl)); ExpectNull(wolfSSL_GetCookieCtx(NULL)); SSL_free(ssl); SSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } static int test_wolfSSL_set_options(void) { EXPECT_DECLS; #if !defined(NO_CERTS) && !defined(NO_TLS) && !defined(NO_FILESYSTEM) && \ (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) && \ !defined(NO_RSA) WOLFSSL* ssl = NULL; WOLFSSL_CTX* ctx = NULL; #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) char appData[] = "extra msg"; #endif #ifdef OPENSSL_EXTRA unsigned char protos[] = { 7, 't', 'l', 's', '/', '1', '.', '2', 8, 'h', 't', 't', 'p', '/', '1', '.', '1' }; unsigned int len = sizeof(protos); void *arg = (void *)TEST_ARG; #endif #ifndef NO_WOLFSSL_SERVER ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); #else ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); #endif ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile, CERT_FILETYPE)); ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, CERT_FILETYPE)); ExpectTrue(wolfSSL_CTX_set_options(ctx, WOLFSSL_OP_NO_TLSv1) == WOLFSSL_OP_NO_TLSv1); ExpectTrue(wolfSSL_CTX_get_options(ctx) == WOLFSSL_OP_NO_TLSv1); ExpectIntGT((int)wolfSSL_CTX_set_options(ctx, (WOLFSSL_OP_COOKIE_EXCHANGE | WOLFSSL_OP_NO_SSLv2)), 0); ExpectTrue((wolfSSL_CTX_set_options(ctx, WOLFSSL_OP_COOKIE_EXCHANGE) & WOLFSSL_OP_COOKIE_EXCHANGE) == WOLFSSL_OP_COOKIE_EXCHANGE); ExpectTrue((wolfSSL_CTX_set_options(ctx, WOLFSSL_OP_NO_TLSv1_2) & WOLFSSL_OP_NO_TLSv1_2) == WOLFSSL_OP_NO_TLSv1_2); ExpectTrue((wolfSSL_CTX_set_options(ctx, WOLFSSL_OP_NO_COMPRESSION) & WOLFSSL_OP_NO_COMPRESSION) == WOLFSSL_OP_NO_COMPRESSION); ExpectFalse((wolfSSL_CTX_clear_options(ctx, WOLFSSL_OP_NO_COMPRESSION) & WOLFSSL_OP_NO_COMPRESSION)); wolfSSL_CTX_free(ctx); ctx = NULL; #ifndef NO_WOLFSSL_SERVER ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); #else ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); #endif ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile, CERT_FILETYPE)); ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, CERT_FILETYPE)); #ifdef OPENSSL_EXTRA ExpectTrue(wolfSSL_CTX_set_msg_callback(ctx, msg_cb) == WOLFSSL_SUCCESS); #endif ExpectNotNull(ssl = wolfSSL_new(ctx)); #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) #ifdef HAVE_EX_DATA ExpectIntEQ(wolfSSL_set_app_data(ssl, (void*)appData), WOLFSSL_SUCCESS); ExpectNotNull(wolfSSL_get_app_data((const WOLFSSL*)ssl)); if (ssl != NULL) { ExpectIntEQ(XMEMCMP(wolfSSL_get_app_data((const WOLFSSL*)ssl), appData, sizeof(appData)), 0); } #else ExpectIntEQ(wolfSSL_set_app_data(ssl, (void*)appData), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectNull(wolfSSL_get_app_data((const WOLFSSL*)ssl)); #endif #endif ExpectTrue(wolfSSL_set_options(ssl, WOLFSSL_OP_NO_TLSv1) == WOLFSSL_OP_NO_TLSv1); ExpectTrue(wolfSSL_get_options(ssl) == WOLFSSL_OP_NO_TLSv1); ExpectIntGT((int)wolfSSL_set_options(ssl, (WOLFSSL_OP_COOKIE_EXCHANGE | WOLFSSL_OP_NO_SSLv2)), 0); ExpectTrue((wolfSSL_set_options(ssl, WOLFSSL_OP_COOKIE_EXCHANGE) & WOLFSSL_OP_COOKIE_EXCHANGE) == WOLFSSL_OP_COOKIE_EXCHANGE); ExpectTrue((wolfSSL_set_options(ssl, WOLFSSL_OP_NO_TLSv1_2) & WOLFSSL_OP_NO_TLSv1_2) == WOLFSSL_OP_NO_TLSv1_2); ExpectTrue((wolfSSL_set_options(ssl, WOLFSSL_OP_NO_COMPRESSION) & WOLFSSL_OP_NO_COMPRESSION) == WOLFSSL_OP_NO_COMPRESSION); #ifdef OPENSSL_EXTRA ExpectFalse((wolfSSL_clear_options(ssl, WOLFSSL_OP_NO_COMPRESSION) & WOLFSSL_OP_NO_COMPRESSION)); #endif #ifdef OPENSSL_EXTRA ExpectTrue(wolfSSL_set_msg_callback(ssl, msg_cb) == WOLFSSL_SUCCESS); wolfSSL_set_msg_callback_arg(ssl, arg); #ifdef WOLFSSL_ERROR_CODE_OPENSSL ExpectTrue(wolfSSL_CTX_set_alpn_protos(ctx, protos, len) == 0); #else ExpectTrue(wolfSSL_CTX_set_alpn_protos(ctx, protos, len) == WOLFSSL_SUCCESS); #endif #endif #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \ defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(OPENSSL_ALL) || \ defined(HAVE_LIGHTY) || defined(HAVE_STUNNEL) #if defined(HAVE_ALPN) && !defined(NO_BIO) #ifdef WOLFSSL_ERROR_CODE_OPENSSL ExpectTrue(wolfSSL_set_alpn_protos(ssl, protos, len) == 0); #else ExpectTrue(wolfSSL_set_alpn_protos(ssl, protos, len) == WOLFSSL_SUCCESS); #endif #endif /* HAVE_ALPN && !NO_BIO */ #endif wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } static int test_wolfSSL_sk_SSL_CIPHER(void) { EXPECT_DECLS; #if defined(OPENSSL_ALL) && !defined(NO_CERTS) && !defined(NO_TLS) && \ !defined(NO_FILESYSTEM) && !defined(NO_RSA) #if !defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER) SSL* ssl = NULL; SSL_CTX* ctx = NULL; STACK_OF(SSL_CIPHER) *sk = NULL; STACK_OF(SSL_CIPHER) *dupSk = NULL; #ifndef NO_WOLFSSL_SERVER ExpectNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); #else ExpectNotNull(ctx = SSL_CTX_new(wolfSSLv23_client_method())); #endif ExpectTrue(SSL_CTX_use_certificate_file(ctx, svrCertFile, SSL_FILETYPE_PEM)); ExpectTrue(SSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, SSL_FILETYPE_PEM)); ExpectNotNull(ssl = SSL_new(ctx)); ExpectNotNull(sk = SSL_get_ciphers(ssl)); ExpectNotNull(dupSk = sk_SSL_CIPHER_dup(sk)); ExpectIntGT(sk_SSL_CIPHER_num(sk), 0); ExpectIntEQ(sk_SSL_CIPHER_num(sk), sk_SSL_CIPHER_num(dupSk)); /* error case because connection has not been established yet */ ExpectIntEQ(sk_SSL_CIPHER_find(sk, SSL_get_current_cipher(ssl)), -1); sk_SSL_CIPHER_free(dupSk); /* sk is pointer to internal struct that should be free'd in SSL_free */ SSL_free(ssl); SSL_CTX_free(ctx); #endif /* !NO_WOLFSSL_CLIENT || !NO_WOLFSSL_SERVER */ #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ !defined(NO_FILESYSTEM) && !defined(NO_RSA) */ return EXPECT_RESULT(); } static int test_wolfSSL_set1_curves_list(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && defined(HAVE_ECC) && !defined(NO_TLS) && \ (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) && \ !defined(NO_FILESYSTEM) SSL* ssl = NULL; SSL_CTX* ctx = NULL; #ifndef NO_WOLFSSL_SERVER ExpectNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); #else ExpectNotNull(ctx = SSL_CTX_new(wolfSSLv23_client_method())); #endif ExpectTrue(SSL_CTX_use_certificate_file(ctx, eccCertFile, SSL_FILETYPE_PEM)); ExpectTrue(SSL_CTX_use_PrivateKey_file(ctx, eccKeyFile, SSL_FILETYPE_PEM)); ExpectNotNull(ssl = SSL_new(ctx)); ExpectIntEQ(SSL_CTX_set1_curves_list(ctx, NULL), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); #ifdef HAVE_ECC ExpectIntEQ(SSL_CTX_set1_curves_list(ctx, "P-25X"), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(SSL_CTX_set1_curves_list(ctx, "P-256"), WOLFSSL_SUCCESS); #endif #ifdef HAVE_CURVE25519 ExpectIntEQ(SSL_CTX_set1_curves_list(ctx, "X25519"), WOLFSSL_SUCCESS); #else ExpectIntEQ(SSL_CTX_set1_curves_list(ctx, "X25519"), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); #endif #ifdef HAVE_CURVE448 ExpectIntEQ(SSL_CTX_set1_curves_list(ctx, "X448"), WOLFSSL_SUCCESS); #else ExpectIntEQ(SSL_CTX_set1_curves_list(ctx, "X448"), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); #endif ExpectIntEQ(SSL_set1_curves_list(ssl, NULL), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); #ifdef HAVE_ECC ExpectIntEQ(SSL_set1_curves_list(ssl, "P-25X"), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(SSL_set1_curves_list(ssl, "P-256"), WOLFSSL_SUCCESS); #endif #ifdef HAVE_CURVE25519 ExpectIntEQ(SSL_set1_curves_list(ssl, "X25519"), WOLFSSL_SUCCESS); #else ExpectIntEQ(SSL_set1_curves_list(ssl, "X25519"), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); #endif #ifdef HAVE_CURVE448 ExpectIntEQ(SSL_set1_curves_list(ssl, "X448"), WOLFSSL_SUCCESS); #else ExpectIntEQ(SSL_set1_curves_list(ssl, "X448"), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); #endif SSL_free(ssl); SSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } #if defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && \ (defined(OPENSSL_EXTRA) || defined(HAVE_CURL)) && defined(HAVE_ECC) static int test_wolfSSL_curves_mismatch_ctx_ready(WOLFSSL_CTX* ctx) { static int counter = 0; EXPECT_DECLS; if (counter % 2) { ExpectIntEQ(wolfSSL_CTX_set1_curves_list(ctx, "P-256"), WOLFSSL_SUCCESS); } else { ExpectIntEQ(wolfSSL_CTX_set1_curves_list(ctx, "P-384"), WOLFSSL_SUCCESS); } /* Ciphersuites that require curves */ wolfSSL_CTX_set_cipher_list(ctx, "TLS13-AES256-GCM-SHA384:" "TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES128-GCM-SHA256:" "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:" "ECDHE-ECDSA-AES128-GCM-SHA256:" "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-CHACHA20-POLY1305:" "ECDHE-ECDSA-CHACHA20-POLY1305"); counter++; return EXPECT_RESULT(); } #endif static int test_wolfSSL_curves_mismatch(void) { EXPECT_DECLS; #if defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && \ (defined(OPENSSL_EXTRA) || defined(HAVE_CURL)) && defined(HAVE_ECC) test_ssl_cbf func_cb_client; test_ssl_cbf func_cb_server; size_t i; struct { method_provider client_meth; method_provider server_meth; const char* desc; int client_last_err; int server_last_err; } test_params[] = { #ifdef WOLFSSL_TLS13 {wolfTLSv1_3_client_method, wolfTLSv1_3_server_method, "TLS 1.3", /* Client gets error because server will attempt HRR */ WC_NO_ERR_TRACE(BAD_KEY_SHARE_DATA), WC_NO_ERR_TRACE(FATAL_ERROR) }, #endif #ifndef WOLFSSL_NO_TLS12 {wolfTLSv1_2_client_method, wolfTLSv1_2_server_method, "TLS 1.2", WC_NO_ERR_TRACE(FATAL_ERROR), /* Server gets error because <=1.2 doesn't have a mechanism * to negotiate curves. */ #ifdef OPENSSL_EXTRA WC_NO_ERR_TRACE(WOLFSSL_ERROR_SYSCALL) #else WC_NO_ERR_TRACE(MATCH_SUITE_ERROR) #endif }, #endif #ifndef NO_OLD_TLS {wolfTLSv1_1_client_method, wolfTLSv1_1_server_method, "TLS 1.1", WC_NO_ERR_TRACE(FATAL_ERROR), #ifdef OPENSSL_EXTRA WC_NO_ERR_TRACE(WOLFSSL_ERROR_SYSCALL) #else WC_NO_ERR_TRACE(MATCH_SUITE_ERROR) #endif }, #endif }; for (i = 0; i < XELEM_CNT(test_params) && !EXPECT_FAIL(); i++) { XMEMSET(&func_cb_client, 0, sizeof(func_cb_client)); XMEMSET(&func_cb_server, 0, sizeof(func_cb_server)); printf("\tTesting with %s...\n", test_params[i].desc); func_cb_client.ctx_ready = &test_wolfSSL_curves_mismatch_ctx_ready; func_cb_server.ctx_ready = &test_wolfSSL_curves_mismatch_ctx_ready; func_cb_client.method = test_params[i].client_meth; func_cb_server.method = test_params[i].server_meth; ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&func_cb_client, &func_cb_server, NULL), -1001); ExpectIntEQ(func_cb_client.last_err, test_params[i].client_last_err); ExpectIntEQ(func_cb_server.last_err, test_params[i].server_last_err); if (!EXPECT_SUCCESS()) break; printf("\t%s passed\n", test_params[i].desc); } #endif return EXPECT_RESULT(); } static int test_wolfSSL_set1_sigalgs_list(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && !defined(NO_RSA) && \ !defined(NO_TLS) && \ (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) && \ !defined(NO_FILESYSTEM) SSL* ssl = NULL; SSL_CTX* ctx = NULL; #ifndef NO_WOLFSSL_SERVER ExpectNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); #else ExpectNotNull(ctx = SSL_CTX_new(wolfSSLv23_client_method())); #endif ExpectTrue(SSL_CTX_use_certificate_file(ctx, svrCertFile, SSL_FILETYPE_PEM)); ExpectTrue(SSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, SSL_FILETYPE_PEM)); ExpectNotNull(ssl = SSL_new(ctx)); ExpectIntEQ(wolfSSL_CTX_set1_sigalgs_list(NULL, NULL), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_CTX_set1_sigalgs_list(ctx, NULL), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_set1_sigalgs_list(NULL, NULL), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_set1_sigalgs_list(ssl, NULL), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_CTX_set1_sigalgs_list(ctx, ""), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_set1_sigalgs_list(ssl, ""), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); #ifndef NO_RSA #ifndef NO_SHA256 ExpectIntEQ(wolfSSL_CTX_set1_sigalgs_list(NULL, "RSA+SHA256"), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_set1_sigalgs_list(NULL, "RSA+SHA256"), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_CTX_set1_sigalgs_list(ctx, "RSA+SHA256"), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_set1_sigalgs_list(ssl, "RSA+SHA256"), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_set1_sigalgs_list(ctx, "RSA-SHA256"), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_set1_sigalgs_list(ssl, "RSA-SHA256"), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); #ifdef WC_RSA_PSS ExpectIntEQ(wolfSSL_CTX_set1_sigalgs_list(ctx, "RSA-PSS+SHA256"), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_set1_sigalgs_list(ssl, "RSA-PSS+SHA256"), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_set1_sigalgs_list(ctx, "PSS+SHA256"), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_set1_sigalgs_list(ssl, "PSS+SHA256"), WOLFSSL_SUCCESS); #endif #ifdef WOLFSSL_SHA512 ExpectIntEQ(wolfSSL_CTX_set1_sigalgs_list(ctx, "RSA+SHA256:RSA+SHA512"), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_set1_sigalgs_list(ssl, "RSA+SHA256:RSA+SHA512"), WOLFSSL_SUCCESS); #elif defined(WOLFSSL_SHA384) ExpectIntEQ(wolfSSL_CTX_set1_sigalgs_list(ctx, "RSA+SHA256:RSA+SHA384"), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_set1_sigalgs_list(ssl, "RSA+SHA256:RSA+SHA384"), WOLFSSL_SUCCESS); #endif ExpectIntEQ(wolfSSL_CTX_set1_sigalgs_list(ctx, "RSA"), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_set1_sigalgs_list(ssl, "RSA"), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_CTX_set1_sigalgs_list(ctx, "RSA:RSA+SHA256"), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_set1_sigalgs_list(ssl, "RSA:RSA+SHA256"), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_CTX_set1_sigalgs_list(ctx, "RSA+SHA256+SHA256"), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_set1_sigalgs_list(ssl, "RSA+SHA256+RSA"), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); { const char entry[] = "RSA+SHA256"; const int entryLen = (int)sizeof(entry) - 1; const int entries = WOLFSSL_MAX_SIGALGO + 1; int listSz = entries * (entryLen + 1); char* longList = (char*)XMALLOC(listSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); int i; int pos = 0; ExpectNotNull(longList); if (longList != NULL) { for (i = 0; i < entries; i++) { if (i != 0) longList[pos++] = ':'; XMEMCPY(longList + pos, entry, entryLen); pos += entryLen; } longList[pos] = '\0'; ExpectIntEQ(wolfSSL_CTX_set1_sigalgs_list(ctx, longList), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_set1_sigalgs_list(ssl, longList), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); XFREE(longList, NULL, DYNAMIC_TYPE_TMP_BUFFER); } } #endif #endif #ifdef HAVE_ECC #ifndef NO_SHA256 ExpectIntEQ(wolfSSL_CTX_set1_sigalgs_list(ctx, "ECDSA+SHA256"), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_set1_sigalgs_list(ssl, "ECDSA+SHA256"), WOLFSSL_SUCCESS); #ifdef WOLFSSL_SHA512 ExpectIntEQ(wolfSSL_CTX_set1_sigalgs_list(ctx, "ECDSA+SHA256:ECDSA+SHA512"), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_set1_sigalgs_list(ssl, "ECDSA+SHA256:ECDSA+SHA512"), WOLFSSL_SUCCESS); #elif defined(WOLFSSL_SHA384) ExpectIntEQ(wolfSSL_CTX_set1_sigalgs_list(ctx, "ECDSA+SHA256:ECDSA+SHA384"), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_set1_sigalgs_list(ssl, "ECDSA+SHA256:ECDSA+SHA384"), WOLFSSL_SUCCESS); #endif #endif #endif #ifdef HAVE_ED25519 ExpectIntEQ(wolfSSL_CTX_set1_sigalgs_list(ctx, "ED25519"), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_set1_sigalgs_list(ssl, "ED25519"), WOLFSSL_SUCCESS); #endif #ifdef HAVE_ED448 ExpectIntEQ(wolfSSL_CTX_set1_sigalgs_list(ctx, "ED448"), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_set1_sigalgs_list(ssl, "ED448"), WOLFSSL_SUCCESS); #endif #ifndef NO_DSA #ifndef NO_SHA256 ExpectIntEQ(wolfSSL_CTX_set1_sigalgs_list(ctx, "DSA+SHA256"), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_set1_sigalgs_list(ssl, "DSA+SHA256"), WOLFSSL_SUCCESS); #endif #if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \ defined(WOLFSSL_ALLOW_TLS_SHA1)) ExpectIntEQ(wolfSSL_CTX_set1_sigalgs_list(ctx, "DSA+SHA1"), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_set1_sigalgs_list(ssl, "DSA+SHA1"), WOLFSSL_SUCCESS); #endif #endif SSL_free(ssl); SSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } /* Testing wolfSSL_set_tlsext_status_type function. * PRE: OPENSSL and HAVE_CERTIFICATE_STATUS_REQUEST defined. */ static int test_wolfSSL_set_tlsext_status_type(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && defined(HAVE_CERTIFICATE_STATUS_REQUEST) && \ !defined(NO_RSA) && !defined(NO_WOLFSSL_SERVER) SSL* ssl = NULL; SSL_CTX* ctx = NULL; ExpectNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); ExpectTrue(SSL_CTX_use_certificate_file(ctx, svrCertFile, SSL_FILETYPE_PEM)); ExpectTrue(SSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, SSL_FILETYPE_PEM)); ExpectNotNull(ssl = SSL_new(ctx)); ExpectIntEQ(SSL_set_tlsext_status_type(ssl,TLSEXT_STATUSTYPE_ocsp), SSL_SUCCESS); ExpectIntEQ(SSL_get_tlsext_status_type(ssl), TLSEXT_STATUSTYPE_ocsp); SSL_free(ssl); SSL_CTX_free(ctx); #endif /* OPENSSL_EXTRA && HAVE_CERTIFICATE_STATUS_REQUEST && !NO_RSA */ return EXPECT_RESULT(); } static int test_wolfSSL_a2i_IPADDRESS(void) { EXPECT_DECLS; #if defined(OPENSSL_ALL) && !defined(WOLFSSL_USER_IO) const unsigned char* data = NULL; int dataSz = 0; ASN1_OCTET_STRING *st = NULL; const unsigned char ipv4_exp[] = {0x7F, 0, 0, 1}; const unsigned char ipv6_exp[] = { 0x20, 0x21, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x77, 0x77 }; const unsigned char ipv6_home[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }; ExpectNull(st = a2i_IPADDRESS("127.0.0.1bad")); ExpectNotNull(st = a2i_IPADDRESS("127.0.0.1")); ExpectNotNull(data = ASN1_STRING_get0_data(st)); ExpectIntEQ(dataSz = ASN1_STRING_length(st), WOLFSSL_IP4_ADDR_LEN); ExpectIntEQ(XMEMCMP(data, ipv4_exp, dataSz), 0); ASN1_STRING_free(st); st = NULL; ExpectNotNull(st = a2i_IPADDRESS("::1")); ExpectNotNull(data = ASN1_STRING_get0_data(st)); ExpectIntEQ(dataSz = ASN1_STRING_length(st), WOLFSSL_IP6_ADDR_LEN); ExpectIntEQ(XMEMCMP(data, ipv6_home, dataSz), 0); ASN1_STRING_free(st); st = NULL; ExpectNotNull(st = a2i_IPADDRESS("2021:db8::ff00:42:7777")); ExpectNotNull(data = ASN1_STRING_get0_data(st)); ExpectIntEQ(dataSz = ASN1_STRING_length(st), WOLFSSL_IP6_ADDR_LEN); ExpectIntEQ(XMEMCMP(data, ipv6_exp, dataSz), 0); ASN1_STRING_free(st); #endif return EXPECT_RESULT(); } static int test_wolfSSL_X509_ALGOR_get0(void) { EXPECT_DECLS; #if (defined(OPENSSL_ALL) || defined(WOLFSSL_APACHE_HTTPD)) && \ !defined(NO_SHA256) && !defined(NO_RSA) X509* x509 = NULL; const ASN1_OBJECT* obj = NULL; const X509_ALGOR* alg = NULL; X509_ALGOR* alg2 = NULL; int pptype = 0; const void *ppval = NULL; byte* der = NULL; const byte* tmp = NULL; const byte badObj[] = { 0x06, 0x00 }; ExpectNotNull(x509 = wolfSSL_X509_load_certificate_file(cliCertFile, SSL_FILETYPE_PEM)); ExpectNotNull(alg = X509_get0_tbs_sigalg(x509)); /* Invalid case */ X509_ALGOR_get0(&obj, NULL, NULL, NULL); ExpectNull(obj); /* Valid case */ X509_ALGOR_get0(NULL, NULL, NULL, alg); X509_ALGOR_get0(&obj, &pptype, &ppval, alg); ExpectNotNull(obj); ExpectNull(ppval); ExpectIntNE(pptype, 0); /* Make sure NID of X509_ALGOR is Sha256 with RSA */ ExpectIntEQ(OBJ_obj2nid(obj), NID_sha256WithRSAEncryption); ExpectIntEQ(i2d_X509_ALGOR(NULL, NULL), WOLFSSL_FATAL_ERROR); ExpectIntEQ(i2d_X509_ALGOR(alg, &der), 15); ExpectNull(d2i_X509_ALGOR(NULL, NULL, 0)); /* tmp is NULL. */ ExpectNull(d2i_X509_ALGOR(NULL, &tmp, 0)); tmp = badObj; ExpectNull(d2i_X509_ALGOR(NULL, &tmp, (long)sizeof(badObj))); tmp = der; ExpectNull(d2i_X509_ALGOR(NULL, &tmp, 0)); ExpectNotNull(d2i_X509_ALGOR(&alg2, &tmp, 15)); tmp = der; ExpectNotNull(d2i_X509_ALGOR(&alg2, &tmp, 15)); XFREE(der, NULL, DYNAMIC_TYPE_ASN1); X509_free(x509); X509_ALGOR_free(NULL); X509_ALGOR_free(alg2); alg2 = NULL; #endif return EXPECT_RESULT(); } #if defined(OPENSSL_EXTRA) && defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && \ !defined(WOLFSSL_HOSTNAME_VERIFY_ALT_NAME_ONLY) static int test_wolfSSL_check_domain_verify_count = 0; static WC_INLINE int test_wolfSSL_check_domain_verify_cb(int preverify, WOLFSSL_X509_STORE_CTX* store) { EXPECT_DECLS; ExpectIntEQ(X509_STORE_CTX_get_error(store), 0); ExpectIntEQ(preverify, 1); ExpectIntGT(++test_wolfSSL_check_domain_verify_count, 0); return EXPECT_SUCCESS(); } static int test_wolfSSL_check_domain_client_cb(WOLFSSL* ssl) { EXPECT_DECLS; X509_VERIFY_PARAM *param = NULL; ExpectNotNull(param = SSL_get0_param(ssl)); /* Domain check should only be done on the leaf cert */ X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); ExpectIntEQ(X509_VERIFY_PARAM_set1_host(param, "wolfSSL Server Chain", 0), 1); wolfSSL_set_verify(ssl, WOLFSSL_VERIFY_PEER, test_wolfSSL_check_domain_verify_cb); return EXPECT_RESULT(); } static int test_wolfSSL_check_domain_server_cb(WOLFSSL_CTX* ctx) { EXPECT_DECLS; /* Use a cert with different domains in chain */ ExpectIntEQ(wolfSSL_CTX_use_certificate_chain_file(ctx, "certs/intermediate/server-chain.pem"), WOLFSSL_SUCCESS); return EXPECT_RESULT(); } static int test_wolfSSL_check_domain(void) { EXPECT_DECLS; test_ssl_cbf func_cb_client; test_ssl_cbf func_cb_server; XMEMSET(&func_cb_client, 0, sizeof(func_cb_client)); XMEMSET(&func_cb_server, 0, sizeof(func_cb_server)); func_cb_client.ssl_ready = &test_wolfSSL_check_domain_client_cb; func_cb_server.ctx_ready = &test_wolfSSL_check_domain_server_cb; ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&func_cb_client, &func_cb_server, NULL), TEST_SUCCESS); /* Should have been called once for each cert in sent chain */ #ifdef WOLFSSL_VERIFY_CB_ALL_CERTS ExpectIntEQ(test_wolfSSL_check_domain_verify_count, 3); #else ExpectIntEQ(test_wolfSSL_check_domain_verify_count, 1); #endif return EXPECT_RESULT(); } #else static int test_wolfSSL_check_domain(void) { EXPECT_DECLS; return EXPECT_RESULT(); } #endif /* OPENSSL_EXTRA && HAVE_SSL_MEMIO_TESTS_DEPENDENCIES */ #if defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && \ !defined(OPENSSL_COMPATIBLE_DEFAULTS) && !defined(NO_SHA256) static const char* dn = NULL; static int test_wolfSSL_check_domain_basic_client_ssl(WOLFSSL* ssl) { EXPECT_DECLS; ExpectIntEQ(wolfSSL_check_domain_name(ssl, dn), WOLFSSL_SUCCESS); return EXPECT_RESULT(); } /* Verify wolfSSL_check_domain_name() controls DNS-name matching during * handshake with expected fail/pass outcomes. */ static int test_wolfSSL_check_domain_basic(void) { EXPECT_DECLS; test_ssl_cbf func_cb_client; test_ssl_cbf func_cb_server; XMEMSET(&func_cb_client, 0, sizeof(func_cb_client)); XMEMSET(&func_cb_server, 0, sizeof(func_cb_server)); dn = "invalid.com"; func_cb_client.ssl_ready = &test_wolfSSL_check_domain_basic_client_ssl; /* Expect to fail */ ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&func_cb_client, &func_cb_server, NULL), -1001); dn = "example.com"; /* Expect to succeed */ ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&func_cb_client, &func_cb_server, NULL), TEST_SUCCESS); return EXPECT_RESULT(); } #else static int test_wolfSSL_check_domain_basic(void) { EXPECT_DECLS; return EXPECT_RESULT(); } #endif /* HAVE_SSL_MEMIO_TESTS_DEPENDENCIES */ #if defined(OPENSSL_EXTRA) && defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && \ (defined(WOLFSSL_IP_ALT_NAME) || defined(OPENSSL_ALL)) && \ !defined(OPENSSL_COMPATIBLE_DEFAULTS) && !defined(NO_SHA256) static const char* ipaddr = NULL; static int test_wolfSSL_check_ip_param_client_ssl(WOLFSSL* ssl) { EXPECT_DECLS; X509_VERIFY_PARAM* param = NULL; ExpectNotNull(param = SSL_get0_param(ssl)); ExpectIntEQ(X509_VERIFY_PARAM_set1_ip_asc(param, ipaddr), WOLFSSL_SUCCESS); return EXPECT_RESULT(); } /* Verify the OpenSSL-compat verify-param path: * SSL_get0_param() + X509_VERIFY_PARAM_set1_ip_asc() controls IP SAN matching * during handshake. */ static int test_wolfSSL_check_ip_param_basic(void) { EXPECT_DECLS; test_ssl_cbf func_cb_client; test_ssl_cbf func_cb_server; XMEMSET(&func_cb_client, 0, sizeof(func_cb_client)); XMEMSET(&func_cb_server, 0, sizeof(func_cb_server)); func_cb_client.ssl_ready = &test_wolfSSL_check_ip_param_client_ssl; ipaddr = "127.0.0.2"; /* Expect to fail: cert SAN IP is 127.0.0.1 */ ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&func_cb_client, &func_cb_server, NULL), -1001); ipaddr = "127.0.0.1"; /* Expect to succeed */ ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&func_cb_client, &func_cb_server, NULL), TEST_SUCCESS); return EXPECT_RESULT(); } #else static int test_wolfSSL_check_ip_param_basic(void) { EXPECT_DECLS; return EXPECT_RESULT(); } #endif #if defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && \ !defined(OPENSSL_COMPATIBLE_DEFAULTS) && !defined(NO_SHA256) && \ defined(WOLFSSL_IP_ALT_NAME) static const char* ipaddr_api = NULL; static int test_wolfSSL_check_ip_address_basic_client_ssl(WOLFSSL* ssl) { EXPECT_DECLS; ExpectIntEQ(wolfSSL_check_ip_address(ssl, ipaddr_api), WOLFSSL_SUCCESS); return EXPECT_RESULT(); } /* Verify wolfSSL convenience API path: * wolfSSL_check_ip_address() enables IP SAN matching during handshake, * including the non-OPENSSL_EXTRA storage/verification flow. */ static int test_wolfSSL_check_ip_address_basic(void) { EXPECT_DECLS; test_ssl_cbf func_cb_client; test_ssl_cbf func_cb_server; XMEMSET(&func_cb_client, 0, sizeof(func_cb_client)); XMEMSET(&func_cb_server, 0, sizeof(func_cb_server)); func_cb_client.ssl_ready = &test_wolfSSL_check_ip_address_basic_client_ssl; ipaddr_api = "127.0.0.2"; /* Expect to fail: cert SAN IP is 127.0.0.1 */ ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&func_cb_client, &func_cb_server, NULL), -1001); ipaddr_api = "127.0.0.1"; /* Expect to succeed */ ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&func_cb_client, &func_cb_server, NULL), TEST_SUCCESS); return EXPECT_RESULT(); } #else static int test_wolfSSL_check_ip_address_basic(void) { EXPECT_DECLS; return EXPECT_RESULT(); } #endif static int test_wolfSSL_BUF(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) BUF_MEM* buf = NULL; ExpectNotNull(buf = BUF_MEM_new()); ExpectIntEQ(BUF_MEM_grow(buf, 10), 10); ExpectIntEQ(BUF_MEM_grow(buf, -1), 0); BUF_MEM_free(buf); #endif return EXPECT_RESULT(); } static int test_wolfSSL_PKCS8_Compat(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM) && defined(HAVE_ECC) && \ !defined(NO_BIO) PKCS8_PRIV_KEY_INFO* pt = NULL; PKCS8_PRIV_KEY_INFO* pt2 = NULL; BIO* bio = NULL; XFILE f = XBADFILE; int bytes = 0; char pkcs8_buffer[512]; #if defined(OPENSSL_ALL) || defined(WOLFSSL_WPAS_SMALL) EVP_PKEY *pkey = NULL; #endif /* file from wolfssl/certs/ directory */ ExpectTrue((f = XFOPEN("./certs/ecc-keyPkcs8.pem", "rb")) != XBADFILE); ExpectIntGT((bytes = (int)XFREAD(pkcs8_buffer, 1, sizeof(pkcs8_buffer), f)), 0); if (f != XBADFILE) XFCLOSE(f); ExpectNotNull(bio = BIO_new_mem_buf((void*)pkcs8_buffer, bytes)); ExpectNotNull(pt = d2i_PKCS8_PRIV_KEY_INFO_bio(bio, NULL)); #if defined(OPENSSL_ALL) || defined(WOLFSSL_WPAS_SMALL) ExpectNotNull(pkey = EVP_PKCS82PKEY(pt)); ExpectIntEQ(EVP_PKEY_type(pkey->type), EVP_PKEY_EC); /* gets PKCS8 pointer to pkey */ ExpectNotNull(pt2 = EVP_PKEY2PKCS8(pkey)); EVP_PKEY_free(pkey); #endif BIO_free(bio); PKCS8_PRIV_KEY_INFO_free(pt); PKCS8_PRIV_KEY_INFO_free(pt2); #endif return EXPECT_RESULT(); } #if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM) && !defined(NO_BIO) static int NoPasswordCallBack(char* passwd, int sz, int rw, void* userdata) { (void)passwd; (void)sz; (void)rw; (void)userdata; return -1; } #endif static int test_wolfSSL_PKCS8_d2i(void) { EXPECT_DECLS; #if !defined(HAVE_FIPS) && defined(OPENSSL_EXTRA) /* This test ends up using HMAC as a part of PBKDF2, and HMAC * requires a 12 byte password in FIPS mode. This test ends up * trying to use an 8 byte password. */ #ifndef NO_FILESYSTEM unsigned char pkcs8_buffer[2048]; const unsigned char* p = NULL; int bytes = 0; XFILE file = XBADFILE; WOLFSSL_EVP_PKEY* pkey = NULL; #ifndef NO_BIO BIO* bio = NULL; #if defined(OPENSSL_ALL) && \ ((!defined(NO_RSA) && !defined(NO_DES3)) || \ defined(HAVE_ECC)) && \ !defined(NO_BIO) && !defined(NO_PWDBASED) && defined(HAVE_PKCS8) WOLFSSL_EVP_PKEY* evpPkey = NULL; #endif #endif #ifndef NO_RSA const char rsaDerPkcs8File[] = "./certs/server-keyPkcs8.der"; const char rsaPemPkcs8File[] = "./certs/server-keyPkcs8.pem"; #ifndef NO_DES3 const char rsaDerPkcs8EncFile[] = "./certs/server-keyPkcs8Enc.der"; #endif #endif /* NO_RSA */ #ifdef HAVE_ECC const char ecDerPkcs8File[] = "certs/ecc-keyPkcs8.der"; const char ecPemPkcs8File[] = "certs/ecc-keyPkcs8.pem"; #ifndef NO_DES3 const char ecDerPkcs8EncFile[] = "certs/ecc-keyPkcs8Enc.der"; #endif #endif /* HAVE_ECC */ #endif /* !NO_FILESYSTEM */ #if defined(OPENSSL_ALL) && (!defined(NO_RSA) || defined(HAVE_ECC)) #ifndef NO_RSA #ifdef USE_CERT_BUFFERS_1024 const unsigned char* rsa = (unsigned char*)server_key_der_1024; int rsaSz = sizeof_server_key_der_1024; #else const unsigned char* rsa = (unsigned char*)server_key_der_2048; int rsaSz = sizeof_server_key_der_2048; #endif #endif #ifdef HAVE_ECC const unsigned char* ec = (unsigned char*)ecc_key_der_256; int ecSz = sizeof_ecc_key_der_256; #endif #endif /* OPENSSL_ALL && (!NO_RSA || HAVE_ECC) */ #ifndef NO_FILESYSTEM (void)pkcs8_buffer; (void)p; (void)bytes; (void)file; #ifndef NO_BIO (void)bio; #endif #endif #ifdef OPENSSL_ALL #ifndef NO_RSA /* Try to auto-detect normal RSA private key */ ExpectNotNull(pkey = d2i_AutoPrivateKey(NULL, &rsa, rsaSz)); EVP_PKEY_free(pkey); pkey = NULL; #endif #ifdef HAVE_ECC /* Try to auto-detect normal EC private key */ ExpectNotNull(pkey = d2i_AutoPrivateKey(NULL, &ec, ecSz)); EVP_PKEY_free(pkey); pkey = NULL; #endif #endif /* OPENSSL_ALL */ #ifndef NO_FILESYSTEM #if defined(OPENSSL_ALL) && !defined(NO_PWDBASED) && defined(HAVE_PKCS8) ExpectIntEQ(PEM_write_PKCS8PrivateKey(XBADFILE, pkey, NULL, NULL, 0, NULL, NULL), 0); ExpectIntEQ(PEM_write_PKCS8PrivateKey(stderr, NULL, NULL, NULL, 0, NULL, NULL), 0); #endif #ifndef NO_RSA /* Get DER encoded RSA PKCS#8 data. */ ExpectTrue((file = XFOPEN(rsaDerPkcs8File, "rb")) != XBADFILE); ExpectNotNull(XMEMSET(pkcs8_buffer, 0, sizeof(pkcs8_buffer))); ExpectIntGT((bytes = (int)XFREAD(pkcs8_buffer, 1, sizeof(pkcs8_buffer), file)), 0); if (file != XBADFILE) { XFCLOSE(file); file = XBADFILE; } p = pkcs8_buffer; #ifdef OPENSSL_ALL /* Try to decode - auto-detect key type. */ ExpectNotNull(pkey = d2i_AutoPrivateKey(NULL, &p, bytes)); #else ExpectNotNull(pkey = d2i_PrivateKey(EVP_PKEY_RSA, NULL, &p, bytes)); #endif /* Get PEM encoded RSA PKCS#8 data. */ ExpectTrue((file = XFOPEN(rsaPemPkcs8File, "rb")) != XBADFILE); ExpectIntGT((bytes = (int)XFREAD(pkcs8_buffer, 1, sizeof(pkcs8_buffer), file)), 0); if (file != XBADFILE) { XFCLOSE(file); file = XBADFILE; } #if defined(OPENSSL_ALL) && \ !defined(NO_BIO) && !defined(NO_PWDBASED) && defined(HAVE_PKCS8) ExpectNotNull(bio = BIO_new(BIO_s_mem())); ExpectIntEQ(PEM_write_bio_PKCS8PrivateKey(NULL, pkey, NULL, NULL, 0, NULL, NULL), 0); ExpectIntEQ(PEM_write_bio_PKCS8PrivateKey(bio, NULL, NULL, NULL, 0, NULL, NULL), 0); /* Write PKCS#8 PEM to BIO. */ ExpectIntEQ(PEM_write_bio_PKCS8PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL), bytes); /* Write PKCS#8 PEM to stderr. */ ExpectIntEQ(PEM_write_PKCS8PrivateKey(stderr, pkey, NULL, NULL, 0, NULL, NULL), bytes); /* Compare file and written data */ ExpectIntEQ(BIO_get_mem_data(bio, &p), bytes); ExpectIntEQ(XMEMCMP(p, pkcs8_buffer, bytes), 0); BIO_free(bio); bio = NULL; #if !defined(NO_AES) && defined(HAVE_AESGCM) ExpectIntEQ(PEM_write_PKCS8PrivateKey(stderr, pkey, EVP_aes_128_gcm(), NULL, 0, PasswordCallBack, (void*)"yassl123"), 0); #endif #if !defined(NO_DES3) && !defined(NO_SHA) ExpectNotNull(bio = BIO_new(BIO_s_mem())); /* Write Encrypted PKCS#8 PEM to BIO. */ bytes = 1834; ExpectIntEQ(PEM_write_bio_PKCS8PrivateKey(bio, pkey, EVP_des_ede3_cbc(), NULL, 0, PasswordCallBack, (void*)"yassl123"), bytes); ExpectIntEQ(PEM_write_PKCS8PrivateKey(stderr, pkey, EVP_des_ede3_cbc(), NULL, 0, PasswordCallBack, (void*)"yassl123"), bytes); ExpectNotNull(evpPkey = PEM_read_bio_PrivateKey(bio, NULL, PasswordCallBack, (void*)"yassl123")); EVP_PKEY_free(evpPkey); evpPkey = NULL; BIO_free(bio); bio = NULL; #endif /* !NO_DES3 && !NO_SHA */ #endif /* !NO_BIO && !NO_PWDBASED && HAVE_PKCS8 */ EVP_PKEY_free(pkey); pkey = NULL; /* PKCS#8 encrypted RSA key */ #ifndef NO_DES3 ExpectTrue((file = XFOPEN(rsaDerPkcs8EncFile, "rb")) != XBADFILE); ExpectNotNull(XMEMSET(pkcs8_buffer, 0, sizeof(pkcs8_buffer))); ExpectIntGT((bytes = (int)XFREAD(pkcs8_buffer, 1, sizeof(pkcs8_buffer), file)), 0); if (file != XBADFILE) { XFCLOSE(file); file = XBADFILE; } #if defined(OPENSSL_ALL) && \ !defined(NO_BIO) && !defined(NO_PWDBASED) && defined(HAVE_PKCS8) ExpectNotNull(bio = BIO_new_mem_buf((void*)pkcs8_buffer, bytes)); ExpectNotNull(pkey = d2i_PKCS8PrivateKey_bio(bio, NULL, PasswordCallBack, (void*)"yassl123")); EVP_PKEY_free(pkey); pkey = NULL; BIO_free(bio); bio = NULL; #endif /* OPENSSL_ALL && !NO_BIO && !NO_PWDBASED && HAVE_PKCS8 */ #endif /* !NO_DES3 */ #endif /* NO_RSA */ #ifdef HAVE_ECC /* PKCS#8 encode EC key */ ExpectTrue((file = XFOPEN(ecDerPkcs8File, "rb")) != XBADFILE); ExpectNotNull(XMEMSET(pkcs8_buffer, 0, sizeof(pkcs8_buffer))); ExpectIntGT((bytes = (int)XFREAD(pkcs8_buffer, 1, sizeof(pkcs8_buffer), file)), 0); if (file != XBADFILE) { XFCLOSE(file); file = XBADFILE; } p = pkcs8_buffer; #ifdef OPENSSL_ALL /* Try to decode - auto-detect key type. */ ExpectNotNull(pkey = d2i_AutoPrivateKey(NULL, &p, bytes)); #else ExpectNotNull(pkey = d2i_PrivateKey(EVP_PKEY_EC, NULL, &p, bytes)); #endif /* Get PEM encoded RSA PKCS#8 data. */ ExpectTrue((file = XFOPEN(ecPemPkcs8File, "rb")) != XBADFILE); ExpectNotNull(XMEMSET(pkcs8_buffer, 0, sizeof(pkcs8_buffer))); ExpectIntGT((bytes = (int)XFREAD(pkcs8_buffer, 1, sizeof(pkcs8_buffer), file)), 0); if (file != XBADFILE) { XFCLOSE(file); file = XBADFILE; } #if defined(OPENSSL_ALL) && \ !defined(NO_BIO) && !defined(NO_PWDBASED) && defined(HAVE_PKCS8) && \ defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_256) ExpectNotNull(bio = BIO_new(BIO_s_mem())); /* Write PKCS#8 PEM to BIO. */ ExpectIntEQ(PEM_write_bio_PKCS8PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL), bytes); ExpectIntEQ(PEM_write_PKCS8PrivateKey(stderr, pkey, NULL, NULL, 0, NULL, NULL), bytes); /* Compare file and written data */ ExpectIntEQ(BIO_get_mem_data(bio, &p), bytes); ExpectIntEQ(XMEMCMP(p, pkcs8_buffer, bytes), 0); BIO_free(bio); bio = NULL; ExpectNotNull(bio = BIO_new(BIO_s_mem())); /* Write Encrypted PKCS#8 PEM to BIO (test write 0 then 379) */ bytes = 379; ExpectIntEQ(PEM_write_bio_PKCS8PrivateKey(bio, pkey, EVP_aes_256_cbc(), NULL, 0, NoPasswordCallBack, (void*)"yassl123"), 0); ExpectIntEQ(PEM_write_bio_PKCS8PrivateKey(bio, pkey, EVP_aes_256_cbc(), NULL, 0, PasswordCallBack, (void*)"yassl123"), bytes); /* invalid cases to stderr */ #ifdef WOLFSSL_AES_128 ExpectIntEQ(PEM_write_PKCS8PrivateKey(stderr, pkey, EVP_aes_128_cbc(), NULL, 0, PasswordCallBack, (void*)"yassl123"), bytes); ExpectIntEQ(PEM_write_PKCS8PrivateKey(stderr, pkey, EVP_aes_128_cbc(), (char*)"yassl123", 8, PasswordCallBack, NULL), bytes); #endif ExpectIntEQ(PEM_write_PKCS8PrivateKey(stderr, pkey, EVP_aes_256_cbc(), NULL, 0, PasswordCallBack, (void*)"yassl123"), bytes); ExpectIntEQ(PEM_write_PKCS8PrivateKey(stderr, pkey, EVP_aes_256_cbc(), (char*)"yassl123", 8, PasswordCallBack, NULL), bytes); /* read/decode private key with password */ ExpectNotNull(evpPkey = PEM_read_bio_PrivateKey(bio, NULL, PasswordCallBack, (void*)"yassl123")); EVP_PKEY_free(evpPkey); evpPkey = NULL; BIO_free(bio); bio = NULL; /* https://github.com/wolfSSL/wolfssl/issues/8610 */ bytes = (int)XSTRLEN((char *)pkcs8_buffer); ExpectNotNull(bio = BIO_new_mem_buf((void*)pkcs8_buffer, bytes)); ExpectIntEQ(BIO_get_mem_data(bio, &p), bytes); ExpectIntEQ(XMEMCMP(p, pkcs8_buffer, bytes), 0); ExpectNotNull(evpPkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, (void*)"yassl123")); ExpectIntEQ(PEM_write_PKCS8PrivateKey(stderr, evpPkey, NULL, NULL, 0, NULL, NULL), bytes); EVP_PKEY_free(evpPkey); evpPkey = NULL; BIO_free(bio); bio = NULL; #endif /* OPENSSL_ALL && !NO_BIO && !NO_PWDBASED && HAVE_PKCS8 && HAVE_AES_CBC */ EVP_PKEY_free(pkey); pkey = NULL; /* PKCS#8 encrypted EC key */ #ifndef NO_DES3 ExpectTrue((file = XFOPEN(ecDerPkcs8EncFile, "rb")) != XBADFILE); ExpectNotNull(XMEMSET(pkcs8_buffer, 0, sizeof(pkcs8_buffer))); ExpectIntGT((bytes = (int)XFREAD(pkcs8_buffer, 1, sizeof(pkcs8_buffer), file)), 0); if (file != XBADFILE) { XFCLOSE(file); file = XBADFILE; } #if defined(OPENSSL_ALL) && \ !defined(NO_BIO) && !defined(NO_PWDBASED) && defined(HAVE_PKCS8) ExpectNotNull(bio = BIO_new_mem_buf((void*)pkcs8_buffer, bytes)); ExpectNotNull(pkey = d2i_PKCS8PrivateKey_bio(bio, NULL, PasswordCallBack, (void*)"yassl123")); EVP_PKEY_free(pkey); pkey = NULL; BIO_free(bio); bio = NULL; #endif /* OPENSSL_ALL && !NO_BIO && !NO_PWDBASED && HAVE_PKCS8 */ #endif /* !NO_DES3 */ #endif /* HAVE_ECC */ #endif /* !NO_FILESYSTEM */ #endif /* HAVE_FIPS && OPENSSL_EXTRA */ return EXPECT_RESULT(); } #if !defined(SINGLE_THREADED) && defined(ERROR_QUEUE_PER_THREAD) && \ !defined(NO_ERROR_QUEUE) && defined(OPENSSL_EXTRA) && \ defined(DEBUG_WOLFSSL) #define LOGGING_THREADS 5 #define ERROR_COUNT 10 /* copied from logging.c since this is not exposed otherwise */ #ifndef ERROR_QUEUE_MAX #ifdef ERROR_QUEUE_PER_THREAD #define ERROR_QUEUE_MAX 16 #else /* this breaks from compat of unlimited error queue size */ #define ERROR_QUEUE_MAX 100 #endif #endif static volatile int loggingThreadsReady; static THREAD_RETURN WOLFSSL_THREAD test_logging(void* args) { const char* file; int line; unsigned long err; int errorCount = 0; int i; (void)args; while (!loggingThreadsReady); for (i = 0; i < ERROR_COUNT; i++) ERR_put_error(ERR_LIB_PEM, SYS_F_ACCEPT, -990 - i, __FILE__, __LINE__); while ((err = ERR_get_error_line(&file, &line))) { AssertIntEQ(err, 990 + errorCount); errorCount++; } AssertIntEQ(errorCount, ERROR_COUNT); /* test max queue behavior, trying to add an arbitrary 3 errors over */ ERR_clear_error(); /* ERR_get_error_line() does not remove */ errorCount = 0; for (i = 0; i < ERROR_QUEUE_MAX + 3; i++) ERR_put_error(ERR_LIB_PEM, SYS_F_ACCEPT, -990 - i, __FILE__, __LINE__); while ((err = ERR_get_error_line(&file, &line))) { AssertIntEQ(err, 990 + errorCount); errorCount++; } /* test that the 3 errors over the max were dropped */ AssertIntEQ(errorCount, ERROR_QUEUE_MAX); WOLFSSL_RETURN_FROM_THREAD(0); } #endif static int test_error_queue_per_thread(void) { int res = TEST_SKIPPED; #if !defined(SINGLE_THREADED) && defined(ERROR_QUEUE_PER_THREAD) && \ !defined(NO_ERROR_QUEUE) && defined(OPENSSL_EXTRA) && \ defined(DEBUG_WOLFSSL) THREAD_TYPE loggingThreads[LOGGING_THREADS]; int i; ERR_clear_error(); /* clear out any error nodes */ loggingThreadsReady = 0; for (i = 0; i < LOGGING_THREADS; i++) start_thread(test_logging, NULL, &loggingThreads[i]); loggingThreadsReady = 1; for (i = 0; i < LOGGING_THREADS; i++) join_thread(loggingThreads[i]); res = TEST_SUCCESS; #endif return res; } static int test_wolfSSL_ERR_put_error(void) { EXPECT_DECLS; #if !defined(NO_ERROR_QUEUE) && defined(OPENSSL_EXTRA) && \ defined(DEBUG_WOLFSSL) const char* file; int line; ERR_clear_error(); /* clear out any error nodes */ ERR_put_error(0,SYS_F_ACCEPT, 0, "this file", 0); ExpectIntEQ(ERR_get_error_line(&file, &line), 0); ERR_put_error(0,SYS_F_BIND, 1, "this file", 1); ExpectIntEQ(ERR_get_error_line(&file, &line), 1); ERR_put_error(0,SYS_F_CONNECT, 2, "this file", 2); ExpectIntEQ(ERR_get_error_line(&file, &line), 2); ERR_put_error(0,SYS_F_FOPEN, 3, "this file", 3); ExpectIntEQ(ERR_get_error_line(&file, &line), 3); ERR_put_error(0,SYS_F_FREAD, 4, "this file", 4); ExpectIntEQ(ERR_get_error_line(&file, &line), 4); ERR_put_error(0,SYS_F_GETADDRINFO, 5, "this file", 5); ExpectIntEQ(ERR_get_error_line(&file, &line), 5); ERR_put_error(0,SYS_F_GETSOCKOPT, 6, "this file", 6); ExpectIntEQ(ERR_get_error_line(&file, &line), 6); ERR_put_error(0,SYS_F_GETSOCKNAME, 7, "this file", 7); ExpectIntEQ(ERR_get_error_line(&file, &line), 7); ERR_put_error(0,SYS_F_GETHOSTBYNAME, 8, "this file", 8); ExpectIntEQ(ERR_get_error_line(&file, &line), 8); ERR_put_error(0,SYS_F_GETNAMEINFO, 9, "this file", 9); ExpectIntEQ(ERR_get_error_line(&file, &line), 9); ERR_put_error(0,SYS_F_GETSERVBYNAME, 10, "this file", 10); ExpectIntEQ(ERR_get_error_line(&file, &line), 10); ERR_put_error(0,SYS_F_IOCTLSOCKET, 11, "this file", 11); ExpectIntEQ(ERR_get_error_line(&file, &line), 11); ERR_put_error(0,SYS_F_LISTEN, 12, "this file", 12); ExpectIntEQ(ERR_get_error_line(&file, &line), 12); ERR_put_error(0,SYS_F_OPENDIR, 13, "this file", 13); ExpectIntEQ(ERR_get_error_line(&file, &line), 13); ERR_put_error(0,SYS_F_SETSOCKOPT, 14, "this file", 14); ExpectIntEQ(ERR_get_error_line(&file, &line), 14); ERR_put_error(0,SYS_F_SOCKET, 15, "this file", 15); ExpectIntEQ(ERR_get_error_line(&file, &line), 15); #if defined(OPENSSL_ALL) && defined(WOLFSSL_PYTHON) ERR_put_error(ERR_LIB_ASN1, SYS_F_ACCEPT, ASN1_R_HEADER_TOO_LONG, "this file", 100); ExpectIntEQ(wolfSSL_ERR_peek_last_error_line(&file, &line), (ERR_LIB_ASN1 << 24) | ASN1_R_HEADER_TOO_LONG); ExpectIntEQ(line, 100); ExpectIntEQ(wolfSSL_ERR_peek_error(), (ERR_LIB_ASN1 << 24) | ASN1_R_HEADER_TOO_LONG); ExpectIntEQ(ERR_get_error_line(&file, &line), ASN1_R_HEADER_TOO_LONG); #endif /* try reading past end of error queue */ file = NULL; ExpectIntEQ(ERR_get_error_line(&file, &line), 0); ExpectNull(file); ExpectIntEQ(ERR_get_error_line_data(&file, &line, NULL, NULL), 0); PEMerr(4,4); ExpectIntEQ(ERR_get_error(), 4); /* Empty and free up all error nodes */ ERR_clear_error(); /* Verify all nodes are cleared */ ERR_put_error(0,SYS_F_ACCEPT, 0, "this file", 0); ERR_clear_error(); ExpectIntEQ(ERR_get_error_line(&file, &line), 0); #endif return EXPECT_RESULT(); } /* * This is a regression test for a bug where the peek/get error functions were * drawing from the end of the queue rather than the front. */ static int test_wolfSSL_ERR_get_error_order(void) { EXPECT_DECLS; #if defined(WOLFSSL_HAVE_ERROR_QUEUE) && defined(OPENSSL_EXTRA) /* Empty the queue. */ wolfSSL_ERR_clear_error(); wolfSSL_ERR_put_error(0, 0, WC_NO_ERR_TRACE(ASN_NO_SIGNER_E), "test", 0); wolfSSL_ERR_put_error(0, 0, WC_NO_ERR_TRACE(ASN_SELF_SIGNED_E), "test", 0); ExpectIntEQ(wolfSSL_ERR_peek_error(), -WC_NO_ERR_TRACE(ASN_NO_SIGNER_E)); ExpectIntEQ(wolfSSL_ERR_get_error(), -WC_NO_ERR_TRACE(ASN_NO_SIGNER_E)); ExpectIntEQ(wolfSSL_ERR_peek_error(), -WC_NO_ERR_TRACE(ASN_SELF_SIGNED_E)); ExpectIntEQ(wolfSSL_ERR_get_error(), -WC_NO_ERR_TRACE(ASN_SELF_SIGNED_E)); #endif /* WOLFSSL_HAVE_ERROR_QUEUE && OPENSSL_EXTRA */ return EXPECT_RESULT(); } #ifndef NO_BIO static int test_wolfSSL_ERR_print_errors(void) { EXPECT_DECLS; #if !defined(NO_ERROR_QUEUE) && defined(OPENSSL_EXTRA) && \ defined(DEBUG_WOLFSSL) && !defined(NO_ERROR_STRINGS) BIO* bio = NULL; char buf[1024]; ExpectNotNull(bio = BIO_new(BIO_s_mem())); ERR_clear_error(); /* clear out any error nodes */ ERR_put_error(0,SYS_F_ACCEPT, -173, "ssl.c", 0); /* Choosing -600 as an unused errno. */ ERR_put_error(0,SYS_F_BIND, -600, "asn.c", 100); ERR_print_errors(bio); ExpectIntEQ(BIO_gets(bio, buf, sizeof(buf)), 56); ExpectIntEQ(XSTRNCMP( "error:173:wolfSSL library:Bad function argument:ssl.c:0", buf, 55), 0); ExpectIntEQ(BIO_gets(bio, buf, sizeof(buf)), 57); ExpectIntEQ(XSTRNCMP( "error:600:wolfSSL library:unknown error number:asn.c:100", buf, 56), 0); ExpectIntEQ(BIO_gets(bio, buf, sizeof(buf)), 1); ExpectIntEQ(buf[0], '\0'); ExpectIntEQ(ERR_get_error_line(NULL, NULL), 0); BIO_free(bio); #endif return EXPECT_RESULT(); } #if !defined(NO_ERROR_QUEUE) && defined(OPENSSL_EXTRA) && \ defined(DEBUG_WOLFSSL) static int test_wolfSSL_error_cb(const char *str, size_t len, void *u) { if (u != NULL) { wolfSSL_BIO_write((BIO*)u, str, (int)len); } return 0; } #endif static int test_wolfSSL_ERR_print_errors_cb(void) { EXPECT_DECLS; #if !defined(NO_ERROR_QUEUE) && defined(OPENSSL_EXTRA) && \ defined(DEBUG_WOLFSSL) BIO* bio = NULL; char buf[1024]; ExpectNotNull(bio = BIO_new(BIO_s_mem())); ERR_clear_error(); /* clear out any error nodes */ ERR_put_error(0,SYS_F_ACCEPT, -173, "ssl.c", 0); ERR_put_error(0,SYS_F_BIND, -275, "asn.c", 100); ERR_print_errors_cb(test_wolfSSL_error_cb, bio); ExpectIntEQ(BIO_gets(bio, buf, sizeof(buf)), 108); ExpectIntEQ(XSTRNCMP( "wolfSSL error occurred, error = 173 line:0 file:ssl.c", buf, 53), 0); ExpectIntEQ(XSTRNCMP( "wolfSSL error occurred, error = 275 line:100 file:asn.c", buf + 53, 55), 0); ExpectIntEQ(BIO_gets(bio, buf, sizeof(buf)), 0); BIO_free(bio); #endif return EXPECT_RESULT(); } /* * Testing WOLFSSL_ERROR_MSG */ static int test_WOLFSSL_ERROR_MSG(void) { int res = TEST_SKIPPED; #if defined(DEBUG_WOLFSSL) || defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) ||\ defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) const char* msg = TEST_STRING; WOLFSSL_ERROR_MSG(msg); res = TEST_SUCCESS; #endif return res; } /* End test_WOLFSSL_ERROR_MSG */ /* * Testing wc_ERR_remove_state */ static int test_wc_ERR_remove_state(void) { int res = TEST_SKIPPED; #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) wc_ERR_remove_state(); res = TEST_SUCCESS; #endif return res; } /* End test_wc_ERR_remove_state */ /* * Testing wc_ERR_print_errors_fp */ static int test_wc_ERR_print_errors_fp(void) { EXPECT_DECLS; #if (defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)) && \ (!defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM)) long sz; XFILE fp = XBADFILE; WOLFSSL_ERROR(WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectTrue((fp = XFOPEN("./tests/test-log-dump-to-file.txt", "a+")) != XBADFILE); wc_ERR_print_errors_fp(fp); #if defined(DEBUG_WOLFSSL) ExpectTrue(XFSEEK(fp, 0, XSEEK_END) == 0); #ifdef NO_ERROR_QUEUE ExpectIntEQ(sz = XFTELL(fp), 0); #else ExpectIntNE(sz = XFTELL(fp), 0); #endif #endif if (fp != XBADFILE) XFCLOSE(fp); (void)sz; #endif return EXPECT_RESULT(); } /* End test_wc_ERR_print_errors_fp */ #ifdef DEBUG_WOLFSSL static void Logging_cb(const int logLevel, const char *const logMessage) { (void)logLevel; (void)logMessage; } #endif /* * Testing wolfSSL_GetLoggingCb */ static int test_wolfSSL_GetLoggingCb(void) { EXPECT_DECLS; #ifdef DEBUG_WOLFSSL /* Testing without wolfSSL_SetLoggingCb() */ ExpectNull(wolfSSL_GetLoggingCb()); /* Testing with wolfSSL_SetLoggingCb() */ ExpectIntEQ(wolfSSL_SetLoggingCb(Logging_cb), 0); ExpectNotNull(wolfSSL_GetLoggingCb()); ExpectIntEQ(wolfSSL_SetLoggingCb(NULL), 0); #endif ExpectNull(wolfSSL_GetLoggingCb()); return EXPECT_RESULT(); } /* End test_wolfSSL_GetLoggingCb */ #endif /* !NO_BIO */ /* Note the lack of wolfSSL_ prefix...this is a compatibility layer test. */ static int test_GENERAL_NAME_set0_othername(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ) && \ defined(WOLFSSL_CUSTOM_OID) && defined(WOLFSSL_ALT_NAMES) && \ defined(WOLFSSL_CERT_EXT) && !defined(NO_FILESYSTEM) && \ defined(WOLFSSL_FPKI) && !defined(NO_RSA) /* ./configure --enable-opensslall --enable-certgen --enable-certreq * --enable-certext --enable-debug 'CPPFLAGS=-DWOLFSSL_CUSTOM_OID * -DWOLFSSL_ALT_NAMES -DWOLFSSL_FPKI' */ const char * cert_fname = "./certs/server-cert.der"; const char * key_fname = "./certs/server-key.der"; X509* x509 = NULL; GENERAL_NAME* gn = NULL; GENERAL_NAMES* gns = NULL; ASN1_OBJECT* upn_oid = NULL; ASN1_UTF8STRING *utf8str = NULL; ASN1_TYPE *value = NULL; X509_EXTENSION * ext = NULL; byte* pt = NULL; byte der[4096]; int derSz = 0; EVP_PKEY* priv = NULL; XFILE f = XBADFILE; ExpectTrue((f = XFOPEN(cert_fname, "rb")) != XBADFILE); ExpectNotNull(x509 = d2i_X509_fp(f, NULL)); if (f != XBADFILE) { XFCLOSE(f); f = XBADFILE; } ExpectNotNull(gn = GENERAL_NAME_new()); ExpectNotNull(upn_oid = OBJ_txt2obj("1.3.6.1.4.1.311.20.2.3", 1)); ExpectNotNull(utf8str = ASN1_UTF8STRING_new()); ExpectIntEQ(ASN1_STRING_set(utf8str, "othername@wolfssl.com", -1), 1); ExpectNotNull(value = ASN1_TYPE_new()); ASN1_TYPE_set(value, V_ASN1_UTF8STRING, utf8str); if ((value == NULL) || (value->value.ptr != (char*)utf8str)) { wolfSSL_ASN1_STRING_free(utf8str); } ExpectIntEQ(GENERAL_NAME_set0_othername(NULL, NULL , NULL ), WOLFSSL_FAILURE); ExpectIntEQ(GENERAL_NAME_set0_othername(gn , NULL , NULL ), WOLFSSL_FAILURE); ExpectIntEQ(GENERAL_NAME_set0_othername(NULL, upn_oid, NULL ), WOLFSSL_FAILURE); ExpectIntEQ(GENERAL_NAME_set0_othername(NULL, NULL , value), WOLFSSL_FAILURE); ExpectIntEQ(GENERAL_NAME_set0_othername(gn , upn_oid, NULL ), WOLFSSL_FAILURE); ExpectIntEQ(GENERAL_NAME_set0_othername(gn , NULL , value), WOLFSSL_FAILURE); ExpectIntEQ(GENERAL_NAME_set0_othername(NULL, upn_oid, value ), WOLFSSL_FAILURE); ExpectIntEQ(GENERAL_NAME_set0_othername(gn, upn_oid, value), 1); if (EXPECT_FAIL()) { ASN1_TYPE_free(value); } ExpectNotNull(gns = sk_GENERAL_NAME_new(NULL)); ExpectIntEQ(sk_GENERAL_NAME_push(gns, gn), 1); if (EXPECT_FAIL()) { GENERAL_NAME_free(gn); gn = NULL; } ExpectNotNull(ext = X509V3_EXT_i2d(NID_subject_alt_name, 0, gns)); ExpectIntEQ(X509_add_ext(x509, ext, -1), 1); ExpectTrue((f = XFOPEN(key_fname, "rb")) != XBADFILE); ExpectIntGT(derSz = (int)XFREAD(der, 1, sizeof(der), f), 0); if (f != XBADFILE) { XFCLOSE(f); f = XBADFILE; } pt = der; ExpectNotNull(priv = d2i_PrivateKey(EVP_PKEY_RSA, NULL, (const unsigned char**)&pt, derSz)); ExpectIntGT(X509_sign(x509, priv, EVP_sha256()), 0); sk_GENERAL_NAME_pop_free(gns, GENERAL_NAME_free); gns = NULL; ExpectNotNull(gns = (GENERAL_NAMES*)X509_get_ext_d2i(x509, NID_subject_alt_name, NULL, NULL)); ExpectIntEQ(sk_GENERAL_NAME_num(NULL), 0); ExpectIntEQ(sk_GENERAL_NAME_num(gns), 3); ExpectNull(sk_GENERAL_NAME_value(NULL, 0)); ExpectNull(sk_GENERAL_NAME_value(gns, 20)); ExpectNotNull(gn = sk_GENERAL_NAME_value(gns, 2)); ExpectIntEQ(gn->type, 0); sk_GENERAL_NAME_pop_free(gns, GENERAL_NAME_free); ASN1_OBJECT_free(upn_oid); X509_EXTENSION_free(ext); X509_free(x509); EVP_PKEY_free(priv); #endif return EXPECT_RESULT(); } /* Test RID (Registered ID) GENERAL_NAME creation and freeing */ static int test_RID_GENERAL_NAME_free(void) { EXPECT_DECLS; #if defined(OPENSSL_ALL) && defined(WOLFSSL_RID_ALT_NAME) /* RID OID: 1.2.3.4.5 in DER */ const unsigned char ridData[] = { 0x06, 0x04, 0x2a, 0x03, 0x04, 0x05 }; const unsigned char* p = ridData; GENERAL_NAME* gn = NULL; GENERAL_NAMES* gns = NULL; ASN1_OBJECT* ridObj = NULL; /* Create RID ASN1_OBJECT from DER */ ExpectNotNull(ridObj = wolfSSL_d2i_ASN1_OBJECT(NULL, &p, sizeof(ridData))); /* Create GENERAL_NAME and set up as RID */ ExpectNotNull(gn = GENERAL_NAME_new()); if (gn != NULL) { /* GENERAL_NAME_new allocates ia5, must free before using as RID */ gn->type = GEN_RID; wolfSSL_ASN1_STRING_free(gn->d.ia5); gn->d.ia5 = NULL; gn->d.registeredID = ridObj; ridObj = NULL; /* gn owns */ } if (EXPECT_FAIL()) { wolfSSL_ASN1_OBJECT_free(ridObj); } /* Add to stack */ ExpectNotNull(gns = sk_GENERAL_NAME_new(NULL)); ExpectIntEQ(sk_GENERAL_NAME_push(gns, gn), 1); if (EXPECT_FAIL()) { GENERAL_NAME_free(gn); gn = NULL; } /* Verify RID is set up correctly */ ExpectNotNull(gn = sk_GENERAL_NAME_value(gns, 0)); ExpectIntEQ(gn->type, GEN_RID); ExpectNotNull(gn->d.registeredID); /* Free via sk_GENERAL_NAME_pop_free, exercises type_free for RID */ sk_GENERAL_NAME_pop_free(gns, GENERAL_NAME_free); #endif return EXPECT_RESULT(); } /* Test RID (Registered ID) SAN parsing via X509_get_ext_d2i(). * Uses rid-cert.der which contains a RID SAN with OID 1.2.3.4.5. This tests * that ASN_RID_TYPE case in wolfSSL_X509_get_ext_d2i() frees ia5 before * allocating registeredID. */ static int test_RID_X509_get_ext_d2i(void) { EXPECT_DECLS; #if defined(OPENSSL_ALL) && defined(WOLFSSL_RID_ALT_NAME) && \ !defined(NO_RSA) && !defined(NO_FILESYSTEM) int i; int numNames; int foundRID = 0; const char* ridCert = "./certs/rid-cert.der"; X509* x509 = NULL; GENERAL_NAMES* gns = NULL; GENERAL_NAME* gn = NULL; XFILE f = XBADFILE; ExpectTrue((f = XFOPEN(ridCert, "rb")) != XBADFILE); ExpectNotNull(x509 = d2i_X509_fp(f, NULL)); if (f != XBADFILE) { XFCLOSE(f); f = XBADFILE; } /* Get SANs, will exercise ASN_RID_TYPE case */ ExpectNotNull(gns = (GENERAL_NAMES*)X509_get_ext_d2i(x509, NID_subject_alt_name, NULL, NULL)); /* rid-cert.der contains: UPN, RID (1.2.3.4.5), DNS, URI, othername */ numNames = sk_GENERAL_NAME_num(gns); ExpectIntGE(numNames, 2); for (i = 0; i < numNames; i++) { gn = sk_GENERAL_NAME_value(gns, i); if (gn != NULL && gn->type == GEN_RID) { ExpectNotNull(gn->d.registeredID); foundRID = 1; break; } } ExpectIntEQ(foundRID, 1); /* Free via sk_GENERAL_NAME_pop_free, exercises type_free for RID */ sk_GENERAL_NAME_pop_free(gns, GENERAL_NAME_free); X509_free(x509); #endif return EXPECT_RESULT(); } /* Note the lack of wolfSSL_ prefix...this is a compatibility layer test. */ static int test_othername_and_SID_ext(void) { EXPECT_DECLS; #if defined(OPENSSL_ALL) && !defined(NO_CERTS) && \ defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ) && \ defined(WOLFSSL_CUSTOM_OID) && defined(WOLFSSL_ALT_NAMES) && \ defined(WOLFSSL_CERT_EXT) && !defined(NO_FILESYSTEM) && \ defined(WOLFSSL_FPKI) && defined(WOLFSSL_ASN_TEMPLATE) && !defined(NO_RSA) /* ./configure --enable-opensslall --enable-certgen --enable-certreq * --enable-certext --enable-debug 'CPPFLAGS=-DWOLFSSL_CUSTOM_OID * -DWOLFSSL_ALT_NAMES -DWOLFSSL_FPKI' */ const char* csr_fname = "./certs/csr.signed.der"; const char* key_fname = "./certs/server-key.der"; byte der[4096]; int derSz = 0; byte badDer[2] = { 0x30, 0x00 }; X509_REQ* x509 = NULL; STACK_OF(X509_EXTENSION) *exts = NULL; X509_EXTENSION * san_ext = NULL; X509_EXTENSION * ext = NULL; GENERAL_NAME* gn = NULL; GENERAL_NAMES* gns = NULL; ASN1_OBJECT* upn_oid = NULL; ASN1_UTF8STRING *utf8str = NULL; ASN1_TYPE *value = NULL; ASN1_STRING *extval = NULL; /* SID extension. SID data format explained here: * https://blog.qdsecurity.se/2022/05/27/manually-injecting-a-sid-in-a-certificate/ */ byte SidExtension[] = { 48, 64, 160, 62, 6, 10, 43, 6, 1, 4, 1, 130, 55, 25, 2, 1, 160, 48, 4, 46, 83, 45, 49, 45, 53, 45, 50, 49, 45, 50, 56, 52, 51, 57, 48, 55, 52, 49, 56, 45, 51, 57, 50, 54, 50, 55, 55, 52, 50, 49, 45, 51, 56, 49, 53, 57, 57, 51, 57, 55, 50, 45, 52, 54, 48, 49}; byte expectedAltName[] = { 0x30, 0x27, 0xA0, 0x25, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x14, 0x02, 0x03, 0xA0, 0x17, 0x0C, 0x15, 0x6F, 0x74, 0x68, 0x65, 0x72, 0x6E, 0x61, 0x6D, 0x65, 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D}; X509_EXTENSION *sid_ext = NULL; ASN1_OBJECT* sid_oid = NULL; ASN1_OCTET_STRING *sid_data = NULL; ASN1_OBJECT* alt_names_oid = NULL; EVP_PKEY* priv = NULL; XFILE f = XBADFILE; byte* pt = NULL; BIO* bio = NULL; ExpectTrue((f = XFOPEN(csr_fname, "rb")) != XBADFILE); ExpectNotNull(x509 = d2i_X509_REQ_fp(f, NULL)); if (f != XBADFILE) { XFCLOSE(f); f = XBADFILE; } ExpectIntEQ(X509_REQ_set_version(x509, 2), 1); ExpectNotNull(gn = GENERAL_NAME_new()); ExpectNotNull(upn_oid = OBJ_txt2obj("1.3.6.1.4.1.311.20.2.3", 1)); ExpectNotNull(utf8str = ASN1_UTF8STRING_new()); ExpectIntEQ(ASN1_STRING_set(utf8str, "othername@wolfssl.com", -1), 1); ExpectNotNull(value = ASN1_TYPE_new()); ASN1_TYPE_set(value, V_ASN1_UTF8STRING, utf8str); if (EXPECT_FAIL()) { ASN1_UTF8STRING_free(utf8str); } ExpectIntEQ(GENERAL_NAME_set0_othername(gn, upn_oid, value), 1); if (EXPECT_FAIL()) { ASN1_TYPE_free(value); GENERAL_NAME_free(gn); gn = NULL; } ExpectNotNull(gns = sk_GENERAL_NAME_new(NULL)); ExpectIntEQ(sk_GENERAL_NAME_push(gns, gn), 1); if (EXPECT_FAIL()) { GENERAL_NAME_free(gn); } ExpectNotNull(san_ext = X509V3_EXT_i2d(NID_subject_alt_name, 0, gns)); ExpectNotNull(sid_oid = OBJ_txt2obj("1.3.6.1.4.1.311.25.2", 1)); ExpectNotNull(sid_data = ASN1_OCTET_STRING_new()); ASN1_OCTET_STRING_set(sid_data, SidExtension, sizeof(SidExtension)); ExpectNotNull(sid_ext = X509_EXTENSION_create_by_OBJ(NULL, sid_oid, 0, sid_data)); ExpectNotNull(exts = sk_X509_EXTENSION_new_null()); wolfSSL_sk_X509_EXTENSION_free(exts); exts = NULL; ExpectNotNull(exts = sk_X509_EXTENSION_new_null()); /* Ensure an empty stack doesn't raise an error. */ ExpectIntEQ(X509_REQ_add_extensions(NULL, NULL), 0); ExpectIntEQ(X509_REQ_add_extensions(x509, NULL), 0); ExpectIntEQ(X509_REQ_add_extensions(NULL, exts), 0); ExpectIntEQ(X509_REQ_add_extensions(x509, exts), 1); ExpectIntEQ(sk_X509_EXTENSION_push(exts, san_ext), 1); if (EXPECT_FAIL()) { X509_EXTENSION_free(san_ext); } ExpectIntEQ(sk_X509_EXTENSION_push(exts, sid_ext), 2); if (EXPECT_FAIL()) { X509_EXTENSION_free(sid_ext); } ExpectIntEQ(X509_REQ_add_extensions(x509, exts), 1); ExpectTrue((f = XFOPEN(key_fname, "rb")) != XBADFILE); ExpectIntGT(derSz = (int)XFREAD(der, 1, sizeof(der), f), 0); if (f != XBADFILE) XFCLOSE(f); pt = der; ExpectNotNull(priv = d2i_PrivateKey(EVP_PKEY_RSA, NULL, (const unsigned char**)&pt, derSz)); ExpectIntGT(X509_REQ_sign(x509, priv, EVP_sha256()), 0); pt = der; ExpectIntGT(derSz = i2d_X509_REQ(x509, &pt), 0); X509_REQ_free(x509); x509 = NULL; ExpectNull(d2i_X509_REQ_INFO(&x509, NULL, derSz)); pt = badDer; ExpectNull(d2i_X509_REQ_INFO(&x509, (const unsigned char**)&pt, sizeof(badDer))); pt = der; ExpectNotNull(d2i_X509_REQ_INFO(&x509, (const unsigned char**)&pt, derSz)); sk_GENERAL_NAME_pop_free(gns, GENERAL_NAME_free); gns = NULL; sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); exts = NULL; ASN1_OBJECT_free(upn_oid); ASN1_OBJECT_free(sid_oid); sid_oid = NULL; ASN1_OCTET_STRING_free(sid_data); X509_REQ_free(x509); EVP_PKEY_free(priv); /* At this point everything used to generate what is in der is cleaned up. * We now read back from der to confirm the extensions were inserted * correctly. */ bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem()); ExpectNotNull(bio); ExpectIntEQ(BIO_write(bio, der, derSz), derSz); /* d2i consumes BIO */ ExpectNotNull(d2i_X509_REQ_bio(bio, &x509)); ExpectNotNull(x509); BIO_free(bio); ExpectNotNull(exts = (STACK_OF(X509_EXTENSION)*)X509_REQ_get_extensions( x509)); ExpectIntEQ(sk_X509_EXTENSION_num(NULL), WOLFSSL_FATAL_ERROR); ExpectIntEQ(sk_X509_EXTENSION_num(exts), 2); /* Check the SID extension. */ ExpectNotNull(sid_oid = OBJ_txt2obj("1.3.6.1.4.1.311.25.2", 1)); ExpectNotNull(ext = sk_X509_EXTENSION_value(exts, X509_get_ext_by_OBJ(x509, sid_oid, -1))); ExpectNotNull(extval = X509_EXTENSION_get_data(ext)); ExpectIntEQ(extval->length, sizeof(SidExtension)); ExpectIntEQ(XMEMCMP(SidExtension, extval->data, sizeof(SidExtension)), 0); ASN1_OBJECT_free(sid_oid); /* Check the AltNames extension. */ ExpectNotNull(alt_names_oid = OBJ_txt2obj("subjectAltName", 0)); ExpectNotNull(ext = sk_X509_EXTENSION_value(exts, X509_get_ext_by_OBJ(x509, alt_names_oid, -1))); ExpectNotNull(extval = X509_EXTENSION_get_data(ext)); ExpectIntEQ(extval->length, sizeof(expectedAltName)); ExpectIntEQ(XMEMCMP(expectedAltName, extval->data, sizeof(expectedAltName)), 0); ASN1_OBJECT_free(alt_names_oid); /* Cleanup */ ExpectNotNull(gns = (GENERAL_NAMES*)X509_get_ext_d2i(x509, NID_subject_alt_name, NULL, NULL)); ExpectIntEQ(sk_GENERAL_NAME_num(gns), 1); ExpectNotNull(gn = sk_GENERAL_NAME_value(gns, 0)); ExpectIntEQ(gn->type, 0); sk_GENERAL_NAME_pop_free(gns, GENERAL_NAME_free); sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); X509_REQ_free(x509); #endif return EXPECT_RESULT(); } #if defined(OPENSSL_EXTRA) && defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) /* test that the callback arg is correct */ static int certCbArg = 0; static int certCb(WOLFSSL* ssl, void* arg) { if (ssl == NULL || arg != &certCbArg) return 0; if (wolfSSL_is_server(ssl)) { if (wolfSSL_use_certificate_file(ssl, svrCertFile, WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS) return 0; if (wolfSSL_use_PrivateKey_file(ssl, svrKeyFile, WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS) return 0; } else { if (wolfSSL_use_certificate_file(ssl, cliCertFile, WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS) return 0; if (wolfSSL_use_PrivateKey_file(ssl, cliKeyFile, WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS) return 0; } return 1; } static int certSetupCb(WOLFSSL_CTX* ctx) { SSL_CTX_set_cert_cb(ctx, certCb, &certCbArg); return TEST_SUCCESS; } /** * This is only done because test_wolfSSL_client_server_nofail_memio has no way * to stop certificate and key loading */ static int certClearCb(WOLFSSL* ssl) { /* Clear the loaded certs to force the callbacks to set them up */ SSL_certs_clear(ssl); return TEST_SUCCESS; } #endif static int test_wolfSSL_cert_cb(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) test_ssl_cbf func_cb_client; test_ssl_cbf func_cb_server; size_t i; struct { method_provider client_meth; method_provider server_meth; const char* desc; } test_params[] = { #ifdef WOLFSSL_TLS13 {wolfTLSv1_3_client_method, wolfTLSv1_3_server_method, "TLS 1.3"}, #endif #ifndef WOLFSSL_NO_TLS12 {wolfTLSv1_2_client_method, wolfTLSv1_2_server_method, "TLS 1.2"}, #endif #ifndef NO_OLD_TLS {wolfTLSv1_1_client_method, wolfTLSv1_1_server_method, "TLS 1.1"}, #ifdef WOLFSSL_ALLOW_TLSV10 {wolfTLSv1_client_method, wolfTLSv1_server_method, "TLS 1.0"}, #endif #endif }; for (i = 0; i < XELEM_CNT(test_params) && !EXPECT_FAIL(); i++) { XMEMSET(&func_cb_client, 0, sizeof(func_cb_client)); XMEMSET(&func_cb_server, 0, sizeof(func_cb_server)); printf("\tTesting with %s...\n", test_params[i].desc); func_cb_client.method = test_params[i].client_meth; func_cb_server.method = test_params[i].server_meth; func_cb_client.ctx_ready = certSetupCb; func_cb_client.ssl_ready = certClearCb; func_cb_server.ctx_ready = certSetupCb; func_cb_server.ssl_ready = certClearCb; ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&func_cb_client, &func_cb_server, NULL), TEST_SUCCESS); } #endif return EXPECT_RESULT(); } #if defined(OPENSSL_EXTRA) && defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) static const char* test_wolfSSL_cert_cb_dyn_ciphers_client_cipher = NULL; static const char* test_wolfSSL_cert_cb_dyn_ciphers_client_sigalgs = NULL; static int test_wolfSSL_cert_cb_dyn_ciphers_client_ctx_ready(WOLFSSL_CTX* ctx) { EXPECT_DECLS; ExpectIntEQ(wolfSSL_CTX_set_cipher_list(ctx, test_wolfSSL_cert_cb_dyn_ciphers_client_cipher), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_set1_sigalgs_list(ctx, test_wolfSSL_cert_cb_dyn_ciphers_client_sigalgs), WOLFSSL_SUCCESS); return EXPECT_RESULT(); } static int test_wolfSSL_cert_cb_dyn_ciphers_certCB(WOLFSSL* ssl, void* arg) { const byte* suites = NULL; word16 suiteSz = 0; const byte* hashSigAlgo = NULL; word16 hashSigAlgoSz = 0; word16 idx = 0; int haveRSA = 0; int haveECC = 0; (void)arg; if (wolfSSL_get_client_suites_sigalgs(ssl, &suites, &suiteSz, &hashSigAlgo, &hashSigAlgoSz) != WOLFSSL_SUCCESS) return 0; if (suites == NULL || suiteSz == 0 || hashSigAlgo == NULL || hashSigAlgoSz == 0) return 0; for (idx = 0; idx < suiteSz; idx += 2) { WOLFSSL_CIPHERSUITE_INFO info = wolfSSL_get_ciphersuite_info(suites[idx], suites[idx+1]); if (info.rsaAuth) haveRSA = 1; else if (info.eccAuth) haveECC = 1; } if (hashSigAlgoSz > 0) { /* sigalgs extension takes precedence over ciphersuites */ haveRSA = 0; haveECC = 0; } for (idx = 0; idx < hashSigAlgoSz; idx += 2) { int hashAlgo = 0; int sigAlgo = 0; if (wolfSSL_get_sigalg_info(hashSigAlgo[idx+0], hashSigAlgo[idx+1], &hashAlgo, &sigAlgo) != 0) return 0; if (sigAlgo == RSAk || sigAlgo == RSAPSSk) haveRSA = 1; else if (sigAlgo == ECDSAk) haveECC = 1; } if (haveRSA) { if (wolfSSL_use_certificate_file(ssl, svrCertFile, WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS) return 0; if (wolfSSL_use_PrivateKey_file(ssl, svrKeyFile, WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS) return 0; } else if (haveECC) { if (wolfSSL_use_certificate_file(ssl, eccCertFile, WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS) return 0; if (wolfSSL_use_PrivateKey_file(ssl, eccKeyFile, WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS) return 0; } return 1; } static int test_wolfSSL_cert_cb_dyn_ciphers_server_ctx_ready(WOLFSSL_CTX* ctx) { SSL_CTX_set_cert_cb(ctx, test_wolfSSL_cert_cb_dyn_ciphers_certCB, NULL); wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_NONE, NULL); return TEST_SUCCESS; } #endif /* Testing dynamic ciphers offered by client */ static int test_wolfSSL_cert_cb_dyn_ciphers(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) test_ssl_cbf func_cb_client; test_ssl_cbf func_cb_server; struct { method_provider client_meth; const char* client_ciphers; const char* client_sigalgs; const char* client_ca; method_provider server_meth; } test_params[] = { #if !defined(NO_SHA256) && defined(HAVE_AESGCM) #ifdef WOLFSSL_TLS13 #if !defined(NO_RSA) && defined(WC_RSA_PSS) {wolfTLSv1_3_client_method, "TLS13-AES256-GCM-SHA384:TLS13-AES128-GCM-SHA256", "RSA-PSS+SHA256", caCertFile, wolfTLSv1_3_server_method}, #endif #ifdef HAVE_ECC {wolfTLSv1_3_client_method, "TLS13-AES256-GCM-SHA384:TLS13-AES128-GCM-SHA256", "ECDSA+SHA256", caEccCertFile, wolfTLSv1_3_server_method}, #endif #endif #if !defined(WOLFSSL_NO_TLS12) && !defined(WOLFSSL_HARDEN_TLS) #if !defined(NO_RSA) && defined(WC_RSA_PSS) && !defined(NO_DH) {wolfTLSv1_2_client_method, "DHE-RSA-AES128-GCM-SHA256", "RSA-PSS+SHA256", caCertFile, wolfTLSv1_2_server_method}, #endif #ifdef HAVE_ECC {wolfTLSv1_2_client_method, "ECDHE-ECDSA-AES128-GCM-SHA256", "ECDSA+SHA256", caEccCertFile, wolfTLSv1_2_server_method}, #endif #endif #endif }; size_t i; size_t testCount = sizeof(test_params)/sizeof(*test_params); if (testCount > 0) { for (i = 0; i < testCount; i++) { printf("\tTesting %s ciphers with %s sigalgs\n", test_params[i].client_ciphers, test_params[i].client_sigalgs); XMEMSET(&func_cb_client, 0, sizeof(func_cb_client)); XMEMSET(&func_cb_server, 0, sizeof(func_cb_server)); test_wolfSSL_cert_cb_dyn_ciphers_client_cipher = test_params[i].client_ciphers; test_wolfSSL_cert_cb_dyn_ciphers_client_sigalgs = test_params[i].client_sigalgs; func_cb_client.method = test_params[i].client_meth; func_cb_client.caPemFile = test_params[i].client_ca; func_cb_client.ctx_ready = test_wolfSSL_cert_cb_dyn_ciphers_client_ctx_ready; func_cb_server.ctx_ready = test_wolfSSL_cert_cb_dyn_ciphers_server_ctx_ready; func_cb_server.ssl_ready = certClearCb; /* Reuse from prev test */ func_cb_server.method = test_params[i].server_meth; ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&func_cb_client, &func_cb_server, NULL), TEST_SUCCESS); } } #endif return EXPECT_RESULT(); } static int test_wolfSSL_ciphersuite_auth(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) WOLFSSL_CIPHERSUITE_INFO info; (void)info; #ifndef WOLFSSL_NO_TLS12 #ifdef HAVE_CHACHA info = wolfSSL_get_ciphersuite_info(CHACHA_BYTE, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256); ExpectIntEQ(info.rsaAuth, 1); ExpectIntEQ(info.eccAuth, 0); ExpectIntEQ(info.eccStatic, 0); ExpectIntEQ(info.psk, 0); info = wolfSSL_get_ciphersuite_info(CHACHA_BYTE, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256); ExpectIntEQ(info.rsaAuth, 0); ExpectIntEQ(info.eccAuth, 1); ExpectIntEQ(info.eccStatic, 0); ExpectIntEQ(info.psk, 0); info = wolfSSL_get_ciphersuite_info(CHACHA_BYTE, TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256); ExpectIntEQ(info.rsaAuth, 0); ExpectIntEQ(info.eccAuth, 0); ExpectIntEQ(info.eccStatic, 0); ExpectIntEQ(info.psk, 1); #endif #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) #ifndef NO_RSA info = wolfSSL_get_ciphersuite_info(ECC_BYTE, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA); ExpectIntEQ(info.rsaAuth, 1); ExpectIntEQ(info.eccAuth, 0); ExpectIntEQ(info.eccStatic, 0); ExpectIntEQ(info.psk, 0); info = wolfSSL_get_ciphersuite_info(ECC_BYTE, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA); ExpectIntEQ(info.rsaAuth, 1); ExpectIntEQ(info.eccAuth, 0); ExpectIntEQ(info.eccStatic, 1); ExpectIntEQ(info.psk, 0); info = wolfSSL_get_ciphersuite_info(ECC_BYTE, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA); ExpectIntEQ(info.rsaAuth, 1); ExpectIntEQ(info.eccAuth, 0); ExpectIntEQ(info.eccStatic, 1); ExpectIntEQ(info.psk, 0); #endif info = wolfSSL_get_ciphersuite_info(ECC_BYTE, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA); ExpectIntEQ(info.rsaAuth, 0); ExpectIntEQ(info.eccAuth, 1); ExpectIntEQ(info.eccStatic, 0); ExpectIntEQ(info.psk, 0); info = wolfSSL_get_ciphersuite_info(ECC_BYTE, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA); ExpectIntEQ(info.rsaAuth, 0); ExpectIntEQ(info.eccAuth, 1); ExpectIntEQ(info.eccStatic, 1); ExpectIntEQ(info.psk, 0); info = wolfSSL_get_ciphersuite_info(ECDHE_PSK_BYTE, TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256); ExpectIntEQ(info.rsaAuth, 0); ExpectIntEQ(info.eccAuth, 0); ExpectIntEQ(info.eccStatic, 0); ExpectIntEQ(info.psk, 1); #endif #endif #ifdef WOLFSSL_TLS13 info = wolfSSL_get_ciphersuite_info(TLS13_BYTE, TLS_AES_128_GCM_SHA256); ExpectIntEQ(info.rsaAuth, 0); ExpectIntEQ(info.eccAuth, 0); ExpectIntEQ(info.eccStatic, 0); ExpectIntEQ(info.psk, 0); #endif #endif return EXPECT_RESULT(); } static int test_wolfSSL_sigalg_info(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) byte hashSigAlgo[WOLFSSL_MAX_SIGALGO]; word16 len = 0; word16 idx = 0; int allSigAlgs = SIG_ECDSA | SIG_RSA | SIG_SM2 | SIG_FALCON | SIG_DILITHIUM; InitSuitesHashSigAlgo(hashSigAlgo, allSigAlgs, 1, 1, 0xFFFFFFFF, &len); for (idx = 0; idx < len; idx += 2) { int hashAlgo = 0; int sigAlgo = 0; ExpectIntEQ(wolfSSL_get_sigalg_info(hashSigAlgo[idx+0], hashSigAlgo[idx+1], &hashAlgo, &sigAlgo), 0); ExpectIntNE(hashAlgo, 0); ExpectIntNE(sigAlgo, 0); } InitSuitesHashSigAlgo(hashSigAlgo, allSigAlgs | SIG_ANON, 1, 1, 0xFFFFFFFF, &len); for (idx = 0; idx < len; idx += 2) { int hashAlgo = 0; int sigAlgo = 0; ExpectIntEQ(wolfSSL_get_sigalg_info(hashSigAlgo[idx+0], hashSigAlgo[idx+1], &hashAlgo, &sigAlgo), 0); ExpectIntNE(hashAlgo, 0); } #endif return EXPECT_RESULT(); } static int test_wolfSSL_d2i_SSL_SESSION_bounds_check(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && defined(HAVE_EXT_CACHE) && \ defined(SESSION_CERTS) && !defined(NO_SESSION_CACHE) WOLFSSL_SESSION* sess = NULL; WOLFSSL_SESSION* restored = NULL; unsigned char* sessDer = NULL; unsigned char* modData = NULL; const unsigned char* ptr = NULL; unsigned char* pp = NULL; int sz = 0; int idx = 0; int sessionIDSz = 0; int altIDLen = 0; int chainOffset = 0; int newLen = 0; word16 oversized = 0; /* Create and serialize a valid empty session to learn the format */ ExpectNotNull(sess = wolfSSL_SESSION_new()); ExpectIntGT((sz = wolfSSL_i2d_SSL_SESSION(sess, NULL)), 0); ExpectNotNull(sessDer = (unsigned char*)XMALLOC(sz, NULL, DYNAMIC_TYPE_OPENSSL)); pp = sessDer; ExpectIntGT(wolfSSL_i2d_SSL_SESSION(sess, &pp), 0); wolfSSL_SESSION_free(sess); sess = NULL; /* Calculate offset to chain.count field: * side(1) + bornOn(4) + timeout(4) + sessionIDSz(1) + sessionID(var) * + masterSecret(SECRET_LEN=48) + haveEMS(1) + altIDLen(1) + altID(var) */ idx = 1 + 4 + 4; if (EXPECT_SUCCESS()) { sessionIDSz = sessDer[idx++]; idx += sessionIDSz + SECRET_LEN + 1; altIDLen = sessDer[idx++]; if (altIDLen == ID_LEN) idx += ID_LEN; chainOffset = idx; } /* * The deserialization must reject this with a BUFFER_ERROR (return NULL). */ newLen = chainOffset + 1 + 50; ExpectNotNull(modData = (unsigned char*)XMALLOC(newLen, NULL, DYNAMIC_TYPE_TMP_BUFFER)); if (EXPECT_SUCCESS()) { XMEMCPY(modData, sessDer, chainOffset); modData[chainOffset] = MAX_CHAIN_DEPTH + 1; XMEMSET(modData + chainOffset + 1, 0, newLen - chainOffset - 1); } ptr = modData; ExpectNull(restored = wolfSSL_d2i_SSL_SESSION(NULL, &ptr, (long)newLen)); XFREE(modData, NULL, DYNAMIC_TYPE_TMP_BUFFER); modData = NULL; /* * chain.count is valid (1), but the cert length field is too large. */ newLen = chainOffset + 1 + 2 + 100; ExpectNotNull(modData = (unsigned char*)XMALLOC(newLen, NULL, DYNAMIC_TYPE_TMP_BUFFER)); if (EXPECT_SUCCESS()) { XMEMCPY(modData, sessDer, chainOffset); idx = chainOffset; modData[idx++] = 1; /* chain.count = 1 */ oversized = MAX_X509_SIZE + 1; modData[idx++] = (byte)(oversized >> 8); modData[idx++] = (byte)(oversized & 0xFF); XMEMSET(modData + idx, 0xCC, newLen - idx); } ptr = modData; ExpectNull(restored = wolfSSL_d2i_SSL_SESSION(NULL, &ptr, (long)newLen)); XFREE(modData, NULL, DYNAMIC_TYPE_TMP_BUFFER); modData = NULL; XFREE(sessDer, NULL, DYNAMIC_TYPE_OPENSSL); #endif return EXPECT_RESULT(); } static int test_wolfSSL_SESSION(void) { EXPECT_DECLS; #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && \ !defined(NO_RSA) && !defined(NO_SHA256) && \ defined(HAVE_IO_TESTS_DEPENDENCIES) && !defined(NO_SESSION_CACHE) WOLFSSL* ssl = NULL; WOLFSSL_CTX* ctx = NULL; WOLFSSL_SESSION* sess = NULL; WOLFSSL_SESSION* sess_copy = NULL; #ifdef OPENSSL_EXTRA #ifdef HAVE_EXT_CACHE unsigned char* sessDer = NULL; unsigned char* ptr = NULL; int sz = 0; #endif const unsigned char context[] = "user app context"; unsigned int contextSz = (unsigned int)sizeof(context); #endif int ret = 0, err = 0; SOCKET_T sockfd; tcp_ready ready; func_args server_args; THREAD_TYPE serverThread; char msg[80]; const char* sendGET = "GET"; /* TLS v1.3 requires session tickets */ /* CHACHA and POLY1305 required for myTicketEncCb */ #if !defined(WOLFSSL_NO_TLS12) && (!defined(WOLFSSL_TLS13) || \ !(defined(HAVE_SESSION_TICKET) && ((defined(HAVE_CHACHA) && \ defined(HAVE_POLY1305)) || defined(HAVE_AESGCM)))) ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method())); #else ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); #endif ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx, cliCertFile, CERT_FILETYPE)); ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, cliKeyFile, CERT_FILETYPE)); ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0), WOLFSSL_SUCCESS); #ifdef WOLFSSL_ENCRYPTED_KEYS wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); #endif #ifdef HAVE_SESSION_TICKET /* Use session tickets, for ticket tests below */ ExpectIntEQ(wolfSSL_CTX_UseSessionTicket(ctx), WOLFSSL_SUCCESS); #endif XMEMSET(&server_args, 0, sizeof(func_args)); #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); #endif StartTCP(); InitTcpReady(&ready); server_args.signal = &ready; start_thread(test_server_nofail, &server_args, &serverThread); wait_tcp_ready(&server_args); /* client connection */ ExpectNotNull(ssl = wolfSSL_new(ctx)); tcp_connect(&sockfd, wolfSSLIP, ready.port, 0, 0, ssl); ExpectIntEQ(wolfSSL_set_fd(ssl, sockfd), WOLFSSL_SUCCESS); WOLFSSL_ASYNC_WHILE_PENDING(ret = wolfSSL_connect(ssl), ret != WOLFSSL_SUCCESS); ExpectIntEQ(ret, WOLFSSL_SUCCESS); WOLFSSL_ASYNC_WHILE_PENDING( ret = wolfSSL_write(ssl, sendGET, (int)XSTRLEN(sendGET)), ret <= 0); ExpectIntEQ(ret, (int)XSTRLEN(sendGET)); WOLFSSL_ASYNC_WHILE_PENDING(ret = wolfSSL_read(ssl, msg, sizeof(msg)), ret != 23); ExpectIntEQ(ret, 23); ExpectPtrNE((sess = wolfSSL_get1_session(ssl)), NULL); /* ref count 1 */ ExpectPtrNE((sess_copy = wolfSSL_get1_session(ssl)), NULL); /* ref count 2 */ ExpectIntEQ(wolfSSL_SessionIsSetup(sess), 1); #ifdef HAVE_EXT_CACHE ExpectPtrEq(sess, sess_copy); /* they should be the same pointer but without * HAVE_EXT_CACHE we get new objects each time */ #endif wolfSSL_SESSION_free(sess_copy); sess_copy = NULL; wolfSSL_SESSION_free(sess); sess = NULL; /* free session ref */ sess = wolfSSL_get_session(ssl); #ifdef OPENSSL_EXTRA ExpectIntEQ(SSL_SESSION_is_resumable(NULL), 0); ExpectIntEQ(SSL_SESSION_is_resumable(sess), 1); ExpectIntEQ(wolfSSL_SESSION_has_ticket(NULL), 0); ExpectIntEQ(wolfSSL_SESSION_get_ticket_lifetime_hint(NULL), 0); #ifdef HAVE_SESSION_TICKET ExpectIntEQ(wolfSSL_SESSION_has_ticket(sess), 1); ExpectIntEQ(wolfSSL_SESSION_get_ticket_lifetime_hint(sess), SESSION_TICKET_HINT_DEFAULT); #else ExpectIntEQ(wolfSSL_SESSION_has_ticket(sess), 0); #endif #else (void)sess; #endif /* OPENSSL_EXTRA */ /* Retain copy of the session for later testing */ ExpectNotNull(sess = wolfSSL_get1_session(ssl)); wolfSSL_shutdown(ssl); wolfSSL_free(ssl); ssl = NULL; CloseSocket(sockfd); join_thread(serverThread); FreeTcpReady(&ready); #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); #endif #if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) { X509 *x509 = NULL; char buf[30]; int bufSz = 0; ExpectNotNull(x509 = SSL_SESSION_get0_peer(sess)); ExpectIntGT((bufSz = X509_NAME_get_text_by_NID( X509_get_subject_name(x509), NID_organizationalUnitName, buf, sizeof(buf))), 0); ExpectIntNE((bufSz == 7 || bufSz == 16), 0); /* should be one of these*/ if (bufSz == 7) { ExpectIntEQ(XMEMCMP(buf, "Support", bufSz), 0); } if (bufSz == 16) { ExpectIntEQ(XMEMCMP(buf, "Programming-2048", bufSz), 0); } } #endif #ifdef HAVE_EXT_CACHE ExpectNotNull(sess_copy = wolfSSL_SESSION_dup(sess)); wolfSSL_SESSION_free(sess_copy); sess_copy = NULL; sess_copy = NULL; #endif #if defined(OPENSSL_EXTRA) && defined(HAVE_EXT_CACHE) /* get session from DER and update the timeout */ ExpectIntEQ(wolfSSL_i2d_SSL_SESSION(NULL, &sessDer), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntGT((sz = wolfSSL_i2d_SSL_SESSION(sess, &sessDer)), 0); wolfSSL_SESSION_free(sess); sess = NULL; sess = NULL; ptr = sessDer; ExpectNull(sess = wolfSSL_d2i_SSL_SESSION(NULL, NULL, sz)); ExpectNotNull(sess = wolfSSL_d2i_SSL_SESSION(NULL, (const unsigned char**)&ptr, sz)); XFREE(sessDer, NULL, DYNAMIC_TYPE_OPENSSL); sessDer = NULL; ExpectIntGT(wolfSSL_SESSION_get_time(sess), 0); ExpectIntEQ(wolfSSL_SSL_SESSION_set_timeout(sess, 500), SSL_SUCCESS); #endif /* successful set session test */ ExpectNotNull(ssl = wolfSSL_new(ctx)); ExpectIntEQ(wolfSSL_set_session(ssl, sess), WOLFSSL_SUCCESS); #ifdef HAVE_SESSION_TICKET /* Test set/get session ticket */ { const char* ticket = "This is a session ticket"; char buf[64] = {0}; word32 bufSz = (word32)sizeof(buf); word32 retSz = 0; ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_set_SessionTicket(ssl, (byte *)ticket, (word32)XSTRLEN(ticket))); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_get_SessionTicket(ssl, (byte *)buf, &bufSz)); ExpectStrEQ(ticket, buf); /* return ticket length if buffer parameter is null */ wolfSSL_get_SessionTicket(ssl, NULL, &retSz); ExpectIntEQ(bufSz, retSz); } #endif #ifdef OPENSSL_EXTRA /* session timeout case */ /* make the session to be expired */ ExpectIntEQ(SSL_SESSION_set_timeout(sess,1), SSL_SUCCESS); XSLEEP_MS(1200); /* SSL_set_session should reject specified session but return success * if WOLFSSL_ERROR_CODE_OPENSSL macro is defined for OpenSSL compatibility. */ #if defined(WOLFSSL_ERROR_CODE_OPENSSL) ExpectIntEQ(wolfSSL_set_session(ssl,sess), SSL_SUCCESS); #else ExpectIntEQ(wolfSSL_set_session(ssl,sess), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); #endif ExpectIntEQ(wolfSSL_SSL_SESSION_set_timeout(sess, 500), SSL_SUCCESS); #ifdef WOLFSSL_SESSION_ID_CTX /* fail case with miss match session context IDs (use compatibility API) */ ExpectIntEQ(SSL_set_session_id_context(ssl, context, contextSz), SSL_SUCCESS); ExpectIntEQ(wolfSSL_set_session(ssl, sess), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); wolfSSL_free(ssl); ssl = NULL; ExpectIntEQ(SSL_CTX_set_session_id_context(NULL, context, contextSz), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(SSL_CTX_set_session_id_context(ctx, context, contextSz), SSL_SUCCESS); ExpectNotNull(ssl = wolfSSL_new(ctx)); ExpectIntEQ(wolfSSL_set_session(ssl, sess), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); #endif #endif /* OPENSSL_EXTRA */ wolfSSL_free(ssl); wolfSSL_SESSION_free(sess); wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && \ !defined(NO_RSA) && defined(HAVE_IO_TESTS_DEPENDENCIES) && \ !defined(NO_SESSION_CACHE) && defined(OPENSSL_EXTRA) && \ !defined(WOLFSSL_NO_TLS12) static WOLFSSL_SESSION* test_wolfSSL_SESSION_expire_sess = NULL; static void test_wolfSSL_SESSION_expire_downgrade_ctx_ready(WOLFSSL_CTX* ctx) { #ifdef WOLFSSL_ERROR_CODE_OPENSSL /* returns previous timeout value */ AssertIntEQ(wolfSSL_CTX_set_timeout(ctx, 1), 500); #else AssertIntEQ(wolfSSL_CTX_set_timeout(ctx, 1), WOLFSSL_SUCCESS); #endif } /* set the session to timeout in a second */ static void test_wolfSSL_SESSION_expire_downgrade_ssl_ready(WOLFSSL* ssl) { AssertIntEQ(wolfSSL_set_timeout(ssl, 2), 1); } /* store the client side session from the first successful connection */ static void test_wolfSSL_SESSION_expire_downgrade_ssl_result(WOLFSSL* ssl) { AssertPtrNE((test_wolfSSL_SESSION_expire_sess = wolfSSL_get1_session(ssl)), NULL); /* ref count 1 */ } /* wait till session is expired then set it in the WOLFSSL struct for use */ static void test_wolfSSL_SESSION_expire_downgrade_ssl_ready_wait(WOLFSSL* ssl) { AssertIntEQ(wolfSSL_set_timeout(ssl, 1), 1); AssertIntEQ(wolfSSL_set_session(ssl, test_wolfSSL_SESSION_expire_sess), WOLFSSL_SUCCESS); XSLEEP_MS(2000); /* wait 2 seconds for session to expire */ } /* set expired session in the WOLFSSL struct for use */ static void test_wolfSSL_SESSION_expire_downgrade_ssl_ready_set(WOLFSSL* ssl) { XSLEEP_MS(1200); /* wait a second for session to expire */ /* set the expired session, call to set session fails but continuing on after failure should be handled here */ #if defined(OPENSSL_EXTRA) && defined(WOLFSSL_ERROR_CODE_OPENSSL) AssertIntEQ(wolfSSL_set_session(ssl, test_wolfSSL_SESSION_expire_sess), WOLFSSL_SUCCESS); #else AssertIntNE(wolfSSL_set_session(ssl, test_wolfSSL_SESSION_expire_sess), WOLFSSL_SUCCESS); #endif } /* check that the expired session was not reused */ static void test_wolfSSL_SESSION_expire_downgrade_ssl_result_reuse(WOLFSSL* ssl) { /* since the session has expired it should not have been reused */ AssertIntEQ(wolfSSL_session_reused(ssl), 0); } #endif static int test_wolfSSL_SESSION_expire_downgrade(void) { EXPECT_DECLS; #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && \ !defined(NO_RSA) && defined(HAVE_IO_TESTS_DEPENDENCIES) && \ !defined(NO_SESSION_CACHE) && defined(OPENSSL_EXTRA) && \ !defined(WOLFSSL_NO_TLS12) callback_functions server_cbf, client_cbf; XMEMSET(&server_cbf, 0, sizeof(callback_functions)); XMEMSET(&client_cbf, 0, sizeof(callback_functions)); /* force server side to use TLS 1.2 */ server_cbf.method = wolfTLSv1_2_server_method; client_cbf.method = wolfSSLv23_client_method; server_cbf.ctx_ready = test_wolfSSL_SESSION_expire_downgrade_ctx_ready; client_cbf.ssl_ready = test_wolfSSL_SESSION_expire_downgrade_ssl_ready; client_cbf.on_result = test_wolfSSL_SESSION_expire_downgrade_ssl_result; test_wolfSSL_client_server_nofail(&client_cbf, &server_cbf); ExpectIntEQ(client_cbf.return_code, TEST_SUCCESS); ExpectIntEQ(server_cbf.return_code, TEST_SUCCESS); client_cbf.method = wolfSSLv23_client_method; server_cbf.ctx_ready = test_wolfSSL_SESSION_expire_downgrade_ctx_ready; client_cbf.ssl_ready = test_wolfSSL_SESSION_expire_downgrade_ssl_ready_wait; client_cbf.on_result = test_wolfSSL_SESSION_expire_downgrade_ssl_result_reuse; test_wolfSSL_client_server_nofail(&client_cbf, &server_cbf); ExpectIntEQ(client_cbf.return_code, TEST_SUCCESS); ExpectIntEQ(server_cbf.return_code, TEST_SUCCESS); client_cbf.method = wolfSSLv23_client_method; server_cbf.ctx_ready = test_wolfSSL_SESSION_expire_downgrade_ctx_ready; client_cbf.ssl_ready = test_wolfSSL_SESSION_expire_downgrade_ssl_ready_set; client_cbf.on_result = test_wolfSSL_SESSION_expire_downgrade_ssl_result_reuse; test_wolfSSL_client_server_nofail(&client_cbf, &server_cbf); ExpectIntEQ(client_cbf.return_code, TEST_SUCCESS); ExpectIntEQ(server_cbf.return_code, TEST_SUCCESS); wolfSSL_SESSION_free(test_wolfSSL_SESSION_expire_sess); #endif return EXPECT_RESULT(); } #if defined(OPENSSL_EXTRA) && defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && \ defined(HAVE_EX_DATA) && !defined(NO_SESSION_CACHE) #ifdef WOLFSSL_ATOMIC_OPS typedef wolfSSL_Atomic_Int SessRemCounter_t; #else typedef int SessRemCounter_t; #endif static SessRemCounter_t clientSessRemCountMalloc; static SessRemCounter_t serverSessRemCountMalloc; static SessRemCounter_t clientSessRemCountFree; static SessRemCounter_t serverSessRemCountFree; static WOLFSSL_CTX* serverSessCtx = NULL; static WOLFSSL_SESSION* serverSess = NULL; #if (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) || \ !defined(NO_SESSION_CACHE_REF) static WOLFSSL_CTX* clientSessCtx = NULL; static WOLFSSL_SESSION* clientSess = NULL; #endif static int serverSessRemIdx = 3; static int sessRemCtx_Server = WOLFSSL_SERVER_END; static int sessRemCtx_Client = WOLFSSL_CLIENT_END; static void SessRemCtxCb(WOLFSSL_CTX *ctx, WOLFSSL_SESSION *sess) { int* side; (void)ctx; side = (int*)SSL_SESSION_get_ex_data(sess, serverSessRemIdx); if (side != NULL) { if (*side == WOLFSSL_CLIENT_END) (void)wolfSSL_Atomic_Int_FetchAdd(&clientSessRemCountFree, 1); else (void)wolfSSL_Atomic_Int_FetchAdd(&serverSessRemCountFree, 1); SSL_SESSION_set_ex_data(sess, serverSessRemIdx, NULL); } } static int SessRemCtxSetupCb(WOLFSSL_CTX* ctx) { SSL_CTX_sess_set_remove_cb(ctx, SessRemCtxCb); #if defined(WOLFSSL_TLS13) && !defined(HAVE_SESSION_TICKET) && \ !defined(NO_SESSION_CACHE_REF) { EXPECT_DECLS; /* Allow downgrade, set min version, and disable TLS 1.3. * Do this because without NO_SESSION_CACHE_REF we will want to return a * reference to the session cache. But with WOLFSSL_TLS13 and without * HAVE_SESSION_TICKET we won't have a session ID to be able to place * the session in the cache. In this case we need to downgrade to * previous versions to just use the legacy session ID field. */ ExpectIntEQ(SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION), SSL_SUCCESS); ExpectIntEQ(SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION), SSL_SUCCESS); return EXPECT_RESULT(); } #else return TEST_SUCCESS; #endif } static int SessRemSslSetupCb(WOLFSSL* ssl) { EXPECT_DECLS; int* side; if (SSL_is_server(ssl)) { side = &sessRemCtx_Server; (void)wolfSSL_Atomic_Int_FetchAdd(&serverSessRemCountMalloc, 1); ExpectNotNull(serverSess = SSL_get1_session(ssl)); ExpectIntEQ(SSL_CTX_up_ref(serverSessCtx = SSL_get_SSL_CTX(ssl)), SSL_SUCCESS); } else { side = &sessRemCtx_Client; (void)wolfSSL_Atomic_Int_FetchAdd(&clientSessRemCountMalloc, 1); #if (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) || \ !defined(NO_SESSION_CACHE_REF) ExpectNotNull(clientSess = SSL_get1_session(ssl)); ExpectIntEQ(SSL_CTX_up_ref(clientSessCtx = SSL_get_SSL_CTX(ssl)), SSL_SUCCESS); #endif } ExpectIntEQ(SSL_SESSION_set_ex_data(SSL_get_session(ssl), serverSessRemIdx, side), SSL_SUCCESS); return EXPECT_RESULT(); } #endif static int test_wolfSSL_CTX_sess_set_remove_cb(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && \ defined(HAVE_EX_DATA) && !defined(NO_SESSION_CACHE) /* Check that the remove callback gets called for external data in a * session object */ test_ssl_cbf func_cb; wolfSSL_Atomic_Int_Init(&clientSessRemCountMalloc, 0); wolfSSL_Atomic_Int_Init(&serverSessRemCountMalloc, 0); wolfSSL_Atomic_Int_Init(&clientSessRemCountFree, 0); wolfSSL_Atomic_Int_Init(&serverSessRemCountFree, 0); XMEMSET(&func_cb, 0, sizeof(func_cb)); func_cb.ctx_ready = SessRemCtxSetupCb; func_cb.on_result = SessRemSslSetupCb; ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&func_cb, &func_cb, NULL), TEST_SUCCESS); /* Both should have been allocated */ ExpectIntEQ(clientSessRemCountMalloc, 1); ExpectIntEQ(serverSessRemCountMalloc, 1); /* This should not be called yet. Session wasn't evicted from cache yet. */ ExpectIntEQ(clientSessRemCountFree, 0); #if (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) || \ !defined(NO_SESSION_CACHE_REF) /* Force a cache lookup */ ExpectNotNull(SSL_SESSION_get_ex_data(clientSess, serverSessRemIdx)); /* Force a cache update */ ExpectNotNull(SSL_SESSION_set_ex_data(clientSess, serverSessRemIdx - 1, 0)); /* This should set the timeout to 0 and call the remove callback from within * the session cache. Returns 1 per OpenSSL semantics (session was * present in the cache and removed). */ ExpectIntEQ(SSL_CTX_remove_session(clientSessCtx, clientSess), 1); ExpectNull(SSL_SESSION_get_ex_data(clientSess, serverSessRemIdx)); ExpectIntEQ(clientSessRemCountFree, 1); #endif /* Server session is in the cache so ex_data isn't free'd with the SSL * object */ ExpectIntEQ(serverSessRemCountFree, 0); /* Force a cache lookup */ ExpectNotNull(SSL_SESSION_get_ex_data(serverSess, serverSessRemIdx)); /* Force a cache update */ ExpectNotNull(SSL_SESSION_set_ex_data(serverSess, serverSessRemIdx - 1, 0)); /* This should set the timeout to 0 and call the remove callback from within * the session cache. Returns 1 per OpenSSL semantics (session was * present in the cache and removed). */ ExpectIntEQ(SSL_CTX_remove_session(serverSessCtx, serverSess), 1); ExpectNull(SSL_SESSION_get_ex_data(serverSess, serverSessRemIdx)); ExpectIntEQ(serverSessRemCountFree, 1); /* Need to free the references that we kept */ SSL_CTX_free(serverSessCtx); SSL_SESSION_free(serverSess); #if (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) || \ !defined(NO_SESSION_CACHE_REF) SSL_CTX_free(clientSessCtx); SSL_SESSION_free(clientSess); #endif #endif return EXPECT_RESULT(); } static int test_wolfSSL_ticket_keys(void) { EXPECT_DECLS; #if defined(HAVE_SESSION_TICKET) && !defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) && \ !defined(NO_WOLFSSL_SERVER) && !defined(NO_TLS) WOLFSSL_CTX* ctx = NULL; byte keys[WOLFSSL_TICKET_KEYS_SZ]; ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); ExpectIntEQ(wolfSSL_CTX_get_tlsext_ticket_keys(NULL, NULL, 0), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_CTX_get_tlsext_ticket_keys(ctx, NULL, 0), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_CTX_get_tlsext_ticket_keys(ctx, keys, 0), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_CTX_get_tlsext_ticket_keys(NULL, keys, 0), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_CTX_get_tlsext_ticket_keys(NULL, NULL, sizeof(keys)), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_CTX_get_tlsext_ticket_keys(ctx, NULL, sizeof(keys)), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_CTX_get_tlsext_ticket_keys(NULL, keys, sizeof(keys)), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_CTX_set_tlsext_ticket_keys(NULL, NULL, 0), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_CTX_set_tlsext_ticket_keys(ctx, NULL, 0), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_CTX_set_tlsext_ticket_keys(ctx, keys, 0), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_CTX_set_tlsext_ticket_keys(NULL, keys, 0), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_CTX_set_tlsext_ticket_keys(NULL, NULL, sizeof(keys)), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_CTX_set_tlsext_ticket_keys(ctx, NULL, sizeof(keys)), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_CTX_set_tlsext_ticket_keys(NULL, keys, sizeof(keys)), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_CTX_get_tlsext_ticket_keys(ctx, keys, sizeof(keys)), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_set_tlsext_ticket_keys(ctx, keys, sizeof(keys)), WOLFSSL_SUCCESS); wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } #ifndef NO_BIO #if defined(OPENSSL_EXTRA) && defined(HAVE_DILITHIUM) /* Verify wc_dilithium auto detects the expected ML-DSA level from the OID * in a SPKI / PKCS#8 DER buffer. Returns 0 on match. */ static int check_dilithium_der_level(const byte* der, word32 derSz, byte expectedLevel, int isPrivate) { dilithium_key key; word32 idx = 0; byte level = 0; int rc; #ifndef WOLFSSL_DILITHIUM_PRIVATE_KEY (void)isPrivate; #endif if ((rc = wc_dilithium_init(&key)) != 0) { return rc; } #if defined(WOLFSSL_DILITHIUM_PRIVATE_KEY) if (isPrivate) { rc = wc_Dilithium_PrivateKeyDecode(der, &idx, &key, derSz); } else #endif { rc = wc_Dilithium_PublicKeyDecode(der, &idx, &key, derSz); } if (rc == 0) { rc = wc_dilithium_get_level(&key, &level); } if (rc == 0 && level != expectedLevel) { rc = -1; } wc_dilithium_free(&key); return rc; } #endif /* OPENSSL_EXTRA && HAVE_DILITHIUM */ static int test_wolfSSL_d2i_PUBKEY(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) BIO* bio = NULL; EVP_PKEY* pkey = NULL; ExpectNotNull(bio = BIO_new(BIO_s_mem())); ExpectNull(d2i_PUBKEY_bio(NULL, NULL)); #if defined(USE_CERT_BUFFERS_2048) && !defined(NO_RSA) /* RSA PUBKEY test */ ExpectIntGT(BIO_write(bio, client_keypub_der_2048, sizeof_client_keypub_der_2048), 0); ExpectNotNull(pkey = d2i_PUBKEY_bio(bio, NULL)); EVP_PKEY_free(pkey); pkey = NULL; #endif #if defined(USE_CERT_BUFFERS_256) && defined(HAVE_ECC) /* ECC PUBKEY test */ ExpectIntGT(BIO_write(bio, ecc_clikeypub_der_256, sizeof_ecc_clikeypub_der_256), 0); ExpectNotNull(pkey = d2i_PUBKEY_bio(bio, NULL)); EVP_PKEY_free(pkey); pkey = NULL; #endif #if defined(USE_CERT_BUFFERS_2048) && !defined(NO_DSA) /* DSA PUBKEY test */ ExpectIntGT(BIO_write(bio, dsa_pub_key_der_2048, sizeof_dsa_pub_key_der_2048), 0); ExpectNotNull(pkey = d2i_PUBKEY_bio(bio, NULL)); EVP_PKEY_free(pkey); pkey = NULL; #endif #if defined(USE_CERT_BUFFERS_2048) && !defined(NO_DH) && \ defined(OPENSSL_EXTRA) && defined(WOLFSSL_DH_EXTRA) #if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \ (HAVE_FIPS_VERSION > 2)) /* DH PUBKEY test */ ExpectIntGT(BIO_write(bio, dh_pub_key_der_2048, sizeof_dh_pub_key_der_2048), 0); ExpectNotNull(pkey = d2i_PUBKEY_bio(bio, NULL)); EVP_PKEY_free(pkey); pkey = NULL; #endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ #endif /* USE_CERT_BUFFERS_2048 && !NO_DH && && OPENSSL_EXTRA */ #if defined(HAVE_DILITHIUM) && !defined(WOLFSSL_DILITHIUM_NO_VERIFY) #if !defined(WOLFSSL_NO_ML_DSA_44) /* ML-DSA-44 PUBKEY test (raw key bytes) */ ExpectIntGT(BIO_write(bio, bench_dilithium_level2_pubkey, sizeof_bench_dilithium_level2_pubkey), 0); ExpectNotNull(pkey = d2i_PUBKEY_bio(bio, NULL)); ExpectIntEQ(EVP_PKEY_id(pkey), EVP_PKEY_DILITHIUM); EVP_PKEY_free(pkey); pkey = NULL; /* ML-DSA-44 PUBKEY test (LAMPS SubjectPublicKeyInfo DER) */ ExpectIntGT(BIO_write(bio, mldsa44_pub_spki, sizeof_mldsa44_pub_spki), 0); ExpectNotNull(pkey = d2i_PUBKEY_bio(bio, NULL)); ExpectIntEQ(EVP_PKEY_id(pkey), EVP_PKEY_DILITHIUM); ExpectIntEQ(check_dilithium_der_level(mldsa44_pub_spki, sizeof_mldsa44_pub_spki, WC_ML_DSA_44, 0), 0); EVP_PKEY_free(pkey); pkey = NULL; #endif #if !defined(WOLFSSL_NO_ML_DSA_65) /* ML-DSA-65 PUBKEY test (raw key bytes) */ ExpectIntGT(BIO_write(bio, bench_dilithium_level3_pubkey, sizeof_bench_dilithium_level3_pubkey), 0); ExpectNotNull(pkey = d2i_PUBKEY_bio(bio, NULL)); ExpectIntEQ(EVP_PKEY_id(pkey), EVP_PKEY_DILITHIUM); EVP_PKEY_free(pkey); pkey = NULL; /* ML-DSA-65 PUBKEY test (LAMPS SubjectPublicKeyInfo DER) */ ExpectIntGT(BIO_write(bio, mldsa65_pub_spki, sizeof_mldsa65_pub_spki), 0); ExpectNotNull(pkey = d2i_PUBKEY_bio(bio, NULL)); ExpectIntEQ(EVP_PKEY_id(pkey), EVP_PKEY_DILITHIUM); ExpectIntEQ(check_dilithium_der_level(mldsa65_pub_spki, sizeof_mldsa65_pub_spki, WC_ML_DSA_65, 0), 0); EVP_PKEY_free(pkey); pkey = NULL; #endif #if !defined(WOLFSSL_NO_ML_DSA_87) /* ML-DSA-87 PUBKEY test (raw key bytes) */ ExpectIntGT(BIO_write(bio, bench_dilithium_level5_pubkey, sizeof_bench_dilithium_level5_pubkey), 0); ExpectNotNull(pkey = d2i_PUBKEY_bio(bio, NULL)); ExpectIntEQ(EVP_PKEY_id(pkey), EVP_PKEY_DILITHIUM); EVP_PKEY_free(pkey); pkey = NULL; /* ML-DSA-87 PUBKEY test (LAMPS SubjectPublicKeyInfo DER) */ ExpectIntGT(BIO_write(bio, mldsa87_pub_spki, sizeof_mldsa87_pub_spki), 0); ExpectNotNull(pkey = d2i_PUBKEY_bio(bio, NULL)); ExpectIntEQ(EVP_PKEY_id(pkey), EVP_PKEY_DILITHIUM); ExpectIntEQ(check_dilithium_der_level(mldsa87_pub_spki, sizeof_mldsa87_pub_spki, WC_ML_DSA_87, 0), 0); EVP_PKEY_free(pkey); pkey = NULL; #endif #endif /* HAVE_DILITHIUM && !NO_VERIFY */ /* Negative test, invalid input must return NULL */ { BIO* nbio = NULL; unsigned char garbage[64]; XMEMSET(garbage, 0xA5, sizeof(garbage)); ExpectNotNull(nbio = BIO_new(BIO_s_mem())); ExpectIntGT(BIO_write(nbio, garbage, (int)sizeof(garbage)), 0); ExpectNull(d2i_PUBKEY_bio(nbio, NULL)); BIO_free(nbio); } /* Negative test: unrecognized input with a pre-allocated *out must * return NULL, not the caller pre-existing key. */ { unsigned char garbage[64]; const unsigned char* p = garbage; EVP_PKEY* preAlloc = NULL; EVP_PKEY* result; XMEMSET(garbage, 0xA5, sizeof(garbage)); ExpectNotNull(preAlloc = EVP_PKEY_new()); result = preAlloc; ExpectNull(d2i_PUBKEY(&result, &p, (long)sizeof(garbage))); EVP_PKEY_free(preAlloc); } BIO_free(bio); (void)pkey; #endif return EXPECT_RESULT(); } #if (defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO)) && !defined(NO_RSA) && \ !defined(NO_TLS) static int test_wolfSSL_d2i_PrivateKeys_bio(void) { EXPECT_DECLS; BIO* bio = NULL; EVP_PKEY* pkey = NULL; WOLFSSL_CTX* ctx = NULL; #if defined(WOLFSSL_KEY_GEN) unsigned char buff[4096]; unsigned char* bufPtr = buff; #endif /* test creating new EVP_PKEY with bad arg */ ExpectNull((pkey = d2i_PrivateKey_bio(NULL, NULL))); /* test loading RSA key using BIO */ #if !defined(NO_RSA) && !defined(NO_FILESYSTEM) { XFILE file = XBADFILE; const char* fname = "./certs/server-key.der"; long lsz = 0; size_t sz = 0; byte* buf = NULL; ExpectTrue((file = XFOPEN(fname, "rb")) != XBADFILE); ExpectTrue(XFSEEK(file, 0, XSEEK_END) == 0); ExpectTrue((lsz = XFTELL(file)) > 0); sz = (size_t)lsz; ExpectTrue(XFSEEK(file, 0, XSEEK_SET) == 0); ExpectNotNull(buf = (byte*)XMALLOC(sz, HEAP_HINT, DYNAMIC_TYPE_FILE)); ExpectIntEQ(XFREAD(buf, 1, sz, file), sz); if (file != XBADFILE) { XFCLOSE(file); } /* Test using BIO new mem and loading DER private key */ ExpectNotNull(bio = BIO_new_mem_buf(buf, (int)sz)); ExpectNotNull((pkey = d2i_PrivateKey_bio(bio, NULL))); XFREE(buf, HEAP_HINT, DYNAMIC_TYPE_FILE); BIO_free(bio); bio = NULL; EVP_PKEY_free(pkey); pkey = NULL; } #endif /* test loading ECC key using BIO */ #if defined(HAVE_ECC) && !defined(NO_FILESYSTEM) { XFILE file = XBADFILE; const char* fname = "./certs/ecc-key.der"; long lsz = 0; size_t sz = 0; byte* buf = NULL; ExpectTrue((file = XFOPEN(fname, "rb")) != XBADFILE); ExpectTrue(XFSEEK(file, 0, XSEEK_END) == 0); ExpectTrue((lsz = XFTELL(file)) > 0); sz = (size_t)lsz; ExpectTrue(XFSEEK(file, 0, XSEEK_SET) == 0); ExpectNotNull(buf = (byte*)XMALLOC(sz, HEAP_HINT, DYNAMIC_TYPE_FILE)); ExpectIntEQ(XFREAD(buf, 1, sz, file), sz); if (file != XBADFILE) XFCLOSE(file); /* Test using BIO new mem and loading DER private key */ ExpectNotNull(bio = BIO_new_mem_buf(buf, (int)sz)); ExpectNotNull((pkey = d2i_PrivateKey_bio(bio, NULL))); XFREE(buf, HEAP_HINT, DYNAMIC_TYPE_FILE); BIO_free(bio); bio = NULL; EVP_PKEY_free(pkey); pkey = NULL; } #endif #if defined(HAVE_DILITHIUM) && !defined(WOLFSSL_DILITHIUM_NO_SIGN) #if !defined(WOLFSSL_NO_ML_DSA_44) /* ML-DSA-44 PrivateKey test (raw bytes) */ ExpectNotNull(bio = BIO_new(BIO_s_mem())); ExpectIntGT(BIO_write(bio, bench_dilithium_level2_key, sizeof_bench_dilithium_level2_key), 0); ExpectNotNull(pkey = d2i_PrivateKey_bio(bio, NULL)); ExpectIntEQ(EVP_PKEY_id(pkey), EVP_PKEY_DILITHIUM); EVP_PKEY_free(pkey); pkey = NULL; BIO_free(bio); bio = NULL; /* ML-DSA-44 PrivateKey test (LAMPS PKCS#8 priv-only DER) */ ExpectNotNull(bio = BIO_new(BIO_s_mem())); ExpectIntGT(BIO_write(bio, mldsa44_priv_only, sizeof_mldsa44_priv_only), 0); ExpectNotNull(pkey = d2i_PrivateKey_bio(bio, NULL)); ExpectIntEQ(EVP_PKEY_id(pkey), EVP_PKEY_DILITHIUM); ExpectIntEQ(check_dilithium_der_level(mldsa44_priv_only, sizeof_mldsa44_priv_only, WC_ML_DSA_44, 1), 0); EVP_PKEY_free(pkey); pkey = NULL; BIO_free(bio); bio = NULL; /* ML-DSA-44 PrivateKey test (LAMPS PKCS#8 seed-priv DER) */ ExpectNotNull(bio = BIO_new(BIO_s_mem())); ExpectIntGT(BIO_write(bio, mldsa44_seed_priv, sizeof_mldsa44_seed_priv), 0); ExpectNotNull(pkey = d2i_PrivateKey_bio(bio, NULL)); ExpectIntEQ(EVP_PKEY_id(pkey), EVP_PKEY_DILITHIUM); EVP_PKEY_free(pkey); pkey = NULL; BIO_free(bio); bio = NULL; #ifndef WOLFSSL_DILITHIUM_NO_MAKE_KEY /* ML-DSA-44 PrivateKey test (LAMPS PKCS#8 seed-only DER) -- * requires wc_dilithium_make_key_from_seed to expand the seed. */ ExpectNotNull(bio = BIO_new(BIO_s_mem())); ExpectIntGT(BIO_write(bio, mldsa44_seed_only, sizeof_mldsa44_seed_only), 0); ExpectNotNull(pkey = d2i_PrivateKey_bio(bio, NULL)); ExpectIntEQ(EVP_PKEY_id(pkey), EVP_PKEY_DILITHIUM); EVP_PKEY_free(pkey); pkey = NULL; BIO_free(bio); bio = NULL; #endif #endif #if !defined(WOLFSSL_NO_ML_DSA_65) /* ML-DSA-65 PrivateKey test (raw bytes) */ ExpectNotNull(bio = BIO_new(BIO_s_mem())); ExpectIntGT(BIO_write(bio, bench_dilithium_level3_key, sizeof_bench_dilithium_level3_key), 0); ExpectNotNull(pkey = d2i_PrivateKey_bio(bio, NULL)); ExpectIntEQ(EVP_PKEY_id(pkey), EVP_PKEY_DILITHIUM); EVP_PKEY_free(pkey); pkey = NULL; BIO_free(bio); bio = NULL; /* ML-DSA-65 PrivateKey test (LAMPS PKCS#8 priv-only DER) */ ExpectNotNull(bio = BIO_new(BIO_s_mem())); ExpectIntGT(BIO_write(bio, mldsa65_priv_only, sizeof_mldsa65_priv_only), 0); ExpectNotNull(pkey = d2i_PrivateKey_bio(bio, NULL)); ExpectIntEQ(EVP_PKEY_id(pkey), EVP_PKEY_DILITHIUM); ExpectIntEQ(check_dilithium_der_level(mldsa65_priv_only, sizeof_mldsa65_priv_only, WC_ML_DSA_65, 1), 0); EVP_PKEY_free(pkey); pkey = NULL; BIO_free(bio); bio = NULL; /* ML-DSA-65 PrivateKey test (LAMPS PKCS#8 seed-priv DER) */ ExpectNotNull(bio = BIO_new(BIO_s_mem())); ExpectIntGT(BIO_write(bio, mldsa65_seed_priv, sizeof_mldsa65_seed_priv), 0); ExpectNotNull(pkey = d2i_PrivateKey_bio(bio, NULL)); ExpectIntEQ(EVP_PKEY_id(pkey), EVP_PKEY_DILITHIUM); EVP_PKEY_free(pkey); pkey = NULL; BIO_free(bio); bio = NULL; #ifndef WOLFSSL_DILITHIUM_NO_MAKE_KEY /* ML-DSA-65 PrivateKey test (LAMPS PKCS#8 seed-only DER) -- * requires wc_dilithium_make_key_from_seed to expand the seed. */ ExpectNotNull(bio = BIO_new(BIO_s_mem())); ExpectIntGT(BIO_write(bio, mldsa65_seed_only, sizeof_mldsa65_seed_only), 0); ExpectNotNull(pkey = d2i_PrivateKey_bio(bio, NULL)); ExpectIntEQ(EVP_PKEY_id(pkey), EVP_PKEY_DILITHIUM); EVP_PKEY_free(pkey); pkey = NULL; BIO_free(bio); bio = NULL; #endif #endif #if !defined(WOLFSSL_NO_ML_DSA_87) /* ML-DSA-87 PrivateKey test (raw bytes) */ ExpectNotNull(bio = BIO_new(BIO_s_mem())); ExpectIntGT(BIO_write(bio, bench_dilithium_level5_key, sizeof_bench_dilithium_level5_key), 0); ExpectNotNull(pkey = d2i_PrivateKey_bio(bio, NULL)); ExpectIntEQ(EVP_PKEY_id(pkey), EVP_PKEY_DILITHIUM); EVP_PKEY_free(pkey); pkey = NULL; BIO_free(bio); bio = NULL; /* ML-DSA-87 PrivateKey test (LAMPS PKCS#8 priv-only DER) */ ExpectNotNull(bio = BIO_new(BIO_s_mem())); ExpectIntGT(BIO_write(bio, mldsa87_priv_only, sizeof_mldsa87_priv_only), 0); ExpectNotNull(pkey = d2i_PrivateKey_bio(bio, NULL)); ExpectIntEQ(EVP_PKEY_id(pkey), EVP_PKEY_DILITHIUM); ExpectIntEQ(check_dilithium_der_level(mldsa87_priv_only, sizeof_mldsa87_priv_only, WC_ML_DSA_87, 1), 0); EVP_PKEY_free(pkey); pkey = NULL; BIO_free(bio); bio = NULL; /* ML-DSA-87 PrivateKey test (LAMPS PKCS#8 seed-priv DER) */ ExpectNotNull(bio = BIO_new(BIO_s_mem())); ExpectIntGT(BIO_write(bio, mldsa87_seed_priv, sizeof_mldsa87_seed_priv), 0); ExpectNotNull(pkey = d2i_PrivateKey_bio(bio, NULL)); ExpectIntEQ(EVP_PKEY_id(pkey), EVP_PKEY_DILITHIUM); EVP_PKEY_free(pkey); pkey = NULL; BIO_free(bio); bio = NULL; #ifndef WOLFSSL_DILITHIUM_NO_MAKE_KEY /* ML-DSA-87 PrivateKey test (LAMPS PKCS#8 seed-only DER) -- * requires wc_dilithium_make_key_from_seed to expand the seed. */ ExpectNotNull(bio = BIO_new(BIO_s_mem())); ExpectIntGT(BIO_write(bio, mldsa87_seed_only, sizeof_mldsa87_seed_only), 0); ExpectNotNull(pkey = d2i_PrivateKey_bio(bio, NULL)); ExpectIntEQ(EVP_PKEY_id(pkey), EVP_PKEY_DILITHIUM); EVP_PKEY_free(pkey); pkey = NULL; BIO_free(bio); bio = NULL; #endif #endif #endif /* HAVE_DILITHIUM && !NO_SIGN */ ExpectNotNull(bio = BIO_new(BIO_s_mem())); #ifndef NO_WOLFSSL_SERVER ExpectNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); #else ExpectNotNull(ctx = SSL_CTX_new(wolfSSLv23_client_method())); #endif #if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) { const unsigned char seqOnly[] = { 0x30, 0x00, 0x00, 0x00, 0x00, 0x00 }; RSA* rsa = NULL; /* Tests bad parameters */ ExpectNull(d2i_RSAPrivateKey_bio(NULL, NULL)); /* Test using bad data. */ ExpectIntGT(BIO_write(bio, seqOnly, sizeof(seqOnly)), 0); ExpectNull(d2i_RSAPrivateKey_bio(bio, NULL)); /* RSA not set yet, expecting to fail*/ rsa = wolfSSL_RSA_new(); ExpectIntEQ(SSL_CTX_use_RSAPrivateKey(ctx, rsa), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); wolfSSL_RSA_free(rsa); rsa = NULL; #if defined(USE_CERT_BUFFERS_2048) && defined(WOLFSSL_KEY_GEN) /* set RSA using bio*/ ExpectIntGT(BIO_write(bio, client_key_der_2048, sizeof_client_key_der_2048), 0); ExpectNotNull(d2i_RSAPrivateKey_bio(bio, &rsa)); ExpectNotNull(rsa); /* Tests bad parameters */ ExpectIntEQ(SSL_CTX_use_RSAPrivateKey(NULL, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(SSL_CTX_use_RSAPrivateKey(ctx, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(SSL_CTX_use_RSAPrivateKey(NULL, rsa), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(SSL_CTX_use_RSAPrivateKey(ctx, rsa), WOLFSSL_SUCCESS); /* i2d RSAprivate key tests */ ExpectIntEQ(wolfSSL_i2d_RSAPrivateKey(NULL, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_i2d_RSAPrivateKey(rsa, NULL), 1192); ExpectIntEQ(wolfSSL_i2d_RSAPrivateKey(rsa, &bufPtr), sizeof_client_key_der_2048); bufPtr -= sizeof_client_key_der_2048; ExpectIntEQ(XMEMCMP(bufPtr, client_key_der_2048, sizeof_client_key_der_2048), 0); bufPtr = NULL; ExpectIntEQ(wolfSSL_i2d_RSAPrivateKey(rsa, &bufPtr), sizeof_client_key_der_2048); ExpectNotNull(bufPtr); ExpectIntEQ(XMEMCMP(bufPtr, client_key_der_2048, sizeof_client_key_der_2048), 0); XFREE(bufPtr, NULL, DYNAMIC_TYPE_OPENSSL); RSA_free(rsa); rsa = NULL; /* d2i_RSA_PUBKEY_bio should fail when given private key DER. * wc_RsaPublicKeyDecode correctly rejects private key format. */ ExpectIntGT(BIO_write(bio, client_key_der_2048, sizeof_client_key_der_2048), 0); ExpectNull(d2i_RSA_PUBKEY_bio(bio, &rsa)); (void)BIO_reset(bio); rsa = RSA_new(); ExpectIntEQ(wolfSSL_i2d_RSAPrivateKey(rsa, NULL), 0); #endif /* USE_CERT_BUFFERS_2048 WOLFSSL_KEY_GEN */ RSA_free(rsa); } #endif /* WOLFSSL_KEY_GEN && !NO_RSA */ /* Negative test, invalid input must return NULL */ { BIO* nbio = NULL; unsigned char garbage[64]; XMEMSET(garbage, 0xA5, sizeof(garbage)); ExpectNotNull(nbio = BIO_new(BIO_s_mem())); ExpectIntGT(BIO_write(nbio, garbage, (int)sizeof(garbage)), 0); ExpectNull(d2i_PrivateKey_bio(nbio, NULL)); BIO_free(nbio); } /* Negative test: unrecognized input with a pre-allocated *out must * return NULL, not the caller pre-existing key. */ { unsigned char garbage[64]; unsigned char* p = garbage; EVP_PKEY* preAlloc = NULL; EVP_PKEY* result; XMEMSET(garbage, 0xA5, sizeof(garbage)); ExpectNotNull(preAlloc = EVP_PKEY_new()); result = preAlloc; ExpectNull(wolfSSL_d2i_PrivateKey_EVP(&result, &p, (long)sizeof(garbage))); EVP_PKEY_free(preAlloc); } SSL_CTX_free(ctx); ctx = NULL; BIO_free(bio); bio = NULL; return EXPECT_RESULT(); } #endif /* OPENSSL_ALL || (WOLFSSL_ASIO && !NO_RSA) */ #endif /* !NO_BIO */ static int test_wolfSSL_sk_GENERAL_NAME(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && \ !defined(NO_RSA) X509* x509 = NULL; GENERAL_NAME* gn = NULL; GENERAL_NAME* dup_gn = NULL; unsigned char buf[4096]; const unsigned char* bufPt = NULL; int bytes = 0; int i; int j; XFILE f = XBADFILE; STACK_OF(GENERAL_NAME)* sk = NULL; ExpectTrue((f = XFOPEN(cliCertDerFileExt, "rb")) != XBADFILE); ExpectIntGT((bytes = (int)XFREAD(buf, 1, sizeof(buf), f)), 0); if (f != XBADFILE) XFCLOSE(f); for (j = 0; j < 2; ++j) { bufPt = buf; ExpectNotNull(x509 = d2i_X509(NULL, &bufPt, bytes)); ExpectNotNull(sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_subject_alt_name, NULL, NULL)); ExpectIntEQ(sk_GENERAL_NAME_num(sk), 1); for (i = 0; i < sk_GENERAL_NAME_num(sk); i++) { ExpectNotNull(gn = sk_GENERAL_NAME_value(sk, i)); if (gn != NULL) { switch (gn->type) { case GEN_DNS: fprintf(stderr, "found type GEN_DNS\n"); break; case GEN_EMAIL: fprintf(stderr, "found type GEN_EMAIL\n"); break; case GEN_URI: fprintf(stderr, "found type GEN_URI\n"); break; } } ExpectNotNull(dup_gn = wolfSSL_GENERAL_NAME_dup(gn)); wolfSSL_GENERAL_NAME_free(dup_gn); dup_gn = NULL; } X509_free(x509); x509 = NULL; if (j == 0) { sk_GENERAL_NAME_pop_free(sk, GENERAL_NAME_free); } else { /* * We had a bug where GENERAL_NAMES_free didn't free all the memory * it was supposed to. This is a regression test for that bug. */ GENERAL_NAMES_free(sk); } sk = NULL; } ExpectNull(wolfSSL_GENERAL_NAME_dup(NULL)); ExpectIntEQ(wolfSSL_GENERAL_NAME_set_type(NULL, WOLFSSL_GEN_IA5), BAD_FUNC_ARG); wolfSSL_GENERAL_NAMES_free(NULL); #endif return EXPECT_RESULT(); } static int test_wolfSSL_GENERAL_NAME_print(void) { EXPECT_DECLS; #if defined(OPENSSL_ALL) && !defined(NO_BIO) && !defined(NO_RSA) X509* x509 = NULL; GENERAL_NAME* gn = NULL; GENERAL_NAME* dup_gn = NULL; unsigned char buf[4096]; const unsigned char* bufPt = NULL; int bytes = 0; XFILE f = XBADFILE; STACK_OF(GENERAL_NAME)* sk = NULL; BIO* out = NULL; unsigned char outbuf[128]; X509_EXTENSION* ext = NULL; AUTHORITY_INFO_ACCESS* aia = NULL; ACCESS_DESCRIPTION* ad = NULL; ASN1_IA5STRING *dnsname = NULL; ASN1_OBJECT* ridObj = NULL; const unsigned char v4Addr[] = {192,168,53,1}; const unsigned char v6Addr[] = {0x20, 0x21, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x77, 0x77}; const unsigned char email[] = {'i', 'n', 'f', 'o', '@', 'w', 'o', 'l', 'f', 's', 's', 'l', '.', 'c', 'o', 'm'}; const unsigned char ridData[] = { 0x06, 0x04, 0x2a, 0x03, 0x04, 0x05 }; const unsigned char* p; unsigned long len; const char* dnsStr = "DNS:example.com"; const char* uriStr = "URI:http://127.0.0.1:22220"; const char* v4addStr = "IP Address:192.168.53.1"; const char* v6addStr = "IP Address:2021:DB8:0:0:0:FF00:42:7777"; const char* emailStr = "email:info@wolfssl.com"; const char* othrStr = "othername:"; const char* x400Str = "X400Name:"; const char* ediStr = "EdiPartyName:"; const char* dirNameStr = "DirName:"; const char* ridStr = "Registered ID:1.2.3.4.5"; /* BIO to output */ ExpectNotNull(out = BIO_new(BIO_s_mem())); /* test for NULL param */ gn = NULL; ExpectIntEQ(GENERAL_NAME_print(NULL, NULL), 0); ExpectIntEQ(GENERAL_NAME_print(NULL, gn), 0); ExpectIntEQ(GENERAL_NAME_print(out, NULL), 0); /* test for GEN_DNS */ ExpectTrue((f = XFOPEN(cliCertDerFileExt, "rb")) != XBADFILE); ExpectIntGT((bytes = (int)XFREAD(buf, 1, sizeof(buf), f)), 0); if (f != XBADFILE) { XFCLOSE(f); f = XBADFILE; } bufPt = buf; ExpectNotNull(x509 = d2i_X509(NULL, &bufPt, bytes)); ExpectNotNull(sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_subject_alt_name, NULL, NULL)); ExpectNotNull(gn = sk_GENERAL_NAME_value(sk, 0)); ExpectIntEQ(GENERAL_NAME_print(out, gn), 1); XMEMSET(outbuf, 0, sizeof(outbuf)); ExpectIntGT(BIO_read(out, outbuf, sizeof(outbuf)), 0); ExpectIntEQ(XSTRNCMP((const char*)outbuf, dnsStr, XSTRLEN(dnsStr)), 0); sk_GENERAL_NAME_pop_free(sk, GENERAL_NAME_free); gn = NULL; sk = NULL; X509_free(x509); x509 = NULL; /* Lets test for setting as well. */ ExpectNotNull(gn = GENERAL_NAME_new()); ExpectNotNull(dnsname = ASN1_IA5STRING_new()); ExpectIntEQ(ASN1_STRING_set(dnsname, "example.com", -1), 1); GENERAL_NAME_set0_value(gn, GEN_DNS, dnsname); dnsname = NULL; ExpectIntEQ(GENERAL_NAME_print(out, gn), 1); XMEMSET(outbuf, 0, sizeof(outbuf)); ExpectIntGT(BIO_read(out, outbuf, sizeof(outbuf)), 0); ExpectIntEQ(XSTRNCMP((const char*)outbuf, dnsStr, XSTRLEN(dnsStr)), 0); ExpectNotNull(dup_gn = GENERAL_NAME_dup(gn)); wolfSSL_GENERAL_NAME_set0_value(NULL, WOLFSSL_GEN_IA5, NULL); wolfSSL_GENERAL_NAME_set0_value(dup_gn, WOLFSSL_GEN_IA5, NULL); wolfSSL_GENERAL_NAME_set0_value(NULL, WOLFSSL_GEN_DNS, NULL); wolfSSL_GENERAL_NAME_set0_value(NULL, WOLFSSL_GEN_IA5, outbuf); wolfSSL_GENERAL_NAME_set0_value(dup_gn, WOLFSSL_GEN_DNS, NULL); wolfSSL_GENERAL_NAME_set0_value(dup_gn, WOLFSSL_GEN_IA5, outbuf); wolfSSL_GENERAL_NAME_set0_value(NULL, WOLFSSL_GEN_DNS, outbuf); GENERAL_NAME_free(dup_gn); dup_gn = NULL; GENERAL_NAME_free(gn); /* test for GEN_URI */ ExpectTrue((f = XFOPEN("./certs/ocsp/root-ca-cert.pem", "rb")) != XBADFILE); ExpectNotNull(x509 = wolfSSL_PEM_read_X509(f, NULL, NULL, NULL)); if (f != XBADFILE) { XFCLOSE(f); f = XBADFILE; } ExpectNotNull(ext = wolfSSL_X509_get_ext(x509, 4)); ExpectNotNull(aia = (WOLFSSL_AUTHORITY_INFO_ACCESS*)wolfSSL_X509V3_EXT_d2i( ext)); ExpectNotNull(ad = (WOLFSSL_ACCESS_DESCRIPTION *)wolfSSL_sk_value(aia, 0)); if (ad != NULL) { gn = ad->location; } ExpectNotNull(dup_gn = GENERAL_NAME_dup(gn)); GENERAL_NAME_free(dup_gn); dup_gn = NULL; ExpectIntEQ(GENERAL_NAME_print(out, gn), 1); gn = NULL; XMEMSET(outbuf,0,sizeof(outbuf)); ExpectIntGT(BIO_read(out, outbuf, sizeof(outbuf)), 0); ExpectIntEQ(XSTRNCMP((const char*)outbuf, uriStr, XSTRLEN(uriStr)), 0); wolfSSL_sk_ACCESS_DESCRIPTION_pop_free(aia, NULL); aia = NULL; aia = (AUTHORITY_INFO_ACCESS*)wolfSSL_X509V3_EXT_d2i(ext); ExpectNotNull(aia); AUTHORITY_INFO_ACCESS_pop_free(aia, NULL); aia = NULL; X509_free(x509); x509 = NULL; /* test for GEN_IPADD */ /* ip v4 address */ ExpectNotNull(gn = wolfSSL_GENERAL_NAME_new()); if (gn != NULL) { gn->type = GEN_IPADD; if (gn->d.iPAddress != NULL) { gn->d.iPAddress->length = sizeof(v4Addr); } } ExpectIntEQ(wolfSSL_ASN1_STRING_set(gn->d.iPAddress, v4Addr, sizeof(v4Addr)), 1); ExpectIntEQ(GENERAL_NAME_print(out, gn), 1); XMEMSET(outbuf,0,sizeof(outbuf)); ExpectIntGT(BIO_read(out, outbuf, sizeof(outbuf)), 0); ExpectIntEQ(XSTRNCMP((const char*)outbuf, v4addStr, XSTRLEN(v4addStr)), 0); ExpectNotNull(dup_gn = GENERAL_NAME_dup(gn)); GENERAL_NAME_free(dup_gn); dup_gn = NULL; GENERAL_NAME_free(gn); gn = NULL; /* ip v6 address */ ExpectNotNull(gn = wolfSSL_GENERAL_NAME_new()); if (gn != NULL) { gn->type = GEN_IPADD; if (gn->d.iPAddress != NULL) { gn->d.iPAddress->length = sizeof(v6Addr); } } ExpectIntEQ(wolfSSL_ASN1_STRING_set(gn->d.iPAddress, v6Addr, sizeof(v6Addr)), 1); ExpectIntEQ(GENERAL_NAME_print(out, gn), 1); XMEMSET(outbuf,0,sizeof(outbuf)); ExpectIntGT(BIO_read(out, outbuf, sizeof(outbuf)), 0); ExpectIntEQ(XSTRNCMP((const char*)outbuf, v6addStr, XSTRLEN(v6addStr)), 0); ExpectNotNull(dup_gn = GENERAL_NAME_dup(gn)); GENERAL_NAME_free(dup_gn); dup_gn = NULL; GENERAL_NAME_free(gn); gn = NULL; /* test for GEN_EMAIL */ ExpectNotNull(gn = wolfSSL_GENERAL_NAME_new()); if (gn != NULL) { gn->type = GEN_EMAIL; if (gn->d.rfc822Name != NULL) { gn->d.rfc822Name->length = sizeof(email); } } ExpectIntEQ(wolfSSL_ASN1_STRING_set(gn->d.rfc822Name, email, sizeof(email)), 1); ExpectIntEQ(GENERAL_NAME_print(out, gn), 1); XMEMSET(outbuf,0,sizeof(outbuf)); ExpectIntGT(BIO_read(out, outbuf, sizeof(outbuf)), 0); ExpectIntEQ(XSTRNCMP((const char*)outbuf, emailStr, XSTRLEN(emailStr)), 0); ExpectNotNull(dup_gn = GENERAL_NAME_dup(gn)); GENERAL_NAME_free(dup_gn); dup_gn = NULL; GENERAL_NAME_free(gn); gn = NULL; /* test for GEN_OTHERNAME */ ExpectNotNull(gn = wolfSSL_GENERAL_NAME_new()); if (gn != NULL) { gn->type = GEN_OTHERNAME; } ExpectIntEQ(GENERAL_NAME_print(out, gn), 1); XMEMSET(outbuf,0,sizeof(outbuf)); ExpectIntGT(BIO_read(out, outbuf, sizeof(outbuf)), 0); ExpectIntEQ(XSTRNCMP((const char*)outbuf, othrStr, XSTRLEN(othrStr)), 0); GENERAL_NAME_free(gn); gn = NULL; /* test for GEN_X400 */ ExpectNotNull(gn = wolfSSL_GENERAL_NAME_new()); if (gn != NULL) { gn->type = GEN_X400; } ExpectIntEQ(GENERAL_NAME_print(out, gn), 1); XMEMSET(outbuf,0,sizeof(outbuf)); ExpectIntGT(BIO_read(out, outbuf, sizeof(outbuf)), 0); ExpectIntEQ(XSTRNCMP((const char*)outbuf, x400Str, XSTRLEN(x400Str)), 0); /* Restore to GEN_IA5 (default) to avoid memory leak. */ if (gn != NULL) { gn->type = GEN_IA5; } /* Duplicating GEN_X400 not supported. */ ExpectNull(GENERAL_NAME_dup(gn)); GENERAL_NAME_free(gn); gn = NULL; /* test for GEN_EDIPARTY */ ExpectNotNull(gn = wolfSSL_GENERAL_NAME_new()); if (gn != NULL) { gn->type = GEN_EDIPARTY; } ExpectIntEQ(GENERAL_NAME_print(out, gn), 1); XMEMSET(outbuf,0,sizeof(outbuf)); ExpectIntGT(BIO_read(out, outbuf, sizeof(outbuf)), 0); ExpectIntEQ(XSTRNCMP((const char*)outbuf, ediStr, XSTRLEN(ediStr)), 0); /* Restore to GEN_IA5 (default) to avoid memory leak. */ if (gn != NULL) { gn->type = GEN_IA5; } /* Duplicating GEN_EDIPARTY not supported. */ ExpectNull(dup_gn = GENERAL_NAME_dup(gn)); GENERAL_NAME_free(gn); gn = NULL; /* test for GEN_DIRNAME */ ExpectNotNull(gn = wolfSSL_GENERAL_NAME_new()); if (gn != NULL) { gn->type = GEN_DIRNAME; } ExpectIntEQ(GENERAL_NAME_print(out, gn), 1); XMEMSET(outbuf,0,sizeof(outbuf)); ExpectIntGT(BIO_read(out, outbuf, sizeof(outbuf)), 0); ExpectIntEQ(XSTRNCMP((const char*)outbuf, dirNameStr, XSTRLEN(dirNameStr)), 0); /* Duplicating GEN_DIRNAME not supported. */ ExpectNull(dup_gn = GENERAL_NAME_dup(gn)); /* Restore to GEN_IA5 (default) to avoid memory leak. */ if (gn != NULL) { gn->type = GEN_IA5; } GENERAL_NAME_free(gn); gn = NULL; /* test for GEN_RID */ p = ridData; len = sizeof(ridData); ExpectNotNull(ridObj = wolfSSL_d2i_ASN1_OBJECT(NULL, &p, len)); ExpectNotNull(gn = wolfSSL_GENERAL_NAME_new()); if (gn != NULL) { gn->type = GEN_RID; wolfSSL_ASN1_STRING_free(gn->d.ia5); gn->d.registeredID = ridObj; } else { wolfSSL_ASN1_OBJECT_free(ridObj); } ExpectIntEQ(GENERAL_NAME_print(out, gn), 1); XMEMSET(outbuf,0,sizeof(outbuf)); ExpectIntGT(BIO_read(out, outbuf, sizeof(outbuf)), 0); ExpectIntEQ(XSTRNCMP((const char*)outbuf, ridStr, XSTRLEN(ridStr)), 0); /* Duplicating GEN_DIRNAME not supported. */ ExpectNull(dup_gn = GENERAL_NAME_dup(gn)); GENERAL_NAME_free(gn); gn = NULL; BIO_free(out); #endif /* OPENSSL_ALL */ return EXPECT_RESULT(); } static int test_wolfSSL_sk_DIST_POINT(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && \ !defined(NO_RSA) X509* x509 = NULL; unsigned char buf[4096]; const unsigned char* bufPt; int bytes = 0; int i = 0; int j = 0; XFILE f = XBADFILE; DIST_POINT* dp = NULL; DIST_POINT_NAME* dpn = NULL; GENERAL_NAME* gn = NULL; ASN1_IA5STRING* uri = NULL; STACK_OF(DIST_POINT)* dps = NULL; STACK_OF(GENERAL_NAME)* gns = NULL; const char cliCertDerCrlDistPoint[] = "./certs/client-crl-dist.der"; ExpectTrue((f = XFOPEN(cliCertDerCrlDistPoint, "rb")) != XBADFILE); ExpectIntGT((bytes = (int)XFREAD(buf, 1, sizeof(buf), f)), 0); if (f != XBADFILE) XFCLOSE(f); bufPt = buf; ExpectNotNull(x509 = d2i_X509(NULL, &bufPt, bytes)); ExpectNotNull(dps = (STACK_OF(DIST_POINT)*)X509_get_ext_d2i(x509, NID_crl_distribution_points, NULL, NULL)); ExpectIntEQ(sk_DIST_POINT_num(dps), 1); for (i = 0; i < sk_DIST_POINT_num(dps); i++) { ExpectNotNull(dp = sk_DIST_POINT_value(dps, i)); ExpectNotNull(dpn = dp->distpoint); /* this should be type 0, fullname */ ExpectIntEQ(dpn->type, 0); ExpectNotNull(gns = dp->distpoint->name.fullname); ExpectIntEQ(sk_GENERAL_NAME_num(gns), 1); for (j = 0; j < sk_GENERAL_NAME_num(gns); j++) { ExpectNotNull(gn = sk_GENERAL_NAME_value(gns, j)); ExpectIntEQ(gn->type, GEN_URI); ExpectNotNull(uri = gn->d.uniformResourceIdentifier); ExpectNotNull(uri->data); ExpectIntGT(uri->length, 0); } } ExpectNotNull(dp = wolfSSL_DIST_POINT_new()); wolfSSL_DIST_POINT_free(NULL); wolfSSL_DIST_POINTS_free(NULL); wolfSSL_sk_DIST_POINT_free(NULL); ExpectIntEQ(wolfSSL_sk_DIST_POINT_push(NULL, NULL), WOLFSSL_FAILURE); ExpectIntEQ(wolfSSL_sk_DIST_POINT_push(dps, NULL), WOLFSSL_FAILURE); ExpectIntEQ(wolfSSL_sk_DIST_POINT_push(NULL, dp), WOLFSSL_FAILURE); ExpectNull(wolfSSL_sk_DIST_POINT_value(NULL, 0)); ExpectIntEQ(wolfSSL_sk_DIST_POINT_num(NULL), WOLFSSL_FATAL_ERROR); wolfSSL_DIST_POINT_free(dp); X509_free(x509); CRL_DIST_POINTS_free(dps); #endif return EXPECT_RESULT(); } static int test_wolfSSL_verify_mode(void) { EXPECT_DECLS; #if !defined(NO_RSA) && !defined(NO_TLS) && (defined(OPENSSL_ALL) || \ defined(HAVE_STUNNEL) || defined(WOLFSSL_MYSQL_COMPATIBLE) || \ defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)) && \ !defined(NO_WOLFSSL_CLIENT) WOLFSSL* ssl = NULL; WOLFSSL_CTX* ctx = NULL; ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); ExpectNotNull(ssl = SSL_new(ctx)); ExpectIntEQ(SSL_get_verify_mode(ssl), SSL_CTX_get_verify_mode(ctx)); SSL_free(ssl); ssl = NULL; SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, 0); ExpectNotNull(ssl = SSL_new(ctx)); ExpectIntEQ(SSL_get_verify_mode(ssl), SSL_CTX_get_verify_mode(ctx)); ExpectIntEQ(SSL_get_verify_mode(ssl), SSL_VERIFY_PEER); wolfSSL_set_verify(ssl, SSL_VERIFY_NONE, 0); ExpectIntEQ(SSL_CTX_get_verify_mode(ctx), SSL_VERIFY_PEER); ExpectIntEQ(SSL_get_verify_mode(ssl), SSL_VERIFY_NONE); SSL_free(ssl); ssl = NULL; wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER | WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0); ExpectNotNull(ssl = SSL_new(ctx)); ExpectIntEQ(SSL_get_verify_mode(ssl), SSL_CTX_get_verify_mode(ctx)); ExpectIntEQ(SSL_get_verify_mode(ssl), WOLFSSL_VERIFY_PEER | WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT); wolfSSL_set_verify(ssl, SSL_VERIFY_PEER, 0); ExpectIntEQ(SSL_CTX_get_verify_mode(ctx), WOLFSSL_VERIFY_PEER | WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT); ExpectIntEQ(SSL_get_verify_mode(ssl), SSL_VERIFY_PEER); wolfSSL_set_verify(ssl, SSL_VERIFY_NONE, 0); ExpectIntEQ(SSL_get_verify_mode(ssl), SSL_VERIFY_NONE); wolfSSL_set_verify(ssl, SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0); ExpectIntEQ(SSL_get_verify_mode(ssl), SSL_VERIFY_FAIL_IF_NO_PEER_CERT); wolfSSL_set_verify(ssl, SSL_VERIFY_FAIL_EXCEPT_PSK, 0); ExpectIntEQ(SSL_get_verify_mode(ssl), SSL_VERIFY_FAIL_EXCEPT_PSK); #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) wolfSSL_set_verify(ssl, SSL_VERIFY_POST_HANDSHAKE, 0); ExpectIntEQ(SSL_get_verify_mode(ssl), SSL_VERIFY_POST_HANDSHAKE); #endif ExpectIntEQ(SSL_CTX_get_verify_mode(ctx), WOLFSSL_VERIFY_PEER | WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT); SSL_free(ssl); SSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } static int test_wolfSSL_verify_depth(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_TLS) && \ !defined(NO_WOLFSSL_CLIENT) WOLFSSL* ssl = NULL; WOLFSSL_CTX* ctx = NULL; long depth = 0; ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); ExpectIntGT((depth = SSL_CTX_get_verify_depth(ctx)), 0); ExpectNotNull(ssl = SSL_new(ctx)); ExpectIntEQ(SSL_get_verify_depth(ssl), SSL_CTX_get_verify_depth(ctx)); SSL_free(ssl); ssl = NULL; SSL_CTX_set_verify_depth(ctx, -1); ExpectIntEQ(depth, SSL_CTX_get_verify_depth(ctx)); SSL_CTX_set_verify_depth(ctx, 2); ExpectIntEQ(2, SSL_CTX_get_verify_depth(ctx)); ExpectNotNull(ssl = SSL_new(ctx)); ExpectIntEQ(2, SSL_get_verify_depth(ssl)); SSL_free(ssl); SSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } static int test_wolfSSL_verify_result(void) { EXPECT_DECLS; #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \ defined(OPENSSL_ALL)) && !defined(NO_TLS) && !defined(NO_WOLFSSL_CLIENT) WOLFSSL* ssl = NULL; WOLFSSL_CTX* ctx = NULL; long result = 0xDEADBEEF; ExpectIntEQ(WC_NO_ERR_TRACE(WOLFSSL_FAILURE), wolfSSL_get_verify_result(ssl)); ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); ExpectNotNull(ssl = SSL_new(ctx)); wolfSSL_set_verify_result(ssl, result); ExpectIntEQ(result, wolfSSL_get_verify_result(ssl)); SSL_free(ssl); SSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } #if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_TLS) && \ !defined(NO_WOLFSSL_CLIENT) static void sslMsgCb(int w, int version, int type, const void* buf, size_t sz, SSL* ssl, void* arg) { int i; unsigned char* pt = (unsigned char*)buf; fprintf(stderr, "%s %d bytes of version %d , type %d : ", (w)?"Writing":"Reading", (int)sz, version, type); for (i = 0; i < (int)sz; i++) fprintf(stderr, "%02X", pt[i]); fprintf(stderr, "\n"); (void)ssl; (void)arg; } #endif /* OPENSSL_EXTRA */ static int test_wolfSSL_msg_callback(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_TLS) && \ !defined(NO_WOLFSSL_CLIENT) WOLFSSL* ssl = NULL; WOLFSSL_CTX* ctx = NULL; ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); ExpectNotNull(ssl = SSL_new(ctx)); ExpectIntEQ(SSL_set_msg_callback(ssl, NULL), SSL_SUCCESS); ExpectIntEQ(SSL_set_msg_callback(ssl, &sslMsgCb), SSL_SUCCESS); ExpectIntEQ(SSL_set_msg_callback(NULL, &sslMsgCb), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); SSL_free(ssl); SSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } static int test_wolfSSL_X509_SEP(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && defined(WOLFSSL_SEP) WOLFSSL_X509* x509 = NULL; #if 0 byte* out; #endif int outSz; ExpectNotNull(x509 = wolfSSL_X509_new()); outSz = 0; ExpectNull(wolfSSL_X509_get_device_type(NULL, NULL, NULL)); ExpectNull(wolfSSL_X509_get_device_type(x509, NULL, NULL)); ExpectNull(wolfSSL_X509_get_device_type(NULL, NULL, &outSz)); ExpectNull(wolfSSL_X509_get_device_type(x509, NULL, &outSz)); outSz = 0; ExpectNull(wolfSSL_X509_get_hw_type(NULL, NULL, NULL)); ExpectNull(wolfSSL_X509_get_hw_type(x509, NULL, NULL)); ExpectNull(wolfSSL_X509_get_hw_type(NULL, NULL, &outSz)); ExpectNull(wolfSSL_X509_get_hw_type(x509, NULL, &outSz)); outSz = 0; ExpectNull(wolfSSL_X509_get_hw_serial_number(NULL, NULL, NULL)); ExpectNull(wolfSSL_X509_get_hw_serial_number(x509, NULL, NULL)); ExpectNull(wolfSSL_X509_get_hw_serial_number(NULL, NULL, &outSz)); ExpectNull(wolfSSL_X509_get_hw_serial_number(x509, NULL, &outSz)); ExpectIntEQ(wolfSSL_X509_ext_isSet_by_NID(x509, WC_NID_certificate_policies), 0); wolfSSL_X509_free(x509); x509 = NULL; #if 0 /* Use certificate with the extension here. */ ExpectNotNull(x509 = wolfSSL_X509_load_certificate_file(svrCertFile, SSL_FILETYPE_PEM)); outSz = 0; ExpectNotNull(out = wolfSSL_X509_get_device_type(x509, NULL, &outSz)); ExpectIntGT(outSz, 0); XFREE(out, NULL, DYNAMIC_TYPE_OPENSSL); outSz = 0; ExpectNotNull(out = wolfSSL_X509_get_hw_type(x509, NULL, &outSz)); ExpectIntGT(outSz, 0); XFREE(out, NULL, DYNAMIC_TYPE_OPENSSL); outSz = 0; ExpectNotNull(out = wolfSSL_X509_get_hw_serial_number(x509, NULL, &outSz)); ExpectIntGT(outSz, 0); XFREE(out, NULL, DYNAMIC_TYPE_OPENSSL); wolfSSL_X509_free(x509); #endif #endif return EXPECT_RESULT(); } /* Test wolfSSL_X509_set_* extension functions */ static int test_wolfSSL_X509_set_extensions(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) WOLFSSL_X509* x509 = NULL; #ifdef WOLFSSL_CERT_EXT byte skid[20] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20}; byte akid[20] = {20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1}; #endif #ifndef IGNORE_NETSCAPE_CERT_TYPE int nsCertType = 0; #endif ExpectNotNull(x509 = wolfSSL_X509_new()); #ifdef WOLFSSL_CERT_EXT /* Test wolfSSL_X509_set_subject_key_id */ ExpectIntEQ(wolfSSL_X509_set_subject_key_id(NULL, skid, sizeof(skid)), WOLFSSL_FAILURE); ExpectIntEQ(wolfSSL_X509_set_subject_key_id(x509, NULL, sizeof(skid)), WOLFSSL_FAILURE); ExpectIntEQ(wolfSSL_X509_set_subject_key_id(x509, skid, 0), WOLFSSL_FAILURE); ExpectIntEQ(wolfSSL_X509_set_subject_key_id(x509, skid, sizeof(skid)), WOLFSSL_SUCCESS); /* Test wolfSSL_X509_set_authority_key_id */ ExpectIntEQ(wolfSSL_X509_set_authority_key_id(NULL, akid, sizeof(akid)), WOLFSSL_FAILURE); ExpectIntEQ(wolfSSL_X509_set_authority_key_id(x509, NULL, sizeof(akid)), WOLFSSL_FAILURE); ExpectIntEQ(wolfSSL_X509_set_authority_key_id(x509, akid, 0), WOLFSSL_FAILURE); ExpectIntEQ(wolfSSL_X509_set_authority_key_id(x509, akid, sizeof(akid)), WOLFSSL_SUCCESS); /* Test wolfSSL_X509_CRL_add_dist_point */ ExpectIntEQ(wolfSSL_X509_CRL_add_dist_point(NULL, "http://crl.example.com/ca.crl", 0), WOLFSSL_FAILURE); ExpectIntEQ(wolfSSL_X509_CRL_add_dist_point(x509, NULL, 0), WOLFSSL_FAILURE); ExpectIntEQ(wolfSSL_X509_CRL_add_dist_point(x509, "http://crl.example.com/ca.crl", 0), WOLFSSL_SUCCESS); /* Test wolfSSL_X509_CRL_set_dist_points with raw DER */ { /* Simple CRL DP DER encoding for "http://example.com/crl" */ byte crlDer[] = { 0x30, 0x1d, /* SEQUENCE (outer) */ 0x30, 0x1b, /* SEQUENCE (DistributionPoint) */ 0xa0, 0x19, /* [0] EXPLICIT */ 0xa0, 0x17, /* [0] IMPLICIT GeneralNames */ 0x86, 0x15, /* [6] URI */ 'h','t','t','p',':','/','/','e','x','a','m','p','l','e','.','c', 'o','m','/','c','r','l' }; ExpectIntEQ(wolfSSL_X509_CRL_set_dist_points(NULL, crlDer, sizeof(crlDer)), WOLFSSL_FAILURE); ExpectIntEQ(wolfSSL_X509_CRL_set_dist_points(x509, NULL, sizeof(crlDer)), WOLFSSL_FAILURE); ExpectIntEQ(wolfSSL_X509_CRL_set_dist_points(x509, crlDer, 0), WOLFSSL_FAILURE); ExpectIntEQ(wolfSSL_X509_CRL_set_dist_points(x509, crlDer, sizeof(crlDer)), WOLFSSL_SUCCESS); } #endif /* WOLFSSL_CERT_EXT */ #ifndef IGNORE_NETSCAPE_CERT_TYPE /* Test wolfSSL_X509_set_ns_cert_type */ nsCertType = WC_NS_SSL_CLIENT | WC_NS_SSL_SERVER; ExpectIntEQ(wolfSSL_X509_set_ns_cert_type(NULL, nsCertType), WOLFSSL_FAILURE); ExpectIntEQ(wolfSSL_X509_set_ns_cert_type(x509, nsCertType), WOLFSSL_SUCCESS); #endif wolfSSL_X509_free(x509); #endif /* OPENSSL_EXTRA && !NO_CERTS */ return EXPECT_RESULT(); } /* Round trip test for wolfSSL_X509_set_authority_key_id() with a raw key ID. * * Builds a cert, calls the setter with a 20-byte raw keyId, signs the cert, * serializes to DER via wolfSSL_i2d_X509(), re-parses the DER, locates the * AKID extension, and asserts the OCTET STRING contents match the * AuthorityKeyIdentifier ASN.1 structure required by RFC 5280 4.2.1.1: * * SEQUENCE (0x30) length 22 (0x16) * [0] (0x80) length 20 (0x14) * <20 keyId bytes> * * The keyId bytes inside the [0] tag must equal the input passed the setter. */ static int test_wolfSSL_X509_set_authority_key_id_roundtrip(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CERT_GEN) && \ !defined(NO_RSA) && !defined(NO_FILESYSTEM) && !defined(NO_ASN_TIME) WOLFSSL_X509* src = NULL; WOLFSSL_X509* built = NULL; WOLFSSL_X509* parsed = NULL; WOLFSSL_EVP_PKEY* priv = NULL; WOLFSSL_EVP_PKEY* pub = NULL; WOLFSSL_ASN1_TIME* notBefore = NULL; WOLFSSL_ASN1_TIME* notAfter = NULL; WOLFSSL_X509_EXTENSION* ext = NULL; WOLFSSL_ASN1_STRING* extData = NULL; unsigned char* der = NULL; const unsigned char* derPtr = NULL; unsigned char* key = NULL; unsigned char* keyPt = NULL; char* name = NULL; char* header = NULL; long keySz = 0; int derSz = 0; int extIdx = -1; XFILE fp = XBADFILE; time_t t; /* Raw 20-byte key identifier */ byte akid[20] = { 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19, 0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23 }; /* Load reference cert + key (RSA) */ src = wolfSSL_X509_load_certificate_file(cliCertFile, WOLFSSL_FILETYPE_PEM); ExpectNotNull(src); ExpectTrue((fp = XFOPEN(cliKeyFile, "rb")) != XBADFILE); ExpectIntEQ(wolfSSL_PEM_read(fp, &name, &header, &key, &keySz), WOLFSSL_SUCCESS); if (fp != XBADFILE) { XFCLOSE(fp); } keyPt = key; ExpectNotNull(priv = wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, NULL, (const unsigned char**)&keyPt, keySz)); /* Build a v3 cert and copy fields from src */ ExpectNotNull(built = wolfSSL_X509_new()); ExpectIntEQ(wolfSSL_X509_set_version(built, 2), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_X509_set_subject_name(built, wolfSSL_X509_get_subject_name(src)), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_X509_set_issuer_name(built, wolfSSL_X509_get_issuer_name(src)), WOLFSSL_SUCCESS); ExpectNotNull(pub = wolfSSL_X509_get_pubkey(src)); ExpectIntEQ(wolfSSL_X509_set_pubkey(built, pub), WOLFSSL_SUCCESS); t = time(NULL); ExpectNotNull(notBefore = wolfSSL_ASN1_TIME_adj(NULL, t, 0, 0)); ExpectNotNull(notAfter = wolfSSL_ASN1_TIME_adj(NULL, t, 365, 0)); ExpectTrue(wolfSSL_X509_set_notBefore(built, notBefore)); ExpectTrue(wolfSSL_X509_set_notAfter(built, notAfter)); /* Set AKID with a raw key identifier */ ExpectIntEQ(wolfSSL_X509_set_authority_key_id(built, akid, sizeof(akid)), WOLFSSL_SUCCESS); /* Sign and serialize. */ ExpectIntGT(wolfSSL_X509_sign(built, priv, EVP_sha256()), 0); ExpectIntGT((derSz = wolfSSL_i2d_X509(built, &der)), 0); /* Re-parse the DER we just produced */ derPtr = der; ExpectNotNull(parsed = wolfSSL_d2i_X509(NULL, &derPtr, derSz)); /* Locate the AKID extension and pull out the OCTET STRING contents * (per RFC 5280 must be a SEQUENCE { [0] keyIdentifier ... }) */ ExpectIntGE((extIdx = wolfSSL_X509_get_ext_by_NID(parsed, NID_authority_key_identifier, -1)), 0); ExpectNotNull(ext = wolfSSL_X509_get_ext(parsed, extIdx)); ExpectNotNull(extData = wolfSSL_X509_EXTENSION_get_data(ext)); /* Encoded inner extension structure for a 20-byte keyId is 24 bytes: * SEQUENCE (0x30) length 22 (0x16) * [0] (0x80) length 20 (0x14) * <20 keyId bytes> */ ExpectIntEQ(extData->length, 24); if (extData != NULL && extData->data != NULL && extData->length == 24) { ExpectIntEQ((unsigned char)extData->data[0], 0x30); ExpectIntEQ((unsigned char)extData->data[1], 0x16); ExpectIntEQ((unsigned char)extData->data[2], 0x80); ExpectIntEQ((unsigned char)extData->data[3], 0x14); ExpectIntEQ(XMEMCMP((const byte*)extData->data + 4, akid, sizeof(akid)), 0); } XFREE(der, HEAP_HINT, DYNAMIC_TYPE_OPENSSL); XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(name, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(header, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wolfSSL_X509_free(src); wolfSSL_X509_free(built); wolfSSL_X509_free(parsed); wolfSSL_EVP_PKEY_free(priv); wolfSSL_EVP_PKEY_free(pub); wolfSSL_ASN1_TIME_free(notBefore); wolfSSL_ASN1_TIME_free(notAfter); #endif return EXPECT_RESULT(); } /* Round trip test for wolfSSL_X509_set_authority_key_id_ex(). * * Inserts a known SubjectKeyIdentifier on the issuer cert, calls the _ex * variant of the setter (which derives the AKID keyId from the issuer SKID, * or from SHA-1 of the issuer public key when no SKID is set), signs, * serializes to DER, re-parses, and asserts the AKID extension OCTET STRING * contents match the RFC 5280 4.2.1.1 structure * * SEQUENCE (0x30) length 22 (0x16) * [0] (0x80) length 20 (0x14) * <20 keyId bytes> * * with the embedded keyId equal to the issuer's SKID. */ static int test_wolfSSL_X509_set_authority_key_id_ex_roundtrip(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CERT_GEN) && \ !defined(NO_RSA) && !defined(NO_FILESYSTEM) && !defined(NO_ASN_TIME) && \ !defined(NO_SHA) WOLFSSL_X509* issuer = NULL; WOLFSSL_X509* built = NULL; WOLFSSL_X509* parsed = NULL; WOLFSSL_EVP_PKEY* priv = NULL; WOLFSSL_EVP_PKEY* pub = NULL; WOLFSSL_ASN1_TIME* notBefore = NULL; WOLFSSL_ASN1_TIME* notAfter = NULL; WOLFSSL_X509_EXTENSION* ext = NULL; WOLFSSL_ASN1_STRING* extData = NULL; unsigned char* der = NULL; const unsigned char* derPtr = NULL; unsigned char* key = NULL; unsigned char* keyPt = NULL; char* name = NULL; char* header = NULL; long keySz = 0; int derSz = 0; int extIdx = -1; XFILE fp = XBADFILE; time_t t; /* SKID on the issuer. The AKID on the built cert should match this. */ byte issuerSkid[20] = { 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39, 0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42,0x43 }; /* Load the cert to use as both issuer and the source of subject/key. */ ExpectNotNull(issuer = wolfSSL_X509_load_certificate_file(cliCertFile, WOLFSSL_FILETYPE_PEM)); /* Stamp known SKID on the issuer so set_authority_key_id_ex has a * deterministic value to copy into the AKID. */ ExpectIntEQ(wolfSSL_X509_set_subject_key_id(issuer, issuerSkid, sizeof(issuerSkid)), WOLFSSL_SUCCESS); ExpectTrue((fp = XFOPEN(cliKeyFile, "rb")) != XBADFILE); ExpectIntEQ(wolfSSL_PEM_read(fp, &name, &header, &key, &keySz), WOLFSSL_SUCCESS); if (fp != XBADFILE) { XFCLOSE(fp); } keyPt = key; ExpectNotNull(priv = wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, NULL, (const unsigned char**)&keyPt, keySz)); ExpectNotNull(built = wolfSSL_X509_new()); ExpectIntEQ(wolfSSL_X509_set_version(built, 2), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_X509_set_subject_name(built, wolfSSL_X509_get_subject_name(issuer)), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_X509_set_issuer_name(built, wolfSSL_X509_get_subject_name(issuer)), WOLFSSL_SUCCESS); ExpectNotNull(pub = wolfSSL_X509_get_pubkey(issuer)); ExpectIntEQ(wolfSSL_X509_set_pubkey(built, pub), WOLFSSL_SUCCESS); t = time(NULL); ExpectNotNull(notBefore = wolfSSL_ASN1_TIME_adj(NULL, t, 0, 0)); ExpectNotNull(notAfter = wolfSSL_ASN1_TIME_adj(NULL, t, 365, 0)); ExpectTrue(wolfSSL_X509_set_notBefore(built, notBefore)); ExpectTrue(wolfSSL_X509_set_notAfter(built, notAfter)); /* Derive AKID from the issuer's SKID */ ExpectIntEQ(wolfSSL_X509_set_authority_key_id_ex(built, issuer), WOLFSSL_SUCCESS); ExpectIntGT(wolfSSL_X509_sign(built, priv, EVP_sha256()), 0); ExpectIntGT((derSz = wolfSSL_i2d_X509(built, &der)), 0); derPtr = der; ExpectNotNull(parsed = wolfSSL_d2i_X509(NULL, &derPtr, derSz)); ExpectIntGE((extIdx = wolfSSL_X509_get_ext_by_NID(parsed, NID_authority_key_identifier, -1)), 0); ExpectNotNull(ext = wolfSSL_X509_get_ext(parsed, extIdx)); ExpectNotNull(extData = wolfSSL_X509_EXTENSION_get_data(ext)); /* AuthorityKeyIdentifier inner structure for a 20-byte keyId is 24 bytes: * SEQUENCE { [0] keyId }. keyId on built cert must equal issuer SKID. */ ExpectIntEQ(extData->length, 24); if (extData != NULL && extData->data != NULL && extData->length == 24) { ExpectIntEQ((unsigned char)extData->data[0], 0x30); ExpectIntEQ((unsigned char)extData->data[1], 0x16); ExpectIntEQ((unsigned char)extData->data[2], 0x80); ExpectIntEQ((unsigned char)extData->data[3], 0x14); ExpectIntEQ(XMEMCMP((const byte*)extData->data + 4, issuerSkid, sizeof(issuerSkid)), 0); } XFREE(der, HEAP_HINT, DYNAMIC_TYPE_OPENSSL); XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(name, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(header, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wolfSSL_X509_free(issuer); wolfSSL_X509_free(built); wolfSSL_X509_free(parsed); wolfSSL_EVP_PKEY_free(priv); wolfSSL_EVP_PKEY_free(pub); wolfSSL_ASN1_TIME_free(notBefore); wolfSSL_ASN1_TIME_free(notAfter); #endif return EXPECT_RESULT(); } /* Verifies that wolfSSL_X509_set_authority_key_id() correctly handles being * called on a WOLFSSL_X509 that already has AKID storage. * * Case 1: two consecutive setter calls on a fresh built cert. Calls setter * twice with different keyIds (second call should replace first AKID). * Case 2: setter called on an X509 loaded from a PEM file that already has * an AKID extension. */ static int test_wolfSSL_X509_set_authority_key_id_overwrite(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CERT_GEN) && \ !defined(NO_RSA) && !defined(NO_FILESYSTEM) && !defined(NO_ASN_TIME) WOLFSSL_X509* src = NULL; WOLFSSL_X509* built = NULL; WOLFSSL_X509* parsed = NULL; WOLFSSL_X509* loaded = NULL; WOLFSSL_EVP_PKEY* priv = NULL; WOLFSSL_EVP_PKEY* pub = NULL; WOLFSSL_ASN1_TIME* notBefore = NULL; WOLFSSL_ASN1_TIME* notAfter = NULL; WOLFSSL_X509_EXTENSION* ext = NULL; WOLFSSL_ASN1_STRING* extData = NULL; unsigned char* der = NULL; const unsigned char* derPtr = NULL; unsigned char* key = NULL; unsigned char* keyPt = NULL; char* name = NULL; char* header = NULL; long keySz = 0; int derSz = 0; int extIdx = -1; XFILE fp = XBADFILE; time_t t; byte akid1[20] = { 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a, 0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14 }; byte akid2[20] = { 0xaa,0xbb,0xcc,0xdd,0xee,0xff,0x00,0x11,0x22,0x33, 0x44,0x55,0x66,0x77,0x88,0x99,0xa0,0xb0,0xc0,0xd0 }; /* Case 1: set twice on a fresh built cert */ ExpectNotNull(src = wolfSSL_X509_load_certificate_file(cliCertFile, WOLFSSL_FILETYPE_PEM)); ExpectTrue((fp = XFOPEN(cliKeyFile, "rb")) != XBADFILE); ExpectIntEQ(wolfSSL_PEM_read(fp, &name, &header, &key, &keySz), WOLFSSL_SUCCESS); if (fp != XBADFILE) { XFCLOSE(fp); } keyPt = key; ExpectNotNull(priv = wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, NULL, (const unsigned char**)&keyPt, keySz)); ExpectNotNull(built = wolfSSL_X509_new()); ExpectIntEQ(wolfSSL_X509_set_version(built, 2), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_X509_set_subject_name(built, wolfSSL_X509_get_subject_name(src)), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_X509_set_issuer_name(built, wolfSSL_X509_get_issuer_name(src)), WOLFSSL_SUCCESS); ExpectNotNull(pub = wolfSSL_X509_get_pubkey(src)); ExpectIntEQ(wolfSSL_X509_set_pubkey(built, pub), WOLFSSL_SUCCESS); t = time(NULL); ExpectNotNull(notBefore = wolfSSL_ASN1_TIME_adj(NULL, t, 0, 0)); ExpectNotNull(notAfter = wolfSSL_ASN1_TIME_adj(NULL, t, 365, 0)); ExpectTrue(wolfSSL_X509_set_notBefore(built, notBefore)); ExpectTrue(wolfSSL_X509_set_notAfter(built, notAfter)); /* Two setter calls with distinct keyIds, no prior AKID on cert */ ExpectIntEQ(wolfSSL_X509_set_authority_key_id(built, akid1, sizeof(akid1)), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_X509_set_authority_key_id(built, akid2, sizeof(akid2)), WOLFSSL_SUCCESS); ExpectIntGT(wolfSSL_X509_sign(built, priv, EVP_sha256()), 0); ExpectIntGT((derSz = wolfSSL_i2d_X509(built, &der)), 0); derPtr = der; ExpectNotNull(parsed = wolfSSL_d2i_X509(NULL, &derPtr, derSz)); ExpectIntGE((extIdx = wolfSSL_X509_get_ext_by_NID(parsed, NID_authority_key_identifier, -1)), 0); ExpectNotNull(ext = wolfSSL_X509_get_ext(parsed, extIdx)); ExpectNotNull(extData = wolfSSL_X509_EXTENSION_get_data(ext)); /* AKID extension must hold akid2, wrapped in: * SEQUENCE { [0] keyId } (24 bytes for a 20-byte keyId) */ ExpectIntEQ(extData->length, 24); if (extData != NULL && extData->data != NULL && extData->length == 24) { ExpectIntEQ((unsigned char)extData->data[0], 0x30); ExpectIntEQ((unsigned char)extData->data[2], 0x80); ExpectIntEQ((unsigned char)extData->data[3], 0x14); ExpectIntEQ(XMEMCMP((const byte*)extData->data + 4, akid2, sizeof(akid2)), 0); } /* Free DER/parsed cert so Case 2 can reuse the variables. */ XFREE(der, HEAP_HINT, DYNAMIC_TYPE_OPENSSL); der = NULL; derSz = 0; wolfSSL_X509_free(parsed); parsed = NULL; /* Case 2: set on cert loaded from PEM file that already has an AKID. */ ExpectNotNull(loaded = wolfSSL_X509_load_certificate_file(cliCertFile, WOLFSSL_FILETYPE_PEM)); ExpectIntEQ(wolfSSL_X509_set_authority_key_id(loaded, akid1, sizeof(akid1)), WOLFSSL_SUCCESS); /* Re-sign with priv and re-encode so we can inspect the freshly * encoded AKID. Signature/issuer binding correctness is not part of * this test; only the DER round-trip of the AKID extension is. */ ExpectIntGT(wolfSSL_X509_sign(loaded, priv, EVP_sha256()), 0); ExpectIntGT((derSz = wolfSSL_i2d_X509(loaded, &der)), 0); derPtr = der; ExpectNotNull(parsed = wolfSSL_d2i_X509(NULL, &derPtr, derSz)); extIdx = -1; ExpectIntGE((extIdx = wolfSSL_X509_get_ext_by_NID(parsed, NID_authority_key_identifier, -1)), 0); ExpectNotNull(ext = wolfSSL_X509_get_ext(parsed, extIdx)); ExpectNotNull(extData = wolfSSL_X509_EXTENSION_get_data(ext)); /* AKID extension must hold akid1 wrapped in SEQUENCE { [0] keyId } * (24 bytes for 20-byte keyId), not the original parsed-cert AKID. */ ExpectIntEQ(extData->length, 24); if (extData != NULL && extData->data != NULL && extData->length == 24) { ExpectIntEQ((unsigned char)extData->data[0], 0x30); ExpectIntEQ((unsigned char)extData->data[2], 0x80); ExpectIntEQ((unsigned char)extData->data[3], 0x14); ExpectIntEQ(XMEMCMP((const byte*)extData->data + 4, akid1, sizeof(akid1)), 0); } XFREE(der, HEAP_HINT, DYNAMIC_TYPE_OPENSSL); XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(name, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(header, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wolfSSL_X509_free(src); wolfSSL_X509_free(built); wolfSSL_X509_free(parsed); wolfSSL_X509_free(loaded); wolfSSL_EVP_PKEY_free(priv); wolfSSL_EVP_PKEY_free(pub); wolfSSL_ASN1_TIME_free(notBefore); wolfSSL_ASN1_TIME_free(notAfter); #endif return EXPECT_RESULT(); } static int test_wolfSSL_OpenSSL_add_all_algorithms(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) ExpectIntEQ(wolfSSL_add_all_algorithms(), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_OpenSSL_add_all_algorithms_noconf(), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_OpenSSL_add_all_algorithms_conf(), WOLFSSL_SUCCESS); #endif return EXPECT_RESULT(); } static int test_wolfSSL_OPENSSL_hexstr2buf(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) #define MAX_HEXSTR_BUFSZ 9 #define NUM_CASES 5 struct Output { const unsigned char buffer[MAX_HEXSTR_BUFSZ]; long ret; }; int i; int j; const char* inputs[NUM_CASES] = { "aabcd1357e", "01:12:23:34:a5:b6:c7:d8:e9", ":01:02", "012", ":ab:ac:d" }; struct Output expectedOutputs[NUM_CASES] = { {{0xaa, 0xbc, 0xd1, 0x35, 0x7e}, 5}, {{0x01, 0x12, 0x23, 0x34, 0xa5, 0xb6, 0xc7, 0xd8, 0xe9}, 9}, {{0x01, 0x02}, 2}, {{0x00}, 0}, {{0x00}, 0} }; long len = 0; unsigned char* returnedBuf = NULL; for (i = 0; i < NUM_CASES && !EXPECT_FAIL(); ++i) { returnedBuf = wolfSSL_OPENSSL_hexstr2buf(inputs[i], &len); if (returnedBuf == NULL) { ExpectIntEQ(expectedOutputs[i].ret, 0); continue; } ExpectIntEQ(expectedOutputs[i].ret, len); for (j = 0; j < len; ++j) { ExpectIntEQ(expectedOutputs[i].buffer[j], returnedBuf[j]); } OPENSSL_free(returnedBuf); } #endif return EXPECT_RESULT(); } #if defined(OPENSSL_ALL) static int test_wolfSSL_sk_CIPHER_description(void) { EXPECT_DECLS; #if !defined(NO_RSA) && !defined(NO_TLS) && !defined(NO_WOLFSSL_CLIENT) const long flags = SSL_OP_NO_SSLv2 | SSL_OP_NO_COMPRESSION; int i; int numCiphers = 0; const SSL_METHOD *method = NULL; const SSL_CIPHER *cipher = NULL; STACK_OF(SSL_CIPHER) *supportedCiphers = NULL; SSL_CTX *ctx = NULL; SSL *ssl = NULL; char buf[256]; char test_str[9] = "0000000"; const char badStr[] = "unknown"; const char certPath[] = "./certs/client-cert.pem"; XMEMSET(buf, 0, sizeof(buf)); ExpectNotNull(method = TLSv1_2_client_method()); ExpectNotNull(ctx = SSL_CTX_new(method)); SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, 0); SSL_CTX_set_verify_depth(ctx, 4); SSL_CTX_set_options(ctx, flags); ExpectIntEQ(SSL_CTX_load_verify_locations(ctx, certPath, NULL), WOLFSSL_SUCCESS); ExpectNotNull(ssl = SSL_new(ctx)); /* SSL_get_ciphers returns a stack of all configured ciphers * A flag, getCipherAtOffset, is set to later have SSL_CIPHER_description */ ExpectNotNull(supportedCiphers = SSL_get_ciphers(ssl)); /* loop through the amount of supportedCiphers */ numCiphers = sk_num(supportedCiphers); for (i = 0; i < numCiphers; ++i) { int j; /* sk_value increments "sk->data.cipher->cipherOffset". * wolfSSL_sk_CIPHER_description sets the description for * the cipher based on the provided offset. */ if ((cipher = (const WOLFSSL_CIPHER*)sk_value(supportedCiphers, i))) { SSL_CIPHER_description(cipher, buf, sizeof(buf)); } /* Search cipher description string for "unknown" descriptor */ for (j = 0; j < (int)XSTRLEN(buf); j++) { int k = 0; while ((k < (int)XSTRLEN(badStr)) && (buf[j] == badStr[k])) { test_str[k] = badStr[k]; j++; k++; } } /* Fail if test_str == badStr == "unknown" */ ExpectStrNE(test_str,badStr); } SSL_free(ssl); SSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } static int test_wolfSSL_get_ciphers_compat(void) { EXPECT_DECLS; #if !defined(NO_RSA) && !defined(NO_TLS) && !defined(NO_WOLFSSL_CLIENT) const SSL_METHOD *method = NULL; const char certPath[] = "./certs/client-cert.pem"; STACK_OF(SSL_CIPHER) *supportedCiphers = NULL; SSL_CTX *ctx = NULL; WOLFSSL *ssl = NULL; const long flags = SSL_OP_NO_SSLv2 | SSL_OP_NO_COMPRESSION; ExpectNotNull(method = SSLv23_client_method()); ExpectNotNull(ctx = SSL_CTX_new(method)); SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, 0); SSL_CTX_set_verify_depth(ctx, 4); SSL_CTX_set_options(ctx, flags); ExpectIntEQ(SSL_CTX_load_verify_locations(ctx, certPath, NULL), WOLFSSL_SUCCESS); ExpectNotNull(ssl = SSL_new(ctx)); /* Test Bad NULL input */ ExpectNull(supportedCiphers = SSL_get_ciphers(NULL)); /* Test for Good input */ ExpectNotNull(supportedCiphers = SSL_get_ciphers(ssl)); /* Further usage of SSL_get_ciphers/wolfSSL_get_ciphers_compat is * tested in test_wolfSSL_sk_CIPHER_description according to Qt usage */ SSL_free(ssl); SSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } /* Test that wolfSSL_get_ciphers_compat returns NULL (not an empty stack) * when no ciphers are available for a given protocol configuration. * wolfSSL_get_ciphers_compat() is mapped to SSL_get_ciphers(), which has * an expected return of NULL when no ciphers are available. */ static int test_wolfSSL_get_ciphers_compat_empty(void) { EXPECT_DECLS; #if !defined(NO_TLS) && !defined(NO_WOLFSSL_CLIENT) const SSL_METHOD *method = NULL; SSL_CTX *ctx = NULL; WOLFSSL *ssl = NULL; STACK_OF(SSL_CIPHER) *ciphers = NULL; ExpectNotNull(method = SSLv23_client_method()); ExpectNotNull(ctx = SSL_CTX_new(method)); ExpectNotNull(ssl = SSL_new(ctx)); /* Disable all protocol versions via options mask so that * sslCipherMinMaxCheck filters out every cipher suite */ wolfSSL_set_options(ssl, SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2 | SSL_OP_NO_TLSv1_3); ciphers = wolfSSL_get_ciphers_compat(ssl); /* Must be NULL, not a non-NULL empty stack */ ExpectNull(ciphers); SSL_free(ssl); SSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } static int test_wolfSSL_CTX_ctrl(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && !defined(NO_TLS) && \ !defined(NO_FILESYSTEM) && !defined(NO_RSA) && !defined(NO_WOLFSSL_SERVER) char caFile[] = "./certs/client-ca.pem"; char clientFile[] = "./certs/client-cert.pem"; SSL_CTX* ctx = NULL; X509* x509 = NULL; #if !defined(NO_DH) && !defined(NO_DSA) && !defined(NO_BIO) byte buf[6000]; char file[] = "./certs/dsaparams.pem"; XFILE f = XBADFILE; int bytes = 0; BIO* bio = NULL; DSA* dsa = NULL; DH* dh = NULL; #endif #ifdef HAVE_ECC WOLFSSL_EC_KEY* ecKey = NULL; #endif ExpectNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); ExpectNotNull(x509 = wolfSSL_X509_load_certificate_file(caFile, WOLFSSL_FILETYPE_PEM)); ExpectIntEQ((int)SSL_CTX_add_extra_chain_cert(ctx, x509), WOLFSSL_SUCCESS); if (EXPECT_FAIL()) { wolfSSL_X509_free(x509); } ExpectNotNull(x509 = wolfSSL_X509_load_certificate_file(clientFile, WOLFSSL_FILETYPE_PEM)); #if !defined(NO_DH) && !defined(NO_DSA) && !defined(NO_BIO) /* Initialize DH */ ExpectTrue((f = XFOPEN(file, "rb")) != XBADFILE); ExpectIntGT(bytes = (int)XFREAD(buf, 1, sizeof(buf), f), 0); if (f != XBADFILE) XFCLOSE(f); ExpectNotNull(bio = BIO_new_mem_buf((void*)buf, bytes)); ExpectNotNull(dsa = wolfSSL_PEM_read_bio_DSAparams(bio, NULL, NULL, NULL)); ExpectNotNull(dh = wolfSSL_DSA_dup_DH(dsa)); #endif #ifdef HAVE_ECC /* Initialize WOLFSSL_EC_KEY */ ExpectNotNull(ecKey = wolfSSL_EC_KEY_new()); ExpectIntEQ(wolfSSL_EC_KEY_generate_key(ecKey), 1); #endif /* additional test of getting EVP_PKEY key size from X509 * Do not run with user RSA because wolfSSL_RSA_size is not currently * allowed with user RSA */ { EVP_PKEY* pkey = NULL; #if defined(HAVE_ECC) X509* ecX509 = NULL; #endif /* HAVE_ECC */ ExpectNotNull(pkey = X509_get_pubkey(x509)); /* current RSA key is 2048 bit (256 bytes) */ ExpectIntEQ(EVP_PKEY_size(pkey), 256); EVP_PKEY_free(pkey); pkey = NULL; #if defined(HAVE_ECC) #if defined(USE_CERT_BUFFERS_256) ExpectNotNull(ecX509 = wolfSSL_X509_load_certificate_buffer( cliecc_cert_der_256, sizeof_cliecc_cert_der_256, SSL_FILETYPE_ASN1)); #else ExpectNotNull(ecX509 = wolfSSL_X509_load_certificate_file( cliEccCertFile, SSL_FILETYPE_PEM)); #endif ExpectNotNull(pkey = X509_get_pubkey(ecX509)); /* current ECC key is 256 bit (32 bytes) */ ExpectIntGE(EVP_PKEY_size(pkey), 72); X509_free(ecX509); EVP_PKEY_free(pkey); #endif /* HAVE_ECC */ } /* Tests should fail with passed in NULL pointer */ ExpectIntEQ((int)wolfSSL_CTX_ctrl(ctx, SSL_CTRL_EXTRA_CHAIN_CERT, 0, NULL), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); #if !defined(NO_DH) && !defined(NO_DSA) ExpectIntEQ((int)wolfSSL_CTX_ctrl(ctx, SSL_CTRL_SET_TMP_DH, 0, NULL), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); #endif #ifdef HAVE_ECC ExpectIntEQ((int)wolfSSL_CTX_ctrl(ctx, SSL_CTRL_SET_TMP_ECDH, 0, NULL), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); #endif /* Test with SSL_CTRL_EXTRA_CHAIN_CERT * wolfSSL_CTX_ctrl should succesffuly call SSL_CTX_add_extra_chain_cert */ ExpectIntEQ((int)wolfSSL_CTX_ctrl(ctx, SSL_CTRL_EXTRA_CHAIN_CERT, 0, x509), SSL_SUCCESS); if (EXPECT_FAIL()) { wolfSSL_X509_free(x509); } /* Test with SSL_CTRL_OPTIONS * wolfSSL_CTX_ctrl should succesffuly call SSL_CTX_set_options */ ExpectTrue(wolfSSL_CTX_ctrl(ctx, SSL_CTRL_OPTIONS, SSL_OP_NO_TLSv1, NULL) == SSL_OP_NO_TLSv1); ExpectTrue(SSL_CTX_get_options(ctx) == SSL_OP_NO_TLSv1); /* Test with SSL_CTRL_SET_TMP_DH * wolfSSL_CTX_ctrl should succesffuly call wolfSSL_SSL_CTX_set_tmp_dh */ #if !defined(NO_DH) && !defined(NO_DSA) && !defined(NO_BIO) ExpectIntEQ((int)wolfSSL_CTX_ctrl(ctx, SSL_CTRL_SET_TMP_DH, 0, dh), SSL_SUCCESS); #endif /* Test with SSL_CTRL_SET_TMP_ECDH * wolfSSL_CTX_ctrl should succesffuly call wolfSSL_SSL_CTX_set_tmp_ecdh */ #ifdef HAVE_ECC ExpectIntEQ((int)wolfSSL_CTX_ctrl(ctx, SSL_CTRL_SET_TMP_ECDH, 0, ecKey), SSL_SUCCESS); #endif #ifdef WOLFSSL_ENCRYPTED_KEYS ExpectNull(SSL_CTX_get_default_passwd_cb(ctx)); ExpectNull(SSL_CTX_get_default_passwd_cb_userdata(ctx)); #endif /* Test for min/max proto */ #ifndef WOLFSSL_NO_TLS12 ExpectIntEQ((int)wolfSSL_CTX_ctrl(ctx, SSL_CTRL_SET_MIN_PROTO_VERSION, 0, NULL), SSL_SUCCESS); ExpectIntEQ((int)wolfSSL_CTX_ctrl(ctx, SSL_CTRL_SET_MIN_PROTO_VERSION, TLS1_2_VERSION, NULL), SSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_get_min_proto_version(ctx), TLS1_2_VERSION); #endif #ifdef WOLFSSL_TLS13 ExpectIntEQ((int)wolfSSL_CTX_ctrl(ctx, SSL_CTRL_SET_MAX_PROTO_VERSION, 0, NULL), SSL_SUCCESS); ExpectIntEQ((int)wolfSSL_CTX_ctrl(ctx, SSL_CTRL_SET_MAX_PROTO_VERSION, TLS1_3_VERSION, NULL), SSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_get_max_proto_version(ctx), TLS1_3_VERSION); #ifndef WOLFSSL_NO_TLS12 ExpectIntEQ((int)wolfSSL_CTX_ctrl(ctx, SSL_CTRL_SET_MAX_PROTO_VERSION, TLS1_2_VERSION, NULL), SSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_get_max_proto_version(ctx), TLS1_2_VERSION); #endif #endif /* Cleanup and Pass */ #if !defined(NO_DH) && !defined(NO_DSA) #ifndef NO_BIO BIO_free(bio); DSA_free(dsa); DH_free(dh); dh = NULL; #endif #endif #ifdef HAVE_ECC wolfSSL_EC_KEY_free(ecKey); #endif SSL_CTX_free(ctx); #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ * !defined(NO_FILESYSTEM) && !defined(NO_RSA) */ return EXPECT_RESULT(); } #if !defined(NO_BIO) static word32 TXT_DB_hash(const WOLFSSL_STRING *s) { return (word32)lh_strhash(s[3]); } static int TXT_DB_cmp(const WOLFSSL_STRING *a, const WOLFSSL_STRING *b) { return XSTRCMP(a[3], b[3]); } #endif static int test_wolfSSL_TXT_DB(void) { EXPECT_DECLS; #if !defined(NO_FILESYSTEM) && !defined(NO_BIO) BIO *bio = NULL; TXT_DB *db = NULL; const int columns = 6; const char *fields[6] = { "V", "320926161116Z", "", "12BD", "unknown", "/CN=rsa doe", }; char** fields_copy = NULL; /* Test read */ ExpectNotNull(bio = BIO_new(BIO_s_file())); ExpectIntGT(BIO_read_filename(bio, "./tests/TXT_DB.txt"), 0); ExpectNotNull(db = TXT_DB_read(bio, columns)); ExpectNotNull(fields_copy = (char**)XMALLOC(sizeof(fields), NULL, DYNAMIC_TYPE_OPENSSL)); if (fields_copy != NULL) { XMEMCPY(fields_copy, fields, sizeof(fields)); } ExpectIntEQ(TXT_DB_insert(db, fields_copy), 1); if (EXPECT_FAIL()) { XFREE(fields_copy, NULL, DYNAMIC_TYPE_OPENSSL); } BIO_free(bio); bio = NULL; /* Test write */ ExpectNotNull(bio = BIO_new(BIO_s_mem())); ExpectIntEQ(TXT_DB_write(bio, db), 1484); BIO_free(bio); /* Test index */ ExpectIntEQ(TXT_DB_create_index(db, 3, NULL, (wolf_sk_hash_cb)(wc_ptr_t)TXT_DB_hash, (wolf_lh_compare_cb)TXT_DB_cmp), 1); ExpectNotNull(TXT_DB_get_by_index(db, 3, (WOLFSSL_STRING*)fields)); fields[3] = "12DA"; ExpectNotNull(TXT_DB_get_by_index(db, 3, (WOLFSSL_STRING*)fields)); fields[3] = "FFFF"; ExpectNull(TXT_DB_get_by_index(db, 3, (WOLFSSL_STRING*)fields)); fields[3] = ""; ExpectNull(TXT_DB_get_by_index(db, 3, (WOLFSSL_STRING*)fields)); TXT_DB_free(db); #endif return EXPECT_RESULT(); } static int test_wolfSSL_NCONF(void) { EXPECT_DECLS; #if !defined(NO_FILESYSTEM) && !defined(NO_BIO) const char* confFile = "./tests/NCONF_test.cnf"; CONF* conf = NULL; long eline = 0; long num = 0; ExpectNotNull(conf = NCONF_new(NULL)); ExpectIntEQ(NCONF_load(conf, confFile, &eline), 1); ExpectIntEQ(NCONF_get_number(conf, NULL, "port", &num), 1); ExpectIntEQ(num, 1234); ExpectIntEQ(NCONF_get_number(conf, "section2", "port", &num), 1); ExpectIntEQ(num, 4321); ExpectStrEQ(NCONF_get_string(conf, NULL, "dir"), "./test-dir"); ExpectStrEQ(NCONF_get_string(conf, "section1", "file1_copy"), "./test-dir/file1"); ExpectStrEQ(NCONF_get_string(conf, "section2", "file_list"), "./test-dir/file1:./test-dir/file2:./section1:file2"); NCONF_free(conf); #endif return EXPECT_RESULT(); } #endif /* OPENSSL_ALL */ static int test_wolfSSL_d2i_and_i2d_PublicKey(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_RSA) EVP_PKEY* pkey = NULL; const unsigned char* p = NULL; unsigned char *der = NULL; unsigned char *tmp = NULL; int derLen = 0; p = client_keypub_der_2048; /* Check that key can be successfully decoded. */ ExpectNotNull(pkey = wolfSSL_d2i_PublicKey(EVP_PKEY_RSA, NULL, &p, sizeof_client_keypub_der_2048)); /* Check that key can be successfully encoded. */ ExpectIntGE((derLen = wolfSSL_i2d_PublicKey(pkey, &der)), 0); /* Ensure that the encoded version matches the original. */ ExpectIntEQ(derLen, sizeof_client_keypub_der_2048); ExpectIntEQ(XMEMCMP(der, client_keypub_der_2048, derLen), 0); /* Do same test except with pre-allocated buffer to ensure the der pointer * is advanced. */ tmp = der; ExpectIntGE((derLen = wolfSSL_i2d_PublicKey(pkey, &tmp)), 0); ExpectIntEQ(derLen, sizeof_client_keypub_der_2048); ExpectIntEQ(XMEMCMP(der, client_keypub_der_2048, derLen), 0); ExpectTrue(der + derLen == tmp); XFREE(der, HEAP_HINT, DYNAMIC_TYPE_OPENSSL); EVP_PKEY_free(pkey); #endif return EXPECT_RESULT(); } static int test_wolfSSL_d2i_and_i2d_PublicKey_ecc(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && defined(HAVE_ECC) && !defined(NO_CERTS) && \ !defined(NO_ASN) && !defined(NO_PWDBASED) EVP_PKEY* pkey = NULL; const unsigned char* p; unsigned char *der = NULL; unsigned char *tmp = NULL; int derLen = -1; unsigned char pub_buf[65]; unsigned char pub_spki_buf[91]; const int pub_len = 65; const int pub_spki_len = 91; BN_CTX* ctx = NULL; EC_GROUP* curve = NULL; EC_KEY* ephemeral_key = NULL; const EC_POINT* h = NULL; ecc_key *eccKey = NULL; /* Generate an x963 key pair and get public part into pub_buf */ ExpectNotNull(ctx = BN_CTX_new()); ExpectNotNull(curve = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)); ExpectNotNull(ephemeral_key = EC_KEY_new_by_curve_name( NID_X9_62_prime256v1)); ExpectIntEQ(EC_KEY_generate_key(ephemeral_key), 1); ExpectNotNull(h = EC_KEY_get0_public_key(ephemeral_key)); ExpectIntEQ(pub_len, EC_POINT_point2oct(curve, h, POINT_CONVERSION_UNCOMPRESSED, pub_buf, pub_len, ctx)); /* Create an ecc key struct from the point. Use it to create a DER with the appropriate SubjectPublicKeyInfo format. */ ExpectNotNull(eccKey = (ecc_key *)XMALLOC(sizeof(*eccKey), NULL, DYNAMIC_TYPE_ECC)); ExpectIntEQ(wc_ecc_init(eccKey), 0); ExpectIntEQ(wc_ecc_import_x963(pub_buf, pub_len, eccKey), 0); ExpectIntEQ(derLen = wc_EccPublicKeyDerSize(eccKey, 1), pub_spki_len); ExpectIntEQ(derLen = wc_EccPublicKeyToDer(eccKey, pub_spki_buf, pub_spki_len, 1), pub_spki_len); /* Prepare the EVP_PKEY */ ExpectNotNull(pkey = EVP_PKEY_new()); p = pub_buf; /* Check that key can be successfully decoded. */ ExpectNotNull(wolfSSL_d2i_PublicKey(EVP_PKEY_EC, &pkey, &p, pub_len)); /* Check that key can be successfully encoded. */ ExpectIntGE((derLen = wolfSSL_i2d_PublicKey(pkey, &der)), 0); /* Ensure that the encoded version matches the original. */ ExpectIntEQ(derLen, pub_spki_len); ExpectIntEQ(XMEMCMP(der, pub_spki_buf, derLen), 0); /* Do same test except with pre-allocated buffer to ensure the der pointer * is advanced. */ tmp = der; ExpectIntGE((derLen = wolfSSL_i2d_PublicKey(pkey, &tmp)), 0); ExpectIntEQ(derLen, pub_spki_len); ExpectIntEQ(XMEMCMP(der, pub_spki_buf, derLen), 0); ExpectTrue(der + derLen == tmp); wc_ecc_free(eccKey); XFREE(eccKey, NULL, DYNAMIC_TYPE_ECC); XFREE(der, HEAP_HINT, DYNAMIC_TYPE_OPENSSL); EVP_PKEY_free(pkey); EC_KEY_free(ephemeral_key); EC_GROUP_free(curve); BN_CTX_free(ctx); #endif return EXPECT_RESULT(); } static int test_wolfSSL_d2i_and_i2d_DSAparams(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_DSA) DSA* dsa = NULL; byte derIn[] = { 0x30, 0x82, 0x01, 0x1f, 0x02, 0x81, 0x81, 0x00, 0xcd, 0xde, 0x25, 0x68, 0x80, 0x53, 0x0d, 0xe5, 0x77, 0xd6, 0xd2, 0x90, 0x39, 0x3f, 0x90, 0xa2, 0x3f, 0x33, 0x94, 0x6e, 0xe8, 0x4f, 0x2b, 0x63, 0xab, 0x30, 0xab, 0x15, 0xba, 0x11, 0xea, 0x8a, 0x5d, 0x8d, 0xcc, 0xb8, 0xd4, 0xa1, 0xd5, 0xc1, 0x47, 0x9d, 0x5a, 0x73, 0x6a, 0x62, 0x49, 0xd1, 0x06, 0x07, 0x67, 0xf6, 0x2f, 0xa3, 0x39, 0xbd, 0x4e, 0x0d, 0xb4, 0xd3, 0x22, 0x23, 0x84, 0xec, 0x93, 0x26, 0x5a, 0x49, 0xee, 0x7c, 0x89, 0x48, 0x66, 0x4d, 0xe8, 0xe8, 0xd8, 0x50, 0xfb, 0xa5, 0x71, 0x9f, 0x22, 0x18, 0xe5, 0xe6, 0x0b, 0x46, 0x87, 0x66, 0xee, 0x52, 0x8f, 0x46, 0x4f, 0xb5, 0x03, 0xce, 0xed, 0xe3, 0xbe, 0xe5, 0xb5, 0x81, 0xd2, 0x59, 0xe9, 0xc0, 0xad, 0x4d, 0xd0, 0x4d, 0x26, 0xf7, 0xba, 0x50, 0xe8, 0xc9, 0x8f, 0xfe, 0x24, 0x19, 0x3d, 0x2e, 0xa7, 0x52, 0x3c, 0x6d, 0x02, 0x15, 0x00, 0xfb, 0x47, 0xfb, 0xec, 0x81, 0x20, 0xc8, 0x1c, 0xe9, 0x4a, 0xba, 0x04, 0x6f, 0x19, 0x9b, 0x94, 0xee, 0x82, 0x67, 0xd3, 0x02, 0x81, 0x81, 0x00, 0x9b, 0x95, 0xbb, 0x85, 0xc5, 0x58, 0x4a, 0x32, 0x9c, 0xaa, 0x44, 0x85, 0xd6, 0x68, 0xdc, 0x3e, 0x14, 0xf4, 0xce, 0x6d, 0xa3, 0x49, 0x38, 0xea, 0xd6, 0x61, 0x48, 0x92, 0x5a, 0x40, 0x95, 0x49, 0x38, 0xaa, 0xe1, 0x39, 0x29, 0x68, 0x58, 0x47, 0x8a, 0x4b, 0x01, 0xe1, 0x2e, 0x8e, 0x6c, 0x63, 0x6f, 0x40, 0xca, 0x50, 0x3f, 0x8c, 0x0b, 0x99, 0xe4, 0x72, 0x42, 0xb8, 0xb1, 0xc2, 0x26, 0x48, 0xf1, 0x9c, 0x83, 0xc6, 0x37, 0x2e, 0x5a, 0xae, 0x11, 0x09, 0xd9, 0xf3, 0xad, 0x1f, 0x6f, 0xad, 0xad, 0x50, 0xe3, 0x78, 0x32, 0xe6, 0xde, 0x8e, 0xaa, 0xbf, 0xd1, 0x00, 0x9f, 0xb3, 0x02, 0x12, 0x19, 0xa2, 0x15, 0xec, 0x14, 0x18, 0x5c, 0x0e, 0x26, 0xce, 0xf9, 0xae, 0xcc, 0x7b, 0xb5, 0xd1, 0x26, 0xfc, 0x85, 0xfe, 0x14, 0x93, 0xb6, 0x9d, 0x7d, 0x76, 0xe3, 0x35, 0x97, 0x1e, 0xde, 0xc4 }; int derInLen = sizeof(derIn); byte* derOut = NULL; int derOutLen = -1; byte* p = derIn; /* Check that params can be successfully decoded. */ ExpectNotNull(dsa = d2i_DSAparams(NULL, (const byte**)&p, derInLen)); /* Check that params can be successfully encoded. */ ExpectIntGE((derOutLen = i2d_DSAparams(dsa, &derOut)), 0); /* Ensure that the encoded version matches the original. */ ExpectIntEQ(derInLen, derOutLen); ExpectIntEQ(XMEMCMP(derIn, derOut, derInLen), 0); XFREE(derOut, HEAP_HINT, DYNAMIC_TYPE_OPENSSL); DSA_free(dsa); #endif return EXPECT_RESULT(); } static int test_wolfSSL_i2d_PrivateKey(void) { EXPECT_DECLS; #if (!defined(NO_RSA) || defined(HAVE_ECC)) && defined(OPENSSL_EXTRA) && \ !defined(NO_ASN) && !defined(NO_PWDBASED) #if !defined(NO_RSA) && defined(USE_CERT_BUFFERS_2048) { EVP_PKEY* pkey = NULL; const unsigned char* server_key = (const unsigned char*)server_key_der_2048; unsigned char buf[FOURK_BUF]; unsigned char* pt = NULL; int bufSz = 0; ExpectNotNull(pkey = d2i_PrivateKey(EVP_PKEY_RSA, NULL, &server_key, (long)sizeof_server_key_der_2048)); ExpectIntEQ(i2d_PrivateKey(pkey, NULL), 1193); pt = buf; ExpectIntEQ((bufSz = i2d_PrivateKey(pkey, &pt)), 1193); ExpectIntNE((pt - buf), 0); ExpectIntEQ(XMEMCMP(buf, server_key_der_2048, bufSz), 0); EVP_PKEY_free(pkey); } #endif #if defined(OPENSSL_EXTRA) && defined(HAVE_ECC) && defined(USE_CERT_BUFFERS_256) { EVP_PKEY* pkey = NULL; const unsigned char* client_key = (const unsigned char*)ecc_clikey_der_256; unsigned char buf[FOURK_BUF]; unsigned char* pt = NULL; int bufSz = 0; ExpectNotNull((pkey = d2i_PrivateKey(EVP_PKEY_EC, NULL, &client_key, (long)sizeof_ecc_clikey_der_256))); ExpectIntEQ(i2d_PrivateKey(pkey, NULL), 121); pt = buf; ExpectIntEQ((bufSz = i2d_PrivateKey(pkey, &pt)), 121); ExpectIntNE((pt - buf), 0); ExpectIntEQ(XMEMCMP(buf, ecc_clikey_der_256, bufSz), 0); EVP_PKEY_free(pkey); } #endif #endif return EXPECT_RESULT(); } static int test_wolfSSL_OCSP_id_get0_info(void) { EXPECT_DECLS; #if (defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY)) && \ defined(HAVE_OCSP) && !defined(NO_FILESYSTEM) && !defined(NO_RSA) && \ !defined(WOLFSSL_SM2) && !defined(WOLFSSL_SM3) X509* cert = NULL; X509* issuer = NULL; OCSP_CERTID* id = NULL; OCSP_CERTID* id2 = NULL; ASN1_STRING* name = NULL; ASN1_OBJECT* pmd = NULL; ASN1_STRING* keyHash = NULL; ASN1_INTEGER* serial = NULL; ASN1_INTEGER* x509Int = NULL; ExpectNotNull(cert = wolfSSL_X509_load_certificate_file(svrCertFile, SSL_FILETYPE_PEM)); ExpectNotNull(issuer = wolfSSL_X509_load_certificate_file(caCertFile, SSL_FILETYPE_PEM)); ExpectNotNull(id = OCSP_cert_to_id(NULL, cert, issuer)); ExpectNotNull(id2 = OCSP_cert_to_id(NULL, cert, issuer)); ExpectIntEQ(OCSP_id_get0_info(NULL, NULL, NULL, NULL, NULL), 0); ExpectIntEQ(OCSP_id_get0_info(NULL, NULL, NULL, NULL, id), 1); /* name, pmd, keyHash not supported yet, expect failure if not NULL */ ExpectIntEQ(OCSP_id_get0_info(&name, NULL, NULL, NULL, id), 0); ExpectIntEQ(OCSP_id_get0_info(NULL, &pmd, NULL, NULL, id), 0); ExpectIntEQ(OCSP_id_get0_info(NULL, NULL, &keyHash, NULL, id), 0); ExpectIntEQ(OCSP_id_get0_info(NULL, NULL, NULL, &serial, id), 1); ExpectNotNull(serial); /* compare serial number to one in cert, should be equal */ ExpectNotNull(x509Int = X509_get_serialNumber(cert)); ExpectIntEQ(x509Int->length, serial->length); ExpectIntEQ(XMEMCMP(x509Int->data, serial->data, serial->length), 0); ExpectNotNull(x509Int = X509_get_serialNumber(cert)); /* test OCSP_id_cmp */ ExpectIntNE(OCSP_id_cmp(NULL, NULL), 0); ExpectIntNE(OCSP_id_cmp(id, NULL), 0); ExpectIntNE(OCSP_id_cmp(NULL, id2), 0); ExpectIntEQ(OCSP_id_cmp(id, id2), 0); if (id != NULL) { id->issuerHash[0] = ~id->issuerHash[0]; } ExpectIntNE(OCSP_id_cmp(id, id2), 0); OCSP_CERTID_free(id); OCSP_CERTID_free(id2); X509_free(cert); /* free's x509Int */ X509_free(issuer); #endif return EXPECT_RESULT(); } static int test_wolfSSL_i2d_OCSP_CERTID(void) { EXPECT_DECLS; #if (defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY)) && defined(HAVE_OCSP) WOLFSSL_OCSP_CERTID certId; byte* targetBuffer = NULL; byte* p; /* OCSP CertID bytes taken from PCAP */ byte rawCertId[] = { 0x30, 0x49, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, 0x80, 0x51, 0x06, 0x01, 0x32, 0xad, 0x9a, 0xc2, 0x7d, 0x51, 0x87, 0xa0, 0xe8, 0x87, 0xfb, 0x01, 0x62, 0x01, 0x55, 0xee, 0x04, 0x14, 0x03, 0xde, 0x50, 0x35, 0x56, 0xd1, 0x4c, 0xbb, 0x66, 0xf0, 0xa3, 0xe2, 0x1b, 0x1b, 0xc3, 0x97, 0xb2, 0x3d, 0xd1, 0x55, 0x02, 0x10, 0x01, 0xfd, 0xa3, 0xeb, 0x6e, 0xca, 0x75, 0xc8, 0x88, 0x43, 0x8b, 0x72, 0x4b, 0xcf, 0xbc, 0x91 }; int ret = 0; int i; XMEMSET(&certId, 0, sizeof(WOLFSSL_OCSP_CERTID)); certId.rawCertId = rawCertId; certId.rawCertIdSize = sizeof(rawCertId); ExpectNotNull(targetBuffer = (byte*)XMALLOC(sizeof(rawCertId), NULL, DYNAMIC_TYPE_TMP_BUFFER)); p = targetBuffer; /* Function returns the size of the encoded data. */ ExpectIntEQ(ret = wolfSSL_i2d_OCSP_CERTID(&certId, &p), sizeof(rawCertId)); /* If target buffer is not null, function increments targetBuffer to point * just past the end of the encoded data. */ ExpectPtrEq(p, (targetBuffer + sizeof(rawCertId))); for (i = 0; EXPECT_SUCCESS() && i < ret; ++i) { ExpectIntEQ(targetBuffer[i], rawCertId[i]); } XFREE(targetBuffer, NULL, DYNAMIC_TYPE_TMP_BUFFER); targetBuffer = NULL; /* If target buffer is null, function allocates memory for a buffer and * copies the encoded data into it. targetBuffer then points to the start of * this newly allocate buffer. */ ExpectIntEQ(ret = wolfSSL_i2d_OCSP_CERTID(&certId, &targetBuffer), sizeof(rawCertId)); for (i = 0; EXPECT_SUCCESS() && i < ret; ++i) { ExpectIntEQ(targetBuffer[i], rawCertId[i]); } XFREE(targetBuffer, NULL, DYNAMIC_TYPE_OPENSSL); #endif return EXPECT_RESULT(); } static int test_wolfSSL_d2i_OCSP_CERTID(void) { EXPECT_DECLS; #if (defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY)) && defined(HAVE_OCSP) WOLFSSL_OCSP_CERTID* certIdGood = NULL; WOLFSSL_OCSP_CERTID* certIdBad = NULL; const unsigned char* rawCertIdPtr = NULL; const unsigned char rawCertId[] = { 0x30, 0x49, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, 0x80, 0x51, 0x06, 0x01, 0x32, 0xad, 0x9a, 0xc2, 0x7d, 0x51, 0x87, 0xa0, 0xe8, 0x87, 0xfb, 0x01, 0x62, 0x01, 0x55, 0xee, 0x04, 0x14, 0x03, 0xde, 0x50, 0x35, 0x56, 0xd1, 0x4c, 0xbb, 0x66, 0xf0, 0xa3, 0xe2, 0x1b, 0x1b, 0xc3, 0x97, 0xb2, 0x3d, 0xd1, 0x55, 0x02, 0x10, 0x01, 0xfd, 0xa3, 0xeb, 0x6e, 0xca, 0x75, 0xc8, 0x88, 0x43, 0x8b, 0x72, 0x4b, 0xcf, 0xbc, 0x91 }; rawCertIdPtr = &rawCertId[0]; /* If the cert ID is NULL the function should allocate it and copy the * data to it. */ { WOLFSSL_OCSP_CERTID* certId = NULL; ExpectNotNull(certId = wolfSSL_d2i_OCSP_CERTID(&certId, &rawCertIdPtr, sizeof(rawCertId))); if (certId != NULL) { XFREE(certId->rawCertId, NULL, DYNAMIC_TYPE_OPENSSL); wolfSSL_OCSP_CERTID_free(certId); } } /* If the cert ID is not NULL the function will just copy the data to it. */ { WOLFSSL_OCSP_CERTID* certId = NULL; ExpectNotNull(certId = (WOLFSSL_OCSP_CERTID*)XMALLOC(sizeof(*certId), NULL, DYNAMIC_TYPE_TMP_BUFFER)); ExpectNotNull(certId); if (certId != NULL) XMEMSET(certId, 0, sizeof(*certId)); /* Reset rawCertIdPtr since it was push forward in the previous call. */ rawCertIdPtr = &rawCertId[0]; ExpectNotNull(certIdGood = wolfSSL_d2i_OCSP_CERTID(&certId, &rawCertIdPtr, sizeof(rawCertId))); ExpectPtrEq(certIdGood, certId); if (certId != NULL) { XFREE(certId->rawCertId, NULL, DYNAMIC_TYPE_OPENSSL); wolfSSL_OCSP_CERTID_free(certId); certId = NULL; } } /* The below tests should fail when passed bad parameters. NULL should * always be returned. */ { WOLFSSL_OCSP_CERTID* certId = NULL; ExpectNull(certIdBad = wolfSSL_d2i_OCSP_CERTID(&certId, NULL, sizeof(rawCertId))); ExpectNull(certIdBad = wolfSSL_d2i_OCSP_CERTID(&certId, &rawCertIdPtr, 0)); } #endif return EXPECT_RESULT(); } static int test_wolfSSL_OCSP_id_cmp(void) { EXPECT_DECLS; #if defined(OPENSSL_ALL) && defined(HAVE_OCSP) OCSP_CERTID id1; OCSP_CERTID id2; XMEMSET(&id1, 0, sizeof(id1)); XMEMSET(&id2, 0, sizeof(id2)); ExpectIntEQ(OCSP_id_cmp(&id1, &id2), 0); ExpectIntNE(OCSP_id_cmp(NULL, NULL), 0); ExpectIntNE(OCSP_id_cmp(&id1, NULL), 0); ExpectIntNE(OCSP_id_cmp(NULL, &id2), 0); #endif return EXPECT_RESULT(); } static int test_wolfSSL_OCSP_SINGLERESP_get0_id(void) { EXPECT_DECLS; #if defined(HAVE_OCSP) && defined(OPENSSL_EXTRA) WOLFSSL_OCSP_SINGLERESP single; const WOLFSSL_OCSP_CERTID* certId; XMEMSET(&single, 0, sizeof(single)); certId = wolfSSL_OCSP_SINGLERESP_get0_id(&single); ExpectPtrEq(&single, certId); ExpectNull(wolfSSL_OCSP_SINGLERESP_get0_id(NULL)); #endif return EXPECT_RESULT(); } static int test_wolfSSL_OCSP_single_get0_status(void) { EXPECT_DECLS; #if defined(HAVE_OCSP) && defined(OPENSSL_EXTRA) && \ defined(WOLFSSL_OCSP_PARSE_STATUS) WOLFSSL_OCSP_SINGLERESP single; CertStatus certStatus; WOLFSSL_ASN1_TIME* thisDate; WOLFSSL_ASN1_TIME* nextDate; int ret, i; XMEMSET(&single, 0, sizeof(WOLFSSL_OCSP_SINGLERESP)); XMEMSET(&certStatus, 0, sizeof(CertStatus)); /* Fill the date fields with some dummy data. */ for (i = 0; i < CTC_DATE_SIZE; ++i) { certStatus.thisDateParsed.data[i] = i; certStatus.nextDateParsed.data[i] = i; } certStatus.status = CERT_GOOD; single.status = &certStatus; ret = wolfSSL_OCSP_single_get0_status(&single, NULL, NULL, &thisDate, &nextDate); ExpectIntEQ(ret, CERT_GOOD); ExpectPtrEq(thisDate, &certStatus.thisDateParsed); ExpectPtrEq(nextDate, &certStatus.nextDateParsed); ExpectIntEQ(wolfSSL_OCSP_single_get0_status(NULL, NULL, NULL, NULL, NULL), -1); ExpectIntEQ(wolfSSL_OCSP_single_get0_status(&single, NULL, NULL, NULL, NULL), CERT_GOOD); #endif return EXPECT_RESULT(); } static int test_wolfSSL_OCSP_resp_count(void) { EXPECT_DECLS; #if defined(HAVE_OCSP) && defined(OPENSSL_EXTRA) WOLFSSL_OCSP_BASICRESP basicResp; WOLFSSL_OCSP_SINGLERESP singleRespOne; WOLFSSL_OCSP_SINGLERESP singleRespTwo; XMEMSET(&basicResp, 0, sizeof(WOLFSSL_OCSP_BASICRESP)); XMEMSET(&singleRespOne, 0, sizeof(WOLFSSL_OCSP_SINGLERESP)); XMEMSET(&singleRespTwo, 0, sizeof(WOLFSSL_OCSP_SINGLERESP)); ExpectIntEQ(wolfSSL_OCSP_resp_count(&basicResp), 0); basicResp.single = &singleRespOne; ExpectIntEQ(wolfSSL_OCSP_resp_count(&basicResp), 1); singleRespOne.next = &singleRespTwo; ExpectIntEQ(wolfSSL_OCSP_resp_count(&basicResp), 2); #endif return EXPECT_RESULT(); } static int test_wolfSSL_OCSP_resp_get0(void) { EXPECT_DECLS; #if defined(HAVE_OCSP) && defined(OPENSSL_EXTRA) WOLFSSL_OCSP_BASICRESP basicResp; WOLFSSL_OCSP_SINGLERESP singleRespOne; WOLFSSL_OCSP_SINGLERESP singleRespTwo; XMEMSET(&basicResp, 0, sizeof(WOLFSSL_OCSP_BASICRESP)); XMEMSET(&singleRespOne, 0, sizeof(WOLFSSL_OCSP_SINGLERESP)); XMEMSET(&singleRespTwo, 0, sizeof(WOLFSSL_OCSP_SINGLERESP)); basicResp.single = &singleRespOne; singleRespOne.next = &singleRespTwo; ExpectPtrEq(wolfSSL_OCSP_resp_get0(&basicResp, 0), &singleRespOne); ExpectPtrEq(wolfSSL_OCSP_resp_get0(&basicResp, 1), &singleRespTwo); #endif return EXPECT_RESULT(); } static int test_wolfSSL_OCSP_parse_url(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && defined(HAVE_OCSP) #define CK_OPU_OK(u, h, po, pa, s) do { \ char* host = NULL; \ char* port = NULL; \ char* path = NULL; \ int isSsl = 0; \ ExpectIntEQ(OCSP_parse_url(u, &host, &port, &path, &isSsl), 1); \ ExpectStrEQ(host, h); \ ExpectStrEQ(port, po); \ ExpectStrEQ(path, pa); \ ExpectIntEQ(isSsl, s); \ XFREE(host, NULL, DYNAMIC_TYPE_OPENSSL); \ XFREE(port, NULL, DYNAMIC_TYPE_OPENSSL); \ XFREE(path, NULL, DYNAMIC_TYPE_OPENSSL); \ } while(0) #define CK_OPU_FAIL(u) do { \ char* host = NULL; \ char* port = NULL; \ char* path = NULL; \ int isSsl = 0; \ ExpectIntEQ(OCSP_parse_url(u, &host, &port, &path, &isSsl), 0); \ XFREE(host, NULL, DYNAMIC_TYPE_OPENSSL); \ XFREE(port, NULL, DYNAMIC_TYPE_OPENSSL); \ XFREE(path, NULL, DYNAMIC_TYPE_OPENSSL); \ } while(0) CK_OPU_OK("http://localhost", "localhost", "80", "/", 0); CK_OPU_OK("https://wolfssl.com", "wolfssl.com", "443", "/", 1); CK_OPU_OK("https://www.wolfssl.com/fips-140-3-announcement-to-the-world/", "www.wolfssl.com", "443", "/fips-140-3-announcement-to-the-world/", 1); CK_OPU_OK("http://localhost:1234", "localhost", "1234", "/", 0); CK_OPU_OK("https://localhost:1234", "localhost", "1234", "/", 1); CK_OPU_FAIL("ftp://localhost"); /* two strings to cppcheck doesn't mark it as a c++ style comment */ CK_OPU_FAIL("http/""/localhost"); CK_OPU_FAIL("http:/localhost"); CK_OPU_FAIL("https://localhost/path:1234"); #undef CK_OPU_OK #undef CK_OPU_FAIL #endif return EXPECT_RESULT(); } #if defined(OPENSSL_ALL) && defined(HAVE_OCSP) && \ defined(WOLFSSL_SIGNER_DER_CERT) && !defined(NO_FILESYSTEM) && \ !defined(NO_ASN_TIME) && \ !defined(WOLFSSL_SM2) && !defined(WOLFSSL_SM3) static time_t test_wolfSSL_OCSP_REQ_CTX_time_cb(time_t* t) { if (t != NULL) { *t = 1722006780; } return 1722006780; } #endif static int test_wolfSSL_OCSP_REQ_CTX(void) { EXPECT_DECLS; #if defined(OPENSSL_ALL) && defined(HAVE_OCSP) && \ defined(WOLFSSL_SIGNER_DER_CERT) && !defined(NO_FILESYSTEM) && \ !defined(WOLFSSL_SM2) && !defined(WOLFSSL_SM3) /* This buffer was taken from the ocsp-stapling.test test case 1. The ocsp * response was captured in wireshark. It contains both the http and binary * parts. The time test_wolfSSL_OCSP_REQ_CTX_time_cb is set exactly so that * the time check passes. */ unsigned char ocspRespBin[] = { 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2d, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x31, 0x38, 0x32, 0x31, 0x0d, 0x0a, 0x0d, 0x0a, 0x30, 0x82, 0x07, 0x19, 0x0a, 0x01, 0x00, 0xa0, 0x82, 0x07, 0x12, 0x30, 0x82, 0x07, 0x0e, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01, 0x04, 0x82, 0x06, 0xff, 0x30, 0x82, 0x06, 0xfb, 0x30, 0x82, 0x01, 0x19, 0xa1, 0x81, 0xa1, 0x30, 0x81, 0x9e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x74, 0x6f, 0x6e, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x07, 0x77, 0x6f, 0x6c, 0x66, 0x53, 0x53, 0x4c, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x0b, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x77, 0x6f, 0x6c, 0x66, 0x53, 0x53, 0x4c, 0x20, 0x4f, 0x43, 0x53, 0x50, 0x20, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x65, 0x72, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6e, 0x66, 0x6f, 0x40, 0x77, 0x6f, 0x6c, 0x66, 0x73, 0x73, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x18, 0x0f, 0x32, 0x30, 0x32, 0x34, 0x30, 0x37, 0x32, 0x36, 0x31, 0x35, 0x31, 0x32, 0x30, 0x35, 0x5a, 0x30, 0x62, 0x30, 0x60, 0x30, 0x38, 0x30, 0x07, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x04, 0x14, 0x71, 0x4d, 0x82, 0x23, 0x40, 0x59, 0xc0, 0x96, 0xa1, 0x37, 0x43, 0xfa, 0x31, 0xdb, 0xba, 0xb1, 0x43, 0x18, 0xda, 0x04, 0x04, 0x14, 0x83, 0xc6, 0x3a, 0x89, 0x2c, 0x81, 0xf4, 0x02, 0xd7, 0x9d, 0x4c, 0xe2, 0x2a, 0xc0, 0x71, 0x82, 0x64, 0x44, 0xda, 0x0e, 0x02, 0x01, 0x05, 0x80, 0x00, 0x18, 0x0f, 0x32, 0x30, 0x32, 0x34, 0x30, 0x37, 0x32, 0x36, 0x31, 0x35, 0x31, 0x32, 0x30, 0x35, 0x5a, 0xa0, 0x11, 0x18, 0x0f, 0x32, 0x30, 0x32, 0x34, 0x30, 0x37, 0x32, 0x36, 0x31, 0x35, 0x31, 0x33, 0x30, 0x35, 0x5a, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x89, 0x7a, 0xe9, 0x6b, 0x66, 0x47, 0x8e, 0x52, 0x16, 0xf9, 0x8a, 0x5a, 0x1e, 0x7a, 0x35, 0xbb, 0x1d, 0x6c, 0xd8, 0x31, 0xbb, 0x24, 0xd2, 0xd7, 0xa4, 0x30, 0x27, 0x06, 0x17, 0x66, 0xd1, 0xf9, 0x8d, 0x24, 0xb0, 0x49, 0x37, 0x62, 0x13, 0x78, 0x5e, 0xa6, 0x6d, 0xea, 0xe3, 0xd0, 0x30, 0x82, 0x7d, 0xb6, 0xf6, 0x55, 0x82, 0x11, 0xdc, 0xe7, 0x0f, 0xd6, 0x24, 0xb4, 0x80, 0x23, 0x4f, 0xfd, 0xa7, 0x9a, 0x4b, 0xac, 0xf2, 0xd3, 0xde, 0x42, 0x10, 0xfb, 0x4b, 0x29, 0x06, 0x02, 0x7b, 0x47, 0x36, 0x70, 0x75, 0x45, 0x38, 0x8d, 0x3e, 0x55, 0x9c, 0xce, 0x78, 0xd8, 0x18, 0x45, 0x47, 0x2d, 0x2a, 0x46, 0x65, 0x13, 0x93, 0x1a, 0x98, 0x90, 0xc6, 0x2d, 0xd5, 0x05, 0x2a, 0xfc, 0xcb, 0xac, 0x53, 0x73, 0x93, 0x42, 0x4e, 0xdb, 0x17, 0x91, 0xcb, 0xe1, 0x08, 0x03, 0xd1, 0x33, 0x57, 0x4b, 0x1d, 0xb8, 0x71, 0x84, 0x01, 0x04, 0x47, 0x6f, 0x06, 0xfa, 0x76, 0x7d, 0xd9, 0x37, 0x64, 0x57, 0x37, 0x3a, 0x8f, 0x4d, 0x88, 0x11, 0xa5, 0xd4, 0xaa, 0xcb, 0x49, 0x47, 0x86, 0xdd, 0xcf, 0x46, 0xa6, 0xfa, 0x8e, 0xf2, 0x62, 0x0f, 0xc9, 0x25, 0xf2, 0x39, 0x62, 0x3e, 0x2d, 0x35, 0xc4, 0x76, 0x7b, 0xae, 0xd5, 0xe8, 0x85, 0xa1, 0xa6, 0x2d, 0x41, 0xd6, 0x8e, 0x3c, 0xfa, 0xdc, 0x6c, 0x66, 0xe2, 0x61, 0xe7, 0xe5, 0x90, 0xa1, 0xfd, 0x7f, 0xdb, 0x18, 0xd0, 0xeb, 0x6d, 0x73, 0x08, 0x5f, 0x6a, 0x65, 0x44, 0x50, 0xad, 0x38, 0x9d, 0xb6, 0xfb, 0xbf, 0x28, 0x55, 0x84, 0x65, 0xfa, 0x0e, 0x34, 0xfc, 0x43, 0x19, 0x80, 0x5c, 0x7d, 0x2d, 0x5b, 0xd8, 0x60, 0xec, 0x0e, 0xf9, 0x1e, 0x6e, 0x32, 0x3f, 0x35, 0xf7, 0xec, 0x7e, 0x47, 0xba, 0xb5, 0xd2, 0xaa, 0x5a, 0x9d, 0x07, 0x2c, 0xc5, 0xa0, 0x82, 0x04, 0xc6, 0x30, 0x82, 0x04, 0xc2, 0x30, 0x82, 0x04, 0xbe, 0x30, 0x82, 0x03, 0xa6, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x04, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x81, 0x97, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x74, 0x6f, 0x6e, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x07, 0x77, 0x6f, 0x6c, 0x66, 0x53, 0x53, 0x4c, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x0b, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f, 0x77, 0x6f, 0x6c, 0x66, 0x53, 0x53, 0x4c, 0x20, 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6e, 0x66, 0x6f, 0x40, 0x77, 0x6f, 0x6c, 0x66, 0x73, 0x73, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x34, 0x30, 0x37, 0x32, 0x36, 0x31, 0x35, 0x31, 0x32, 0x30, 0x34, 0x5a, 0x17, 0x0d, 0x32, 0x37, 0x30, 0x34, 0x32, 0x32, 0x31, 0x35, 0x31, 0x32, 0x30, 0x34, 0x5a, 0x30, 0x81, 0x9e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x74, 0x6f, 0x6e, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x07, 0x77, 0x6f, 0x6c, 0x66, 0x53, 0x53, 0x4c, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x0b, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x77, 0x6f, 0x6c, 0x66, 0x53, 0x53, 0x4c, 0x20, 0x4f, 0x43, 0x53, 0x50, 0x20, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x65, 0x72, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6e, 0x66, 0x6f, 0x40, 0x77, 0x6f, 0x6c, 0x66, 0x73, 0x73, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xb8, 0xba, 0x23, 0xb4, 0xf6, 0xc3, 0x7b, 0x14, 0xc3, 0xa4, 0xf5, 0x1d, 0x61, 0xa1, 0xf5, 0x1e, 0x63, 0xb9, 0x85, 0x23, 0x34, 0x50, 0x6d, 0xf8, 0x7c, 0xa2, 0x8a, 0x04, 0x8b, 0xd5, 0x75, 0x5c, 0x2d, 0xf7, 0x63, 0x88, 0xd1, 0x07, 0x7a, 0xea, 0x0b, 0x45, 0x35, 0x2b, 0xeb, 0x1f, 0xb1, 0x22, 0xb4, 0x94, 0x41, 0x38, 0xe2, 0x9d, 0x74, 0xd6, 0x8b, 0x30, 0x22, 0x10, 0x51, 0xc5, 0xdb, 0xca, 0x3f, 0x46, 0x2b, 0xfe, 0xe5, 0x5a, 0x3f, 0x41, 0x74, 0x67, 0x75, 0x95, 0xa9, 0x94, 0xd5, 0xc3, 0xee, 0x42, 0xf8, 0x8d, 0xeb, 0x92, 0x95, 0xe1, 0xd9, 0x65, 0xb7, 0x43, 0xc4, 0x18, 0xde, 0x16, 0x80, 0x90, 0xce, 0x24, 0x35, 0x21, 0xc4, 0x55, 0xac, 0x5a, 0x51, 0xe0, 0x2e, 0x2d, 0xb3, 0x0a, 0x5a, 0x4f, 0x4a, 0x73, 0x31, 0x50, 0xee, 0x4a, 0x16, 0xbd, 0x39, 0x8b, 0xad, 0x05, 0x48, 0x87, 0xb1, 0x99, 0xe2, 0x10, 0xa7, 0x06, 0x72, 0x67, 0xca, 0x5c, 0xd1, 0x97, 0xbd, 0xc8, 0xf1, 0x76, 0xf8, 0xe0, 0x4a, 0xec, 0xbc, 0x93, 0xf4, 0x66, 0x4c, 0x28, 0x71, 0xd1, 0xd8, 0x66, 0x03, 0xb4, 0x90, 0x30, 0xbb, 0x17, 0xb0, 0xfe, 0x97, 0xf5, 0x1e, 0xe8, 0xc7, 0x5d, 0x9b, 0x8b, 0x11, 0x19, 0x12, 0x3c, 0xab, 0x82, 0x71, 0x78, 0xff, 0xae, 0x3f, 0x32, 0xb2, 0x08, 0x71, 0xb2, 0x1b, 0x8c, 0x27, 0xac, 0x11, 0xb8, 0xd8, 0x43, 0x49, 0xcf, 0xb0, 0x70, 0xb1, 0xf0, 0x8c, 0xae, 0xda, 0x24, 0x87, 0x17, 0x3b, 0xd8, 0x04, 0x65, 0x6c, 0x00, 0x76, 0x50, 0xef, 0x15, 0x08, 0xd7, 0xb4, 0x73, 0x68, 0x26, 0x14, 0x87, 0x95, 0xc3, 0x5f, 0x6e, 0x61, 0xb8, 0x87, 0x84, 0xfa, 0x80, 0x1a, 0x0a, 0x8b, 0x98, 0xf3, 0xe3, 0xff, 0x4e, 0x44, 0x1c, 0x65, 0x74, 0x7c, 0x71, 0x54, 0x65, 0xe5, 0x39, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0x0a, 0x30, 0x82, 0x01, 0x06, 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x32, 0x67, 0xe1, 0xb1, 0x79, 0xd2, 0x81, 0xfc, 0x9f, 0x23, 0x0c, 0x70, 0x40, 0x50, 0xb5, 0x46, 0x56, 0xb8, 0x30, 0x36, 0x30, 0x81, 0xc4, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x81, 0xbc, 0x30, 0x81, 0xb9, 0x80, 0x14, 0x73, 0xb0, 0x1c, 0xa4, 0x2f, 0x82, 0xcb, 0xcf, 0x47, 0xa5, 0x38, 0xd7, 0xb0, 0x04, 0x82, 0x3a, 0x7e, 0x72, 0x15, 0x21, 0xa1, 0x81, 0x9d, 0xa4, 0x81, 0x9a, 0x30, 0x81, 0x97, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x74, 0x6f, 0x6e, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x07, 0x77, 0x6f, 0x6c, 0x66, 0x53, 0x53, 0x4c, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x0b, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f, 0x77, 0x6f, 0x6c, 0x66, 0x53, 0x53, 0x4c, 0x20, 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6e, 0x66, 0x6f, 0x40, 0x77, 0x6f, 0x6c, 0x66, 0x73, 0x73, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x82, 0x01, 0x63, 0x30, 0x13, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x0c, 0x30, 0x0a, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x09, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x37, 0xb9, 0x66, 0xd3, 0xa1, 0x08, 0xfc, 0x37, 0x58, 0x4e, 0xe0, 0x8c, 0xd3, 0x7f, 0xa6, 0x0f, 0x59, 0xd3, 0x14, 0xf7, 0x4b, 0x36, 0xf7, 0x2e, 0x98, 0xeb, 0x7c, 0x03, 0x3f, 0x3a, 0xd6, 0x9c, 0xcd, 0xb4, 0x9e, 0x8d, 0x5f, 0x92, 0xa6, 0x6f, 0x63, 0x87, 0x34, 0xe8, 0x83, 0xfd, 0x6d, 0x34, 0x64, 0xb5, 0xf0, 0x9c, 0x71, 0x02, 0xb8, 0xf6, 0x2f, 0x10, 0xa0, 0x92, 0x8f, 0x3f, 0x86, 0x3e, 0xe2, 0x01, 0x5a, 0x56, 0x39, 0x0a, 0x8d, 0xb1, 0xbe, 0x03, 0xf7, 0xf8, 0xa7, 0x88, 0x46, 0xef, 0x81, 0xa0, 0xad, 0x86, 0xc9, 0xe6, 0x23, 0x89, 0x1d, 0xa6, 0x24, 0x45, 0xf2, 0x6a, 0x83, 0x2d, 0x8e, 0x92, 0x17, 0x1e, 0x44, 0x19, 0xfa, 0x0f, 0x47, 0x6b, 0x8f, 0x4a, 0xa2, 0xda, 0xab, 0xd5, 0x2b, 0xcd, 0xcb, 0x14, 0xf0, 0xb5, 0xcf, 0x7c, 0x76, 0x42, 0x32, 0x90, 0x21, 0xdc, 0xdd, 0x52, 0xfc, 0x53, 0x7e, 0xff, 0x7f, 0xd9, 0x58, 0x6b, 0x1f, 0x73, 0xee, 0x83, 0xf4, 0x67, 0xfa, 0x4a, 0x4f, 0x24, 0xe4, 0x2b, 0x10, 0x74, 0x89, 0x52, 0x9a, 0xf7, 0xa4, 0xe0, 0xaf, 0xf5, 0x63, 0xd7, 0xfa, 0x0b, 0x2c, 0xc9, 0x39, 0x5d, 0xbd, 0x44, 0x93, 0x69, 0xa4, 0x1d, 0x01, 0xe2, 0x66, 0xe7, 0xc1, 0x11, 0x44, 0x7d, 0x0a, 0x7e, 0x5d, 0x1d, 0x26, 0xc5, 0x4a, 0x26, 0x2e, 0xa3, 0x58, 0xc4, 0xf7, 0x10, 0xcb, 0xba, 0xe6, 0x27, 0xfc, 0xdb, 0x54, 0xe2, 0x60, 0x08, 0xc2, 0x0e, 0x4b, 0xd4, 0xaa, 0x22, 0x23, 0x93, 0x9f, 0xe1, 0xcb, 0x85, 0xa4, 0x41, 0x6f, 0x26, 0xa7, 0x77, 0x8a, 0xef, 0x66, 0xd0, 0xf8, 0x33, 0xf6, 0xfd, 0x6d, 0x37, 0x7a, 0x89, 0xcc, 0x88, 0x3b, 0x82, 0xd0, 0xa9, 0xdf, 0xf1, 0x3d, 0xdc, 0xb0, 0x06, 0x1c, 0xe4, 0x4b, 0x57, 0xb4, 0x0c, 0x65, 0xb9, 0xb4, 0x6c }; OCSP_REQ_CTX *ctx = NULL; OCSP_REQUEST *req = NULL; OCSP_CERTID *cid = NULL; OCSP_RESPONSE *rsp = NULL; BIO* bio1 = NULL; BIO* bio2 = NULL; X509* cert = NULL; X509* empty = NULL; X509 *issuer = NULL; X509_LOOKUP *lookup = NULL; X509_STORE *store = NULL; STACK_OF(X509_OBJECT) *str_objs = NULL; X509_OBJECT *x509_obj = NULL; STACK_OF(WOLFSSL_STRING) *skStr = NULL; ExpectNotNull(bio1 = BIO_new(BIO_s_bio())); ExpectNotNull(bio2 = BIO_new(BIO_s_bio())); ExpectIntEQ(BIO_make_bio_pair(bio1, bio2), WOLFSSL_SUCCESS); /* Load the leaf cert */ ExpectNotNull(cert = wolfSSL_X509_load_certificate_file( "certs/ocsp/server1-cert.pem", WOLFSSL_FILETYPE_PEM)); ExpectNull(wolfSSL_X509_get1_ocsp(NULL)); ExpectNotNull(skStr = wolfSSL_X509_get1_ocsp(cert)); wolfSSL_X509_email_free(NULL); wolfSSL_X509_email_free(skStr); ExpectNotNull(empty = wolfSSL_X509_new()); ExpectNull(wolfSSL_X509_get1_ocsp(empty)); wolfSSL_X509_free(empty); ExpectNotNull(store = X509_STORE_new()); ExpectNotNull(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file())); ExpectIntEQ(X509_LOOKUP_load_file(lookup, "certs/ocsp/server1-cert.pem", X509_FILETYPE_PEM), 1); ExpectNotNull(str_objs = X509_STORE_get0_objects(store)); ExpectNull(X509_OBJECT_retrieve_by_subject(NULL, X509_LU_X509, NULL)); ExpectNull(X509_OBJECT_retrieve_by_subject(str_objs, X509_LU_X509, NULL)); ExpectNull(X509_OBJECT_retrieve_by_subject(NULL, X509_LU_X509, X509_get_issuer_name(cert))); ExpectNull(X509_OBJECT_retrieve_by_subject(str_objs, X509_LU_CRL, X509_get_issuer_name(cert))); ExpectNotNull(x509_obj = X509_OBJECT_retrieve_by_subject(str_objs, X509_LU_X509, X509_get_issuer_name(cert))); ExpectNotNull(issuer = X509_OBJECT_get0_X509(x509_obj)); ExpectTrue(wolfSSL_X509_OBJECT_get_type(NULL) == WOLFSSL_X509_LU_NONE); #ifndef NO_WOLFSSL_STUB /* Not implemented and not in OpenSSL 1.1.0+ */ wolfSSL_X509_OBJECT_free_contents(x509_obj); #endif wolfSSL_X509_OBJECT_free(NULL); ExpectNotNull(req = OCSP_REQUEST_new()); ExpectNotNull(cid = OCSP_cert_to_id(EVP_sha1(), cert, issuer)); ExpectNotNull(OCSP_request_add0_id(req, cid)); ExpectIntEQ(OCSP_request_add1_nonce(req, NULL, -1), 1); ExpectNotNull(ctx = OCSP_sendreq_new(bio1, "/", NULL, -1)); ExpectIntEQ(OCSP_REQ_CTX_add1_header(ctx, "Host", "127.0.0.1"), 1); ExpectIntEQ(OCSP_REQ_CTX_set1_req(ctx, req), 1); ExpectIntEQ(OCSP_sendreq_nbio(&rsp, ctx), -1); ExpectIntEQ(BIO_write(bio2, ocspRespBin, sizeof(ocspRespBin)), sizeof(ocspRespBin)); #ifndef NO_ASN_TIME ExpectIntEQ(wc_SetTimeCb(test_wolfSSL_OCSP_REQ_CTX_time_cb), 0); ExpectIntEQ(OCSP_sendreq_nbio(&rsp, ctx), 1); ExpectIntEQ(wc_SetTimeCb(NULL), 0); ExpectNotNull(rsp); #endif OCSP_REQ_CTX_free(ctx); OCSP_REQUEST_free(req); OCSP_RESPONSE_free(rsp); BIO_free(bio1); BIO_free(bio2); X509_free(cert); X509_STORE_free(store); #endif return EXPECT_RESULT(); } static int test_wolfSSL_X509_get1_ca_issuers(void) { EXPECT_DECLS; #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) || \ defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)) && \ defined(WOLFSSL_ASN_CA_ISSUER) && !defined(NO_FILESYSTEM) && \ !defined(NO_RSA) X509* cert = NULL; STACK_OF(WOLFSSL_STRING) *skStr = NULL; WOLFSSL_STRING url = NULL; const char* expected = "http://example.com/ca.pem"; ExpectNull(wolfSSL_X509_get1_ca_issuers(NULL)); ExpectNotNull(cert = wolfSSL_X509_load_certificate_file( "certs/aia/ca-issuers-cert.pem", WOLFSSL_FILETYPE_PEM)); ExpectNotNull(skStr = wolfSSL_X509_get1_ca_issuers(cert)); ExpectIntEQ(wolfSSL_sk_WOLFSSL_STRING_num(skStr), 1); ExpectNotNull(url = wolfSSL_sk_WOLFSSL_STRING_value(skStr, 0)); ExpectIntEQ(XSTRCMP(url, expected), 0); wolfSSL_X509_email_free(skStr); wolfSSL_X509_free(cert); #endif return EXPECT_RESULT(); } static int test_wolfSSL_X509_get1_aia_multi(void) { EXPECT_DECLS; #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) || \ defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)) && \ defined(WOLFSSL_ASN_CA_ISSUER) && !defined(NO_FILESYSTEM) && \ !defined(NO_RSA) X509* cert = NULL; STACK_OF(WOLFSSL_STRING) *ocsp = NULL; STACK_OF(WOLFSSL_STRING) *ca = NULL; const char* ocspExp1 = "http://127.0.0.1:22221"; const char* ocspExp2 = "http://127.0.0.1:22222"; const char* caExp1 = "http://www.wolfssl.com/ca.pem"; const char* caExp2 = "https://www.wolfssl.com/ca2.pem"; int i; int ocspFound1 = 0, ocspFound2 = 0; int caFound1 = 0, caFound2 = 0; ExpectNotNull(cert = wolfSSL_X509_load_certificate_file( "certs/aia/multi-aia-cert.pem", WOLFSSL_FILETYPE_PEM)); ExpectIntEQ(wolfSSL_X509_get_aia_overflow(cert), 0); ExpectNotNull(ocsp = wolfSSL_X509_get1_ocsp(cert)); ExpectIntEQ(wolfSSL_sk_WOLFSSL_STRING_num(ocsp), 2); for (i = 0; i < wolfSSL_sk_WOLFSSL_STRING_num(ocsp); i++) { WOLFSSL_STRING url = wolfSSL_sk_WOLFSSL_STRING_value(ocsp, i); if (url == NULL) continue; if (XSTRCMP(url, ocspExp1) == 0) ocspFound1 = 1; if (XSTRCMP(url, ocspExp2) == 0) ocspFound2 = 1; } ExpectIntEQ(ocspFound1, 1); ExpectIntEQ(ocspFound2, 1); ExpectNotNull(ca = wolfSSL_X509_get1_ca_issuers(cert)); ExpectIntEQ(wolfSSL_sk_WOLFSSL_STRING_num(ca), 2); for (i = 0; i < wolfSSL_sk_WOLFSSL_STRING_num(ca); i++) { WOLFSSL_STRING url = wolfSSL_sk_WOLFSSL_STRING_value(ca, i); if (url == NULL) continue; if (XSTRCMP(url, caExp1) == 0) caFound1 = 1; if (XSTRCMP(url, caExp2) == 0) caFound2 = 1; } ExpectIntEQ(caFound1, 1); ExpectIntEQ(caFound2, 1); wolfSSL_X509_email_free(ocsp); wolfSSL_X509_email_free(ca); wolfSSL_X509_free(cert); #endif return EXPECT_RESULT(); } static int test_wolfSSL_X509_get1_aia_overflow(void) { EXPECT_DECLS; #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) || \ defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)) && \ !defined(NO_FILESYSTEM) && !defined(NO_RSA) X509* cert = NULL; STACK_OF(WOLFSSL_STRING) *ocsp = NULL; int count; ExpectNotNull(cert = wolfSSL_X509_load_certificate_file( "certs/aia/overflow-aia-cert.pem", WOLFSSL_FILETYPE_PEM)); ExpectNotNull(ocsp = wolfSSL_X509_get1_ocsp(cert)); count = wolfSSL_sk_WOLFSSL_STRING_num(ocsp); ExpectIntEQ(count, 8); ExpectIntEQ(wolfSSL_X509_get_aia_overflow(cert), 1); wolfSSL_X509_email_free(ocsp); wolfSSL_X509_free(cert); #endif return EXPECT_RESULT(); } /* Parse a certificate whose subjectInfoAccess extension is present but does * not contain an id-ad-caRepository entry. RFC 5280 4.2.2.2 only requires * the SIA sequence be non-empty; previously wolfSSL incorrectly rejected * such certificates with ASN_PARSE_E. */ static int test_wolfSSL_SubjectInfoAccess_no_caRepository(void) { EXPECT_DECLS; #if defined(WOLFSSL_SUBJ_INFO_ACC) && !defined(NO_RSA) && \ !defined(NO_FILESYSTEM) && defined(WOLFSSL_PEM_TO_DER) const char* siaCert = "./certs/sia/timestamping-sia-cert.pem"; byte* pemBuf = NULL; size_t pemSz = 0; byte* derBuf = NULL; word32 derSz = 0; DecodedCert cert; int ret = 0; ExpectIntEQ(load_file(siaCert, &pemBuf, &pemSz), 0); derSz = (word32)pemSz; /* DER will be smaller than PEM */ ExpectNotNull(derBuf = (byte*)malloc(derSz)); ExpectIntGE(ret = wc_CertPemToDer(pemBuf, (int)pemSz, derBuf, (int)derSz, CERT_TYPE), 0); if (ret > 0) { derSz = (word32)ret; wc_InitDecodedCert(&cert, derBuf, derSz, NULL); ExpectIntEQ(wc_ParseCert(&cert, CERT_TYPE, NO_VERIFY, NULL), 0); /* SIA was present and decoded successfully. */ ExpectIntEQ(cert.extSubjInfoAccSet, 1); /* No id-ad-caRepository entry exists in this cert's SIA. */ ExpectNull(cert.extSubjInfoAccCaRepo); ExpectIntEQ((int)cert.extSubjInfoAccCaRepoSz, 0); wc_FreeDecodedCert(&cert); } free(derBuf); XFREE(pemBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return EXPECT_RESULT(); } static int test_no_op_functions(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) /* this makes sure wolfSSL can compile and run these no-op functions */ SSL_load_error_strings(); ENGINE_load_builtin_engines(); OpenSSL_add_all_ciphers(); ExpectIntEQ(CRYPTO_malloc_init(), 0); #endif return EXPECT_RESULT(); } static int test_wolfSSL_CRYPTO_memcmp(void) { EXPECT_DECLS; #ifdef OPENSSL_EXTRA char a[] = "wolfSSL (formerly CyaSSL) is a small, fast, portable " "implementation of TLS/SSL for embedded devices to the cloud."; char b[] = "wolfSSL (formerly CyaSSL) is a small, fast, portable " "implementation of TLS/SSL for embedded devices to the cloud."; char c[] = "wolfSSL (formerly CyaSSL) is a small, fast, portable " "implementation of TLS/SSL for embedded devices to the cloud!"; ExpectIntEQ(CRYPTO_memcmp(a, b, sizeof(a)), 0); ExpectIntNE(CRYPTO_memcmp(a, c, sizeof(a)), 0); #endif return EXPECT_RESULT(); } /*----------------------------------------------------------------------------* | wolfCrypt ASN *----------------------------------------------------------------------------*/ static int test_wc_CreateEncryptedPKCS8Key(void) { EXPECT_DECLS; #if defined(HAVE_PKCS8) && !defined(NO_PWDBASED) && defined(WOLFSSL_AES_256) \ && !defined(NO_AES_CBC) && !defined(NO_RSA) && !defined(NO_SHA) && \ !defined(NO_ASN_CRYPT) WC_RNG rng; byte* encKey = NULL; word32 encKeySz = 0; word32 decKeySz = 0; const char password[] = "Lorem ipsum dolor sit amet"; word32 passwordSz = (word32)XSTRLEN(password); word32 tradIdx = 0; XMEMSET(&rng, 0, sizeof(WC_RNG)); ExpectIntEQ(wc_InitRng(&rng), 0); PRIVATE_KEY_UNLOCK(); /* Call with NULL for out buffer to get necessary length. */ ExpectIntEQ(wc_CreateEncryptedPKCS8Key((byte*)server_key_der_2048, sizeof_server_key_der_2048, NULL, &encKeySz, password, (int)passwordSz, PKCS5, PBES2, AES256CBCb, NULL, 0, WC_PKCS12_ITT_DEFAULT, &rng, NULL), WC_NO_ERR_TRACE(LENGTH_ONLY_E)); ExpectNotNull(encKey = (byte*)XMALLOC(encKeySz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER)); /* Call with the allocated out buffer. */ ExpectIntGT(wc_CreateEncryptedPKCS8Key((byte*)server_key_der_2048, sizeof_server_key_der_2048, encKey, &encKeySz, password, (int)passwordSz, PKCS5, PBES2, AES256CBCb, NULL, 0, WC_PKCS12_ITT_DEFAULT, &rng, NULL), 0); /* Decrypt the encrypted PKCS8 key we just made. */ ExpectIntGT((decKeySz = (word32)wc_DecryptPKCS8Key(encKey, encKeySz, password, (int)passwordSz)), 0); /* encKey now holds the decrypted key (decrypted in place). */ ExpectIntGT(wc_GetPkcs8TraditionalOffset(encKey, &tradIdx, decKeySz), 0); /* Check that the decrypted key matches the key prior to encryption. */ ExpectIntEQ(XMEMCMP(encKey + tradIdx, server_key_der_2048, sizeof_server_key_der_2048), 0); PRIVATE_KEY_LOCK(); XFREE(encKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_FreeRng(&rng); #endif return EXPECT_RESULT(); } static int test_wc_DecryptedPKCS8Key(void) { EXPECT_DECLS; #if defined(HAVE_PKCS8) && !defined(NO_PWDBASED) && defined(WOLFSSL_AES_256) \ && !defined(NO_AES_CBC) && !defined(NO_RSA) && !defined(NO_SHA) && \ !defined(NO_ASN_CRYPT) static byte badPkcs5RsaEnc[] = { 0x30, 0x82, 0x05, 0x2d, 0x30, 0x57, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x0d, 0x30, 0x4a, 0x30, 0x29, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x0c, 0x30, 0x1c, 0x04, 0x09, 0xad, 0x8f, 0xb7, 0x90, 0x43, 0xd9, 0x3f, 0xe5, 0x02, 0x02, 0x04, 0x02, 0x02, 0x04, 0x80, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0xbc, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x09, 0x05, 0x00, 0x30, 0x1d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x2a, 0x04, 0x10, 0x90, 0xf9, 0xa4, 0xd7, 0xf2, 0xae, 0x58, 0xd6, 0xe1, 0x7c, 0x60, 0x7b, 0x84, 0xc0, 0x8c, 0x44, 0x04, 0x50, 0xc8, 0xd0, 0x03, 0xa7, 0x79, 0xa9, 0x11, 0x8b, 0xbd, 0xd6, 0xcb, 0xd9, 0x9e, 0xd7, 0x2d, 0xac, 0x2c, 0xb8, 0xc9, 0x5f, 0xe7, 0x8b, 0x36, 0x26, 0x26, 0x23, 0x2a, 0x21, 0x25, 0x6f, 0xd0, 0x52, 0xd3, 0xeb, 0xff, 0x1f, 0x06, 0xb0, 0x40, 0xd1, 0x4b, 0x9e, 0x73, 0xbf, 0x17, 0x24, 0x0b, 0x2d, 0xf6, 0x4f, 0xce, 0xb4, 0x47, 0x82, 0x7c, 0x23, 0x21, 0xdc, 0x71, 0xc7, 0x1c, 0x71, 0xc7, 0x1c, 0x71, 0xc7, 0x1c, 0x71, 0xc7, 0x1c, 0x71, 0xc7, 0x1c, 0x71, 0xc7, 0x1c, 0x71, 0xc7, 0x1c, 0x71, 0xc7, 0x1c, 0x71, 0xc7, 0x1c, 0x71, 0xc7, 0x1c, 0x71, 0xc7, 0x1c, 0x71, 0xc7, 0x07, 0x27, 0x82, 0xcd, 0x36, 0xd7, 0xf4, 0xa1, 0xb5, 0xc5, 0x17, 0x5f, 0xe6, 0xd0, 0xf3, 0x97, 0x3e, 0x1a, 0xcd, 0x39, 0x9d, 0x41, 0xce, 0xed, 0x14, 0xdb, 0x3d, 0xa5, 0x7b, 0xd3, 0xcb, 0x93, 0x1a, 0x4c, 0x32, 0x0e, 0x8b, 0xa3, 0x41, 0xbe, 0xcb, 0xa3, 0xd5, 0xfb, 0x8d, 0xb6, 0x8a, 0x4e, 0x0b, 0x0b, 0xbd, 0x74, 0x33, 0xd2, 0xb6, 0x43, 0x20, 0x96, 0xf9, 0x46, 0x57, 0x66, 0x54, 0x94, 0xfa, 0x1c, 0x3a, 0xe4, 0xf7, 0x0a, 0x59, 0x37, 0x5f, 0x6a, 0xc2, 0xba, 0xea, 0xfd, 0xd4, 0xd7, 0x64, 0xee, 0x53, 0x40, 0xe9, 0x3c, 0x71, 0xbf, 0x93, 0x87, 0xf3, 0x53, 0x0c, 0x92, 0x0b, 0xbe, 0x4c, 0xde, 0x35, 0xd7, 0xb0, 0x60, 0xc6, 0x37, 0x1c, 0x4c, 0x08, 0x8f, 0xe1, 0x95, 0xba, 0xde, 0x42, 0x68, 0x6a, 0x76, 0x0b, 0x84, 0x14, 0xc6, 0x5e, 0xb1, 0xa1, 0x45, 0xa7, 0x31, 0x72, 0xfe, 0xaa, 0x43, 0x86, 0xa3, 0x31, 0x41, 0x68, 0x66, 0x41, 0x31, 0xe0, 0xa4, 0x63, 0x1d, 0x62, 0x57, 0x2c, 0x49, 0x9b, 0x9c, 0x32, 0x4a, 0x4f, 0x3c, 0xf3, 0xcf, 0x3c, 0xf3, 0xcf, 0x3c, 0xf3, 0xcf, 0x3c, 0xf3, 0xcf, 0x3c, 0xf3, 0xcf, 0x3c, 0xf3, 0xcf, 0x3c, 0xf3, 0xcf, 0x3c, 0xf3, 0xcf, 0x3c, 0xf3, 0xcf, 0x3c, 0xf3, 0xcf, 0x3c, 0xf3, 0xcf, 0x3c, 0xf3, 0xcf, 0x3c, 0xf3, 0xcf, 0x3c, 0xf3, 0xcf, 0x3c, 0xf3, 0xcf, 0x3c, 0xf3, 0xcf, 0x3c, 0xf3, 0xcf, 0x3c, 0xf3, 0xcf, 0x3c, 0xf3, 0xcf, 0x3c, 0xf3, 0xcf, 0x3c, 0xf3, 0xcf, 0x3d, 0x4c, 0x72, 0x7d, 0xc7, 0xa8, 0x07, 0x4f, 0xa4, 0x52, 0x1f, 0xb8, 0xa9, 0x89, 0x4c, 0x65, 0xd1, 0x8f, 0x3c, 0xf3, 0xcf, 0x3c, 0xf3, 0xcf, 0x3f, 0x1e, 0x31, 0x53, 0x77, 0x37, 0xaf, 0xe4, 0x43, 0x23, 0x34, 0xfc, 0x8e, 0xc2, 0xba, 0x32, 0x40, 0xb3, 0xe7, 0xab, 0x6d, 0xc3, 0xa0, 0x9e, 0xc7, 0x6c, 0x13, 0xe7, 0x77, 0xd5, 0x0a, 0x1a, 0x04, 0xb7, 0xd4, 0x13, 0xcd, 0x04, 0x39, 0x22, 0x67, 0xc4, 0x00, 0xe4, 0xd0, 0x1f, 0xf7, 0x9d, 0x2b, 0x73, 0xda, 0xee, 0x00, 0x1b, 0x9a, 0x5c, 0xb0, 0x4c, 0x90, 0x9b, 0x38, 0x41, 0xd3, 0x13, 0xd0, 0xfa, 0xec, 0x0f, 0x65, 0xe9, 0x02, 0x90, 0x39, 0xa8, 0xe4, 0xd4, 0x52, 0xa6, 0x1f, 0x7a, 0x54, 0x00, 0x19, 0x13, 0x94, 0xae, 0x7a, 0xf2, 0xa7, 0xce, 0xf5, 0x29, 0x78, 0x66, 0x1c, 0x03, 0x26, 0x65, 0xe8, 0x03, 0x8e, 0x97, 0x67, 0x20, 0x61, 0x4c, 0xbd, 0xa0, 0xb3, 0x88, 0x10, 0x8b, 0x74, 0x40, 0x8d, 0xc6, 0xe6, 0x26, 0x32, 0x0f, 0x01, 0x47, 0x35, 0xb3, 0x86, 0x87, 0xa9, 0x6d, 0xf8, 0xf8, 0x9f, 0xca, 0x30, 0x69, 0xf7, 0x5d, 0x89, 0x3f, 0xf5, 0x1d, 0xd5, 0x26, 0xd7, 0xef, 0x43, 0x26, 0x06, 0x26, 0x7b, 0xf0, 0xdd, 0x86, 0xa6, 0x58, 0x71, 0xd6, 0xcb, 0x45, 0xb4, 0x4f, 0x52, 0xd7, 0xf1, 0xae, 0x06, 0xad, 0xc7, 0x94, 0x17, 0xe8, 0x44, 0x59, 0x02, 0xe1, 0x22, 0x9e, 0x59, 0xa6, 0xcc, 0x3b, 0x20, 0x5b, 0x95, 0xf1, 0x34, 0x31, 0x52, 0x7e, 0x6d, 0xff, 0x4b, 0x45, 0x9a, 0xff, 0xba, 0x1a, 0x41, 0x48, 0x20, 0x49, 0xb8, 0x62, 0xef, 0x82, 0xca, 0x14, 0x7e, 0x14, 0xfa, 0x49, 0x3f, 0xfb, 0x5e, 0xb1, 0x60, 0x30, 0x94, 0x4c, 0xee, 0x4b, 0x78, 0xa2, 0x79, 0xb2, 0xa1, 0xbd, 0xb1, 0x94, 0x24, 0xd6, 0x9c, 0xf0, 0x41, 0x3b, 0xc6, 0xf2, 0x30, 0x8c, 0x8a, 0xdd, 0x2e, 0x44, 0x41, 0x7e, 0x92, 0x3b, 0x09, 0x2e, 0x19, 0x9d, 0xb3, 0xb8, 0xa6, 0x9f, 0x86, 0x7e, 0x88, 0x5d, 0xe0, 0x13, 0x7c, 0x89, 0xf6, 0x96, 0xb1, 0x66, 0x3f, 0xc2, 0x8f, 0x71, 0x43, 0x6a, 0xd5, 0x8c, 0x6e, 0xae, 0xdf, 0x80, 0xd6, 0x01, 0x7a, 0x50, 0xf6, 0x2b, 0x25, 0x0f, 0x8d, 0x84, 0x3b, 0xd5, 0xb5, 0x61, 0xb1, 0x61, 0x58, 0xff, 0x4c, 0xe8, 0x6a, 0xa4, 0xae, 0x2b, 0xf5, 0xfe, 0xee, 0xeb, 0xa6, 0xf2, 0xf3, 0xc5, 0xa1, 0x63, 0x92, 0xde, 0x67, 0x2f, 0x40, 0xfc, 0x3b, 0x36, 0x64, 0xcc, 0x7b, 0xe9, 0xd8, 0xf7, 0x5d, 0x40, 0x56, 0x10, 0xaf, 0xd4, 0x52, 0xe2, 0xa6, 0x7c, 0xe9, 0xe4, 0x4b, 0x0b, 0xbd, 0x74, 0x33, 0xd2, 0xb6, 0x43, 0xd6, 0x0a, 0xe0, 0x12, 0x21, 0xa7, 0xab, 0x45, 0x19, 0x6e, 0xae, 0x71, 0x83, 0x22, 0x1a, 0x0d, 0xde, 0xd5, 0xb6, 0x82, 0xd2, 0xd7, 0xd8, 0x14, 0x6d, 0xfa, 0xb4, 0xae, 0xee, 0x55, 0x43, 0xd2, 0x1e, 0x59, 0xe2, 0x01, 0xe0, 0xfa, 0x53, 0x43, 0x3b, 0x40, 0x17, 0x06, 0x6a, 0x5e, 0x5f, 0x42, 0xc2, 0x6a, 0x4e, 0x7c, 0x5a, 0x69, 0x41, 0x8b, 0x62, 0x76, 0xd4, 0x1b, 0x00, 0xbc, 0x24, 0x27, 0x71, 0xf8, 0xf3, 0xca, 0x57, 0x10, 0xb9, 0x32, 0x14, 0x9b, 0x92, 0x35, 0xdd, 0xb7, 0xb8, 0x2e, 0xd8, 0xb3, 0xe9, 0x62, 0x8e, 0xe2, 0x5e, 0x16, 0xd4, 0xed, 0xf4, 0xd3, 0xc1, 0xba, 0x5d, 0x49, 0xce, 0x78, 0x5c, 0xf5, 0xbb, 0xad, 0x61, 0x1f, 0x64, 0x52, 0x22, 0xb4, 0xa3, 0x07, 0x18, 0x3d, 0xd3, 0x9d, 0xec, 0xe6, 0x9e, 0xb5, 0xad, 0x0c, 0xd3, 0x3b, 0xb6, 0xeb, 0xcd, 0x9c, 0x69, 0x45, 0xf2, 0x07, 0x24, 0xe9, 0xd7, 0xe0, 0xe7, 0x62, 0xe5, 0x01, 0x34, 0x24, 0x4e, 0xf6, 0x32, 0xe8, 0x42, 0x97, 0x3e, 0x14, 0xaf, 0xbc, 0x26, 0xbd, 0x73, 0xc5, 0xde, 0x5a, 0x8e, 0x65, 0x61, 0x97, 0x81, 0x31, 0x52, 0xa3, 0xbd, 0x9b, 0x9e, 0xda, 0xdd, 0x37, 0x15, 0x30, 0xfb, 0x3b, 0x59, 0x0c, 0x91, 0x8b, 0x54, 0x49, 0x68, 0xc6, 0x41, 0x38, 0x77, 0x1c, 0x00, 0xb2, 0xc3, 0x37, 0xe2, 0x50, 0x67, 0xeb, 0x49, 0xa4, 0xde, 0x04, 0x1e, 0xf5, 0xcc, 0x49, 0x24, 0x5a, 0x8d, 0x94, 0x33, 0xbf, 0x55, 0xf8, 0x70, 0x7d, 0x1e, 0x5b, 0xe3, 0x74, 0x6b, 0x34, 0xb3, 0xf6, 0x8a, 0x47, 0xf9, 0x2f, 0xc9, 0xcb, 0x6a, 0x80, 0x89, 0xf2, 0x19, 0x24, 0x5b, 0xdf, 0x04, 0x9a, 0x53, 0x1c, 0x9f, 0x71, 0xea, 0x01, 0xd3, 0xe9, 0x14, 0x87, 0xee, 0x2a, 0x62, 0x53, 0x19, 0x74, 0x64, 0x19, 0x03, 0x00, 0xd6, 0xa1, 0xcb, 0xdf, 0x59, 0x77, 0x6b, 0xa9, 0x25, 0x32, 0xff, 0xe9, 0xa9, 0x41, 0x06, 0x0c, 0x06, 0xd4, 0xae, 0xfb, 0x58, 0x20, 0x2e, 0xe3, 0xe0, 0xce, 0x53, 0xea, 0x03, 0xcb, 0x3f, 0x64, 0xe9, 0xd9, 0xc1, 0x0e, 0xf8, 0xec, 0x97, 0xee, 0x05, 0x42, 0x41, 0x61, 0xcc, 0x75, 0x13, 0x8d, 0x88, 0x62, 0x84, 0xa1, 0x3c, 0xa3, 0x30, 0xce, 0x12, 0xf1, 0x84, 0xee, 0x26, 0x08, 0x04, 0xae, 0x67, 0x56, 0xa0, 0x84, 0x91, 0x8a, 0xbd, 0xc4, 0xba, 0x07, 0xb3, 0x06, 0xe7, 0xc8, 0x12, 0xae, 0x56, 0x46, 0xcd, 0x8d, 0x5c, 0x91, 0x05, 0x90, 0x11, 0x37, 0xef, 0xe0, 0x3e, 0xf3, 0xc6, 0x95, 0x13, 0xeb, 0x2f, 0xe4, 0x3e, 0xfc, 0xe4, 0xc0, 0x61, 0xfb, 0x1b, 0x74, 0x78, 0xe9, 0x6b, 0x7d, 0xe4, 0xa2, 0xc4, 0x6d, 0x26, 0x6d, 0xc0, 0x06, 0xba, 0x9f, 0x7e, 0x7d, 0x5e, 0x7f, 0xfa, 0x66, 0x08, 0xd9, 0x70, 0x39, 0x05, 0xfa, 0x10, 0xfd, 0x5f, 0xaa, 0xc4, 0x9d, 0x02, 0xd4, 0xf8, 0x0f, 0x3f, 0xd3, 0xbe, 0xaa, 0x86, 0x4a, 0x0f, 0x8e, 0x23, 0x02, 0xbf, 0x48, 0x26, 0x93, 0x5f, 0xc2, 0xc5, 0x05, 0xca, 0xa1, 0x6d, 0x96, 0xd1, 0x3a, 0x30, 0x66, 0xe1, 0x97, 0x1d, 0x4c, 0xb0, 0x93, 0xd7, 0x8d, 0x3c, 0xc0, 0xf9, 0x2b, 0x81, 0x0d, 0xd7, 0x68, 0x49, 0x18, 0xab, 0xdc, 0x4b, 0xa0, 0x7b, 0x30, 0x6e, 0x7c, 0x81, 0x2a, 0xe5, 0x64, 0x6c, 0xd8, 0xd5, 0xc9, 0x10, 0x59, 0x01, 0x13, 0x7e, 0xfe, 0x03, 0xef, 0x3c, 0x69, 0x51, 0x3e, 0xb2, 0xfe, 0x43, 0xef, 0xce, 0x4c, 0x06, 0x1f, 0xb1, 0xb7, 0x47, 0x8e, 0x96, 0xb7, 0xde, 0x4a, 0x2c, 0x46, 0xd2, 0x66, 0xdc, 0x00, 0x6b, 0xa9, 0xf7, 0xe7, 0xd5, 0xe7, 0xff, 0xa6, 0x60, 0x8d, 0x97, 0x03, 0x90, 0x5f, 0xa1, 0x0f, 0xd5, 0xfa, 0xac, 0x49, 0xd0, 0x2d, 0x4f, 0x80, 0xf3, 0xfd, 0x3b, 0xea, 0xa8, 0x64, 0xa0, 0xf8, 0xe2, 0x30, 0x2b, 0xf4, 0x80, 0x2c, 0x50, 0x5c, 0xaa, 0x16, 0xd9, 0x6d, 0x13, 0xa3, 0x06, 0x6e, 0x19, 0x71, 0xd4, 0xcb, 0x09, 0x3d, 0x78, 0xd3, 0xcc, 0x0f, 0x92, 0xb8, 0x10, 0xdd, 0x76, 0x88, 0x97, 0x1b, 0x7f, 0xf0, 0x5c, 0xfb, 0x97, 0x66, 0x3e, 0x7f, 0x66, 0xf9, 0xa4, 0xd5, 0x29, 0xb5, 0x54, 0x8a, 0xaa, 0xfc, 0xe2, 0xdb, 0xb7, }; const char password[] = "password"; word32 passwordSz = (word32)XSTRLEN(password); /* Decrypt the encrypted PKCS8 key we just made. */ ExpectIntEQ(wc_DecryptPKCS8Key(badPkcs5RsaEnc, sizeof(badPkcs5RsaEnc), password, (int)passwordSz), ASN_PARSE_E); #endif return EXPECT_RESULT(); } static int test_wc_GetPkcs8TraditionalOffset(void) { EXPECT_DECLS; #if !defined(NO_ASN) && !defined(NO_FILESYSTEM) && defined(HAVE_PKCS8) int length; int derSz = 0; word32 inOutIdx; const char* path = "./certs/server-keyPkcs8.der"; const char* pathAttributes = "./certs/ca-key-pkcs8-attribute.der"; XFILE file = XBADFILE; byte der[2048]; ExpectTrue((file = XFOPEN(path, "rb")) != XBADFILE); ExpectIntGT(derSz = (int)XFREAD(der, 1, sizeof(der), file), 0); if (file != XBADFILE) XFCLOSE(file); file = XBADFILE; /* reset file to avoid warning of use after close */ /* valid case */ inOutIdx = 0; ExpectIntGT(length = wc_GetPkcs8TraditionalOffset(der, &inOutIdx, (word32)derSz), 0); /* inOutIdx > sz */ inOutIdx = 4000; ExpectIntEQ(length = wc_GetPkcs8TraditionalOffset(der, &inOutIdx, (word32)derSz), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* null input */ inOutIdx = 0; ExpectIntEQ(length = wc_GetPkcs8TraditionalOffset(NULL, &inOutIdx, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* invalid input, fill buffer with 1's */ XMEMSET(der, 1, sizeof(der)); inOutIdx = 0; ExpectIntEQ(length = wc_GetPkcs8TraditionalOffset(der, &inOutIdx, (word32)derSz), WC_NO_ERR_TRACE(ASN_PARSE_E)); /* test parsing with attributes */ ExpectTrue((file = XFOPEN(pathAttributes, "rb")) != XBADFILE); ExpectIntGT(derSz = (int)XFREAD(der, 1, sizeof(der), file), 0); if (file != XBADFILE) XFCLOSE(file); inOutIdx = 0; ExpectIntGT(length = wc_GetPkcs8TraditionalOffset(der, &inOutIdx, (word32)derSz), 0); #endif /* NO_ASN */ return EXPECT_RESULT(); } static int test_wc_SetSubjectRaw(void) { EXPECT_DECLS; #if !defined(NO_ASN) && !defined(NO_FILESYSTEM) && defined(OPENSSL_EXTRA) && \ defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT) && !defined(NO_RSA) const char* joiCertFile = "./certs/test/cert-ext-joi.der"; WOLFSSL_X509* x509 = NULL; int peerCertSz; const byte* peerCertBuf = NULL; Cert forgedCert; ExpectNotNull(x509 = wolfSSL_X509_load_certificate_file(joiCertFile, WOLFSSL_FILETYPE_ASN1)); ExpectNotNull(peerCertBuf = wolfSSL_X509_get_der(x509, &peerCertSz)); ExpectIntEQ(0, wc_InitCert(&forgedCert)); ExpectIntEQ(0, wc_SetSubjectRaw(&forgedCert, peerCertBuf, peerCertSz)); wolfSSL_FreeX509(x509); #endif return EXPECT_RESULT(); } static int test_wc_GetSubjectRaw(void) { EXPECT_DECLS; #if !defined(NO_ASN) && !defined(NO_FILESYSTEM) && defined(OPENSSL_EXTRA) && \ defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT) Cert cert; byte *subjectRaw; ExpectIntEQ(0, wc_InitCert(&cert)); ExpectIntEQ(0, wc_GetSubjectRaw(&subjectRaw, &cert)); #endif return EXPECT_RESULT(); } static int test_wc_SetIssuerRaw(void) { EXPECT_DECLS; #if !defined(NO_ASN) && !defined(NO_FILESYSTEM) && defined(OPENSSL_EXTRA) && \ defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT) && !defined(NO_RSA) const char* joiCertFile = "./certs/test/cert-ext-joi.der"; WOLFSSL_X509* x509 = NULL; int peerCertSz; const byte* peerCertBuf = NULL; Cert forgedCert; ExpectNotNull(x509 = wolfSSL_X509_load_certificate_file(joiCertFile, WOLFSSL_FILETYPE_ASN1)); ExpectNotNull(peerCertBuf = wolfSSL_X509_get_der(x509, &peerCertSz)); ExpectIntEQ(0, wc_InitCert(&forgedCert)); ExpectIntEQ(0, wc_SetIssuerRaw(&forgedCert, peerCertBuf, peerCertSz)); wolfSSL_FreeX509(x509); #endif return EXPECT_RESULT(); } static int test_wc_SetIssueBuffer(void) { EXPECT_DECLS; #if !defined(NO_ASN) && !defined(NO_FILESYSTEM) && defined(OPENSSL_EXTRA) && \ defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT) && !defined(NO_RSA) const char* joiCertFile = "./certs/test/cert-ext-joi.der"; WOLFSSL_X509* x509 = NULL; int peerCertSz; const byte* peerCertBuf = NULL; Cert forgedCert; ExpectNotNull(x509 = wolfSSL_X509_load_certificate_file(joiCertFile, WOLFSSL_FILETYPE_ASN1)); ExpectNotNull(peerCertBuf = wolfSSL_X509_get_der(x509, &peerCertSz)); ExpectIntEQ(0, wc_InitCert(&forgedCert)); ExpectIntEQ(0, wc_SetIssuerBuffer(&forgedCert, peerCertBuf, peerCertSz)); wolfSSL_FreeX509(x509); #endif return EXPECT_RESULT(); } /* * Testing wc_SetSubjectKeyId */ static int test_wc_SetSubjectKeyId(void) { EXPECT_DECLS; #if !defined(NO_ASN) && !defined(NO_FILESYSTEM) && defined(OPENSSL_EXTRA) && \ defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT) && defined(HAVE_ECC) Cert cert; const char* file = "certs/ecc-client-keyPub.pem"; ExpectIntEQ(0, wc_InitCert(&cert)); ExpectIntEQ(0, wc_SetSubjectKeyId(&cert, file)); ExpectIntEQ(WC_NO_ERR_TRACE(BAD_FUNC_ARG), wc_SetSubjectKeyId(NULL, file)); ExpectIntGT(0, wc_SetSubjectKeyId(&cert, "badfile.name")); #endif return EXPECT_RESULT(); } /* END test_wc_SetSubjectKeyId */ /* * Testing wc_SetSubject */ static int test_wc_SetSubject(void) { EXPECT_DECLS; #if !defined(NO_ASN) && !defined(NO_FILESYSTEM) && defined(OPENSSL_EXTRA) && \ defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT) && defined(HAVE_ECC) Cert cert; const char* file = "./certs/ca-ecc-cert.pem"; ExpectIntEQ(0, wc_InitCert(&cert)); ExpectIntEQ(0, wc_SetSubject(&cert, file)); ExpectIntEQ(WC_NO_ERR_TRACE(BAD_FUNC_ARG), wc_SetSubject(NULL, file)); ExpectIntGT(0, wc_SetSubject(&cert, "badfile.name")); #endif return EXPECT_RESULT(); } /* END test_wc_SetSubject */ static int test_CheckCertSignature(void) { EXPECT_DECLS; #if !defined(NO_CERTS) && defined(WOLFSSL_SMALL_CERT_VERIFY) WOLFSSL_CERT_MANAGER* cm = NULL; #if !defined(NO_FILESYSTEM) && (!defined(NO_RSA) || defined(HAVE_ECC)) XFILE fp = XBADFILE; byte cert[4096]; int certSz; #endif ExpectIntEQ(WC_NO_ERR_TRACE(BAD_FUNC_ARG), wc_CheckCertSignature(NULL, 0, NULL, NULL)); ExpectNotNull(cm = wolfSSL_CertManagerNew_ex(NULL)); ExpectIntEQ(WC_NO_ERR_TRACE(BAD_FUNC_ARG), wc_CheckCertSignature(NULL, 0, NULL, cm)); #ifndef NO_RSA #ifdef USE_CERT_BUFFERS_1024 ExpectIntEQ(WC_NO_ERR_TRACE(ASN_NO_SIGNER_E), wc_CheckCertSignature(server_cert_der_1024, sizeof_server_cert_der_1024, NULL, cm)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CertManagerLoadCABuffer(cm, ca_cert_der_1024, sizeof_ca_cert_der_1024, WOLFSSL_FILETYPE_ASN1)); ExpectIntEQ(0, wc_CheckCertSignature(server_cert_der_1024, sizeof_server_cert_der_1024, NULL, cm)); #elif defined(USE_CERT_BUFFERS_2048) ExpectIntEQ(WC_NO_ERR_TRACE(ASN_NO_SIGNER_E), wc_CheckCertSignature(server_cert_der_2048, sizeof_server_cert_der_2048, NULL, cm)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CertManagerLoadCABuffer(cm, ca_cert_der_2048, sizeof_ca_cert_der_2048, WOLFSSL_FILETYPE_ASN1)); ExpectIntEQ(0, wc_CheckCertSignature(server_cert_der_2048, sizeof_server_cert_der_2048, NULL, cm)); #endif #endif #if defined(HAVE_ECC) && defined(USE_CERT_BUFFERS_256) ExpectIntEQ(WC_NO_ERR_TRACE(ASN_NO_SIGNER_E), wc_CheckCertSignature(serv_ecc_der_256, sizeof_serv_ecc_der_256, NULL, cm)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CertManagerLoadCABuffer(cm, ca_ecc_cert_der_256, sizeof_ca_ecc_cert_der_256, WOLFSSL_FILETYPE_ASN1)); ExpectIntEQ(0, wc_CheckCertSignature(serv_ecc_der_256, sizeof_serv_ecc_der_256, NULL, cm)); #endif #if !defined(NO_FILESYSTEM) wolfSSL_CertManagerFree(cm); cm = NULL; ExpectNotNull(cm = wolfSSL_CertManagerNew_ex(NULL)); #ifndef NO_RSA ExpectTrue((fp = XFOPEN("./certs/server-cert.der", "rb")) != XBADFILE); ExpectIntGT((certSz = (int)XFREAD(cert, 1, sizeof(cert), fp)), 0); if (fp != XBADFILE) { XFCLOSE(fp); fp = XBADFILE; } ExpectIntEQ(WC_NO_ERR_TRACE(ASN_NO_SIGNER_E), wc_CheckCertSignature(cert, certSz, NULL, cm)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CertManagerLoadCA(cm, "./certs/ca-cert.pem", NULL)); ExpectIntEQ(0, wc_CheckCertSignature(cert, certSz, NULL, cm)); #endif #ifdef HAVE_ECC ExpectTrue((fp = XFOPEN("./certs/server-ecc.der", "rb")) != XBADFILE); ExpectIntGT((certSz = (int)XFREAD(cert, 1, sizeof(cert), fp)), 0); if (fp != XBADFILE) { XFCLOSE(fp); fp = XBADFILE; } ExpectIntEQ(WC_NO_ERR_TRACE(ASN_NO_SIGNER_E), wc_CheckCertSignature(cert, certSz, NULL, cm)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CertManagerLoadCA(cm, "./certs/ca-ecc-cert.pem", NULL)); ExpectIntEQ(0, wc_CheckCertSignature(cert, certSz, NULL, cm)); #endif #endif #if !defined(NO_FILESYSTEM) && (!defined(NO_RSA) || defined(HAVE_ECC)) (void)fp; (void)cert; (void)certSz; #endif wolfSSL_CertManagerFree(cm); #endif return EXPECT_RESULT(); } static int test_wc_ParseCert(void) { EXPECT_DECLS; #if !defined(NO_CERTS) && !defined(NO_RSA) DecodedCert decodedCert; const byte* rawCert = client_cert_der_2048; const int rawCertSize = sizeof_client_cert_der_2048; wc_InitDecodedCert(&decodedCert, rawCert, rawCertSize, NULL); ExpectIntEQ(wc_ParseCert(&decodedCert, CERT_TYPE, NO_VERIFY, NULL), 0); #ifndef IGNORE_NAME_CONSTRAINTS /* check that the subjects emailAddress was not put in the alt name list */ ExpectNotNull(decodedCert.subjectEmail); ExpectNull(decodedCert.altEmailNames); #endif wc_FreeDecodedCert(&decodedCert); #endif return EXPECT_RESULT(); } /* Test wc_ParseCert decoding of various encodings and scenarios ensuring that * the API safely errors out on badly-formed ASN input. * NOTE: Test not compatible with released FIPS implementations! */ static int test_wc_ParseCert_Error(void) { EXPECT_DECLS; #if !defined(NO_CERTS) && !defined(NO_RSA) && !defined(HAVE_SELFTEST) && \ (!defined(HAVE_FIPS) || \ (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2))) DecodedCert decodedCert; int i; /* Certificate data */ const byte c0[] = { 0x30, 0x04, 0x30, 0x02, 0x02, 0x80, 0x00, 0x00}; const byte c1[] = { 0x30, 0x04, 0x30, 0x04, 0x02, 0x80, 0x00, 0x00}; const byte c2[] = { 0x30, 0x06, 0x30, 0x04, 0x02, 0x80, 0x00, 0x00}; const byte c3[] = { 0x30, 0x07, 0x30, 0x05, 0x02, 0x80, 0x10, 0x00, 0x00}; const byte c4[] = { 0x02, 0x80, 0x10, 0x00, 0x00}; /* Test data */ struct testStruct { const byte* c; word32 cSz; int expRet; } t[5]; const int tSz = (int)(sizeof(t) / sizeof(struct testStruct)); #define INIT_TEST_DATA(i,x,y) \ t[i].c = x; t[i].cSz = sizeof(x); t[i].expRet = y INIT_TEST_DATA(0, c0, WC_NO_ERR_TRACE(ASN_PARSE_E) ); INIT_TEST_DATA(1, c1, WC_NO_ERR_TRACE(ASN_PARSE_E) ); INIT_TEST_DATA(2, c2, WC_NO_ERR_TRACE(ASN_PARSE_E) ); INIT_TEST_DATA(3, c3, WC_NO_ERR_TRACE(ASN_PARSE_E) ); INIT_TEST_DATA(4, c4, WC_NO_ERR_TRACE(ASN_PARSE_E) ); #undef INIT_TEST_DATA for (i = 0; i < tSz; i++) { WOLFSSL_MSG_EX("i == %d", i); wc_InitDecodedCert(&decodedCert, t[i].c, t[i].cSz, NULL); ExpectIntEQ(wc_ParseCert(&decodedCert, CERT_TYPE, NO_VERIFY, NULL), t[i].expRet); wc_FreeDecodedCert(&decodedCert); } #endif return EXPECT_RESULT(); } static int test_MakeCertWithPathLen(void) { EXPECT_DECLS; #if defined(WOLFSSL_CERT_REQ) && !defined(NO_ASN_TIME) && \ defined(WOLFSSL_CERT_GEN) && defined(HAVE_ECC) const byte expectedPathLen = 7; Cert cert; DecodedCert decodedCert; byte der[FOURK_BUF]; int derSize = 0; WC_RNG rng; ecc_key key; int ret; XMEMSET(&rng, 0, sizeof(WC_RNG)); XMEMSET(&key, 0, sizeof(ecc_key)); XMEMSET(&cert, 0, sizeof(Cert)); XMEMSET(&decodedCert, 0, sizeof(DecodedCert)); ExpectIntEQ(wc_InitRng(&rng), 0); ExpectIntEQ(wc_ecc_init(&key), 0); ExpectIntEQ(wc_ecc_make_key(&rng, 32, &key), 0); ExpectIntEQ(wc_InitCert(&cert), 0); (void)XSTRNCPY(cert.subject.country, "US", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.state, "state", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.locality, "Bozeman", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.org, "yourOrgNameHere", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.unit, "yourUnitNameHere", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.commonName, "www.yourDomain.com", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.email, "yourEmail@yourDomain.com", CTC_NAME_SIZE); cert.selfSigned = 1; cert.isCA = 1; cert.pathLen = expectedPathLen; cert.pathLenSet = 1; cert.sigType = CTC_SHA256wECDSA; #ifdef WOLFSSL_CERT_EXT cert.keyUsage |= KEYUSE_KEY_CERT_SIGN; #endif ExpectIntGE(wc_MakeCert(&cert, der, FOURK_BUF, NULL, &key, &rng), 0); ExpectIntGE(derSize = wc_SignCert(cert.bodySz, cert.sigType, der, FOURK_BUF, NULL, &key, &rng), 0); wc_InitDecodedCert(&decodedCert, der, (word32)derSize, NULL); ExpectIntEQ(wc_ParseCert(&decodedCert, CERT_TYPE, NO_VERIFY, NULL), 0); ExpectIntEQ(decodedCert.pathLength, expectedPathLen); wc_FreeDecodedCert(&decodedCert); ret = wc_ecc_free(&key); ExpectIntEQ(ret, 0); ret = wc_FreeRng(&rng); ExpectIntEQ(ret, 0); #endif return EXPECT_RESULT(); } static int test_PathLenSelfIssued(void) { EXPECT_DECLS; #if defined(WOLFSSL_CERT_REQ) && !defined(NO_ASN_TIME) && \ defined(WOLFSSL_CERT_GEN) && defined(HAVE_ECC) && \ defined(WOLFSSL_CERT_EXT) && !defined(NO_CERTS) && \ (!defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH)) Cert cert; DecodedCert decodedCert; byte rootDer[FOURK_BUF]; byte icaDer[FOURK_BUF]; byte entityDer[FOURK_BUF]; int rootDerSz = 0; int icaDerSz = 0; int entityDerSz = 0; WC_RNG rng; ecc_key rootKey; ecc_key icaKey; ecc_key entityKey; WOLFSSL_CERT_MANAGER* cm = NULL; XMEMSET(&rng, 0, sizeof(WC_RNG)); XMEMSET(&rootKey, 0, sizeof(ecc_key)); XMEMSET(&icaKey, 0, sizeof(ecc_key)); XMEMSET(&entityKey, 0, sizeof(ecc_key)); ExpectIntEQ(wc_InitRng(&rng), 0); ExpectIntEQ(wc_ecc_init(&rootKey), 0); ExpectIntEQ(wc_ecc_init(&icaKey), 0); ExpectIntEQ(wc_ecc_init(&entityKey), 0); ExpectIntEQ(wc_ecc_make_key(&rng, 32, &rootKey), 0); ExpectIntEQ(wc_ecc_make_key(&rng, 32, &icaKey), 0); ExpectIntEQ(wc_ecc_make_key(&rng, 32, &entityKey), 0); /* Step 1: Create root CA with pathLen=0 */ ExpectIntEQ(wc_InitCert(&cert), 0); (void)XSTRNCPY(cert.subject.country, "US", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.state, "MT", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.locality, "Bozeman", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.org, "TestCA", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.unit, "Test", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.commonName, "TestRootCA", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.email, "root@test.com", CTC_NAME_SIZE); cert.selfSigned = 1; cert.isCA = 1; cert.pathLen = 0; cert.pathLenSet = 1; cert.sigType = CTC_SHA256wECDSA; cert.keyUsage = KEYUSE_KEY_CERT_SIGN | KEYUSE_CRL_SIGN; ExpectIntEQ(wc_SetSubjectKeyIdFromPublicKey_ex(&cert, ECC_TYPE, &rootKey), 0); ExpectIntGE(wc_MakeCert(&cert, rootDer, FOURK_BUF, NULL, &rootKey, &rng), 0); ExpectIntGE(rootDerSz = wc_SignCert(cert.bodySz, cert.sigType, rootDer, FOURK_BUF, NULL, &rootKey, &rng), 0); /* Step 2: Create self-issued intermediate (same subject DN as root, * different key, signed by root) - this should be blocked by pathLen=0 */ ExpectIntEQ(wc_InitCert(&cert), 0); cert.selfSigned = 0; cert.isCA = 1; cert.sigType = CTC_SHA256wECDSA; cert.keyUsage = KEYUSE_KEY_CERT_SIGN | KEYUSE_CRL_SIGN; /* Set both subject and issuer from the root cert so they match */ ExpectIntEQ(wc_SetSubjectBuffer(&cert, rootDer, rootDerSz), 0); ExpectIntEQ(wc_SetIssuerBuffer(&cert, rootDer, rootDerSz), 0); ExpectIntEQ(wc_SetAuthKeyIdFromPublicKey_ex(&cert, ECC_TYPE, &rootKey), 0); ExpectIntEQ(wc_SetSubjectKeyIdFromPublicKey_ex(&cert, ECC_TYPE, &icaKey), 0); ExpectIntGE(wc_MakeCert(&cert, icaDer, FOURK_BUF, NULL, &icaKey, &rng), 0); ExpectIntGE(icaDerSz = wc_SignCert(cert.bodySz, cert.sigType, icaDer, FOURK_BUF, NULL, &rootKey, &rng), 0); /* Step 3: Create entity cert signed by the intermediate */ ExpectIntEQ(wc_InitCert(&cert), 0); cert.selfSigned = 0; cert.isCA = 0; cert.sigType = CTC_SHA256wECDSA; (void)XSTRNCPY(cert.subject.country, "US", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.state, "MT", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.locality, "Bozeman", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.org, "TestEntity", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.commonName, "entity.test", CTC_NAME_SIZE); ExpectIntEQ(wc_SetIssuerBuffer(&cert, icaDer, icaDerSz), 0); ExpectIntEQ(wc_SetAuthKeyIdFromPublicKey_ex(&cert, ECC_TYPE, &icaKey), 0); ExpectIntGE(wc_MakeCert(&cert, entityDer, FOURK_BUF, NULL, &entityKey, &rng), 0); ExpectIntGE(entityDerSz = wc_SignCert(cert.bodySz, cert.sigType, entityDer, FOURK_BUF, NULL, &icaKey, &rng), 0); /* Step 4: Load root CA into cert manager */ ExpectNotNull(cm = wolfSSL_CertManagerNew()); ExpectIntEQ(wolfSSL_CertManagerLoadCABuffer(cm, rootDer, rootDerSz, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); /* Step 5: Parse the self-issued intermediate as a chain cert. * This simulates TLS chain verification where the intermediate is * received as part of the certificate chain. * Root CA has pathLen=0, so it should NOT be allowed to sign any * intermediate CA (including self-issued ones). * BUG: wolfSSL sets selfSigned=1 for this cert (issuer==subject DN), * which causes the pathLen enforcement to be entirely skipped. */ wc_InitDecodedCert(&decodedCert, icaDer, (word32)icaDerSz, NULL); ExpectIntEQ(wc_ParseCert(&decodedCert, CHAIN_CERT_TYPE, VERIFY, cm), WC_NO_ERR_TRACE(ASN_PATHLEN_INV_E)); wc_FreeDecodedCert(&decodedCert); /* Step 6: Parse the trust anchor itself as a chain cert. * A peer is allowed to include the root in the chain it sends. * Per RFC 5280 6.1 the trust anchor is not part of the prospective * certification path, so its own pathLen=0 must not fire against * itself. */ wc_InitDecodedCert(&decodedCert, rootDer, (word32)rootDerSz, NULL); ExpectIntEQ(wc_ParseCert(&decodedCert, CHAIN_CERT_TYPE, VERIFY, cm), 0); wc_FreeDecodedCert(&decodedCert); wolfSSL_CertManagerFree(cm); wc_ecc_free(&entityKey); wc_ecc_free(&icaKey); wc_ecc_free(&rootKey); wc_FreeRng(&rng); #endif return EXPECT_RESULT(); } /* Verifies that a self-issued intermediate under a CA with pathLen > 0 is * accepted AND that maxPathLen is propagated as min(ca->maxPathLen, * cert->pathLength) without being decremented (RFC 5280 6.1.4(l)). * Pins the `else` branch in asn.c so deletion or an accidental decrement * (like the non-self-issued path) is detected. */ static int test_PathLenSelfIssuedAllowed(void) { EXPECT_DECLS; #if defined(WOLFSSL_CERT_REQ) && !defined(NO_ASN_TIME) && \ defined(WOLFSSL_CERT_GEN) && defined(HAVE_ECC) && \ defined(WOLFSSL_CERT_EXT) && !defined(NO_CERTS) && \ (!defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH)) Cert cert; DecodedCert decodedCert; byte rootDer[FOURK_BUF]; byte icaDer[FOURK_BUF]; int rootDerSz = 0; int icaDerSz = 0; WC_RNG rng; ecc_key rootKey; ecc_key icaKey; WOLFSSL_CERT_MANAGER* cm = NULL; XMEMSET(&rng, 0, sizeof(WC_RNG)); XMEMSET(&rootKey, 0, sizeof(ecc_key)); XMEMSET(&icaKey, 0, sizeof(ecc_key)); ExpectIntEQ(wc_InitRng(&rng), 0); ExpectIntEQ(wc_ecc_init(&rootKey), 0); ExpectIntEQ(wc_ecc_init(&icaKey), 0); ExpectIntEQ(wc_ecc_make_key(&rng, 32, &rootKey), 0); ExpectIntEQ(wc_ecc_make_key(&rng, 32, &icaKey), 0); /* Step 1: Create root CA with pathLen=1 */ ExpectIntEQ(wc_InitCert(&cert), 0); (void)XSTRNCPY(cert.subject.country, "US", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.state, "MT", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.locality, "Bozeman", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.org, "TestCA3", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.unit, "Test", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.commonName, "TestRootCA3", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.email, "root@test3.com", CTC_NAME_SIZE); cert.selfSigned = 1; cert.isCA = 1; cert.pathLen = 1; cert.pathLenSet = 1; cert.sigType = CTC_SHA256wECDSA; cert.keyUsage = KEYUSE_KEY_CERT_SIGN | KEYUSE_CRL_SIGN; ExpectIntEQ(wc_SetSubjectKeyIdFromPublicKey_ex(&cert, ECC_TYPE, &rootKey), 0); ExpectIntGE(wc_MakeCert(&cert, rootDer, FOURK_BUF, NULL, &rootKey, &rng), 0); ExpectIntGE(rootDerSz = wc_SignCert(cert.bodySz, cert.sigType, rootDer, FOURK_BUF, NULL, &rootKey, &rng), 0); /* Step 2: Create a self-issued intermediate with its OWN pathLen=5. * The intentionally-larger pathLen lets the test distinguish: * - Correct self-issued path: maxPathLen = min(1, 5) = 1 * - Deleted else branch: maxPathLen stays at 5 (cert->pathLength) * - Mutated to decrement: maxPathLen = min(0, 5) = 0 */ ExpectIntEQ(wc_InitCert(&cert), 0); cert.selfSigned = 0; cert.isCA = 1; cert.pathLen = 5; cert.pathLenSet = 1; cert.sigType = CTC_SHA256wECDSA; cert.keyUsage = KEYUSE_KEY_CERT_SIGN | KEYUSE_CRL_SIGN; /* Same subject/issuer DN as root -> self-issued */ ExpectIntEQ(wc_SetSubjectBuffer(&cert, rootDer, rootDerSz), 0); ExpectIntEQ(wc_SetIssuerBuffer(&cert, rootDer, rootDerSz), 0); ExpectIntEQ(wc_SetAuthKeyIdFromPublicKey_ex(&cert, ECC_TYPE, &rootKey), 0); ExpectIntEQ(wc_SetSubjectKeyIdFromPublicKey_ex(&cert, ECC_TYPE, &icaKey), 0); ExpectIntGE(wc_MakeCert(&cert, icaDer, FOURK_BUF, NULL, &icaKey, &rng), 0); ExpectIntGE(icaDerSz = wc_SignCert(cert.bodySz, cert.sigType, icaDer, FOURK_BUF, NULL, &rootKey, &rng), 0); /* Step 3: Load root CA into cert manager */ ExpectNotNull(cm = wolfSSL_CertManagerNew()); ExpectIntEQ(wolfSSL_CertManagerLoadCABuffer(cm, rootDer, rootDerSz, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); /* Step 4: Parse the self-issued intermediate. Must be accepted AND * maxPathLen must be exactly 1 (honors root's constraint without * decrementing). */ wc_InitDecodedCert(&decodedCert, icaDer, (word32)icaDerSz, NULL); ExpectIntEQ(wc_ParseCert(&decodedCert, CHAIN_CERT_TYPE, VERIFY, cm), 0); ExpectIntEQ(decodedCert.maxPathLen, 1); wc_FreeDecodedCert(&decodedCert); wolfSSL_CertManagerFree(cm); wc_ecc_free(&icaKey); wc_ecc_free(&rootKey); wc_FreeRng(&rng); #endif return EXPECT_RESULT(); } static int test_PathLenNoKeyUsage(void) { EXPECT_DECLS; #if defined(WOLFSSL_CERT_REQ) && !defined(NO_ASN_TIME) && \ defined(WOLFSSL_CERT_GEN) && defined(HAVE_ECC) && \ defined(WOLFSSL_CERT_EXT) && !defined(NO_CERTS) && \ (!defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH)) Cert cert; DecodedCert decodedCert; byte rootDer[FOURK_BUF]; byte icaDer[FOURK_BUF]; int rootDerSz = 0; int icaDerSz = 0; WC_RNG rng; ecc_key rootKey; ecc_key icaKey; WOLFSSL_CERT_MANAGER* cm = NULL; XMEMSET(&rng, 0, sizeof(WC_RNG)); XMEMSET(&rootKey, 0, sizeof(ecc_key)); XMEMSET(&icaKey, 0, sizeof(ecc_key)); ExpectIntEQ(wc_InitRng(&rng), 0); ExpectIntEQ(wc_ecc_init(&rootKey), 0); ExpectIntEQ(wc_ecc_init(&icaKey), 0); ExpectIntEQ(wc_ecc_make_key(&rng, 32, &rootKey), 0); ExpectIntEQ(wc_ecc_make_key(&rng, 32, &icaKey), 0); /* Step 1: Create root CA with pathLen=0 and KeyUsage */ ExpectIntEQ(wc_InitCert(&cert), 0); (void)XSTRNCPY(cert.subject.country, "US", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.state, "MT", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.locality, "Bozeman", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.org, "TestCA2", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.unit, "Test", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.commonName, "TestRootCA2", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.email, "root@test2.com", CTC_NAME_SIZE); cert.selfSigned = 1; cert.isCA = 1; cert.pathLen = 0; cert.pathLenSet = 1; cert.sigType = CTC_SHA256wECDSA; cert.keyUsage = KEYUSE_KEY_CERT_SIGN | KEYUSE_CRL_SIGN; ExpectIntEQ(wc_SetSubjectKeyIdFromPublicKey_ex(&cert, ECC_TYPE, &rootKey), 0); ExpectIntGE(wc_MakeCert(&cert, rootDer, FOURK_BUF, NULL, &rootKey, &rng), 0); ExpectIntGE(rootDerSz = wc_SignCert(cert.bodySz, cert.sigType, rootDer, FOURK_BUF, NULL, &rootKey, &rng), 0); /* Step 2: Create intermediate CA WITHOUT KeyUsage extension. * Per RFC 5280, when KeyUsage is absent all uses are valid. * The root's pathLen=0 should still block this intermediate CA. * BUG: pathLen check requires extKeyUsageSet which is false when * KeyUsage is absent, so the check is skipped entirely. */ ExpectIntEQ(wc_InitCert(&cert), 0); cert.selfSigned = 0; cert.isCA = 1; cert.sigType = CTC_SHA256wECDSA; /* Intentionally do NOT set keyUsage - test that pathLen is still enforced */ cert.keyUsage = 0; (void)XSTRNCPY(cert.subject.country, "US", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.state, "MT", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.locality, "Bozeman", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.org, "TestICA", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.unit, "Test", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.commonName, "TestICA-NoKU", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.email, "ica@test2.com", CTC_NAME_SIZE); ExpectIntEQ(wc_SetIssuerBuffer(&cert, rootDer, rootDerSz), 0); ExpectIntEQ(wc_SetAuthKeyIdFromPublicKey_ex(&cert, ECC_TYPE, &rootKey), 0); ExpectIntEQ(wc_SetSubjectKeyIdFromPublicKey_ex(&cert, ECC_TYPE, &icaKey), 0); ExpectIntGE(wc_MakeCert(&cert, icaDer, FOURK_BUF, NULL, &icaKey, &rng), 0); ExpectIntGE(icaDerSz = wc_SignCert(cert.bodySz, cert.sigType, icaDer, FOURK_BUF, NULL, &rootKey, &rng), 0); /* Step 3: Load root CA into cert manager */ ExpectNotNull(cm = wolfSSL_CertManagerNew()); ExpectIntEQ(wolfSSL_CertManagerLoadCABuffer(cm, rootDer, rootDerSz, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); /* Step 4: Parse the intermediate (no KeyUsage) as a chain cert. * Root CA has pathLen=0, this intermediate CA should be rejected. * The intermediate does NOT have the KeyUsage extension, but per * RFC 5280 4.2.1.3 all key uses are valid when the extension is * absent, so pathLen must still be enforced. */ wc_InitDecodedCert(&decodedCert, icaDer, (word32)icaDerSz, NULL); ExpectIntEQ(wc_ParseCert(&decodedCert, CHAIN_CERT_TYPE, VERIFY, cm), WC_NO_ERR_TRACE(ASN_PATHLEN_INV_E)); wc_FreeDecodedCert(&decodedCert); wolfSSL_CertManagerFree(cm); wc_ecc_free(&icaKey); wc_ecc_free(&rootKey); wc_FreeRng(&rng); #endif return EXPECT_RESULT(); } /* Exhaustive matrix coverage of the serial-0 predicate in * ParseCertRelative (asn.c). Inputs are openssl-generated PEM fixtures * under certs/test-serial0/ -- no cert-under-test data is generated by * wolfSSL, so the test cannot pass for the wrong reason if wc_MakeCert * encoding ever drifts. * * Predicate exempts only (CA_TYPE|TRUSTED_PEER_TYPE) && isCA && selfSigned. * * Fixture isCA selfSigned CERT_TYPE CA_TYPE * root_serial0.pem 1 1 reject accept * intermediate_serial0.pem 1 0 reject reject * selfsigned_nonca_serial0.pem 0 1 reject reject * ee_serial0.pem 0 0 reject reject */ static int test_ParseSerial0FixtureMatrix(void) { EXPECT_DECLS; #if !defined(NO_CERTS) && !defined(NO_FILESYSTEM) && !defined(NO_RSA) && \ defined(WOLFSSL_PEM_TO_DER) && !defined(WOLFSSL_NO_PEM) && \ !defined(WOLFSSL_NO_ASN_STRICT) && !defined(WOLFSSL_PYTHON) && \ !defined(WOLFSSL_ASN_ALLOW_0_SERIAL) /* Fixture certs are RSA-2048; NO_RSA builds can't parse them. Mirrors * the gate on the sibling test_SerialNumber0_RootCA. */ /* Each case asserts a policy outcome (accept vs reject), not a specific * error code. wc_ParseCert can fail via several distinct codes * (ASN_PARSE_E, ASN_UNKNOWN_OID_E, etc.) depending on which * OID-recognition features are compiled into the build; matching any * specific code is brittle across configs. */ struct { const char* path; int certTypeShouldPass; /* 1: expect ret == 0; 0: expect ret != 0 */ int caTypeShouldPass; } cases[] = { /* Root CA serial 0 is rejected as CERT_TYPE, accepted as trust * anchor (CA_TYPE) per the exemption in ParseCertRelative. */ { "./certs/test-serial0/root_serial0.pem", 0, 1 }, /* Intermediate CA: CA:TRUE but issuer != subject, so the trust * anchor exemption (cert->selfSigned) does not apply. */ { "./certs/test-serial0/intermediate_serial0.pem", 0, 0 }, { "./certs/test-serial0/selfsigned_nonca_serial0.pem", 0, 0 }, { "./certs/test-serial0/ee_serial0.pem", 0, 0 }, }; size_t i; for (i = 0; i < sizeof(cases) / sizeof(cases[0]); ++i) { byte* pemBuf = NULL; size_t pemSz = 0; byte* derBuf = NULL; int derSz = 0; DecodedCert dc; int ret; ExpectIntEQ(load_file(cases[i].path, &pemBuf, &pemSz), 0); ExpectNotNull(derBuf = (byte*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_TMP_BUFFER)); ExpectIntGE(derSz = wc_CertPemToDer(pemBuf, (int)pemSz, derBuf, (int)pemSz, CERT_TYPE), 0); wc_InitDecodedCert(&dc, derBuf, (word32)derSz, NULL); ret = wc_ParseCert(&dc, CERT_TYPE, NO_VERIFY, NULL); if (cases[i].certTypeShouldPass) ExpectIntEQ(ret, 0); else ExpectIntNE(ret, 0); wc_FreeDecodedCert(&dc); wc_InitDecodedCert(&dc, derBuf, (word32)derSz, NULL); ret = wc_ParseCert(&dc, CA_TYPE, NO_VERIFY, NULL); if (cases[i].caTypeShouldPass) ExpectIntEQ(ret, 0); else ExpectIntNE(ret, 0); wc_FreeDecodedCert(&dc); XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(pemBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); } #endif return EXPECT_RESULT(); } #if defined(WOLFSSL_ASN_TEMPLATE) && \ defined(WOLFSSL_CERT_REQ) && !defined(NO_ASN_TIME) && \ defined(WOLFSSL_CERT_GEN) && defined(HAVE_ECC) && \ defined(WOLFSSL_CERT_EXT) && !defined(NO_CERTS) && \ defined(WOLFSSL_ALT_NAMES) && defined(WOLFSSL_CUSTOM_OID) && \ defined(HAVE_OID_ENCODING) && !defined(IGNORE_NAME_CONSTRAINTS) /* Build a SubjectAltName extension value (a SEQUENCE wrapping a single * otherName GeneralName) for the Microsoft UPN OID 1.3.6.1.4.1.311.20.2.3 * with the given 7-byte UTF8String value. */ static word32 build_otherName_san(byte* out, word32 outSz, const char* val7) { static const byte prefix[] = { 0x30, 0x19, /* SEQUENCE, 25 */ 0xA0, 0x17, /* [0] CONSTRUCTED, 23 */ 0x06, 0x0A, /* OBJECT ID, 10 */ 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x14, 0x02, 0x03, /* UPN OID */ 0xA0, 0x09, /* [0] EXPLICIT, 9 */ 0x0C, 0x07 /* UTF8String, 7 */ }; if (outSz < sizeof(prefix) + 7) return 0; XMEMCPY(out, prefix, sizeof(prefix)); XMEMCPY(out + sizeof(prefix), val7, 7); return (word32)(sizeof(prefix) + 7); } /* Build a SubjectAltName extension value with a single registeredID * GeneralName for OID 1.2.3.4, to use as the leaf SAN in RID tests. */ static word32 build_registeredID_san(byte* out, word32 outSz) { static const byte ridSan[] = { 0x30, 0x05, /* SEQUENCE, 5 */ 0x88, 0x03, /* [8] regId, 3 */ 0x2A, 0x03, 0x04 /* OID 1.2.3.4 */ }; if (outSz < sizeof(ridSan)) return 0; XMEMCPY(out, ridSan, sizeof(ridSan)); return (word32)sizeof(ridSan); } /* Build a NameConstraints extension value with a single excludedSubtree * carrying a registeredID GeneralName for OID 1.2.3.4. wolfSSL enforces * registeredID name constraints by byte-comparing OID bodies, so a leaf * whose registeredID SAN matches this exclusion must be rejected. */ static word32 build_registeredID_nameConstraints(byte* out, word32 outSz) { static const byte ridNc[] = { 0x30, 0x09, /* SEQUENCE, 9 */ 0xA1, 0x07, /* [1] excluded, 7 */ 0x30, 0x05, /* GeneralSubtree, 5 */ 0x88, 0x03, /* [8] regId, 3 */ 0x2A, 0x03, 0x04 /* OID 1.2.3.4 */ }; if (outSz < sizeof(ridNc)) return 0; XMEMCPY(out, ridNc, sizeof(ridNc)); return (word32)sizeof(ridNc); } /* Build a NameConstraints extension value carrying a single subtree of * the given list type ([0] permitted or [1] excluded) for an otherName * UPN whose UTF8 value is the given 7-byte string. */ static word32 build_otherName_nameConstraints(byte* out, word32 outSz, int excluded, const char* val7) { static const byte common[] = { 0x30, 0x1D, /* SEQUENCE, 29 */ 0x00, 0x1B, /* listTag, 27 (patched) */ 0x30, 0x19, /* GeneralSubtree, 25 */ 0xA0, 0x17, /* [0] CONSTRUCTED, 23 */ 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x14, 0x02, 0x03, 0xA0, 0x09, 0x0C, 0x07 }; if (outSz < sizeof(common) + 7) return 0; XMEMCPY(out, common, sizeof(common)); out[2] = excluded ? 0xA1 : 0xA0; /* listTag */ XMEMCPY(out + sizeof(common), val7, 7); return (word32)(sizeof(common) + 7); } /* Build a chain (root -> intermediate -> leaf) where the intermediate * carries `nameConstraintsDer` as a (possibly critical) nameConstraints * extension and the leaf carries `sanDer` as its SAN. Loads root and * intermediate as trusted CAs into a fresh CertManager, parses the leaf * with VERIFY, and returns the result code from wc_ParseCert(). */ static int verify_with_otherName_chain(const byte* nameConstraintsDer, word32 nameConstraintsDerSz, int critical, const byte* sanDer, word32 sanDerSz) { Cert cert; DecodedCert decodedCert; byte rootDer[FOURK_BUF]; byte icaDer[FOURK_BUF]; byte leafDer[FOURK_BUF]; int rootDerSz = 0, icaDerSz = 0, leafDerSz = 0; int parseRet = -1; WC_RNG rng; ecc_key rootKey, icaKey, leafKey; WOLFSSL_CERT_MANAGER* cm = NULL; XMEMSET(&rng, 0, sizeof(rng)); XMEMSET(&rootKey, 0, sizeof(rootKey)); XMEMSET(&icaKey, 0, sizeof(icaKey)); XMEMSET(&leafKey, 0, sizeof(leafKey)); if (wc_InitRng(&rng) != 0) goto done; if (wc_ecc_init(&rootKey) != 0) goto done; if (wc_ecc_init(&icaKey) != 0) goto done; if (wc_ecc_init(&leafKey) != 0) goto done; if (wc_ecc_make_key(&rng, 32, &rootKey) != 0) goto done; if (wc_ecc_make_key(&rng, 32, &icaKey) != 0) goto done; if (wc_ecc_make_key(&rng, 32, &leafKey) != 0) goto done; /* Self-signed root. */ if (wc_InitCert(&cert) != 0) goto done; (void)XSTRNCPY(cert.subject.country, "US", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.org, "OtherNCRoot", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.commonName, "OtherNCRoot", CTC_NAME_SIZE); cert.selfSigned = 1; cert.isCA = 1; cert.sigType = CTC_SHA256wECDSA; cert.keyUsage = KEYUSE_KEY_CERT_SIGN | KEYUSE_CRL_SIGN; if (wc_SetSubjectKeyIdFromPublicKey_ex(&cert, ECC_TYPE, &rootKey) != 0) goto done; if (wc_MakeCert(&cert, rootDer, FOURK_BUF, NULL, &rootKey, &rng) < 0) goto done; rootDerSz = wc_SignCert(cert.bodySz, cert.sigType, rootDer, FOURK_BUF, NULL, &rootKey, &rng); if (rootDerSz < 0) goto done; /* Intermediate, signed by root, carrying nameConstraints. */ if (wc_InitCert(&cert) != 0) goto done; cert.selfSigned = 0; cert.isCA = 1; cert.sigType = CTC_SHA256wECDSA; cert.keyUsage = KEYUSE_KEY_CERT_SIGN | KEYUSE_CRL_SIGN; (void)XSTRNCPY(cert.subject.country, "US", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.org, "OtherNCICA", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.commonName, "OtherNCICA", CTC_NAME_SIZE); if (wc_SetIssuerBuffer(&cert, rootDer, rootDerSz) != 0) goto done; if (wc_SetAuthKeyIdFromPublicKey_ex(&cert, ECC_TYPE, &rootKey) != 0) goto done; if (wc_SetSubjectKeyIdFromPublicKey_ex(&cert, ECC_TYPE, &icaKey) != 0) goto done; if (nameConstraintsDer != NULL) { /* nameConstraints OID = 2.5.29.30 */ if (wc_SetCustomExtension(&cert, critical ? 1 : 0, "2.5.29.30", nameConstraintsDer, nameConstraintsDerSz) != 0) goto done; } if (wc_MakeCert(&cert, icaDer, FOURK_BUF, NULL, &icaKey, &rng) < 0) goto done; icaDerSz = wc_SignCert(cert.bodySz, cert.sigType, icaDer, FOURK_BUF, NULL, &rootKey, &rng); if (icaDerSz < 0) goto done; /* Leaf, signed by intermediate, carrying the otherName SAN. */ if (wc_InitCert(&cert) != 0) goto done; cert.selfSigned = 0; cert.isCA = 0; cert.sigType = CTC_SHA256wECDSA; (void)XSTRNCPY(cert.subject.country, "US", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.org, "OtherNCLeaf", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.commonName, "OtherNCLeaf", CTC_NAME_SIZE); if (wc_SetIssuerBuffer(&cert, icaDer, icaDerSz) != 0) goto done; if (wc_SetAuthKeyIdFromPublicKey_ex(&cert, ECC_TYPE, &icaKey) != 0) goto done; if (wc_SetSubjectKeyIdFromPublicKey_ex(&cert, ECC_TYPE, &leafKey) != 0) goto done; if (sanDer != NULL && sanDerSz > 0) { if (sanDerSz > sizeof(cert.altNames)) goto done; XMEMCPY(cert.altNames, sanDer, sanDerSz); cert.altNamesSz = (int)sanDerSz; } if (wc_MakeCert(&cert, leafDer, FOURK_BUF, NULL, &leafKey, &rng) < 0) goto done; leafDerSz = wc_SignCert(cert.bodySz, cert.sigType, leafDer, FOURK_BUF, NULL, &icaKey, &rng); if (leafDerSz < 0) goto done; cm = wolfSSL_CertManagerNew(); if (cm == NULL) goto done; if (wolfSSL_CertManagerLoadCABuffer(cm, rootDer, rootDerSz, WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) goto done; if (wolfSSL_CertManagerLoadCABuffer(cm, icaDer, icaDerSz, WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) goto done; wc_InitDecodedCert(&decodedCert, leafDer, (word32)leafDerSz, NULL); parseRet = wc_ParseCert(&decodedCert, CERT_TYPE, VERIFY, cm); wc_FreeDecodedCert(&decodedCert); done: if (cm != NULL) wolfSSL_CertManagerFree(cm); wc_ecc_free(&leafKey); wc_ecc_free(&icaKey); wc_ecc_free(&rootKey); wc_FreeRng(&rng); return parseRet; } #endif /* Verifies wolfSSL enforces an issuing CA's nameConstraints extension on a * leaf certificate's otherName SAN (RFC 5280 4.2.1.10). The vulnerability * was that ConfirmNameConstraints() ignored ASN_OTHER_TYPE entirely, so a * malicious intermediate could issue leaves whose otherName SAN violated * its own subtree. * * Coverage: * 1. Critical excluded subtree, leaf SAN matches -> reject * 2. Critical excluded subtree, leaf SAN does NOT match -> accept * (positive control: distinguishes 'right rule fired' from * 'broke everything with otherName') * 3. Non-critical excluded subtree, leaf SAN matches -> reject * (excluded is enforced regardless of criticality) * 4. Critical permitted subtree, leaf SAN matches -> accept * 5. Critical permitted subtree, leaf SAN does NOT match -> reject * 6. Critical excluded registeredID subtree, leaf SAN matches -> reject * (registeredID is enforced by byte-comparison of OID bodies) * 7. Non-critical excluded registeredID subtree, leaf SAN matches -> reject * (excluded subtrees are enforced regardless of criticality) * 8. Critical excluded registeredID subtree, leaf has no RID SAN -> accept * (no match in excluded list, constraint is satisfied) */ static int test_NameConstraints_OtherName(void) { EXPECT_DECLS; #if defined(WOLFSSL_ASN_TEMPLATE) && \ defined(WOLFSSL_CERT_REQ) && !defined(NO_ASN_TIME) && \ defined(WOLFSSL_CERT_GEN) && defined(HAVE_ECC) && \ defined(WOLFSSL_CERT_EXT) && !defined(NO_CERTS) && \ defined(WOLFSSL_ALT_NAMES) && defined(WOLFSSL_CUSTOM_OID) && \ defined(HAVE_OID_ENCODING) && !defined(IGNORE_NAME_CONSTRAINTS) byte sanBlocked[64]; byte sanAllowed[64]; byte sanRegisteredID[16]; byte ncExcludedBlocked[64]; byte ncPermittedAllowed[64]; byte ncRegisteredID[16]; word32 sanBlockedSz, sanAllowedSz, sanRegisteredIDSz; word32 ncExcludedBlockedSz, ncPermittedAllowedSz, ncRegisteredIDSz; sanBlockedSz = build_otherName_san(sanBlocked, sizeof(sanBlocked), "blocked"); sanAllowedSz = build_otherName_san(sanAllowed, sizeof(sanAllowed), "allowed"); sanRegisteredIDSz = build_registeredID_san(sanRegisteredID, sizeof(sanRegisteredID)); ncExcludedBlockedSz = build_otherName_nameConstraints( ncExcludedBlocked, sizeof(ncExcludedBlocked), 1, "blocked"); ncPermittedAllowedSz = build_otherName_nameConstraints( ncPermittedAllowed, sizeof(ncPermittedAllowed), 0, "allowed"); ncRegisteredIDSz = build_registeredID_nameConstraints( ncRegisteredID, sizeof(ncRegisteredID)); ExpectIntGT((int)sanBlockedSz, 0); ExpectIntGT((int)sanAllowedSz, 0); ExpectIntGT((int)sanRegisteredIDSz, 0); ExpectIntGT((int)ncExcludedBlockedSz, 0); ExpectIntGT((int)ncPermittedAllowedSz, 0); ExpectIntGT((int)ncRegisteredIDSz, 0); /* (1) Original bypass scenario: critical excluded otherName matches * the leaf's otherName SAN. Must be rejected. */ ExpectIntEQ(verify_with_otherName_chain( ncExcludedBlocked, ncExcludedBlockedSz, 1, sanBlocked, sanBlockedSz), WC_NO_ERR_TRACE(ASN_NAME_INVALID_E)); /* (2) Positive control: same critical excluded subtree, but the leaf * carries a DIFFERENT otherName value, so byte-comparison says no * match and the chain MUST verify. This pins the rejection in (1) * to the matching path rather than to a blanket 'reject any * otherName under critical'. */ ExpectIntEQ(verify_with_otherName_chain( ncExcludedBlocked, ncExcludedBlockedSz, 1, sanAllowed, sanAllowedSz), 0); /* (3) Non-critical excluded subtree, leaf SAN matches: exclusion is * enforced regardless of criticality. */ ExpectIntEQ(verify_with_otherName_chain( ncExcludedBlocked, ncExcludedBlockedSz, 0, sanBlocked, sanBlockedSz), WC_NO_ERR_TRACE(ASN_NAME_INVALID_E)); /* (4) Critical permitted subtree, leaf SAN inside the permitted set: * verification succeeds. */ ExpectIntEQ(verify_with_otherName_chain( ncPermittedAllowed, ncPermittedAllowedSz, 1, sanAllowed, sanAllowedSz), 0); /* (5) Critical permitted subtree, leaf SAN outside the permitted set: * verification rejects. */ ExpectIntEQ(verify_with_otherName_chain( ncPermittedAllowed, ncPermittedAllowedSz, 1, sanBlocked, sanBlockedSz), WC_NO_ERR_TRACE(ASN_NAME_INVALID_E)); /* (6) Critical excluded registeredID subtree, leaf SAN matches: * registeredID is now enforced by byte-comparing OID bodies, so a * matching excluded entry must be rejected. */ ExpectIntEQ(verify_with_otherName_chain( ncRegisteredID, ncRegisteredIDSz, 1, sanRegisteredID, sanRegisteredIDSz), WC_NO_ERR_TRACE(ASN_NAME_INVALID_E)); /* (7) Non-critical excluded registeredID subtree, leaf SAN matches: * excluded subtrees are enforced regardless of criticality. */ ExpectIntEQ(verify_with_otherName_chain( ncRegisteredID, ncRegisteredIDSz, 0, sanRegisteredID, sanRegisteredIDSz), WC_NO_ERR_TRACE(ASN_NAME_INVALID_E)); /* (8) Critical excluded registeredID subtree, leaf has no RID SAN: * no excluded match, so verification succeeds. */ ExpectIntEQ(verify_with_otherName_chain( ncRegisteredID, ncRegisteredIDSz, 1, NULL, 0), 0); #endif return EXPECT_RESULT(); } static int test_MakeCertWithCaFalse(void) { EXPECT_DECLS; #if defined(WOLFSSL_ALLOW_ENCODING_CA_FALSE) && defined(WOLFSSL_CERT_REQ) && \ !defined(NO_ASN_TIME) && defined(WOLFSSL_CERT_GEN) && defined(HAVE_ECC) const byte expectedIsCa = 0; Cert cert; DecodedCert decodedCert; byte der[FOURK_BUF]; int derSize = 0; WC_RNG rng; ecc_key key; int ret; XMEMSET(&rng, 0, sizeof(WC_RNG)); XMEMSET(&key, 0, sizeof(ecc_key)); XMEMSET(&cert, 0, sizeof(Cert)); XMEMSET(&decodedCert, 0, sizeof(DecodedCert)); ExpectIntEQ(wc_InitRng(&rng), 0); ExpectIntEQ(wc_ecc_init(&key), 0); ExpectIntEQ(wc_ecc_make_key(&rng, 32, &key), 0); ExpectIntEQ(wc_InitCert(&cert), 0); (void)XSTRNCPY(cert.subject.country, "US", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.state, "state", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.locality, "Bozeman", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.org, "yourOrgNameHere", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.unit, "yourUnitNameHere", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.commonName, "www.yourDomain.com", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.email, "yourEmail@yourDomain.com", CTC_NAME_SIZE); cert.selfSigned = 1; cert.isCA = expectedIsCa; cert.isCaSet = 1; cert.sigType = CTC_SHA256wECDSA; ExpectIntGE(wc_MakeCert(&cert, der, FOURK_BUF, NULL, &key, &rng), 0); ExpectIntGE(derSize = wc_SignCert(cert.bodySz, cert.sigType, der, FOURK_BUF, NULL, &key, &rng), 0); wc_InitDecodedCert(&decodedCert, der, derSize, NULL); ExpectIntEQ(wc_ParseCert(&decodedCert, CERT_TYPE, NO_VERIFY, NULL), 0); ExpectIntEQ(decodedCert.isCA, expectedIsCa); wc_FreeDecodedCert(&decodedCert); ret = wc_ecc_free(&key); ExpectIntEQ(ret, 0); ret = wc_FreeRng(&rng); ExpectIntEQ(ret, 0); #endif return EXPECT_RESULT(); } /* Mock callback for testing wc_SignCert_cb */ #if defined(WOLFSSL_CERT_SIGN_CB) && (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_CERT_REQ)) /* Context structure for mock signing callback */ typedef struct { void* key; /* Pointer to RSA or ECC key */ WC_RNG* rng; /* Random number generator (required for ECC) */ } MockSignCtx; static int mockSignCb(const byte* in, word32 inLen, byte* out, word32* outLen, int sigAlgo, int keyType, void* ctx) { int ret = 0; MockSignCtx* signCtx = (MockSignCtx*)ctx; if (signCtx == NULL || signCtx->key == NULL || in == NULL || out == NULL || outLen == NULL) { return BAD_FUNC_ARG; } (void)sigAlgo; #ifndef NO_RSA if (keyType == RSA_TYPE) { RsaKey* rsaKey = (RsaKey*)signCtx->key; word32 outSz = *outLen; /* For RSA, input is DER-encoded digest (DigestInfo structure) */ ret = wc_RsaSSL_Sign(in, inLen, out, outSz, rsaKey, signCtx->rng); if (ret > 0) { *outLen = (word32)ret; ret = 0; } } else #endif #ifdef HAVE_ECC if (keyType == ECC_TYPE) { ecc_key* eccKey = (ecc_key*)signCtx->key; word32 outSz = *outLen; /* For ECC, input is raw hash, sign it (RNG required for ECDSA k value) */ ret = wc_ecc_sign_hash(in, inLen, out, &outSz, signCtx->rng, eccKey); if (ret == 0) { *outLen = outSz; } } else #endif { ret = BAD_FUNC_ARG; } return ret; } /* Mock callback that always returns an error for testing */ static int mockSignCbError(const byte* in, word32 inLen, byte* out, word32* outLen, int sigAlgo, int keyType, void* ctx) { (void)in; (void)inLen; (void)out; (void)outLen; (void)sigAlgo; (void)keyType; (void)ctx; return BAD_STATE_E; /* Return an error */ } #endif #ifdef WOLFSSL_CERT_SIGN_CB static int test_wc_SignCert_cb(void) { EXPECT_DECLS; #if defined(WOLFSSL_CERT_GEN) && !defined(NO_ASN_TIME) #ifdef HAVE_ECC /* Test with ECC key */ { Cert cert; byte der[FOURK_BUF]; int derSize = 0; WC_RNG rng; ecc_key key; MockSignCtx signCtx; DecodedCert decodedCert; int ret; XMEMSET(&rng, 0, sizeof(WC_RNG)); XMEMSET(&key, 0, sizeof(ecc_key)); XMEMSET(&cert, 0, sizeof(Cert)); XMEMSET(&signCtx, 0, sizeof(MockSignCtx)); XMEMSET(&decodedCert, 0, sizeof(DecodedCert)); ExpectIntEQ(wc_InitRng(&rng), 0); ExpectIntEQ(wc_ecc_init(&key), 0); ExpectIntEQ(wc_ecc_make_key(&rng, 32, &key), 0); ExpectIntEQ(wc_InitCert(&cert), 0); (void)XSTRNCPY(cert.subject.country, "US", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.state, "state", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.locality, "locality", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.org, "org", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.unit, "unit", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.commonName, "www.example.com", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.email, "test@example.com", CTC_NAME_SIZE); cert.selfSigned = 1; cert.isCA = 0; cert.sigType = CTC_SHA256wECDSA; /* Make cert body */ ExpectIntGT(wc_MakeCert(&cert, der, FOURK_BUF, NULL, &key, &rng), 0); /* Setup signing context with key and RNG */ signCtx.key = &key; signCtx.rng = &rng; /* Sign using callback API */ ExpectIntGT(derSize = wc_SignCert_cb(cert.bodySz, cert.sigType, der, FOURK_BUF, ECC_TYPE, mockSignCb, &signCtx, &rng), 0); /* Verify the certificate was created properly */ ExpectIntGT(derSize, 0); /* Parse the certificate and verify it's well-formed */ if (EXPECT_SUCCESS()) { wc_InitDecodedCert(&decodedCert, der, (word32)derSize, NULL); ExpectIntEQ(wc_ParseCert(&decodedCert, CERT_TYPE, NO_VERIFY, NULL), 0); /* Verify signature algorithm matches what we set */ ExpectIntEQ(decodedCert.signatureOID, CTC_SHA256wECDSA); wc_FreeDecodedCert(&decodedCert); } /* Test error cases */ /* NULL callback */ ExpectIntEQ(wc_SignCert_cb(cert.bodySz, cert.sigType, der, FOURK_BUF, ECC_TYPE, NULL, &signCtx, &rng), BAD_FUNC_ARG); /* NULL buffer */ ExpectIntEQ(wc_SignCert_cb(cert.bodySz, cert.sigType, NULL, FOURK_BUF, ECC_TYPE, mockSignCb, &signCtx, &rng), BAD_FUNC_ARG); /* Zero buffer size */ ExpectIntEQ(wc_SignCert_cb(cert.bodySz, cert.sigType, der, 0, ECC_TYPE, mockSignCb, &signCtx, &rng), BAD_FUNC_ARG); /* Negative requestSz - should return the negative value */ ExpectIntLT(wc_SignCert_cb(-1, cert.sigType, der, FOURK_BUF, ECC_TYPE, mockSignCb, &signCtx, &rng), 0); /* Callback returning error */ ExpectIntEQ(wc_SignCert_cb(cert.bodySz, cert.sigType, der, FOURK_BUF, ECC_TYPE, mockSignCbError, &signCtx, &rng), BAD_STATE_E); #ifndef NO_RSA /* Invalid keyType for ECC signature */ ExpectIntEQ(wc_SignCert_cb(cert.bodySz, cert.sigType, der, FOURK_BUF, ED25519_TYPE, mockSignCb, &signCtx, &rng), BAD_FUNC_ARG); #endif ret = wc_ecc_free(&key); ExpectIntEQ(ret, 0); ret = wc_FreeRng(&rng); ExpectIntEQ(ret, 0); } #endif /* HAVE_ECC */ #if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) /* Test with RSA key */ { Cert cert; byte der[FOURK_BUF]; int derSize = 0; WC_RNG rng; RsaKey key; MockSignCtx signCtx; DecodedCert decodedCert; int ret; XMEMSET(&rng, 0, sizeof(WC_RNG)); XMEMSET(&key, 0, sizeof(RsaKey)); XMEMSET(&cert, 0, sizeof(Cert)); XMEMSET(&signCtx, 0, sizeof(MockSignCtx)); XMEMSET(&decodedCert, 0, sizeof(DecodedCert)); ExpectIntEQ(wc_InitRng(&rng), 0); ExpectIntEQ(wc_InitRsaKey(&key, NULL), 0); ExpectIntEQ(wc_MakeRsaKey(&key, 2048, WC_RSA_EXPONENT, &rng), 0); ExpectIntEQ(wc_InitCert(&cert), 0); (void)XSTRNCPY(cert.subject.country, "US", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.state, "state", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.locality, "locality", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.org, "org", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.unit, "unit", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.commonName, "www.example.com", CTC_NAME_SIZE); (void)XSTRNCPY(cert.subject.email, "test@example.com", CTC_NAME_SIZE); cert.selfSigned = 1; cert.isCA = 0; cert.sigType = CTC_SHA256wRSA; /* Make cert body */ ExpectIntGT(wc_MakeCert(&cert, der, FOURK_BUF, &key, NULL, &rng), 0); /* Setup signing context with key and RNG */ signCtx.key = &key; signCtx.rng = &rng; /* Sign using callback API with RSA */ ExpectIntGT(derSize = wc_SignCert_cb(cert.bodySz, cert.sigType, der, FOURK_BUF, RSA_TYPE, mockSignCb, &signCtx, &rng), 0); /* Verify the certificate was created properly */ ExpectIntGT(derSize, 0); /* Parse the certificate and verify it's well-formed */ if (EXPECT_SUCCESS()) { wc_InitDecodedCert(&decodedCert, der, (word32)derSize, NULL); ExpectIntEQ(wc_ParseCert(&decodedCert, CERT_TYPE, NO_VERIFY, NULL), 0); /* Verify signature algorithm matches what we set */ ExpectIntEQ(decodedCert.signatureOID, CTC_SHA256wRSA); wc_FreeDecodedCert(&decodedCert); } /* Test error cases */ /* NULL callback */ ExpectIntEQ(wc_SignCert_cb(cert.bodySz, cert.sigType, der, FOURK_BUF, RSA_TYPE, NULL, &signCtx, &rng), BAD_FUNC_ARG); /* NULL buffer */ ExpectIntEQ(wc_SignCert_cb(cert.bodySz, cert.sigType, NULL, FOURK_BUF, RSA_TYPE, mockSignCb, &signCtx, &rng), BAD_FUNC_ARG); /* Zero buffer size */ ExpectIntEQ(wc_SignCert_cb(cert.bodySz, cert.sigType, der, 0, RSA_TYPE, mockSignCb, &signCtx, &rng), BAD_FUNC_ARG); /* Callback returning error */ ExpectIntEQ(wc_SignCert_cb(cert.bodySz, cert.sigType, der, FOURK_BUF, RSA_TYPE, mockSignCbError, &signCtx, &rng), BAD_STATE_E); #ifdef HAVE_ECC /* Invalid keyType */ ExpectIntEQ(wc_SignCert_cb(cert.bodySz, cert.sigType, der, FOURK_BUF, ED448_TYPE, mockSignCb, &signCtx, &rng), BAD_FUNC_ARG); #endif ret = wc_FreeRsaKey(&key); ExpectIntEQ(ret, 0); ret = wc_FreeRng(&rng); ExpectIntEQ(ret, 0); } #endif /* !NO_RSA && WOLFSSL_KEY_GEN */ #endif /* WOLFSSL_CERT_GEN && !NO_ASN_TIME */ return EXPECT_RESULT(); } #endif /* WOLFSSL_CERT_SIGN_CB */ static int test_ERR_load_crypto_strings(void) { #if defined(OPENSSL_ALL) ERR_load_crypto_strings(); return TEST_SUCCESS; #else return TEST_SKIPPED; #endif } #if defined(OPENSSL_ALL) && !defined(NO_CERTS) static WOLFSSL_X509 x1; static WOLFSSL_X509 x2; static void free_x509(X509* x) { AssertIntEQ((x == &x1 || x == &x2), 1); } #endif static int test_sk_X509(void) { EXPECT_DECLS; #if defined(OPENSSL_ALL) && !defined(NO_CERTS) { STACK_OF(X509)* s = NULL; ExpectNotNull(s = wolfSSL_sk_X509_new(NULL)); ExpectIntEQ(sk_X509_num(s), 0); sk_X509_pop_free(s, NULL); s = NULL; ExpectNotNull(s = sk_X509_new_null()); ExpectIntEQ(sk_X509_num(s), 0); sk_X509_pop_free(s, NULL); s = NULL; ExpectNotNull(s = sk_X509_new_null()); /* Test invalid parameters. */ ExpectIntEQ(sk_X509_push(NULL, NULL), WOLFSSL_FAILURE); ExpectIntEQ(sk_X509_push(s, NULL), WOLFSSL_FAILURE); ExpectIntEQ(sk_X509_push(NULL, (X509*)1), WOLFSSL_FAILURE); ExpectNull(sk_X509_pop(NULL)); ExpectNull(sk_X509_value(NULL, 0)); ExpectNull(sk_X509_value(NULL, 1)); sk_X509_push(s, &x1); ExpectIntEQ(sk_X509_num(s), 1); ExpectIntEQ((sk_X509_value(s, 0) == &x1), 1); sk_X509_push(s, &x2); ExpectIntEQ(sk_X509_num(s), 2); ExpectNull(sk_X509_value(s, 2)); ExpectIntEQ((sk_X509_value(s, 0) == &x1), 1); ExpectIntEQ((sk_X509_value(s, 1) == &x2), 1); sk_X509_push(s, &x2); sk_X509_pop_free(s, free_x509); } { /* Push a list of 10 X509s onto stack, then verify that * value(), push(), shift(), and pop() behave as expected. */ STACK_OF(X509)* s = NULL; X509* xList[10]; int i = 0; const int len = (sizeof(xList) / sizeof(xList[0])); for (i = 0; i < len; ++i) { xList[i] = NULL; ExpectNotNull(xList[i] = X509_new()); } /* test push, pop, and free */ ExpectNotNull(s = sk_X509_new_null()); for (i = 0; i < len; ++i) { sk_X509_push(s, xList[i]); ExpectIntEQ(sk_X509_num(s), i + 1); ExpectIntEQ((sk_X509_value(s, 0) == xList[0]), 1); ExpectIntEQ((sk_X509_value(s, i) == xList[i]), 1); } /* pop returns and removes last pushed on stack, which is the last index * in sk_x509_value */ for (i = len-1; i >= 0; --i) { X509 * x = sk_X509_value(s, i); X509 * y = sk_X509_pop(s); X509 * z = xList[i]; ExpectPtrEq(x, y); ExpectPtrEq(x, z); ExpectIntEQ(sk_X509_num(s), i); } sk_free(s); s = NULL; /* test push, shift, and free */ ExpectNotNull(s = sk_X509_new_null()); for (i = 0; i < len; ++i) { sk_X509_push(s, xList[i]); ExpectIntEQ(sk_X509_num(s), i + 1); ExpectIntEQ((sk_X509_value(s, 0) == xList[0]), 1); ExpectIntEQ((sk_X509_value(s, i) == xList[i]), 1); } /* shift returns and removes first pushed on stack, which is index i * in sk_x509_value() */ for (i = 0; i < len; ++i) { X509 * x = sk_X509_value(s, 0); X509 * y = sk_X509_shift(s); X509 * z = xList[i]; ExpectIntEQ((x == y), 1); ExpectIntEQ((x == z), 1); ExpectIntEQ(sk_X509_num(s), len - 1 - i); } ExpectNull(sk_X509_shift(NULL)); ExpectNull(sk_X509_shift(s)); sk_free(s); for (i = 0; i < len; ++i) X509_free(xList[i]); } #endif return EXPECT_RESULT(); } static int test_sk_X509_CRL_decode(void) { EXPECT_DECLS; #if (defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)) && !defined(NO_CERTS) && \ defined(HAVE_CRL) && !defined(NO_RSA) X509_CRL* crl = NULL; XFILE fp = XBADFILE; STACK_OF(X509_CRL)* s = NULL; #ifndef NO_BIO BIO* bio = NULL; #endif #if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM) RevokedCert* rev = NULL; byte buff[1024]; int len = 0; #endif #if (!defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM)) || \ !defined(NO_BIO) X509_CRL empty; #endif WOLFSSL_X509_REVOKED revoked; WOLFSSL_ASN1_INTEGER* asnInt = NULL; const WOLFSSL_ASN1_INTEGER* sn = NULL; XMEMSET(&revoked, 0, sizeof(revoked)); revoked.reason = CRL_REASON_NONE; #if (!defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM)) || \ !defined(NO_BIO) XMEMSET(&empty, 0, sizeof(X509_CRL)); #endif #ifndef NO_BIO ExpectNotNull(bio = BIO_new_file("./certs/crl/crl.der", "rb")); ExpectNull(wolfSSL_d2i_X509_CRL_bio(NULL, NULL)); ExpectNotNull(crl = wolfSSL_d2i_X509_CRL_bio(bio, NULL)); BIO_free(bio); bio = NULL; ExpectNotNull(bio = BIO_new(BIO_s_mem())); ExpectIntEQ(wolfSSL_X509_CRL_print(NULL, NULL), WOLFSSL_FAILURE); ExpectIntEQ(wolfSSL_X509_CRL_print(bio, NULL), WOLFSSL_FAILURE); ExpectIntEQ(wolfSSL_X509_CRL_print(NULL, crl), WOLFSSL_FAILURE); ExpectIntEQ(wolfSSL_X509_CRL_print(bio, &empty), WOLFSSL_FAILURE); ExpectIntEQ(wolfSSL_X509_CRL_print(bio, crl), WOLFSSL_SUCCESS); #ifndef NO_ASN_TIME ExpectIntEQ(BIO_get_mem_data(bio, NULL), 1466); #else ExpectIntEQ(BIO_get_mem_data(bio, NULL), 1324); #endif BIO_free(bio); bio = NULL; wolfSSL_X509_CRL_free(crl); crl = NULL; #ifndef NO_ASN_TIME /* Test CRL with invalid GeneralizedTime */ ExpectNotNull(bio = BIO_new_file("./certs/crl/bad_time_fmt.pem", "rb")); ExpectNotNull(crl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL)); BIO_free(bio); bio = NULL; ExpectNotNull(bio = BIO_new(BIO_s_mem())); ExpectIntEQ(wolfSSL_X509_CRL_print(bio, crl), WOLFSSL_FAILURE); BIO_free(bio); bio = NULL; wolfSSL_X509_CRL_free(crl); crl = NULL; #endif /* !NO_ASN_TIME */ #endif /* !NO_BIO */ #if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM) ExpectTrue((fp = XFOPEN("./certs/crl/crl.der", "rb")) != XBADFILE); ExpectNotNull(crl = d2i_X509_CRL_fp(fp, (X509_CRL **)NULL)); if (fp != XBADFILE) { XFCLOSE(fp); fp = XBADFILE; } wolfSSL_X509_CRL_free(crl); crl = NULL; ExpectTrue((fp = XFOPEN("./certs/crl/crl.der", "rb")) != XBADFILE); ExpectIntEQ(len = (int)XFREAD(buff, 1, sizeof(buff), fp), 520); if (fp != XBADFILE) { XFCLOSE(fp); fp = XBADFILE; } ExpectNull(crl = d2i_X509_CRL((X509_CRL **)NULL, NULL, len)); ExpectNotNull(crl = d2i_X509_CRL((X509_CRL **)NULL, buff, len)); ExpectNotNull(rev = crl->crlList->certs); ExpectNull(wolfSSL_X509_CRL_get_issuer_name(NULL)); ExpectNull(wolfSSL_X509_CRL_get_issuer_name(&empty)); ExpectIntEQ(wolfSSL_X509_CRL_version(NULL), 0); ExpectIntEQ(wolfSSL_X509_CRL_version(&empty), 0); ExpectIntEQ(wolfSSL_X509_CRL_get_signature_type(NULL), 0); ExpectIntEQ(wolfSSL_X509_CRL_get_signature_type(&empty), 0); ExpectIntEQ(wolfSSL_X509_CRL_get_signature_nid(NULL), 0); ExpectIntEQ(wolfSSL_X509_CRL_get_signature_nid(&empty), 0); { int sigSz = 0; ExpectIntEQ(wolfSSL_X509_CRL_get_signature(NULL, NULL, NULL), BAD_FUNC_ARG); ExpectIntEQ(wolfSSL_X509_CRL_get_signature(crl, NULL, NULL), BAD_FUNC_ARG); ExpectIntEQ(wolfSSL_X509_CRL_get_signature(NULL, NULL, &sigSz), BAD_FUNC_ARG); ExpectIntEQ(wolfSSL_X509_CRL_get_signature(&empty, NULL, &sigSz), BAD_FUNC_ARG); } ExpectIntEQ(wolfSSL_X509_REVOKED_get_serial_number(NULL, NULL, NULL), BAD_FUNC_ARG); ExpectIntEQ(wolfSSL_X509_REVOKED_get_serial_number(rev , NULL, NULL), BAD_FUNC_ARG); ExpectIntEQ(wolfSSL_X509_REVOKED_get_serial_number(NULL, NULL, &len), BAD_FUNC_ARG); ExpectNull(wolfSSL_X509_CRL_get_lastUpdate(NULL)); ExpectNull(wolfSSL_X509_CRL_get_lastUpdate(&empty)); ExpectNull(wolfSSL_X509_CRL_get_nextUpdate(NULL)); ExpectNull(wolfSSL_X509_CRL_get_nextUpdate(&empty)); ExpectNotNull(wolfSSL_X509_CRL_get_issuer_name(crl)); ExpectIntEQ(wolfSSL_X509_CRL_version(crl), 2); ExpectIntEQ(wolfSSL_X509_CRL_get_signature_type(crl), CTC_SHA256wRSA); ExpectIntEQ(wolfSSL_X509_CRL_get_signature_nid(crl), WC_NID_sha256WithRSAEncryption); { int sigSz = 0; ExpectIntEQ(wolfSSL_X509_CRL_get_signature(crl, NULL, &sigSz), WOLFSSL_SUCCESS); ExpectIntEQ(sigSz, 256); } ExpectNotNull(wolfSSL_X509_CRL_get_lastUpdate(crl)); ExpectNotNull(wolfSSL_X509_CRL_get_nextUpdate(crl)); ExpectIntEQ(wolfSSL_X509_REVOKED_get_serial_number(rev, NULL, &len), WOLFSSL_SUCCESS); ExpectIntEQ(len, 1); len--; ExpectIntEQ(wolfSSL_X509_REVOKED_get_serial_number(rev, buff, &len), BUFFER_E); len += 2; ExpectIntEQ(wolfSSL_X509_REVOKED_get_serial_number(rev, buff, &len), WOLFSSL_SUCCESS); ExpectIntEQ(len, 1); /* Test X509_CRL_get_REVOKED and stack iteration */ ExpectIntEQ(wolfSSL_sk_X509_REVOKED_num(NULL), 0); ExpectNull(wolfSSL_X509_CRL_get_REVOKED(NULL)); { WOLFSSL_STACK* revokedSk = NULL; ExpectNotNull(revokedSk = wolfSSL_X509_CRL_get_REVOKED(crl)); if (revokedSk != NULL) { int numRevoked = wolfSSL_sk_X509_REVOKED_num(revokedSk); ExpectIntGT(numRevoked, 0); /* Verify first revoked entry has a serial number */ { WOLFSSL_X509_REVOKED* r = NULL; ExpectNotNull(r = wolfSSL_sk_X509_REVOKED_value(revokedSk, 0)); if (r != NULL) { ExpectNotNull(r->serialNumber); /* Verify revocation date is populated */ ExpectNotNull( wolfSSL_X509_REVOKED_get0_revocation_date(r)); /* Verify sequence field (first entry should be 0) */ ExpectIntEQ(r->sequence, 0); } } } ExpectNull(wolfSSL_sk_X509_REVOKED_value(NULL, 0)); } #ifndef NO_WOLFSSL_STUB ExpectIntEQ(wolfSSL_X509_CRL_verify(NULL, NULL), 0); ExpectIntEQ(X509_OBJECT_set1_X509_CRL(NULL, NULL), 0); ExpectIntEQ(X509_OBJECT_set1_X509(NULL, NULL), 0); #endif wolfSSL_X509_CRL_free(crl); crl = NULL; #endif ExpectNotNull(asnInt = wolfSSL_ASN1_INTEGER_new()); ExpectIntEQ(wolfSSL_ASN1_INTEGER_set(asnInt, 1), 1); revoked.serialNumber = asnInt; ExpectNull(wolfSSL_X509_REVOKED_get0_serial_number(NULL)); ExpectNotNull(sn = wolfSSL_X509_REVOKED_get0_serial_number(&revoked)); ExpectPtrEq(sn, asnInt); ExpectNull(wolfSSL_X509_REVOKED_get0_revocation_date(NULL)); /* revoked on stack has no revocationDate set, so should be NULL */ ExpectNull(wolfSSL_X509_REVOKED_get0_revocation_date(&revoked)); wolfSSL_ASN1_INTEGER_free(asnInt); ExpectTrue((fp = XFOPEN("./certs/crl/crl.pem", "rb")) != XBADFILE); ExpectNotNull(crl = (X509_CRL*)PEM_read_X509_CRL(fp, (X509_CRL **)NULL, NULL, NULL)); if (fp != XBADFILE) XFCLOSE(fp); ExpectNotNull(s = sk_X509_CRL_new()); ExpectIntEQ(sk_X509_CRL_push(NULL, NULL), WOLFSSL_FAILURE); ExpectIntEQ(sk_X509_CRL_push(NULL, crl), WOLFSSL_FAILURE); ExpectIntEQ(sk_X509_CRL_push(s, NULL), WOLFSSL_FAILURE); ExpectNull(sk_X509_CRL_value(NULL, 0)); ExpectIntEQ(sk_X509_CRL_num(NULL), 0); ExpectIntEQ(sk_X509_CRL_num(s), 0); ExpectIntEQ(sk_X509_CRL_push(s, crl), 1); if (EXPECT_FAIL()) { X509_CRL_free(crl); } ExpectIntEQ(sk_X509_CRL_num(s), 1); ExpectPtrEq(sk_X509_CRL_value(s, 0), crl); sk_X509_CRL_free(s); #endif return EXPECT_RESULT(); } #if (defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)) && !defined(NO_CERTS) && \ defined(HAVE_CRL) && defined(WOLFSSL_CERT_GEN) /* Ensure oversized caller-provided revocationDate is rejected. */ static int test_wolfSSL_X509_CRL_add_revoked_oversized_revocation_date(void) { EXPECT_DECLS; WOLFSSL_X509_CRL* crl = NULL; WOLFSSL_ASN1_INTEGER* serial = NULL; WOLFSSL_X509_REVOKED revoked; WOLFSSL_ASN1_TIME revDate; byte serialData[] = { 0x01 }; XMEMSET(&revoked, 0, sizeof(revoked)); XMEMSET(&revDate, 0, sizeof(revDate)); ExpectNotNull(crl = wolfSSL_X509_CRL_new()); ExpectNotNull(serial = wolfSSL_ASN1_INTEGER_new()); if (serial != NULL) { serial->data = serialData; serial->dataMax = (int)sizeof(serialData); serial->length = (int)sizeof(serialData); serial->isDynamic = 0; } revDate.length = MAX_DATE_SIZE + 1; /* intentionally too large */ revDate.type = ASN_GENERALIZED_TIME; revoked.serialNumber = serial; revoked.revocationDate = &revDate; revoked.reason = CRL_REASON_NONE; ExpectIntEQ(wolfSSL_X509_CRL_add_revoked(crl, &revoked), BAD_FUNC_ARG); wolfSSL_ASN1_INTEGER_free(serial); wolfSSL_X509_CRL_free(crl); return EXPECT_RESULT(); } #endif #if (defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)) && !defined(NO_CERTS) && \ defined(HAVE_CRL) && !defined(NO_FILESYSTEM) && \ !defined(NO_STDIO_FILESYSTEM) /* Ensure reason-code parsing handles optional critical BOOLEAN in entry ext. */ static int test_wolfSSL_X509_CRL_reason_critical_boolean(void) { EXPECT_DECLS; int reasonCode = CRL_REASON_NONE; /* One Extension SEQUENCE with: * OID: 2.5.29.21 (CRL Reason Code) * critical: TRUE * extnValue: OCTET STRING wrapping ENUMERATED 2 (CA compromise) */ static const byte ext[] = { 0x30, 0x0d, 0x06, 0x03, 0x55, 0x1d, 0x15, 0x01, 0x01, 0xff, 0x04, 0x03, 0x0a, 0x01, 0x02 }; ExpectIntEQ(wc_ParseCRLReasonFromExtensions(ext, (word32)sizeof(ext), &reasonCode), 0); ExpectIntEQ(reasonCode, CRL_REASON_CA_COMPROMISE); return EXPECT_RESULT(); } #endif #if (defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)) && !defined(NO_CERTS) && \ defined(HAVE_CRL) && !defined(NO_FILESYSTEM) && \ !defined(NO_STDIO_FILESYSTEM) && defined(WOLFSSL_CERT_GEN) && \ !defined(NO_ASN_TIME) /* Helper function to create, sign, and write a CRL */ static int generate_crl_test(const char* keyFile, const char* certFile, const char* derFile, const char* pemFile, const char* certToRevokePath) { EXPECT_DECLS; X509_NAME* issuer = NULL; X509_NAME* decodedIssuer = NULL; WOLFSSL_X509* cert = NULL; WOLFSSL_ASN1_TIME asnTime; XFILE fp = XBADFILE; WOLFSSL_X509_CRL* crl = NULL; WOLFSSL_X509_CRL* decodedCrl = NULL; WOLFSSL_EVP_PKEY* pkey = NULL; int i = 0; int revokedCount = 0; byte certSerial[EXTERNAL_SERIAL_SIZE]; int certSerialSz = 0; byte serialsToRevokeBytes[][1] = { { 0x02 }, { 0x03 }, { 0x04 } }; static const int numSerials = (int)(sizeof(serialsToRevokeBytes) / sizeof(serialsToRevokeBytes[0])); WOLFSSL_ASN1_INTEGER serialsToRevoke[3] = { { .intData = {0}, .negative = 0, .data = serialsToRevokeBytes[0], .dataMax = sizeof(serialsToRevokeBytes[0]), .isDynamic = 0, .length = sizeof(serialsToRevokeBytes[0]), .type = 0 }, { .intData = {0}, .negative = 0, .data = serialsToRevokeBytes[1], .dataMax = sizeof(serialsToRevokeBytes[1]), .isDynamic = 0, .length = sizeof(serialsToRevokeBytes[1]), .type = 0 }, { .intData = {0}, .negative = 0, .data = serialsToRevokeBytes[2], .dataMax = sizeof(serialsToRevokeBytes[2]), .isDynamic = 0, .length = sizeof(serialsToRevokeBytes[2]), .type = 0 } }; WOLFSSL_X509_REVOKED revoked[3]; WOLFSSL_X509* certToRevoke = NULL; /* Load certificate to get issuer name (CRL issuer = cert subject) */ ExpectTrue((fp = XFOPEN(certFile, "rb")) != XBADFILE); if (fp != XBADFILE) { ExpectNotNull(cert = PEM_read_X509(fp, NULL, NULL, NULL)); XFCLOSE(fp); fp = XBADFILE; } /* Create a new empty CRL */ ExpectNotNull(crl = wolfSSL_X509_CRL_new()); ExpectIntEQ(wolfSSL_X509_CRL_version(crl), 2); /* Set issuer name, must match certificate subject for verification */ ExpectNotNull(issuer = X509_get_subject_name(cert)); ExpectIntEQ(wolfSSL_X509_CRL_set_issuer_name(crl, issuer), WOLFSSL_SUCCESS); /* Set thisUpdate to current time */ XMEMSET(&asnTime, 0, sizeof(asnTime)); ExpectNotNull(wolfSSL_ASN1_TIME_adj(&asnTime, XTIME(NULL), 0, 0)); ExpectIntEQ(wolfSSL_X509_CRL_set_lastUpdate(crl, &asnTime), WOLFSSL_SUCCESS); /* Set nextUpdate to 30 days from now */ ExpectNotNull(wolfSSL_ASN1_TIME_adj(&asnTime, XTIME(NULL), 30, 0)); ExpectIntEQ(wolfSSL_X509_CRL_set_nextUpdate(crl, &asnTime), WOLFSSL_SUCCESS); XMEMSET(revoked, 0, sizeof(revoked)); for (i = 0; i < numSerials; i++) { revoked[i].serialNumber = &serialsToRevoke[i]; revoked[i].reason = CRL_REASON_NONE; } /* Add revoked certificates based on serial numbers */ for (i = 0; i < numSerials; i++) { ExpectIntEQ(wolfSSL_X509_CRL_add_revoked(crl, &revoked[i]), WOLFSSL_SUCCESS); } /* Add a revoked certificate entry to CRL by parsing a different * certificate buffer */ ExpectTrue((fp = XFOPEN(certToRevokePath, "rb")) != XBADFILE); if (fp != XBADFILE) { ExpectNotNull(certToRevoke = PEM_read_X509(fp, NULL, NULL, NULL)); XFCLOSE(fp); fp = XBADFILE; } { const byte* certDer = NULL; int certDerSz = 0; ExpectNotNull(certDer = wolfSSL_X509_get_der(certToRevoke, &certDerSz)); ExpectIntEQ(wolfSSL_X509_CRL_add_revoked_cert(crl, certDer, certDerSz), WOLFSSL_SUCCESS); } /* Save cert serial for verification after round-trip */ certSerialSz = (int)sizeof(certSerial); ExpectIntEQ(wolfSSL_X509_get_serial_number(certToRevoke, certSerial, &certSerialSz), WOLFSSL_SUCCESS); wolfSSL_X509_free(certToRevoke); certToRevoke = NULL; /* Count revoked certificates - should be 'numSerials' + 1 */ revokedCount = 0; if (EXPECT_SUCCESS() && crl != NULL && crl->crlList != NULL) { RevokedCert* rev = crl->crlList->certs; while (rev != NULL) { revokedCount++; rev = rev->next; } } ExpectIntEQ(revokedCount, numSerials + 1); /* Load private key for signing */ ExpectTrue((fp = XFOPEN(keyFile, "rb")) != XBADFILE); if (fp != XBADFILE) { ExpectNotNull(pkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL)); XFCLOSE(fp); fp = XBADFILE; } /* Sign the CRL */ ExpectIntEQ(wolfSSL_X509_CRL_sign(crl, pkey, wolfSSL_EVP_sha256()), WOLFSSL_SUCCESS); /* Encode CRL to DER */ ExpectIntEQ(wolfSSL_write_X509_CRL(crl, derFile, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); /* Encode CRL to PEM */ ExpectIntEQ(wolfSSL_write_X509_CRL(crl, pemFile, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); /* ===== Validate encoded DER CRL by decoding and checking contents ===== */ ExpectTrue((fp = XFOPEN(derFile, "rb")) != XBADFILE); if (fp != XBADFILE) { ExpectNotNull(decodedCrl = d2i_X509_CRL_fp(fp, NULL)); XFCLOSE(fp); fp = XBADFILE; } /* Verify CRL version is v2 */ ExpectIntEQ(wolfSSL_X509_CRL_version(decodedCrl), 2); /* Verify issuer name matches */ ExpectNotNull(decodedIssuer = wolfSSL_X509_CRL_get_issuer_name(decodedCrl)); ExpectIntEQ(X509_NAME_cmp(issuer, decodedIssuer), 0); /* Verify signature type is SHA256 with RSA or ECDSA */ ExpectIntNE(wolfSSL_X509_CRL_get_signature_type(decodedCrl), 0); /* Verify lastUpdate and nextUpdate are set */ ExpectNotNull(wolfSSL_X509_CRL_get_lastUpdate(decodedCrl)); ExpectNotNull(wolfSSL_X509_CRL_get_nextUpdate(decodedCrl)); /* Count revoked certificates and verify serial values. * CRL parsing prepends entries, so decoded list is in reverse order. */ revokedCount = 0; if (EXPECT_SUCCESS() && decodedCrl != NULL && decodedCrl->crlList != NULL) { RevokedCert* rev = decodedCrl->crlList->certs; while (rev != NULL) { if (revokedCount == 0) { /* Last added (cert serial) appears first in decoded list */ ExpectIntEQ(rev->serialSz, certSerialSz); ExpectIntEQ(XMEMCMP(rev->serialNumber, certSerial, rev->serialSz), 0); } else { /* Remaining serials in reverse: index numSerials-revokedCount */ int idx = numSerials - revokedCount; ExpectIntEQ(rev->serialSz, (int)sizeof(serialsToRevokeBytes[0])); ExpectIntEQ(XMEMCMP(rev->serialNumber, serialsToRevokeBytes[idx], rev->serialSz), 0); } revokedCount++; rev = rev->next; } } ExpectIntEQ(revokedCount, numSerials + 1); wolfSSL_X509_CRL_free(decodedCrl); decodedCrl = NULL; /* ===== Validate encoded PEM CRL by decoding and checking contents ===== */ ExpectTrue((fp = XFOPEN(pemFile, "rb")) != XBADFILE); if (fp != XBADFILE) { ExpectNotNull(decodedCrl = (X509_CRL*)PEM_read_X509_CRL(fp, NULL, NULL, NULL)); XFCLOSE(fp); fp = XBADFILE; } /* Verify CRL version is v2 */ ExpectIntEQ(wolfSSL_X509_CRL_version(decodedCrl), 2); /* Verify issuer name matches */ ExpectNotNull(decodedIssuer = wolfSSL_X509_CRL_get_issuer_name(decodedCrl)); ExpectIntEQ(X509_NAME_cmp(issuer, decodedIssuer), 0); /* Count revoked certificates from PEM and verify serial values. * CRL parsing prepends entries, so decoded list is in reverse order. */ revokedCount = 0; if (EXPECT_SUCCESS() && decodedCrl != NULL && decodedCrl->crlList != NULL) { RevokedCert* rev = decodedCrl->crlList->certs; while (rev != NULL) { if (revokedCount == 0) { ExpectIntEQ(rev->serialSz, certSerialSz); ExpectIntEQ(XMEMCMP(rev->serialNumber, certSerial, rev->serialSz), 0); } else { int idx = numSerials - revokedCount; ExpectIntEQ(rev->serialSz, (int)sizeof(serialsToRevokeBytes[0])); ExpectIntEQ(XMEMCMP(rev->serialNumber, serialsToRevokeBytes[idx], rev->serialSz), 0); } revokedCount++; rev = rev->next; } } ExpectIntEQ(revokedCount, numSerials + 1); wolfSSL_X509_CRL_free(decodedCrl); wolfSSL_EVP_PKEY_free(pkey); wolfSSL_X509_CRL_free(crl); wolfSSL_X509_free(cert); return EXPECT_RESULT(); } #endif static int test_sk_X509_CRL_encode(void) { EXPECT_DECLS; #if (defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)) && !defined(NO_CERTS) && \ defined(HAVE_CRL) && !defined(NO_FILESYSTEM) && \ !defined(NO_STDIO_FILESYSTEM) && defined(WOLFSSL_CERT_GEN) && \ !defined(NO_ASN_TIME) #ifndef NO_RSA static const char* crlRsaPemFile = "./certs/crl/crlRsaOut.pem"; static const char* crlRsaDerFile = "./certs/crl/crlRsaOut.der"; static const char* testRsaKeyFile = "./certs/ca-key.pem"; /* Use ca-cert.pem to match ca-key.pem for proper CRL verification */ static const char* testRsaCertFile = "./certs/ca-cert.pem"; static const char* revokeRsaCertFile = "./certs/server-cert.pem"; #endif #ifdef HAVE_ECC static const char* crlEccPemFile = "./certs/crl/crlEccOut.pem"; static const char* crlEccDerFile = "./certs/crl/crlEccOut.der"; static const char* testEccKeyFile = "./certs/ca-ecc-key.pem"; /* Use ca-ecc-cert.pem to match ca-ecc-key.pem for proper CRL * verification */ static const char* testEccCertFile = "./certs/ca-ecc-cert.pem"; static const char* revokeEccCertFile = "./certs/server-ecc.pem"; #endif #ifndef NO_RSA /* Generate RSA-signed CRL (PEM and DER) */ ExpectIntEQ(generate_crl_test(testRsaKeyFile, testRsaCertFile, crlRsaDerFile, crlRsaPemFile, revokeRsaCertFile), TEST_SUCCESS); #endif #ifdef HAVE_ECC /* Generate ECC-signed CRL (PEM and DER) */ ExpectIntEQ(generate_crl_test(testEccKeyFile, testEccCertFile, crlEccDerFile, crlEccPemFile, revokeEccCertFile), TEST_SUCCESS); #endif #endif return EXPECT_RESULT(); } static int test_wolfSSL_X509_CRL_sign_large(void) { EXPECT_DECLS; #if (defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)) && !defined(NO_CERTS) && \ defined(HAVE_CRL) && !defined(NO_FILESYSTEM) && \ !defined(NO_STDIO_FILESYSTEM) && defined(WOLFSSL_CERT_GEN) && \ !defined(NO_ASN_TIME) #ifndef NO_RSA static const char* testRsaKeyFile = "./certs/ca-key.pem"; static const char* testRsaCertFile = "./certs/ca-cert.pem"; X509_NAME* issuer = NULL; WOLFSSL_X509* cert = NULL; WOLFSSL_X509_CRL* crl = NULL; WOLFSSL_EVP_PKEY* pkey = NULL; WOLFSSL_ASN1_TIME asnTime; WOLFSSL_X509_REVOKED revoked; XFILE fp = XBADFILE; int i; byte serial[4]; ExpectTrue((fp = XFOPEN(testRsaCertFile, "rb")) != XBADFILE); if (fp != XBADFILE) { ExpectNotNull(cert = PEM_read_X509(fp, NULL, NULL, NULL)); XFCLOSE(fp); fp = XBADFILE; } ExpectNotNull(crl = wolfSSL_X509_CRL_new()); ExpectNotNull(issuer = X509_get_subject_name(cert)); ExpectIntEQ(wolfSSL_X509_CRL_set_issuer_name(crl, issuer), WOLFSSL_SUCCESS); XMEMSET(&asnTime, 0, sizeof(asnTime)); ExpectNotNull(wolfSSL_ASN1_TIME_adj(&asnTime, XTIME(NULL), 0, 0)); ExpectIntEQ(wolfSSL_X509_CRL_set_lastUpdate(crl, &asnTime), WOLFSSL_SUCCESS); ExpectNotNull(wolfSSL_ASN1_TIME_adj(&asnTime, XTIME(NULL), 30, 0)); ExpectIntEQ(wolfSSL_X509_CRL_set_nextUpdate(crl, &asnTime), WOLFSSL_SUCCESS); XMEMSET(&revoked, 0, sizeof(revoked)); revoked.serialNumber = wolfSSL_ASN1_INTEGER_new(); ExpectNotNull(revoked.serialNumber); revoked.reason = CRL_REASON_NONE; if (revoked.serialNumber != NULL) { revoked.serialNumber->data = serial; revoked.serialNumber->length = (int)sizeof(serial); } for (i = 1; i <= 1024; i++) { serial[0] = (byte)(i & 0xff); serial[1] = (byte)((i >> 8) & 0xff); serial[2] = (byte)((i >> 16) & 0xff); serial[3] = (byte)((i >> 24) & 0xff); ExpectIntEQ(wolfSSL_X509_CRL_add_revoked(crl, &revoked), WOLFSSL_SUCCESS); } ExpectTrue((fp = XFOPEN(testRsaKeyFile, "rb")) != XBADFILE); if (fp != XBADFILE) { ExpectNotNull(pkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL)); XFCLOSE(fp); fp = XBADFILE; } ExpectIntEQ(wolfSSL_X509_CRL_sign(crl, pkey, wolfSSL_EVP_sha256()), WOLFSSL_SUCCESS); if (revoked.serialNumber != NULL) { revoked.serialNumber->data = NULL; wolfSSL_ASN1_INTEGER_free(revoked.serialNumber); revoked.serialNumber = NULL; } wolfSSL_EVP_PKEY_free(pkey); wolfSSL_X509_CRL_free(crl); wolfSSL_X509_free(cert); #endif /* !NO_RSA */ #endif return EXPECT_RESULT(); } /* Test round-trip of a CRL with the maximum size CRL number (CRL_MAX_NUM_SZ * = 20 bytes). Build TBS with wc_MakeCRL_ex, sign with wc_SignCRL_ex, then * decode with d2i_X509_CRL and verify the CRL number survives. * Then patch the DER to make the CRL number negative and verify rejection. */ static int test_wc_MakeCRL_max_crlnum(void) { EXPECT_DECLS; #if defined(WOLFSSL_CERT_GEN) && defined(HAVE_CRL) && !defined(NO_RSA) && \ !defined(NO_FILESYSTEM) && !defined(NO_ASN) && defined(OPENSSL_EXTRA) const char* caCertDerFile = "./certs/ca-cert.der"; const char* caKeyDerFile = "./certs/ca-key.der"; byte certBuf[4096]; byte keyBuf[4096]; int certSz = 0; int keySz = 0; XFILE f = XBADFILE; DecodedCert caCert; int caCertInit = 0; RsaKey rsaKey; WC_RNG rng; word32 idx = 0; int rsaKeyInit = 0; int rngInit = 0; /* 20-byte CRL number: 0x01..0x14. First byte < 0x80 so no ASN.1 * padding byte is needed - the encoded INTEGER content is exactly * 20 bytes, matching CRL_MAX_NUM_SZ. */ byte crlNum[CRL_MAX_NUM_SZ]; const char* expHex = "0102030405060708090A0B0C0D0E0F1011121314"; /* thisUpdate/nextUpdate dates in UTC time format */ const byte thisUpdate[] = "260101000000Z"; /* Jan 1, 2026 */ const byte nextUpdate[] = "270101000000Z"; /* Jan 1, 2027 */ /* issuer DER (SEQUENCE-wrapped Name) */ byte issuerDer[512]; word32 issuerDerSz = 0; byte* tbsBuf = NULL; int tbsSz = 0; byte* crlBuf = NULL; int crlSz = 0; int bufSz = 0; WOLFSSL_X509_CRL* decodedCrl = NULL; int i; /* CRL Number OID 2.5.29.20: used to locate the extension in the DER */ static const byte crlNumOid[] = { 0x55, 0x1D, 0x14 }; /* Fill CRL number with 0x01..0x14 */ for (i = 0; i < (int)CRL_MAX_NUM_SZ; i++) { crlNum[i] = (byte)(i + 1); } /* Load CA cert DER */ ExpectTrue((f = XFOPEN(caCertDerFile, "rb")) != XBADFILE); if (f != XBADFILE) { ExpectIntGT(certSz = (int)XFREAD(certBuf, 1, sizeof(certBuf), f), 0); XFCLOSE(f); f = XBADFILE; } /* Load CA key DER */ ExpectTrue((f = XFOPEN(caKeyDerFile, "rb")) != XBADFILE); if (f != XBADFILE) { ExpectIntGT(keySz = (int)XFREAD(keyBuf, 1, sizeof(keyBuf), f), 0); XFCLOSE(f); f = XBADFILE; } /* Parse CA cert to extract the subject (= CRL issuer) DER. * subjectRaw is the Name contents without the outer SEQUENCE tag, * so we re-wrap it with SetSequence to produce a valid issuer Name. */ wc_InitDecodedCert(&caCert, certBuf, (word32)certSz, NULL); caCertInit = 1; ExpectIntEQ(wc_ParseCert(&caCert, CERT_TYPE, 0, NULL), 0); if (EXPECT_SUCCESS()) { word32 seqHdrSz = SetSequence((word32)caCert.subjectRawLen, issuerDer); XMEMCPY(issuerDer + seqHdrSz, caCert.subjectRaw, (size_t)caCert.subjectRawLen); issuerDerSz = seqHdrSz + (word32)caCert.subjectRawLen; } /* Decode RSA private key */ ExpectIntEQ(wc_InitRsaKey(&rsaKey, NULL), 0); if (EXPECT_SUCCESS()) { rsaKeyInit = 1; } idx = 0; ExpectIntEQ(wc_RsaPrivateKeyDecode(keyBuf, &idx, &rsaKey, (word32)keySz), 0); /* Init RNG for signing */ ExpectIntEQ(wc_InitRng(&rng), 0); if (EXPECT_SUCCESS()) { rngInit = 1; } /* --- Build TBS --- */ /* First call with NULL output to get required size */ tbsSz = wc_MakeCRL_ex( issuerDer, issuerDerSz, thisUpdate, ASN_UTC_TIME, /* thisUpdate */ nextUpdate, ASN_UTC_TIME, /* nextUpdate */ NULL, /* no revoked certs */ crlNum, (word32)sizeof(crlNum), /* max-size CRL number */ CTC_SHA256wRSA, 2, /* v2 for extensions */ NULL, 0); ExpectIntGT(tbsSz, 0); /* Allocate buffer large enough for TBS + signature overhead */ if (EXPECT_SUCCESS()) { bufSz = tbsSz + 512; /* generous room for signature wrapper */ ExpectNotNull(tbsBuf = (byte*)XMALLOC(bufSz, NULL, DYNAMIC_TYPE_TMP_BUFFER)); } /* Second call to actually encode TBS */ if (EXPECT_SUCCESS()) { tbsSz = wc_MakeCRL_ex( issuerDer, issuerDerSz, thisUpdate, ASN_UTC_TIME, nextUpdate, ASN_UTC_TIME, NULL, crlNum, (word32)sizeof(crlNum), CTC_SHA256wRSA, 2, tbsBuf, (word32)bufSz); ExpectIntGT(tbsSz, 0); } /* --- Sign the CRL --- */ if (EXPECT_SUCCESS()) { ExpectNotNull(crlBuf = (byte*)XMALLOC(bufSz, NULL, DYNAMIC_TYPE_TMP_BUFFER)); } if (EXPECT_SUCCESS()) { crlSz = wc_SignCRL_ex(tbsBuf, tbsSz, CTC_SHA256wRSA, crlBuf, (word32)bufSz, &rsaKey, NULL, &rng); ExpectIntGT(crlSz, 0); } /* --- Decode the CRL and verify CRL number --- */ if (EXPECT_SUCCESS()) { ExpectNotNull(decodedCrl = d2i_X509_CRL(NULL, crlBuf, crlSz)); } if (decodedCrl != NULL && decodedCrl->crlList != NULL) { ExpectTrue(decodedCrl->crlList->crlNumberSet); if (decodedCrl->crlList->crlNumberSet) { ExpectIntEQ(XMEMCMP(decodedCrl->crlList->crlNumber, expHex, XSTRLEN(expHex)), 0); } } wolfSSL_X509_CRL_free(decodedCrl); decodedCrl = NULL; /* --- Negative test: patch the CRL number to be negative --- */ /* The encoded CRL number INTEGER is: 02 14 01 02 03 ... 14 * (tag=0x02, length=0x14=20, content bytes 0x01..0x14). * Flip the high bit of the first content byte (0x01 -> 0x81) to make * the INTEGER negative. No lengths change, so the DER stays * structurally valid. The signature is now wrong, but d2i_X509_CRL * uses NO_VERIFY so that doesn't matter. */ if (EXPECT_SUCCESS()) { /* Find CRL Number OID (55 1D 14) in the DER */ int found = 0; for (i = 0; i < crlSz - (int)sizeof(crlNumOid); i++) { if (XMEMCMP(crlBuf + i, crlNumOid, sizeof(crlNumOid)) == 0) { /* OID found at i. Skip past: OID (3 bytes) -> OCTET STRING * tag (1) + length (1) -> INTEGER tag (1) + length (1) -> * first content byte. */ int contentIdx = i + 3 + 2 + 2; if (contentIdx < crlSz) { crlBuf[contentIdx] |= 0x80; found = 1; } break; } } ExpectTrue(found); } /* Decoding the patched CRL must fail - the CRL number is negative. */ if (EXPECT_SUCCESS()) { decodedCrl = d2i_X509_CRL(NULL, crlBuf, crlSz); ExpectNull(decodedCrl); wolfSSL_X509_CRL_free(decodedCrl); } XFREE(crlBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(tbsBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (caCertInit) { wc_FreeDecodedCert(&caCert); } if (rngInit) { wc_FreeRng(&rng); } if (rsaKeyInit) { wc_FreeRsaKey(&rsaKey); } #endif return EXPECT_RESULT(); } static int test_X509_REQ(void) { EXPECT_DECLS; #if defined(OPENSSL_ALL) && !defined(NO_CERTS) && \ defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ) && !defined(NO_BIO) X509_NAME* name = NULL; #ifndef NO_RSA X509_NAME* subject = NULL; #endif #if !defined(NO_RSA) || defined(HAVE_ECC) X509_REQ* req = NULL; EVP_PKEY* priv = NULL; EVP_PKEY* pub = NULL; unsigned char* der = NULL; int len; #endif #ifndef NO_RSA EVP_MD_CTX *mctx = NULL; EVP_PKEY_CTX *pkctx = NULL; #ifdef USE_CERT_BUFFERS_1024 const unsigned char* rsaPriv = (const unsigned char*)client_key_der_1024; const unsigned char* rsaPub = (unsigned char*)client_keypub_der_1024; #elif defined(USE_CERT_BUFFERS_2048) const unsigned char* rsaPriv = (const unsigned char*)client_key_der_2048; const unsigned char* rsaPub = (unsigned char*)client_keypub_der_2048; #endif #endif #ifdef HAVE_ECC const unsigned char* ecPriv = (const unsigned char*)ecc_clikey_der_256; const unsigned char* ecPub = (unsigned char*)ecc_clikeypub_der_256; BIO* bio = NULL; #endif unsigned char tooLongPassword[WC_CTC_NAME_SIZE + 1]; XMEMSET(tooLongPassword, 0, sizeof(tooLongPassword)); ExpectNotNull(name = X509_NAME_new()); ExpectIntEQ(X509_NAME_add_entry_by_txt(name, "commonName", MBSTRING_UTF8, (byte*)"wolfssl.com", 11, 0, 1), WOLFSSL_SUCCESS); ExpectIntEQ(X509_NAME_add_entry_by_txt(name, "emailAddress", MBSTRING_UTF8, (byte*)"support@wolfssl.com", 19, -1, 1), WOLFSSL_SUCCESS); #ifndef NO_RSA ExpectNotNull(priv = d2i_PrivateKey(EVP_PKEY_RSA, NULL, &rsaPriv, (long)sizeof_client_key_der_2048)); ExpectNotNull(pub = d2i_PUBKEY(NULL, &rsaPub, (long)sizeof_client_keypub_der_2048)); ExpectNotNull(req = X509_REQ_new()); ExpectIntEQ(X509_REQ_set_subject_name(NULL, name), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(X509_REQ_set_subject_name(req, NULL), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(X509_REQ_set_subject_name(req, name), WOLFSSL_SUCCESS); ExpectIntEQ(X509_REQ_set_pubkey(NULL, pub), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(X509_REQ_set_pubkey(req, NULL), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(X509_REQ_set_pubkey(req, pub), WOLFSSL_SUCCESS); ExpectIntEQ(X509_REQ_sign(NULL, priv, EVP_sha256()), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(X509_REQ_sign(req, NULL, EVP_sha256()), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(X509_REQ_sign(req, priv, NULL), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(X509_REQ_sign(req, priv, EVP_sha256()), WOLFSSL_SUCCESS); ExpectIntEQ(i2d_X509_REQ(NULL, NULL), BAD_FUNC_ARG); ExpectIntEQ(i2d_X509_REQ(req, NULL), BAD_FUNC_ARG); ExpectIntEQ(i2d_X509_REQ(NULL, &der), BAD_FUNC_ARG); len = i2d_X509_REQ(req, &der); DEBUG_WRITE_DER(der, len, "req.der"); #ifdef USE_CERT_BUFFERS_1024 ExpectIntEQ(len, 381); #else ExpectIntEQ(len, 643); #endif XFREE(der, NULL, DYNAMIC_TYPE_OPENSSL); der = NULL; mctx = EVP_MD_CTX_new(); ExpectIntEQ(EVP_DigestSignInit(mctx, &pkctx, EVP_sha256(), NULL, priv), WOLFSSL_SUCCESS); ExpectIntEQ(X509_REQ_sign_ctx(NULL, NULL), WOLFSSL_FAILURE); ExpectIntEQ(X509_REQ_sign_ctx(req, NULL), WOLFSSL_FAILURE); ExpectIntEQ(X509_REQ_sign_ctx(NULL, mctx), WOLFSSL_FAILURE); ExpectIntEQ(X509_REQ_sign_ctx(req, mctx), WOLFSSL_SUCCESS); EVP_MD_CTX_free(mctx); mctx = NULL; X509_REQ_free(NULL); X509_REQ_free(req); req = NULL; /* Test getting the subject from a newly created X509_REQ */ ExpectNotNull(req = X509_REQ_new()); ExpectNotNull(subject = X509_REQ_get_subject_name(req)); ExpectIntEQ(X509_NAME_add_entry_by_NID(subject, NID_commonName, MBSTRING_UTF8, (unsigned char*)"www.wolfssl.com", -1, -1, 0), 1); ExpectIntEQ(X509_NAME_add_entry_by_NID(subject, NID_countryName, MBSTRING_UTF8, (unsigned char*)"US", -1, -1, 0), 1); ExpectIntEQ(X509_NAME_add_entry_by_NID(subject, NID_localityName, MBSTRING_UTF8, (unsigned char*)"Bozeman", -1, -1, 0), 1); ExpectIntEQ(X509_NAME_add_entry_by_NID(subject, NID_stateOrProvinceName, MBSTRING_UTF8, (unsigned char*)"Montana", -1, -1, 0), 1); ExpectIntEQ(X509_NAME_add_entry_by_NID(subject, NID_organizationName, MBSTRING_UTF8, (unsigned char*)"wolfSSL", -1, -1, 0), 1); ExpectIntEQ(X509_NAME_add_entry_by_NID(subject, NID_organizationalUnitName, MBSTRING_UTF8, (unsigned char*)"Testing", -1, -1, 0), 1); ExpectIntEQ(X509_REQ_set_pubkey(req, pub), WOLFSSL_SUCCESS); ExpectIntEQ(X509_REQ_sign(req, priv, EVP_sha256()), WOLFSSL_SUCCESS); len = i2d_X509_REQ(req, &der); DEBUG_WRITE_DER(der, len, "req2.der"); #ifdef USE_CERT_BUFFERS_1024 ExpectIntEQ(len, 435); #else ExpectIntEQ(len, 696); #endif XFREE(der, NULL, DYNAMIC_TYPE_OPENSSL); der = NULL; EVP_PKEY_free(pub); pub = NULL; EVP_PKEY_free(priv); priv = NULL; X509_REQ_free(req); req = NULL; #endif #ifdef HAVE_ECC ExpectNotNull(priv = wolfSSL_d2i_PrivateKey(EVP_PKEY_EC, NULL, &ecPriv, sizeof_ecc_clikey_der_256)); ExpectNotNull(pub = wolfSSL_d2i_PUBKEY(NULL, &ecPub, sizeof_ecc_clikeypub_der_256)); ExpectNotNull(req = X509_REQ_new()); ExpectIntEQ(X509_REQ_set_subject_name(req, name), WOLFSSL_SUCCESS); ExpectIntEQ(X509_REQ_set_pubkey(req, pub), WOLFSSL_SUCCESS); ExpectIntEQ(X509_REQ_sign(req, priv, EVP_sha256()), WOLFSSL_SUCCESS); /* Signature is random and may be shorter or longer. */ ExpectIntGE((len = i2d_X509_REQ(req, &der)), 245); ExpectIntLE(len, 253); ExpectNotNull(bio = BIO_new_fp(stderr, BIO_NOCLOSE)); ExpectIntEQ(X509_REQ_print(bio, req), WOLFSSL_SUCCESS); ExpectIntEQ(X509_REQ_print(bio, NULL), WOLFSSL_FAILURE); BIO_free(bio); XFREE(der, NULL, DYNAMIC_TYPE_OPENSSL); X509_REQ_free(req); req = NULL; EVP_PKEY_free(pub); EVP_PKEY_free(priv); #ifdef FP_ECC wc_ecc_fp_free(); #endif #endif /* HAVE_ECC */ X509_NAME_free(name); ExpectNull(wolfSSL_X509_REQ_get_extensions(NULL)); /* Stub function. */ ExpectNull(wolfSSL_X509_to_X509_REQ(NULL, NULL, NULL)); ExpectNotNull(req = X509_REQ_new()); #ifdef HAVE_LIBEST ExpectIntEQ(wolfSSL_X509_REQ_add1_attr_by_txt(NULL, NULL, WOLFSSL_MBSTRING_UTF8, NULL, 0), WOLFSSL_FAILURE); ExpectIntEQ(wolfSSL_X509_REQ_add1_attr_by_txt(req, NULL, WOLFSSL_MBSTRING_UTF8, NULL, 0), WOLFSSL_FAILURE); ExpectIntEQ(wolfSSL_X509_REQ_add1_attr_by_txt(NULL, "name", WOLFSSL_MBSTRING_UTF8, NULL, 0), WOLFSSL_FAILURE); ExpectIntEQ(wolfSSL_X509_REQ_add1_attr_by_txt(NULL, NULL, WOLFSSL_MBSTRING_ASC, NULL, 0), WOLFSSL_FAILURE); ExpectIntEQ(wolfSSL_X509_REQ_add1_attr_by_txt(NULL, NULL, WOLFSSL_MBSTRING_UTF8, (byte*)"1.3.6.1.1.1.1.22", 16), WOLFSSL_FAILURE); ExpectIntEQ(wolfSSL_X509_REQ_add1_attr_by_txt(NULL, "name", WOLFSSL_MBSTRING_ASC, (byte*)"1.3.6.1.1.1.1.22", 16), WOLFSSL_FAILURE); ExpectIntEQ(wolfSSL_X509_REQ_add1_attr_by_txt(req, NULL, WOLFSSL_MBSTRING_ASC, (byte*)"1.3.6.1.1.1.1.22", 16), WOLFSSL_FAILURE); ExpectIntEQ(wolfSSL_X509_REQ_add1_attr_by_txt(req, "name", WOLFSSL_MBSTRING_UTF8, (byte*)"1.3.6.1.1.1.1.22", 16), WOLFSSL_FAILURE); ExpectIntEQ(wolfSSL_X509_REQ_add1_attr_by_txt(req, "name", WOLFSSL_MBSTRING_ASC, NULL, 0), WOLFSSL_FAILURE); /* Unsupported bytes. */ ExpectIntEQ(wolfSSL_X509_REQ_add1_attr_by_txt(req, "name", WOLFSSL_MBSTRING_ASC, (byte*)"1.3.6.1.1.1.1.23", 16), WOLFSSL_FAILURE); ExpectIntEQ(wolfSSL_X509_REQ_add1_attr_by_txt(req, "MAC Address", WOLFSSL_MBSTRING_ASC, (byte*)"1.3.6.1.1.1.1.22", 16), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_X509_REQ_add1_attr_by_txt(req, "ecpublicKey", WOLFSSL_MBSTRING_ASC, (byte*)"1.2.840.10045.2.1", -1), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_X509_REQ_add1_attr_by_txt(req, "ecdsa-with-SHA384", WOLFSSL_MBSTRING_ASC, (byte*)"1.2.840.10045.4.3.3", -1), WOLFSSL_SUCCESS); #else /* Stub function. */ ExpectIntEQ(wolfSSL_X509_REQ_add1_attr_by_txt(NULL, NULL, WOLFSSL_MBSTRING_UTF8, NULL, 0), WOLFSSL_FAILURE); ExpectIntEQ(wolfSSL_X509_REQ_add1_attr_by_txt(req, "MAC Address", WOLFSSL_MBSTRING_ASC, (byte*)"1.3.6.1.1.1.1.22", 16), WOLFSSL_FAILURE); #endif ExpectIntEQ(X509_REQ_add1_attr_by_NID(NULL, WC_NID_subject_alt_name, WOLFSSL_MBSTRING_UTF8, NULL, 0), WOLFSSL_FAILURE); ExpectIntEQ(X509_REQ_add1_attr_by_NID(req, WC_NID_subject_alt_name, WOLFSSL_MBSTRING_UTF8, NULL, 0), WOLFSSL_FAILURE); ExpectIntEQ(X509_REQ_add1_attr_by_NID(NULL, WC_NID_subject_alt_name, WOLFSSL_MBSTRING_ASC, NULL, 0), WOLFSSL_FAILURE); ExpectIntEQ(X509_REQ_add1_attr_by_NID(NULL, WC_NID_pkcs9_challengePassword, WOLFSSL_MBSTRING_UTF8, NULL, 0), WOLFSSL_FAILURE); ExpectIntEQ(X509_REQ_add1_attr_by_NID(NULL, WC_NID_subject_alt_name, WOLFSSL_MBSTRING_UTF8, (byte*)"password", 8), WOLFSSL_FAILURE); ExpectIntEQ(X509_REQ_add1_attr_by_NID(NULL, WC_NID_pkcs9_challengePassword, WOLFSSL_MBSTRING_ASC, (byte*)"password", 8), WOLFSSL_FAILURE); ExpectIntEQ(X509_REQ_add1_attr_by_NID(req, WC_NID_subject_alt_name, WOLFSSL_MBSTRING_ASC, (byte*)"password", 8), WOLFSSL_FAILURE); ExpectIntEQ(X509_REQ_add1_attr_by_NID(req, WC_NID_pkcs9_challengePassword, WOLFSSL_MBSTRING_UTF8, (byte*)"password", 8), WOLFSSL_FAILURE); ExpectIntEQ(X509_REQ_add1_attr_by_NID(req, WC_NID_pkcs9_challengePassword, WOLFSSL_MBSTRING_ASC, NULL, -1), WOLFSSL_FAILURE); ExpectIntEQ(X509_REQ_add1_attr_by_NID(req, WC_NID_pkcs9_challengePassword, WOLFSSL_MBSTRING_ASC, (byte*)"password", -1), WOLFSSL_SUCCESS); ExpectIntEQ(X509_REQ_add1_attr_by_NID(req, WC_NID_pkcs9_challengePassword, WOLFSSL_MBSTRING_ASC, tooLongPassword, sizeof(tooLongPassword)), WOLFSSL_FAILURE); ExpectIntEQ(X509_REQ_add1_attr_by_NID(req, WC_NID_serialNumber, WOLFSSL_MBSTRING_ASC, (byte*)"123456", -1), WOLFSSL_SUCCESS); ExpectIntEQ(X509_REQ_add1_attr_by_NID(req, WC_NID_serialNumber, WOLFSSL_MBSTRING_ASC, tooLongPassword, sizeof(tooLongPassword)), WOLFSSL_FAILURE); ExpectIntEQ(X509_REQ_add1_attr_by_NID(req, WC_NID_pkcs9_unstructuredName, WOLFSSL_MBSTRING_ASC, (byte*)"name", 4), WOLFSSL_SUCCESS); ExpectIntEQ(X509_REQ_add1_attr_by_NID(req, WC_NID_pkcs9_contentType, WOLFSSL_MBSTRING_ASC, (byte*)"type", 4), WOLFSSL_SUCCESS); ExpectIntEQ(X509_REQ_add1_attr_by_NID(req, WC_NID_surname, WOLFSSL_MBSTRING_ASC, (byte*)"surname", 7), WOLFSSL_SUCCESS); ExpectIntEQ(X509_REQ_add1_attr_by_NID(req, WC_NID_initials, WOLFSSL_MBSTRING_ASC, (byte*)"s.g", 3), WOLFSSL_SUCCESS); ExpectIntEQ(X509_REQ_add1_attr_by_NID(req, WC_NID_givenName, WOLFSSL_MBSTRING_ASC, (byte*)"givenname", 9), WOLFSSL_SUCCESS); ExpectIntEQ(X509_REQ_add1_attr_by_NID(req, WC_NID_dnQualifier, WOLFSSL_MBSTRING_ASC, (byte*)"dnQualifier", 11), WOLFSSL_SUCCESS); wolfSSL_X509_REQ_free(req); #endif return EXPECT_RESULT(); } static int test_wolfSSL_X509_REQ_print(void) { EXPECT_DECLS; #if defined(OPENSSL_ALL) && !defined(NO_RSA) && !defined(NO_CERTS) && \ defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ) && !defined(NO_BIO) WOLFSSL_X509* req = NULL; XFILE fp = XBADFILE; const char* csrFileName = "certs/csr.attr.der"; const char* csrExtFileName = "certs/csr.ext.der"; BIO* bio = NULL; ExpectTrue((fp = XFOPEN(csrFileName, "rb")) != XBADFILE); ExpectNotNull(req = d2i_X509_REQ_fp(fp, NULL)); if (fp != XBADFILE) { XFCLOSE(fp); fp = XBADFILE; } ExpectNotNull(bio = BIO_new(BIO_s_mem())); ExpectIntEQ(wolfSSL_X509_REQ_print(bio, req), WOLFSSL_SUCCESS); ExpectIntEQ(BIO_get_mem_data(bio, NULL), 2681); BIO_free(bio); bio = NULL; wolfSSL_X509_REQ_free(req); req = NULL; ExpectTrue((fp = XFOPEN(csrExtFileName, "rb")) != XBADFILE); ExpectNotNull(req = d2i_X509_REQ_fp(fp, NULL)); if (fp != XBADFILE) { XFCLOSE(fp); } ExpectNotNull(bio = BIO_new(BIO_s_mem())); ExpectIntEQ(wolfSSL_X509_REQ_print(bio, req), WOLFSSL_SUCCESS); ExpectIntEQ(BIO_get_mem_data(bio, NULL), 1889); BIO_free(bio); wolfSSL_X509_REQ_free(req); #endif return EXPECT_RESULT(); } /*----------------------------------------------------------------------------* | Certificate Failure Checks *----------------------------------------------------------------------------*/ #if !defined(NO_CERTS) && (!defined(NO_WOLFSSL_CLIENT) || \ !defined(WOLFSSL_NO_CLIENT_AUTH)) && !defined(NO_FILESYSTEM) #if (!defined(NO_RSA) || defined(HAVE_ECC)) && !defined(NO_SHA256) /* Use the Cert Manager(CM) API to generate the error ASN_SIG_CONFIRM_E */ #ifndef WOLFSSL_TEST_APPLE_NATIVE_CERT_VALIDATION static int verify_sig_cm(const char* ca, byte* cert_buf, size_t cert_sz, int type) { int ret; WOLFSSL_CERT_MANAGER* cm = NULL; switch (type) { case TESTING_RSA: #ifdef NO_RSA fprintf(stderr, "RSA disabled, skipping test\n"); return ASN_SIG_CONFIRM_E; #else break; #endif case TESTING_ECC: #ifndef HAVE_ECC fprintf(stderr, "ECC disabled, skipping test\n"); return ASN_SIG_CONFIRM_E; #else break; #endif default: fprintf(stderr, "Bad function argument\n"); return BAD_FUNC_ARG; } cm = wolfSSL_CertManagerNew(); if (cm == NULL) { fprintf(stderr, "wolfSSL_CertManagerNew failed\n"); return -1; } #ifndef NO_FILESYSTEM ret = wolfSSL_CertManagerLoadCA(cm, ca, 0); if (ret != WOLFSSL_SUCCESS) { fprintf(stderr, "wolfSSL_CertManagerLoadCA failed\n"); wolfSSL_CertManagerFree(cm); return ret; } #else (void)ca; #endif ret = wolfSSL_CertManagerVerifyBuffer(cm, cert_buf, (long int)cert_sz, WOLFSSL_FILETYPE_ASN1); /* Let ExpectIntEQ handle return code */ wolfSSL_CertManagerFree(cm); return ret; } #if !defined(NO_FILESYSTEM) static int test_RsaSigFailure_cm(void) { EXPECT_DECLS; #ifndef NO_RSA #ifdef WOLFSSL_PEM_TO_DER const char* ca_cert = "./certs/ca-cert.pem"; #else const char* ca_cert = "./certs/ca-cert.der"; #endif const char* server_cert = "./certs/server-cert.der"; byte* cert_buf = NULL; size_t cert_sz = 0; ExpectIntEQ(load_file(server_cert, &cert_buf, &cert_sz), 0); if ((cert_buf != NULL) && (cert_sz > 0)) { /* corrupt DER - invert last byte, which is signature */ cert_buf[cert_sz-1] = ~cert_buf[cert_sz-1]; /* test bad cert */ #if defined(NO_WOLFSSL_CLIENT) && defined(NO_WOLFSSL_SERVER) ExpectIntEQ(verify_sig_cm(ca_cert, cert_buf, cert_sz, TESTING_RSA), WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)); #elif defined(NO_ASN_CRYPT) /* RSA verify is not called when ASN crypt support is disabled */ ExpectIntEQ(verify_sig_cm(ca_cert, cert_buf, cert_sz, TESTING_RSA), WOLFSSL_SUCCESS); #else ExpectIntEQ(verify_sig_cm(ca_cert, cert_buf, cert_sz, TESTING_RSA), WC_NO_ERR_TRACE(ASN_SIG_CONFIRM_E)); #endif } /* load_file() uses XMALLOC. */ if (cert_buf != NULL) { XFREE(cert_buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); } #endif /* !NO_RSA */ return EXPECT_RESULT(); } static int test_EccSigFailure_cm(void) { EXPECT_DECLS; #ifdef HAVE_ECC /* self-signed ECC cert, so use server cert as CA */ #ifdef WOLFSSL_PEM_TO_DER const char* ca_cert = "./certs/ca-ecc-cert.pem"; #else const char* ca_cert = "./certs/ca-ecc-cert.der"; #endif const char* server_cert = "./certs/server-ecc.der"; byte* cert_buf = NULL; size_t cert_sz = 0; ExpectIntEQ(load_file(server_cert, &cert_buf, &cert_sz), 0); if (cert_buf != NULL && cert_sz > 0) { /* corrupt DER - invert last byte, which is signature */ cert_buf[cert_sz-1] = ~cert_buf[cert_sz-1]; /* test bad cert */ #if defined(NO_WOLFSSL_CLIENT) && defined(NO_WOLFSSL_SERVER) ExpectIntEQ(verify_sig_cm(ca_cert, cert_buf, cert_sz, TESTING_ECC), WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)); #elif defined(NO_ASN_CRYPT) /* ECC verify is not called when ASN crypt support is disabled */ ExpectIntEQ(verify_sig_cm(ca_cert, cert_buf, cert_sz, TESTING_ECC), WOLFSSL_SUCCESS); #else ExpectIntEQ(verify_sig_cm(ca_cert, cert_buf, cert_sz, TESTING_ECC), WC_NO_ERR_TRACE(ASN_SIG_CONFIRM_E)); #endif } /* load_file() uses XMALLOC. */ if (cert_buf != NULL) { XFREE(cert_buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); } #ifdef FP_ECC wc_ecc_fp_free(); #endif #endif /* HAVE_ECC */ return EXPECT_RESULT(); } #endif /* !NO_FILESYSTEM */ #endif /* !WOLFSSL_TEST_APPLE_NATIVE_CERT_VALIDATION*/ #endif /* !NO_RSA || HAVE_ECC */ #endif /* NO_CERTS */ static int test_wc_CheckPrivateKey_RSA_pub_only(void) { EXPECT_DECLS; #if !defined(NO_RSA) && !defined(NO_ASN_CRYPT) && \ !defined(NO_CHECK_PRIVATE_KEY) && \ (defined(WOLFSSL_RSA_PUBLIC_ONLY) || defined(WOLFSSL_RSA_VERIFY_ONLY)) /* With RSA public-only or verify-only, wc_CheckPrivateKey should return * NOT_COMPILED_IN for RSA key types since private key operations are not * available. */ ExpectIntEQ(wc_CheckPrivateKey(server_key_der_2048, sizeof_server_key_der_2048, server_cert_der_2048, sizeof_server_cert_der_2048, RSAk, NULL), WC_NO_ERR_TRACE(NOT_COMPILED_IN)); #endif return EXPECT_RESULT(); } #if defined(HAVE_PK_CALLBACKS) && !defined(WOLFSSL_NO_TLS12) #if !defined(NO_FILESYSTEM) && !defined(NO_DH) && \ !defined(NO_AES) && defined(HAVE_AES_CBC) && \ defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) static int my_DhCallback(WOLFSSL* ssl, struct DhKey* key, const unsigned char* priv, unsigned int privSz, const unsigned char* pubKeyDer, unsigned int pubKeySz, unsigned char* out, unsigned int* outlen, void* ctx) { int result; /* Test fail when context associated with WOLFSSL is NULL */ if (ctx == NULL) { return -1; } (void)ssl; /* return 0 on success */ PRIVATE_KEY_UNLOCK(); result = wc_DhAgree(key, out, outlen, priv, privSz, pubKeyDer, pubKeySz); PRIVATE_KEY_LOCK(); return result; } static int test_dh_ctx_setup(WOLFSSL_CTX* ctx) { EXPECT_DECLS; wolfSSL_CTX_SetDhAgreeCb(ctx, my_DhCallback); #if defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_128) ExpectIntEQ(wolfSSL_CTX_set_cipher_list(ctx, "DHE-RSA-AES128-SHA256"), WOLFSSL_SUCCESS); #endif #if defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_256) ExpectIntEQ(wolfSSL_CTX_set_cipher_list(ctx, "DHE-RSA-AES256-SHA256"), WOLFSSL_SUCCESS); #endif return EXPECT_RESULT(); } static int test_dh_ssl_setup(WOLFSSL* ssl) { EXPECT_DECLS; static int dh_test_ctx = 1; int ret; wolfSSL_SetDhAgreeCtx(ssl, &dh_test_ctx); ExpectIntEQ(*((int*)wolfSSL_GetDhAgreeCtx(ssl)), dh_test_ctx); ret = wolfSSL_SetTmpDH_file(ssl, dhParamFile, WOLFSSL_FILETYPE_PEM); if (ret != WOLFSSL_SUCCESS && ret != WC_NO_ERR_TRACE(SIDE_ERROR)) { ExpectIntEQ(ret, WOLFSSL_SUCCESS); } return EXPECT_RESULT(); } static int test_dh_ssl_setup_fail(WOLFSSL* ssl) { EXPECT_DECLS; int ret; wolfSSL_SetDhAgreeCtx(ssl, NULL); ExpectNull(wolfSSL_GetDhAgreeCtx(ssl)); ret = wolfSSL_SetTmpDH_file(ssl, dhParamFile, WOLFSSL_FILETYPE_PEM); if (ret != WOLFSSL_SUCCESS && ret != WC_NO_ERR_TRACE(SIDE_ERROR)) { ExpectIntEQ(ret, WOLFSSL_SUCCESS); } return EXPECT_RESULT(); } #endif static int test_DhCallbacks(void) { EXPECT_DECLS; #if !defined(NO_FILESYSTEM) && !defined(NO_DH) && \ !defined(NO_AES) && defined(HAVE_AES_CBC) && \ defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) WOLFSSL_CTX *ctx = NULL; WOLFSSL *ssl = NULL; int test; test_ssl_cbf func_cb_client; test_ssl_cbf func_cb_server; /* Test that DH callback APIs work. */ ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); ExpectIntEQ(wolfSSL_CTX_set_cipher_list(NULL, "NONE"), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); wolfSSL_CTX_SetDhAgreeCb(ctx, &my_DhCallback); /* load client ca cert */ ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0), WOLFSSL_SUCCESS); /* test with NULL arguments */ wolfSSL_SetDhAgreeCtx(NULL, &test); ExpectNull(wolfSSL_GetDhAgreeCtx(NULL)); /* test success case */ test = 1; ExpectNotNull(ssl = wolfSSL_new(ctx)); wolfSSL_SetDhAgreeCtx(ssl, &test); ExpectIntEQ(*((int*)wolfSSL_GetDhAgreeCtx(ssl)), test); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); XMEMSET(&func_cb_client, 0, sizeof(func_cb_client)); XMEMSET(&func_cb_server, 0, sizeof(func_cb_server)); /* set callbacks to use DH functions */ func_cb_client.ctx_ready = &test_dh_ctx_setup; func_cb_client.ssl_ready = &test_dh_ssl_setup; func_cb_client.method = wolfTLSv1_2_client_method; func_cb_server.ctx_ready = &test_dh_ctx_setup; func_cb_server.ssl_ready = &test_dh_ssl_setup; func_cb_server.method = wolfTLSv1_2_server_method; ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&func_cb_client, &func_cb_server, NULL), TEST_SUCCESS); /* Test fail */ XMEMSET(&func_cb_client, 0, sizeof(func_cb_client)); XMEMSET(&func_cb_server, 0, sizeof(func_cb_server)); /* set callbacks to use DH functions */ func_cb_client.ctx_ready = &test_dh_ctx_setup; func_cb_client.ssl_ready = &test_dh_ssl_setup_fail; func_cb_client.method = wolfTLSv1_2_client_method; func_cb_server.ctx_ready = &test_dh_ctx_setup; func_cb_server.ssl_ready = &test_dh_ssl_setup_fail; func_cb_server.method = wolfTLSv1_2_server_method; ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&func_cb_client, &func_cb_server, NULL), -1001); #endif return EXPECT_RESULT(); } #endif /* HAVE_PK_CALLBACKS */ static int test_wolfSSL_X509_CRL(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && defined(HAVE_CRL) X509_CRL *crl = NULL; char pem[][100] = { "./certs/crl/crl.pem", "./certs/crl/crl2.pem", "./certs/crl/caEccCrl.pem", "./certs/crl/eccCliCRL.pem", "./certs/crl/eccSrvCRL.pem", "" }; #ifndef NO_BIO BIO *bio = NULL; #endif #ifdef HAVE_TEST_d2i_X509_CRL_fp char der[][100] = { "./certs/crl/crl.der", "./certs/crl/crl2.der", ""}; #endif XFILE fp = XBADFILE; int i; for (i = 0; pem[i][0] != '\0'; i++) { ExpectTrue((fp = XFOPEN(pem[i], "rb")) != XBADFILE); ExpectNotNull(crl = (X509_CRL *)PEM_read_X509_CRL(fp, (X509_CRL **)NULL, NULL, NULL)); ExpectNotNull(crl); X509_CRL_free(crl); if (fp != XBADFILE) { XFCLOSE(fp); fp = XBADFILE; } ExpectTrue((fp = XFOPEN(pem[i], "rb")) != XBADFILE); ExpectNotNull((X509_CRL *)PEM_read_X509_CRL(fp, (X509_CRL **)&crl, NULL, NULL)); if (EXPECT_FAIL()) { crl = NULL; } ExpectNotNull(crl); X509_CRL_free(crl); crl = NULL; if (fp != XBADFILE) { XFCLOSE(fp); fp = XBADFILE; } } #ifndef NO_BIO for (i = 0; pem[i][0] != '\0'; i++) { ExpectNotNull(bio = BIO_new_file(pem[i], "rb")); ExpectNotNull(crl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL)); X509_CRL_free(crl); crl = NULL; BIO_free(bio); bio = NULL; } #endif #ifdef HAVE_TEST_d2i_X509_CRL_fp for (i = 0; der[i][0] != '\0'; i++) { ExpectTrue((fp = XFOPEN(der[i], "rb")) != XBADFILE); ExpectTrue((fp != XBADFILE)); ExpectNotNull(crl = (X509_CRL *)d2i_X509_CRL_fp((fp, X509_CRL **)NULL)); ExpectNotNull(crl); X509_CRL_free(crl); if (fp != XBADFILE) { XFCLOSE(fp); fp = XBADFILE; } fp = XFOPEN(der[i], "rb"); ExpectTrue((fp != XBADFILE)); ExpectNotNull((X509_CRL *)d2i_X509_CRL_fp(fp, (X509_CRL **)&crl)); if (EXPECT_FAIL()) { crl = NULL; } ExpectNotNull(crl); X509_CRL_free(crl); crl = NULL; if (fp != XBADFILE) { XFCLOSE(fp); fp = XBADFILE; } } #endif #endif return EXPECT_RESULT(); } static int test_wolfSSL_d2i_X509_REQ(void) { EXPECT_DECLS; #if defined(WOLFSSL_CERT_REQ) && !defined(NO_RSA) && !defined(NO_BIO) && \ (defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)) && \ !defined(WOLFSSL_SP_MATH) /* ./certs/csr.signed.der, ./certs/csr.ext.der, and ./certs/csr.attr.der * were generated by libest * ./certs/csr.attr.der contains sample attributes * ./certs/csr.ext.der contains sample extensions */ const char* csrFile = "./certs/csr.signed.der"; const char* csrPopFile = "./certs/csr.attr.der"; const char* csrExtFile = "./certs/csr.ext.der"; /* ./certs/csr.dsa.pem is generated using * openssl req -newkey dsa:certs/dsaparams.pem \ * -keyout certs/csr.dsa.key.pem -keyform PEM -out certs/csr.dsa.pem \ * -outform PEM * with the passphrase "wolfSSL" */ #if !defined(NO_DSA) && !defined(HAVE_SELFTEST) const char* csrDsaFile = "./certs/csr.dsa.pem"; XFILE f = XBADFILE; #endif BIO* bio = NULL; X509* req = NULL; EVP_PKEY *pub_key = NULL; { ExpectNotNull(bio = BIO_new_file(csrFile, "rb")); ExpectNotNull(d2i_X509_REQ_bio(bio, &req)); /* * Extract the public key from the CSR */ ExpectNotNull(pub_key = X509_REQ_get_pubkey(req)); /* * Verify the signature in the CSR */ ExpectIntEQ(X509_REQ_verify(req, pub_key), 1); X509_free(req); req = NULL; BIO_free(bio); bio = NULL; EVP_PKEY_free(pub_key); pub_key = NULL; } { X509_REQ* empty = NULL; #ifdef OPENSSL_ALL X509_ATTRIBUTE* attr = NULL; ASN1_TYPE *at = NULL; #endif ExpectNotNull(empty = wolfSSL_X509_REQ_new()); ExpectNotNull(bio = BIO_new_file(csrPopFile, "rb")); ExpectNotNull(d2i_X509_REQ_bio(bio, &req)); /* * Extract the public key from the CSR */ ExpectNotNull(pub_key = X509_REQ_get_pubkey(req)); /* * Verify the signature in the CSR */ ExpectIntEQ(X509_REQ_verify(req, pub_key), 1); ExpectIntEQ(wolfSSL_X509_REQ_get_attr_count(NULL), 0); ExpectIntEQ(wolfSSL_X509_REQ_get_attr_count(empty), 0); #ifdef OPENSSL_ALL ExpectIntEQ(wolfSSL_X509_REQ_get_attr_count(req), 2); #else ExpectIntEQ(wolfSSL_X509_REQ_get_attr_count(req), 0); #endif #ifdef OPENSSL_ALL /* * Obtain the challenge password from the CSR */ ExpectIntEQ(X509_REQ_get_attr_by_NID(NULL, NID_pkcs9_challengePassword, -1), -1); ExpectIntEQ(X509_REQ_get_attr_by_NID(req, NID_pkcs9_challengePassword, -1), 1); ExpectNull(X509_REQ_get_attr(NULL, 3)); ExpectNull(X509_REQ_get_attr(req, 3)); ExpectNull(X509_REQ_get_attr(NULL, 0)); ExpectNull(X509_REQ_get_attr(empty, 0)); ExpectNotNull(attr = X509_REQ_get_attr(req, 1)); ExpectNull(X509_ATTRIBUTE_get0_type(NULL, 1)); ExpectNull(X509_ATTRIBUTE_get0_type(attr, 1)); ExpectNull(X509_ATTRIBUTE_get0_type(NULL, 0)); ExpectNotNull(at = X509_ATTRIBUTE_get0_type(attr, 0)); ExpectNotNull(at->value.asn1_string); ExpectStrEQ((char*)ASN1_STRING_data(at->value.asn1_string), "2xIE+qqp/rhyTXP+"); ExpectIntEQ(X509_get_ext_by_NID(req, NID_subject_alt_name, -1), -1); #endif X509_free(req); req = NULL; BIO_free(bio); bio = NULL; EVP_PKEY_free(pub_key); pub_key = NULL; wolfSSL_X509_REQ_free(empty); } { #ifdef OPENSSL_ALL X509_ATTRIBUTE* attr = NULL; ASN1_TYPE *at = NULL; STACK_OF(X509_EXTENSION) *exts = NULL; #endif ExpectNotNull(bio = BIO_new_file(csrExtFile, "rb")); /* This CSR contains an Extension Request attribute so * we test extension parsing in a CSR attribute here. */ ExpectNotNull(d2i_X509_REQ_bio(bio, &req)); /* * Extract the public key from the CSR */ ExpectNotNull(pub_key = X509_REQ_get_pubkey(req)); /* * Verify the signature in the CSR */ ExpectIntEQ(X509_REQ_verify(req, pub_key), 1); #ifdef OPENSSL_ALL ExpectNotNull(exts = (STACK_OF(X509_EXTENSION)*)X509_REQ_get_extensions( req)); ExpectIntEQ(sk_X509_EXTENSION_num(exts), 2); sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); /* * Obtain the challenge password from the CSR */ ExpectIntEQ(X509_REQ_get_attr_by_NID(req, NID_pkcs9_challengePassword, -1), 0); ExpectNotNull(attr = X509_REQ_get_attr(req, 0)); ExpectNotNull(at = X509_ATTRIBUTE_get0_type(attr, 0)); ExpectNotNull(at->value.asn1_string); ExpectStrEQ((char*)ASN1_STRING_data(at->value.asn1_string), "IGCu/xNL4/0/wOgo"); ExpectIntGE(X509_get_ext_by_NID(req, NID_key_usage, -1), 0); ExpectIntGE(X509_get_ext_by_NID(req, NID_subject_alt_name, -1), 0); #endif X509_free(req); req = NULL; BIO_free(bio); bio = NULL; EVP_PKEY_free(pub_key); pub_key = NULL; } #if !defined(NO_DSA) && !defined(HAVE_SELFTEST) { ExpectNotNull(bio = BIO_new_file(csrDsaFile, "rb")); ExpectNotNull(PEM_read_bio_X509_REQ(bio, &req, NULL, NULL)); /* * Extract the public key from the CSR */ ExpectNotNull(pub_key = X509_REQ_get_pubkey(req)); /* * Verify the signature in the CSR */ ExpectIntEQ(X509_REQ_verify(req, pub_key), 1); X509_free(req); req = NULL; BIO_free(bio); /* Run the same test, but with a file pointer instead of a BIO. * (PEM_read_X509_REQ)*/ ExpectTrue((f = XFOPEN(csrDsaFile, "rb")) != XBADFILE); ExpectNull(PEM_read_X509_REQ(XBADFILE, &req, NULL, NULL)); if (EXPECT_SUCCESS()) ExpectNotNull(PEM_read_X509_REQ(f, &req, NULL, NULL)); else if (f != XBADFILE) XFCLOSE(f); ExpectIntEQ(X509_REQ_verify(req, pub_key), 1); X509_free(req); EVP_PKEY_free(pub_key); } #endif /* !NO_DSA && !HAVE_SELFTEST */ #endif /* WOLFSSL_CERT_REQ && (OPENSSL_ALL || OPENSSL_EXTRA) */ return EXPECT_RESULT(); } static int test_wolfSSL_PEM_read(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM) && !defined(NO_BIO) const char* filename = "./certs/server-keyEnc.pem"; XFILE fp = XBADFILE; char* name = NULL; char* header = NULL; byte* data = NULL; long len; EVP_CIPHER_INFO cipher; WOLFSSL_BIO* bio = NULL; byte* fileData = NULL; size_t fileDataSz = 0; byte* out; ExpectNotNull(bio = BIO_new_file(filename, "rb")); ExpectIntEQ(PEM_read_bio(bio, NULL, &header, &data, &len), 0); ExpectIntEQ(PEM_read_bio(bio, &name, NULL, &data, &len), 0); ExpectIntEQ(PEM_read_bio(bio, &name, &header, NULL, &len), 0); ExpectIntEQ(PEM_read_bio(bio, &name, &header, &data, NULL), 0); ExpectIntEQ(PEM_read_bio(bio, &name, &header, &data, &len), 1); ExpectIntEQ(XSTRNCMP(name, "RSA PRIVATE KEY", 15), 0); ExpectIntGT(XSTRLEN(header), 0); ExpectIntGT(len, 0); XFREE(name, NULL, DYNAMIC_TYPE_TMP_BUFFER); name = NULL; XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER); header = NULL; XFREE(data, NULL, DYNAMIC_TYPE_TMP_BUFFER); data = NULL; BIO_free(bio); bio = NULL; ExpectTrue((fp = XFOPEN(filename, "rb")) != XBADFILE); /* Fail cases. */ ExpectIntEQ(PEM_read(fp, NULL, &header, &data, &len), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(PEM_read(fp, &name, NULL, &data, &len), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(PEM_read(fp, &name, &header, NULL, &len), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(PEM_read(fp, &name, &header, &data, NULL), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(PEM_read(fp, &name, &header, &data, &len), WOLFSSL_SUCCESS); ExpectIntEQ(XSTRNCMP(name, "RSA PRIVATE KEY", 15), 0); ExpectIntGT(XSTRLEN(header), 0); ExpectIntGT(len, 0); ExpectIntEQ(XFSEEK(fp, 0, SEEK_END), 0); ExpectIntGT((fileDataSz = XFTELL(fp)), 0); ExpectIntEQ(XFSEEK(fp, 0, SEEK_SET), 0); ExpectNotNull(fileData = (unsigned char*)XMALLOC(fileDataSz, NULL, DYNAMIC_TYPE_TMP_BUFFER)); ExpectIntEQ(XFREAD(fileData, 1, fileDataSz, fp), fileDataSz); if (fp != XBADFILE) { XFCLOSE(fp); fp = XBADFILE; } ExpectNotNull(bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem())); /* Fail cases. */ ExpectIntEQ(PEM_write_bio(NULL, name, header, data, len), 0); ExpectIntEQ(PEM_write_bio(bio, NULL, header, data, len), 0); ExpectIntEQ(PEM_write_bio(bio, name, NULL, data, len), 0); ExpectIntEQ(PEM_write_bio(bio, name, header, NULL, len), 0); ExpectIntEQ(PEM_write_bio(bio, name, header, data, len), fileDataSz); ExpectIntEQ(wolfSSL_BIO_get_mem_data(bio, &out), fileDataSz); ExpectIntEQ(XMEMCMP(out, fileData, fileDataSz), 0); /* Fail cases. */ ExpectIntEQ(PEM_write(XBADFILE, name, header, data, len), 0); ExpectIntEQ(PEM_write(stderr, NULL, header, data, len), 0); ExpectIntEQ(PEM_write(stderr, name, NULL, data, len), 0); ExpectIntEQ(PEM_write(stderr, name, header, NULL, len), 0); /* Pass case */ ExpectIntEQ(PEM_write(stderr, name, header, data, len), fileDataSz); XFREE(name, NULL, DYNAMIC_TYPE_TMP_BUFFER); name = NULL; XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER); header = NULL; XFREE(data, NULL, DYNAMIC_TYPE_TMP_BUFFER); data = NULL; /* Read out of a fixed buffer BIO - forces malloc in PEM_read_bio. */ ExpectIntEQ(PEM_read_bio(bio, &name, &header, &data, &len), 1); ExpectIntEQ(XSTRNCMP(name, "RSA PRIVATE KEY", 15), 0); ExpectIntGT(XSTRLEN(header), 0); ExpectIntGT(len, 0); /* Fail cases. */ ExpectIntEQ(PEM_get_EVP_CIPHER_INFO(NULL, &cipher), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(PEM_get_EVP_CIPHER_INFO(header, NULL), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(PEM_get_EVP_CIPHER_INFO((char*)"", &cipher), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); #ifndef NO_DES3 ExpectIntEQ(PEM_get_EVP_CIPHER_INFO(header, &cipher), WOLFSSL_SUCCESS); #endif /* Fail cases. */ ExpectIntEQ(PEM_do_header(NULL, data, &len, PasswordCallBack, (void*)"yassl123"), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(PEM_do_header(&cipher, NULL, &len, PasswordCallBack, (void*)"yassl123"), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(PEM_do_header(&cipher, data, NULL, PasswordCallBack, (void*)"yassl123"), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(PEM_do_header(&cipher, data, &len, NULL, (void*)"yassl123"), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(PEM_do_header(&cipher, data, &len, NoPasswordCallBack, (void*)"yassl123"), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); #if !defined(NO_DES3) && !defined(NO_MD5) ExpectIntEQ(PEM_do_header(&cipher, data, &len, PasswordCallBack, (void*)"yassl123"), WOLFSSL_SUCCESS); #else ExpectIntEQ(PEM_do_header(&cipher, data, &len, PasswordCallBack, (void*)"yassl123"), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); #endif BIO_free(bio); bio = NULL; XFREE(fileData, NULL, DYNAMIC_TYPE_TMP_BUFFER); fileData = NULL; XFREE(name, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(data, NULL, DYNAMIC_TYPE_TMP_BUFFER); name = NULL; header = NULL; data = NULL; ExpectTrue((fp = XFOPEN(svrKeyFile, "rb")) != XBADFILE); ExpectIntEQ(PEM_read(fp, &name, &header, &data, &len), WOLFSSL_SUCCESS); ExpectIntEQ(XSTRNCMP(name, "RSA PRIVATE KEY", 15), 0); ExpectIntEQ(XSTRLEN(header), 0); ExpectIntGT(len, 0); ExpectIntEQ(XFSEEK(fp, 0, SEEK_END), 0); ExpectIntGT((fileDataSz = XFTELL(fp)), 0); ExpectIntEQ(XFSEEK(fp, 0, SEEK_SET), 0); ExpectNotNull(fileData = (unsigned char*)XMALLOC(fileDataSz, NULL, DYNAMIC_TYPE_TMP_BUFFER)); ExpectIntEQ(XFREAD(fileData, 1, fileDataSz, fp), fileDataSz); if (fp != XBADFILE) XFCLOSE(fp); ExpectNotNull(bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem())); ExpectIntEQ(PEM_write_bio(bio, name, header, data, len), fileDataSz); ExpectIntEQ(wolfSSL_BIO_get_mem_data(bio, &out), fileDataSz); ExpectIntEQ(XMEMCMP(out, fileData, fileDataSz), 0); BIO_free(bio); XFREE(fileData, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(name, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(data, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return EXPECT_RESULT(); } static int test_wolfSSL_dup_CA_list(void) { int res = TEST_SKIPPED; #if defined(OPENSSL_ALL) EXPECT_DECLS; STACK_OF(X509_NAME) *originalStack = NULL; STACK_OF(X509_NAME) *copyStack = NULL; int originalCount = 0; int copyCount = 0; X509_NAME *name = NULL; int i; originalStack = sk_X509_NAME_new_null(); ExpectNotNull(originalStack); for (i = 0; i < 3; i++) { name = X509_NAME_new(); ExpectNotNull(name); ExpectIntEQ(sk_X509_NAME_push(originalStack, name), i+1); if (EXPECT_FAIL()) { X509_NAME_free(name); } } copyStack = SSL_dup_CA_list(originalStack); ExpectNotNull(copyStack); ExpectIntEQ(sk_X509_NAME_num(NULL), BAD_FUNC_ARG); originalCount = sk_X509_NAME_num(originalStack); copyCount = sk_X509_NAME_num(copyStack); ExpectIntEQ(originalCount, copyCount); sk_X509_NAME_pop_free(originalStack, X509_NAME_free); sk_X509_NAME_pop_free(copyStack, X509_NAME_free); originalStack = NULL; copyStack = NULL; originalStack = sk_X509_NAME_new_null(); ExpectNull(sk_X509_NAME_pop(NULL)); ExpectNull(sk_X509_NAME_pop(originalStack)); for (i = 0; i < 3; i++) { name = X509_NAME_new(); ExpectNotNull(name); ExpectIntEQ(sk_X509_NAME_push(originalStack, name), i+1); if (EXPECT_FAIL()) { X509_NAME_free(name); } name = NULL; } ExpectNotNull(name = sk_X509_NAME_pop(originalStack)); X509_NAME_free(name); wolfSSL_sk_X509_NAME_set_cmp_func(NULL, NULL); wolfSSL_sk_X509_NAME_set_cmp_func(originalStack, NULL); wolfSSL_sk_X509_NAME_pop_free(originalStack, X509_NAME_free); res = EXPECT_RESULT(); #endif /* OPENSSL_ALL */ return res; } static int test_ForceZero(void) { EXPECT_DECLS; unsigned char data[32]; unsigned int i, j, len; /* Test case with 0 length */ ForceZero(data, 0); /* Test ForceZero */ for (i = 0; i < sizeof(data); i++) { for (len = 1; len < sizeof(data) - i; len++) { for (j = 0; j < sizeof(data); j++) data[j] = ((unsigned char)j + 1); ForceZero(data + i, len); for (j = 0; j < sizeof(data); j++) { if (j < i || j >= i + len) { ExpectIntNE(data[j], 0x00); } else { ExpectIntEQ(data[j], 0x00); } } } } return EXPECT_RESULT(); } #ifndef NO_BIO static int test_wolfSSL_X509_print(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM) && \ !defined(NO_RSA) && defined(XSNPRINTF) && !defined(WC_DISABLE_RADIX_ZERO_PAD) X509 *x509 = NULL; BIO *bio = NULL; #if defined(OPENSSL_ALL) && !defined(NO_WOLFSSL_DIR) const X509_ALGOR *cert_sig_alg = NULL; #endif ExpectNotNull(x509 = X509_load_certificate_file(svrCertFile, WOLFSSL_FILETYPE_PEM)); /* print to memory */ ExpectNotNull(bio = BIO_new(BIO_s_mem())); ExpectIntEQ(X509_print(bio, x509), SSL_SUCCESS); #if defined(OPENSSL_ALL) || defined(WOLFSSL_IP_ALT_NAME) #if defined(WC_DISABLE_RADIX_ZERO_PAD) /* Will print IP address subject alt name. */ ExpectIntEQ(BIO_get_mem_data(bio, NULL), 3349); #elif defined(NO_ASN_TIME) /* Will print IP address subject alt name but not Validity. */ ExpectIntEQ(BIO_get_mem_data(bio, NULL), 3235); #else /* Will print IP address subject alt name. */ ExpectIntEQ(BIO_get_mem_data(bio, NULL), 3350); #endif #elif defined(IGNORE_NAME_CONSTRAINTS) /* DecodeGeneralName skips iPAddress entries when name constraints * are disabled, so the IP SAN never reaches the print path. */ #if defined(NO_ASN_TIME) ExpectIntEQ(BIO_get_mem_data(bio, NULL), 3213); #else ExpectIntEQ(BIO_get_mem_data(bio, NULL), 3328); #endif #elif defined(NO_ASN_TIME) /* With NO_ASN_TIME defined, X509_print skips printing Validity. * iPAddress SAN now always parsed; prints as * "IP Address:" (+26 bytes) without * WOLFSSL_IP_ALT_NAME. */ ExpectIntEQ(BIO_get_mem_data(bio, NULL), 3239); #else /* iPAddress SAN now always parsed; prints as * "IP Address:" (+26 bytes) without * WOLFSSL_IP_ALT_NAME. */ ExpectIntEQ(BIO_get_mem_data(bio, NULL), 3354); #endif BIO_free(bio); bio = NULL; ExpectNotNull(bio = BIO_new_fd(STDERR_FILENO, BIO_NOCLOSE)); #if defined(OPENSSL_ALL) && !defined(NO_WOLFSSL_DIR) /* Print signature */ ExpectNotNull(cert_sig_alg = X509_get0_tbs_sigalg(x509)); ExpectIntEQ(X509_signature_print(bio, cert_sig_alg, NULL), SSL_SUCCESS); #endif /* print to stderr */ #if !defined(NO_WOLFSSL_DIR) ExpectIntEQ(X509_print(bio, x509), SSL_SUCCESS); #endif /* print again */ ExpectIntEQ(X509_print_fp(stderr, x509), SSL_SUCCESS); X509_free(x509); BIO_free(bio); #endif return EXPECT_RESULT(); } static int test_wolfSSL_X509_CRL_print(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && defined(HAVE_CRL) && \ !defined(NO_RSA) && !defined(NO_FILESYSTEM) && defined(XSNPRINTF) X509_CRL* crl = NULL; BIO *bio = NULL; XFILE fp = XBADFILE; ExpectTrue((fp = XFOPEN("./certs/crl/crl.pem", "rb")) != XBADFILE); ExpectNotNull(crl = (X509_CRL*)PEM_read_X509_CRL(fp, (X509_CRL **)NULL, NULL, NULL)); if (fp != XBADFILE) XFCLOSE(fp); ExpectNotNull(bio = BIO_new(BIO_s_mem())); ExpectIntEQ(X509_CRL_print(bio, crl), SSL_SUCCESS); X509_CRL_free(crl); BIO_free(bio); #endif return EXPECT_RESULT(); } #endif /* !NO_BIO */ #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ) && \ !defined(NO_ASN_TIME) static int test_openssl_make_self_signed_certificate(EVP_PKEY* pkey, int expectedDerSz) { EXPECT_DECLS; X509* x509 = NULL; BIGNUM* serial_number = NULL; X509_NAME* name = NULL; time_t epoch_off = 0; ASN1_INTEGER* asn1_serial_number = NULL; long not_before, not_after; int derSz; ExpectNotNull(x509 = X509_new()); ExpectIntNE(X509_set_pubkey(x509, pkey), 0); ExpectNotNull(serial_number = BN_new()); ExpectIntNE(BN_pseudo_rand(serial_number, 64, 0, 0), 0); ExpectNotNull(asn1_serial_number = X509_get_serialNumber(x509)); ExpectNotNull(BN_to_ASN1_INTEGER(serial_number, asn1_serial_number)); /* version 3 */ ExpectIntNE(X509_set_version(x509, 2L), 0); ExpectNotNull(name = X509_NAME_new()); ExpectIntNE(X509_NAME_add_entry_by_NID(name, NID_commonName, MBSTRING_UTF8, (unsigned char*)"www.wolfssl.com", -1, -1, 0), 0); ExpectIntNE(X509_NAME_add_entry_by_NID(name, NID_pkcs9_contentType, MBSTRING_UTF8,(unsigned char*)"Server", -1, -1, 0), 0); ExpectIntNE(X509_set_subject_name(x509, name), 0); ExpectIntNE(X509_set_issuer_name(x509, name), 0); not_before = (long)wc_Time(NULL); not_after = not_before + (365 * 24 * 60 * 60); ExpectNotNull(X509_time_adj(X509_get_notBefore(x509), not_before, &epoch_off)); ExpectNotNull(X509_time_adj(X509_get_notAfter(x509), not_after, &epoch_off)); ExpectIntNE(X509_sign(x509, pkey, EVP_sha256()), 0); ExpectNotNull(wolfSSL_X509_get_der(x509, &derSz)); ExpectIntGE(derSz, expectedDerSz); BN_free(serial_number); X509_NAME_free(name); X509_free(x509); return EXPECT_RESULT(); } #endif static int test_openssl_generate_key_and_cert(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) int expectedDerSz; EVP_PKEY* pkey = NULL; #ifdef HAVE_ECC EC_KEY* ec_key = NULL; #endif #if !defined(NO_RSA) int key_length = 2048; BIGNUM* exponent = NULL; RSA* rsa = NULL; ExpectNotNull(pkey = EVP_PKEY_new()); ExpectNotNull(exponent = BN_new()); ExpectNotNull(rsa = RSA_new()); ExpectIntNE(BN_set_word(exponent, WC_RSA_EXPONENT), 0); #ifndef WOLFSSL_KEY_GEN ExpectIntEQ(RSA_generate_key_ex(rsa, key_length, exponent, NULL), 0); #if defined(USE_CERT_BUFFERS_1024) ExpectIntNE(wolfSSL_RSA_LoadDer_ex(rsa, server_key_der_1024, sizeof_server_key_der_1024, WOLFSSL_RSA_LOAD_PRIVATE), 0); key_length = 1024; #elif defined(USE_CERT_BUFFERS_2048) ExpectIntNE(wolfSSL_RSA_LoadDer_ex(rsa, server_key_der_2048, sizeof_server_key_der_2048, WOLFSSL_RSA_LOAD_PRIVATE), 0); #else RSA_free(rsa); rsa = NULL; #endif #else ExpectIntEQ(RSA_generate_key_ex(NULL, key_length, exponent, NULL), 0); ExpectIntEQ(RSA_generate_key_ex(rsa, 0, exponent, NULL), 0); ExpectIntEQ(RSA_generate_key_ex(rsa, key_length, NULL, NULL), 0); ExpectIntNE(RSA_generate_key_ex(rsa, key_length, exponent, NULL), 0); #endif if (rsa) { ExpectIntNE(EVP_PKEY_assign_RSA(pkey, rsa), 0); if (EXPECT_FAIL()) { RSA_free(rsa); } #if !defined(NO_CERTS) && defined(WOLFSSL_CERT_GEN) && \ defined(WOLFSSL_CERT_REQ) && !defined(NO_ASN_TIME) expectedDerSz = 743; ExpectIntEQ(test_openssl_make_self_signed_certificate(pkey, expectedDerSz), TEST_SUCCESS); #endif } EVP_PKEY_free(pkey); pkey = NULL; BN_free(exponent); #endif /* !NO_RSA */ #ifdef HAVE_ECC ExpectNotNull(pkey = EVP_PKEY_new()); ExpectNotNull(ec_key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); #ifndef NO_WOLFSSL_STUB EC_KEY_set_asn1_flag(ec_key, OPENSSL_EC_NAMED_CURVE); #endif ExpectIntNE(EC_KEY_generate_key(ec_key), 0); ExpectIntNE(EVP_PKEY_assign_EC_KEY(pkey, ec_key), 0); if (EXPECT_FAIL()) { EC_KEY_free(ec_key); } #if !defined(NO_CERTS) && defined(WOLFSSL_CERT_GEN) && \ defined(WOLFSSL_CERT_REQ) && !defined(NO_ASN_TIME) expectedDerSz = 344; ExpectIntEQ(test_openssl_make_self_signed_certificate(pkey, expectedDerSz), TEST_SUCCESS); #endif EVP_PKEY_free(pkey); #endif /* HAVE_ECC */ (void)pkey; (void)expectedDerSz; #endif /* OPENSSL_EXTRA */ return EXPECT_RESULT(); } static int test_stubs_are_stubs(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_WOLFSSL_STUB) && \ !defined(NO_TLS) && \ (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) WOLFSSL_CTX* ctx = NULL; WOLFSSL_CTX* ctxN = NULL; #ifndef NO_WOLFSSL_CLIENT ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); #elif !defined(NO_WOLFSSL_SERVER) ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); #endif #define CHECKZERO_RET(x, y, z) ExpectIntEQ((int) x(y), 0); \ ExpectIntEQ((int) x(z), 0) /* test logic, all stubs return same result regardless of ctx being NULL * as there are no sanity checks, it's just a stub! If at some * point a stub is not a stub it should begin to return BAD_FUNC_ARG * if invalid inputs are supplied. Test calling both * with and without valid inputs, if a stub functionality remains unchanged. */ CHECKZERO_RET(wolfSSL_CTX_sess_accept, ctx, ctxN); CHECKZERO_RET(wolfSSL_CTX_sess_connect, ctx, ctxN); CHECKZERO_RET(wolfSSL_CTX_sess_accept_good, ctx, ctxN); CHECKZERO_RET(wolfSSL_CTX_sess_connect_good, ctx, ctxN); CHECKZERO_RET(wolfSSL_CTX_sess_accept_renegotiate, ctx, ctxN); CHECKZERO_RET(wolfSSL_CTX_sess_connect_renegotiate, ctx, ctxN); CHECKZERO_RET(wolfSSL_CTX_sess_hits, ctx, ctxN); CHECKZERO_RET(wolfSSL_CTX_sess_cb_hits, ctx, ctxN); CHECKZERO_RET(wolfSSL_CTX_sess_cache_full, ctx, ctxN); CHECKZERO_RET(wolfSSL_CTX_sess_misses, ctx, ctxN); CHECKZERO_RET(wolfSSL_CTX_sess_timeouts, ctx, ctxN); /* when implemented this should take WOLFSSL object instead, right now * always returns 0 */ ExpectPtrEq(SSL_get_current_expansion(NULL), NULL); wolfSSL_CTX_free(ctx); ctx = NULL; ExpectStrEQ(SSL_COMP_get_name(NULL), "not supported"); ExpectPtrEq(SSL_get_current_expansion(NULL), NULL); #endif /* OPENSSL_EXTRA && !NO_WOLFSSL_STUB && (!NO_WOLFSSL_CLIENT || * !NO_WOLFSSL_SERVER) */ return EXPECT_RESULT(); } static int test_CONF_modules_xxx(void) { int res = TEST_SKIPPED; #if defined(OPENSSL_EXTRA) CONF_modules_free(); CONF_modules_unload(0); CONF_modules_unload(1); CONF_modules_unload(-1); res = TEST_SUCCESS; #endif /* OPENSSL_EXTRA */ return res; } static int test_CRYPTO_set_dynlock_xxx(void) { int res = TEST_SKIPPED; #if defined(OPENSSL_EXTRA) CRYPTO_set_dynlock_create_callback( (struct CRYPTO_dynlock_value *(*)(const char*, int))NULL); CRYPTO_set_dynlock_create_callback( (struct CRYPTO_dynlock_value *(*)(const char*, int))1); CRYPTO_set_dynlock_destroy_callback( (void (*)(struct CRYPTO_dynlock_value*, const char*, int))NULL); CRYPTO_set_dynlock_destroy_callback( (void (*)(struct CRYPTO_dynlock_value*, const char*, int))1); CRYPTO_set_dynlock_lock_callback( (void (*)(int, struct CRYPTO_dynlock_value *, const char*, int))NULL); CRYPTO_set_dynlock_lock_callback( (void (*)(int, struct CRYPTO_dynlock_value *, const char*, int))1); res = TEST_SUCCESS; #endif /* OPENSSL_EXTRA */ return res; } static int test_CRYPTO_THREADID_xxx(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) CRYPTO_THREADID_current((CRYPTO_THREADID*)NULL); CRYPTO_THREADID_current((CRYPTO_THREADID*)1); ExpectIntEQ(CRYPTO_THREADID_hash((const CRYPTO_THREADID*)NULL), 0); #endif /* OPENSSL_EXTRA */ return EXPECT_RESULT(); } static int test_ENGINE_cleanup(void) { int res = TEST_SKIPPED; #if defined(OPENSSL_EXTRA) ENGINE_cleanup(); res = TEST_SUCCESS; #endif /* OPENSSL_EXTRA */ return res; } static int test_wolfSSL_CTX_LoadCRL(void) { EXPECT_DECLS; #if defined(HAVE_CRL) && !defined(NO_RSA) && !defined(NO_FILESYSTEM) && \ (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) WOLFSSL_CERT_MANAGER* cm = NULL; const char* issuerCert = "./certs/client-cert.pem"; const char* validFilePath = "./certs/crl/cliCrl.pem"; int pemType = WOLFSSL_FILETYPE_PEM; #ifndef NO_TLS WOLFSSL_CTX* ctx = NULL; WOLFSSL* ssl = NULL; const char* badPath = "dummypath"; const char* validPath = "./certs/crl"; int derType = WOLFSSL_FILETYPE_ASN1; #ifdef HAVE_CRL_MONITOR int monitor = WOLFSSL_CRL_MONITOR; #else int monitor = 0; #endif #define FAIL_T1(x, y, z, p, d) ExpectIntEQ((int) x(y, z, p, d), \ WC_NO_ERR_TRACE(BAD_FUNC_ARG)) #define FAIL_T2(x, y, z, p, d) ExpectIntEQ((int) x(y, z, p, d), \ WC_NO_ERR_TRACE(NOT_COMPILED_IN)) #define SUCC_T(x, y, z, p, d) ExpectIntEQ((int) x(y, z, p, d), \ WOLFSSL_SUCCESS) #ifndef NO_WOLFSSL_CLIENT #define NEW_CTX(ctx) ExpectNotNull( \ (ctx) = wolfSSL_CTX_new(wolfSSLv23_client_method())) #elif !defined(NO_WOLFSSL_SERVER) #define NEW_CTX(ctx) ExpectNotNull( \ (ctx) = wolfSSL_CTX_new(wolfSSLv23_server_method())) #else #define NEW_CTX(ctx) return #endif FAIL_T1(wolfSSL_CTX_LoadCRL, ctx, validPath, pemType, monitor); NEW_CTX(ctx); #ifndef HAVE_CRL_MONITOR FAIL_T2(wolfSSL_CTX_LoadCRL, ctx, validPath, pemType, WOLFSSL_CRL_MONITOR); wolfSSL_CTX_free(ctx); NEW_CTX(ctx); #endif SUCC_T (wolfSSL_CTX_LoadCRL, ctx, validPath, pemType, monitor); SUCC_T (wolfSSL_CTX_LoadCRL, ctx, badPath, pemType, monitor); SUCC_T (wolfSSL_CTX_LoadCRL, ctx, badPath, derType, monitor); wolfSSL_CTX_free(ctx); ctx = NULL; NEW_CTX(ctx); ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx, issuerCert, NULL), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_LoadCRLFile(ctx, validFilePath, pemType), WOLFSSL_SUCCESS); wolfSSL_CTX_free(ctx); ctx = NULL; NEW_CTX(ctx); ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx, issuerCert, NULL), WOLFSSL_SUCCESS); ExpectNotNull(ssl = wolfSSL_new(ctx)); ExpectIntEQ(wolfSSL_LoadCRLFile(ssl, validFilePath, pemType), WOLFSSL_SUCCESS); wolfSSL_free(ssl); ssl = NULL; wolfSSL_CTX_free(ctx); ctx = NULL; #endif /* !NO_TLS */ ExpectNotNull(cm = wolfSSL_CertManagerNew()); ExpectIntEQ(wolfSSL_CertManagerLoadCA(cm, issuerCert, NULL), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CertManagerLoadCRLFile(cm, validFilePath, pemType), WOLFSSL_SUCCESS); wolfSSL_CertManagerFree(cm); #endif return EXPECT_RESULT(); } static int test_wolfSSL_CTX_LoadCRL_largeCRLnum(void) { EXPECT_DECLS; #if defined(HAVE_CRL) && !defined(NO_RSA) && !defined(NO_FILESYSTEM) && \ defined(HAVE_CRL_UPDATE_CB) WOLFSSL_CERT_MANAGER* cm = NULL; const char* caCert = "./certs/ca-cert.pem"; const char* crl_lrgcrlnum = "./certs/crl/extra-crls/large_crlnum.pem"; const char* crl_lrgcrlnum2 = "./certs/crl/extra-crls/large_crlnum2.pem"; const char* crl_57oct = "./certs/crl/extra-crls/crlnum_57oct.pem"; const char* crl_64oct = "./certs/crl/extra-crls/crlnum_64oct.pem"; const char* exp_crlnum = "D8AFADA7F08B38E6178BD0E5CD7B0DF80071BA74"; byte *crlLrgCrlNumBuff = NULL; word32 crlLrgCrlNumSz; CrlInfo crlInfo; XFILE f; word32 sz; cm = wolfSSL_CertManagerNew(); ExpectNotNull(cm); ExpectIntEQ(wolfSSL_CertManagerLoadCA(cm, caCert, NULL), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CertManagerLoadCRLFile(cm, crl_lrgcrlnum, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); AssertTrue((f = XFOPEN(crl_lrgcrlnum, "rb")) != XBADFILE); AssertTrue(XFSEEK(f, 0, XSEEK_END) == 0); AssertIntGE(sz = (word32) XFTELL(f), 1); AssertTrue(XFSEEK(f, 0, XSEEK_SET) == 0); AssertTrue( \ (crlLrgCrlNumBuff = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE)) != NULL); AssertTrue(XFREAD(crlLrgCrlNumBuff, 1, sz, f) == sz); XFCLOSE(f); crlLrgCrlNumSz = sz; AssertIntEQ(wolfSSL_CertManagerGetCRLInfo( cm, &crlInfo, crlLrgCrlNumBuff, crlLrgCrlNumSz, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); AssertIntEQ(XMEMCMP( crlInfo.crlNumber, exp_crlnum, XSTRLEN(exp_crlnum)), 0); /* Expect to fail loading CRL because of >21 octets CRL number */ ExpectIntEQ(wolfSSL_CertManagerLoadCRLFile(cm, crl_lrgcrlnum2, WOLFSSL_FILETYPE_PEM), ASN_PARSE_E); /* Expect to fail loading CRL because of >57 octets CRL number */ ExpectIntEQ(wolfSSL_CertManagerLoadCRLFile(cm, crl_57oct, WOLFSSL_FILETYPE_PEM), ASN_PARSE_E); /* Expect to fail loading CRL because of >64 octets CRL number */ ExpectIntEQ(wolfSSL_CertManagerLoadCRLFile(cm, crl_64oct, WOLFSSL_FILETYPE_PEM), ASN_PARSE_E); XFREE(crlLrgCrlNumBuff, NULL, DYNAMIC_TYPE_FILE); wolfSSL_CertManagerFree(cm); #endif return EXPECT_RESULT(); } #if defined(HAVE_CRL) && !defined(NO_RSA) && !defined(NO_FILESYSTEM) && \ defined(HAVE_CRL_UPDATE_CB) int crlUpdateTestStatus = 0; WOLFSSL_CERT_MANAGER* updateCrlTestCm = NULL; static void updateCrlCb(CrlInfo* old, CrlInfo* cnew) { const char* crl1 = "./certs/crl/crl.pem"; const char* crlRevoked = "./certs/crl/crl.revoked"; byte *crl1Buff = NULL; word32 crl1Sz; byte *crlRevBuff = NULL; word32 crlRevSz; WOLFSSL_CERT_MANAGER* cm = updateCrlTestCm; XFILE f; word32 sz; CrlInfo crl1Info; CrlInfo crlRevInfo; crlUpdateTestStatus = 0; if (old == NULL || cnew == NULL) { return; } AssertTrue((f = XFOPEN(crl1, "rb")) != XBADFILE); AssertTrue(XFSEEK(f, 0, XSEEK_END) == 0); AssertIntGE(sz = (word32) XFTELL(f), 1); AssertTrue(XFSEEK(f, 0, XSEEK_SET) == 0); AssertTrue( \ (crl1Buff = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE)) != NULL); AssertTrue(XFREAD(crl1Buff, 1, sz, f) == sz); XFCLOSE(f); crl1Sz = sz; AssertTrue((f = XFOPEN(crlRevoked, "rb")) != XBADFILE); AssertTrue(XFSEEK(f, 0, XSEEK_END) == 0); AssertIntGE(sz = (word32) XFTELL(f), 1); AssertTrue(XFSEEK(f, 0, XSEEK_SET) == 0); AssertTrue( \ (crlRevBuff = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE)) != NULL); AssertTrue(XFREAD(crlRevBuff, 1, sz, f) == sz); XFCLOSE(f); crlRevSz = sz; AssertIntEQ(wolfSSL_CertManagerGetCRLInfo( cm, &crl1Info, crl1Buff, crl1Sz, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); AssertIntEQ(wolfSSL_CertManagerGetCRLInfo( cm, &crlRevInfo, crlRevBuff, crlRevSz, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); /* Old entry being replaced should match crl1 */ AssertIntEQ(crl1Info.issuerHashLen, old->issuerHashLen); AssertIntEQ(crl1Info.lastDateMaxLen, old->lastDateMaxLen); AssertIntEQ(crl1Info.lastDateFormat, old->lastDateFormat); AssertIntEQ(crl1Info.nextDateMaxLen, old->nextDateMaxLen); AssertIntEQ(crl1Info.nextDateFormat, old->nextDateFormat); AssertIntEQ(XMEMCMP( crl1Info.crlNumber, old->crlNumber, sizeof(old->crlNumber)), 0); AssertIntEQ(XMEMCMP( crl1Info.issuerHash, old->issuerHash, old->issuerHashLen), 0); AssertIntEQ(XMEMCMP( crl1Info.lastDate, old->lastDate, old->lastDateMaxLen), 0); AssertIntEQ(XMEMCMP( crl1Info.nextDate, old->nextDate, old->nextDateMaxLen), 0); /* Newer entry should match crl revoked */ AssertIntEQ(crlRevInfo.issuerHashLen, cnew->issuerHashLen); AssertIntEQ(crlRevInfo.lastDateMaxLen, cnew->lastDateMaxLen); AssertIntEQ(crlRevInfo.lastDateFormat, cnew->lastDateFormat); AssertIntEQ(crlRevInfo.nextDateMaxLen, cnew->nextDateMaxLen); AssertIntEQ(crlRevInfo.nextDateFormat, cnew->nextDateFormat); AssertIntEQ(XMEMCMP( crlRevInfo.crlNumber, cnew->crlNumber, sizeof(cnew->crlNumber)), 0); AssertIntEQ(XMEMCMP( crlRevInfo.issuerHash, cnew->issuerHash, cnew->issuerHashLen), 0); AssertIntEQ(XMEMCMP( crlRevInfo.lastDate, cnew->lastDate, cnew->lastDateMaxLen), 0); AssertIntEQ(XMEMCMP( crlRevInfo.nextDate, cnew->nextDate, cnew->nextDateMaxLen), 0); XFREE(crl1Buff, NULL, DYNAMIC_TYPE_FILE); XFREE(crlRevBuff, NULL, DYNAMIC_TYPE_FILE); crlUpdateTestStatus = 1; } #endif static int test_wolfSSL_crl_update_cb(void) { EXPECT_DECLS; #if defined(HAVE_CRL) && !defined(NO_RSA) && !defined(NO_FILESYSTEM) && \ defined(HAVE_CRL_UPDATE_CB) const char* crl1 = "./certs/crl/crl.pem"; const char* crlRevoked = "./certs/crl/crl.revoked"; const char* issuerCert = "./certs/client-cert.pem"; const char* caCert = "./certs/ca-cert.pem"; const char* goodCert = "./certs/server-cert.pem"; const char* revokedCert = "./certs/server-revoked-cert.pem"; int pemType = WOLFSSL_FILETYPE_PEM; WOLFSSL_CERT_MANAGER* cm = NULL; updateCrlTestCm = wolfSSL_CertManagerNew(); ExpectNotNull(updateCrlTestCm); cm = updateCrlTestCm; ExpectIntEQ(wolfSSL_CertManagerSetCRLUpdate_Cb(cm, updateCrlCb), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CertManagerLoadCA(cm, caCert, NULL), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CertManagerLoadCA(cm, issuerCert, NULL), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CertManagerLoadCRLFile(cm, crl1, pemType), WOLFSSL_SUCCESS); /* CRL1 does not have good cert revoked */ ExpectIntEQ(wolfSSL_CertManagerVerify(cm, goodCert, pemType), WOLFSSL_SUCCESS); ExpectIntNE(wolfSSL_CertManagerVerify(cm, revokedCert, pemType), WOLFSSL_SUCCESS); /* Load newer CRL from same issuer, callback verifies CRL entry details */ ExpectIntEQ(wolfSSL_CertManagerLoadCRLFile(cm, crlRevoked, pemType), WOLFSSL_SUCCESS); /* CRL callback verified entry info was as expected */ ExpectIntEQ(crlUpdateTestStatus, 1); /* Ensure that both certs fail with newer CRL */ ExpectIntNE(wolfSSL_CertManagerVerify(cm, goodCert, pemType), WOLFSSL_SUCCESS); ExpectIntNE(wolfSSL_CertManagerVerify(cm, revokedCert, pemType), WOLFSSL_SUCCESS); #endif return EXPECT_RESULT(); } static int test_SetTmpEC_DHE_Sz(void) { EXPECT_DECLS; #if defined(HAVE_ECC) && !defined(NO_WOLFSSL_CLIENT) && !defined(NO_TLS) WOLFSSL_CTX *ctx = NULL; WOLFSSL *ssl = NULL; ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_SetTmpEC_DHE_Sz(ctx, 32)); ExpectNotNull(ssl = wolfSSL_new(ctx)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_SetTmpEC_DHE_Sz(ssl, 32)); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } static int test_wolfSSL_CTX_get0_privatekey(void) { EXPECT_DECLS; #if defined(OPENSSL_ALL) && !defined(NO_TLS) WOLFSSL_CTX* ctx = NULL; (void)ctx; #ifndef NO_RSA ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_method())); ExpectNull(SSL_CTX_get0_privatekey(ctx)); ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile, WOLFSSL_FILETYPE_PEM)); ExpectNull(SSL_CTX_get0_privatekey(ctx)); ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, WOLFSSL_FILETYPE_PEM)); ExpectNotNull(SSL_CTX_get0_privatekey(ctx)); wolfSSL_CTX_free(ctx); ctx = NULL; #endif #ifdef HAVE_ECC ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_method())); ExpectNull(SSL_CTX_get0_privatekey(ctx)); ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx, eccCertFile, WOLFSSL_FILETYPE_PEM)); ExpectNull(SSL_CTX_get0_privatekey(ctx)); ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, eccKeyFile, WOLFSSL_FILETYPE_PEM)); ExpectNotNull(SSL_CTX_get0_privatekey(ctx)); wolfSSL_CTX_free(ctx); #endif #endif return EXPECT_RESULT(); } static int test_wolfSSL_dtls_set_mtu(void) { EXPECT_DECLS; #if (defined(WOLFSSL_DTLS_MTU) || defined(WOLFSSL_SCTP)) && \ !defined(NO_WOLFSSL_SERVER) && defined(WOLFSSL_DTLS) && \ !defined(WOLFSSL_NO_TLS12) WOLFSSL_CTX* ctx = NULL; WOLFSSL* ssl = NULL; const char* testCertFile; const char* testKeyFile; ExpectNotNull(ctx = wolfSSL_CTX_new(wolfDTLSv1_2_server_method())); #ifndef NO_RSA testCertFile = svrCertFile; testKeyFile = svrKeyFile; #elif defined(HAVE_ECC) testCertFile = eccCertFile; testKeyFile = eccKeyFile; #endif if (testCertFile != NULL && testKeyFile != NULL) { ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx, testCertFile, WOLFSSL_FILETYPE_PEM)); ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, testKeyFile, WOLFSSL_FILETYPE_PEM)); } ExpectNotNull(ssl = wolfSSL_new(ctx)); ExpectIntEQ(wolfSSL_CTX_dtls_set_mtu(NULL, 1488), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_dtls_set_mtu(NULL, 1488), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_CTX_dtls_set_mtu(ctx, 20000), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_dtls_set_mtu(ssl, 20000), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_get_error(ssl, WC_NO_ERR_TRACE(WOLFSSL_FAILURE)), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_CTX_dtls_set_mtu(ctx, 1488), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_dtls_set_mtu(ssl, 1488), WOLFSSL_SUCCESS); #ifdef OPENSSL_EXTRA ExpectIntEQ(SSL_set_mtu(ssl, 1488), WOLFSSL_SUCCESS); #endif wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } #if defined(HAVE_IO_TESTS_DEPENDENCIES) && !defined(SINGLE_THREADED) && \ defined(WOLFSSL_DTLS) && !defined(WOLFSSL_NO_TLS12) static WC_INLINE void generateDTLSMsg(byte* out, int outSz, word32 seq, enum HandShakeType hsType, word16 length) { size_t idx = 0; byte* l; /* record layer */ /* handshake type */ out[idx++] = handshake; /* protocol version */ out[idx++] = 0xfe; out[idx++] = 0xfd; /* DTLS 1.2 */ /* epoch 0 */ XMEMSET(out + idx, 0, 2); idx += 2; /* sequence number */ XMEMSET(out + idx, 0, 6); c32toa(seq, out + idx + 2); idx += 6; /* length in BE */ if (length) c16toa(length, out + idx); else c16toa(outSz - idx - 2, out + idx); idx += 2; /* handshake layer */ /* handshake type */ out[idx++] = (byte)hsType; /* length */ l = out + idx; idx += 3; /* message seq */ c16toa(0, out + idx); idx += 2; /* frag offset */ c32to24(0, out + idx); idx += 3; /* frag length */ c32to24((word32)outSz - (word32)idx - 3, l); c32to24((word32)outSz - (word32)idx - 3, out + idx); idx += 3; XMEMSET(out + idx, 0, outSz - idx); } static void test_wolfSSL_dtls_plaintext_server(WOLFSSL* ssl) { byte msg[] = "This is a msg for the client"; byte reply[40]; AssertIntGT(wolfSSL_read(ssl, reply, sizeof(reply)),0); reply[sizeof(reply) - 1] = '\0'; fprintf(stderr, "Client message: %s\n", reply); AssertIntEQ(wolfSSL_write(ssl, msg, sizeof(msg)), sizeof(msg)); } static void test_wolfSSL_dtls_plaintext_client(WOLFSSL* ssl) { byte ch[50]; int fd = wolfSSL_get_wfd(ssl); byte msg[] = "This is a msg for the server"; byte reply[40]; AssertIntGE(fd, 0); generateDTLSMsg(ch, sizeof(ch), 20, client_hello, 0); /* Server should ignore this datagram */ AssertIntEQ(send(fd, (MESSAGE_TYPE_CAST)ch, sizeof(ch), 0), sizeof(ch)); generateDTLSMsg(ch, sizeof(ch), 20, client_hello, 10000); /* Server should ignore this datagram */ AssertIntEQ(send(fd, (MESSAGE_TYPE_CAST)ch, sizeof(ch), 0), sizeof(ch)); AssertIntEQ(wolfSSL_write(ssl, msg, sizeof(msg)), sizeof(msg)); AssertIntGT(wolfSSL_read(ssl, reply, sizeof(reply)),0); reply[sizeof(reply) - 1] = '\0'; fprintf(stderr, "Server response: %s\n", reply); } static int test_wolfSSL_dtls_plaintext(void) { callback_functions func_cb_client; callback_functions func_cb_server; size_t i; struct test_params { method_provider client_meth; method_provider server_meth; ssl_callback on_result_server; ssl_callback on_result_client; } params[] = { {wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method, test_wolfSSL_dtls_plaintext_server, test_wolfSSL_dtls_plaintext_client}, }; for (i = 0; i < sizeof(params)/sizeof(*params); i++) { XMEMSET(&func_cb_client, 0, sizeof(callback_functions)); XMEMSET(&func_cb_server, 0, sizeof(callback_functions)); func_cb_client.doUdp = func_cb_server.doUdp = 1; func_cb_server.method = params[i].server_meth; func_cb_client.method = params[i].client_meth; func_cb_client.on_result = params[i].on_result_client; func_cb_server.on_result = params[i].on_result_server; test_wolfSSL_client_server_nofail(&func_cb_client, &func_cb_server); if (!func_cb_client.return_code) return TEST_FAIL; if (!func_cb_server.return_code) return TEST_FAIL; } return TEST_RES_CHECK(1); } #else static int test_wolfSSL_dtls_plaintext(void) { return TEST_SKIPPED; } #endif #if defined(HAVE_IO_TESTS_DEPENDENCIES) && !defined(SINGLE_THREADED) && \ defined(WOLFSSL_DTLS) && !defined(WOLFSSL_NO_TLS12) static void test_wolfSSL_dtls12_fragments_spammer(WOLFSSL* ssl) { byte b[1100]; /* buffer for the messages to send */ size_t idx = 0; size_t seq_offset = 0; size_t msg_offset = 0; int i; int fd = wolfSSL_get_wfd(ssl); int ret = wolfSSL_connect_cert(ssl); /* This gets us past the cookie */ word32 seq_number = 100; /* start high so server definitely reads this */ word16 msg_number = 50; /* start high so server has to buffer this */ AssertIntEQ(ret, 1); /* Now let's start spamming the peer with fragments it needs to store */ XMEMSET(b, -1, sizeof(b)); /* record layer */ /* handshake type */ b[idx++] = 22; /* protocol version */ b[idx++] = 0xfe; b[idx++] = 0xfd; /* DTLS 1.2 */ /* epoch 0 */ XMEMSET(b + idx, 0, 2); idx += 2; /* sequence number */ XMEMSET(b + idx, 0, 6); seq_offset = idx + 2; /* increment only the low 32 bits */ idx += 6; /* static length in BE */ c16toa(42, b + idx); idx += 2; /* handshake layer */ /* cert type */ b[idx++] = 11; /* length */ c32to24(1000, b + idx); idx += 3; /* message seq */ c16toa(0, b + idx); msg_offset = idx; idx += 2; /* frag offset */ c32to24(500, b + idx); idx += 3; /* frag length */ c32to24(30, b + idx); idx += 3; (void)idx; /* inhibit clang-analyzer-deadcode.DeadStores */ for (i = 0; i < DTLS_POOL_SZ * 2 && ret > 0; seq_number++, msg_number++, i++) { struct timespec delay; XMEMSET(&delay, 0, sizeof(delay)); delay.tv_nsec = 10000000; /* wait 0.01 seconds */ c32toa(seq_number, b + seq_offset); c16toa(msg_number, b + msg_offset); ret = (int)send(fd, (MESSAGE_TYPE_CAST)b, 55, 0); nanosleep(&delay, NULL); } } #ifdef WOLFSSL_DTLS13 static void test_wolfSSL_dtls13_fragments_spammer(WOLFSSL* ssl) { const word16 sendCountMax = 100; byte b[150]; /* buffer for the messages to send */ size_t idx = 0; size_t msg_offset = 0; int fd = wolfSSL_get_wfd(ssl); word16 msg_number = 10; /* start high so server has to buffer this */ int ret = wolfSSL_connect_cert(ssl); /* This gets us past the cookie */ AssertIntEQ(ret, 1); /* Now let's start spamming the peer with fragments it needs to store */ XMEMSET(b, -1, sizeof(b)); /* handshake type */ b[idx++] = 11; /* length */ c32to24(10000, b + idx); idx += 3; /* message_seq */ msg_offset = idx; idx += 2; /* fragment_offset */ c32to24(5000, b + idx); idx += 3; /* fragment_length */ c32to24(100, b + idx); idx += 3; /* fragment contents */ idx += 100; for (; ret > 0 && msg_number < sendCountMax; msg_number++) { byte sendBuf[150]; int sendSz = sizeof(sendBuf); struct timespec delay; XMEMSET(&delay, 0, sizeof(delay)); delay.tv_nsec = 10000000; /* wait 0.01 seconds */ c16toa(msg_number, b + msg_offset); ret = sendSz = BuildTls13Message(ssl, sendBuf, sendSz, b, (int)idx, handshake, 0, 0, 0); if (sendSz > 0) ret = (int)send(fd, (MESSAGE_TYPE_CAST)sendBuf, (size_t)sendSz, 0); nanosleep(&delay, NULL); } } #endif static int test_wolfSSL_dtls_fragments(void) { EXPECT_DECLS; callback_functions func_cb_client; callback_functions func_cb_server; size_t i; struct test_params { method_provider client_meth; method_provider server_meth; ssl_callback spammer; } params[] = { #if !defined(WOLFSSL_NO_TLS12) {wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method, test_wolfSSL_dtls12_fragments_spammer}, #endif #ifdef WOLFSSL_DTLS13 {wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method, test_wolfSSL_dtls13_fragments_spammer}, #endif }; for (i = 0; i < sizeof(params)/sizeof(*params); i++) { XMEMSET(&func_cb_client, 0, sizeof(callback_functions)); XMEMSET(&func_cb_server, 0, sizeof(callback_functions)); func_cb_client.doUdp = func_cb_server.doUdp = 1; func_cb_server.method = params[i].server_meth; func_cb_client.method = params[i].client_meth; func_cb_client.ssl_ready = params[i].spammer; test_wolfSSL_client_server_nofail(&func_cb_client, &func_cb_server); /* If the client failed, check that the error it encountered was from * the server aborting, resulting in a socket error, fatal error or * reading a close notify alert. * * Under slow execution (e.g. valgrind + noasm), the server may * still be processing fragments when the client completes its * handshake and write, so the client may succeed -- in that * case return_code is TEST_SUCCESS and these checks don't apply. */ if (func_cb_client.return_code == TEST_FAIL) { if (func_cb_client.last_err != WC_NO_ERR_TRACE(SOCKET_ERROR_E) && func_cb_client.last_err != WOLFSSL_ERROR_ZERO_RETURN && func_cb_client.last_err != WC_NO_ERR_TRACE(FATAL_ERROR)) { ExpectIntEQ(func_cb_client.last_err, WC_NO_ERR_TRACE(SOCKET_ERROR_E)); } } /* Check the server returned an error indicating the msg buffer * was full. * * Under slow execution (e.g. valgrind + noasm), the real handshake * from wolfSSL_negotiate() may complete before enough spam fragments * accumulate to trigger DTLS_TOO_MANY_FRAGMENTS_E. Accept both * outcomes: server hit the fragment limit, or completed normally. */ if (func_cb_server.return_code == TEST_FAIL) { ExpectIntEQ(func_cb_server.last_err, WC_NO_ERR_TRACE(DTLS_TOO_MANY_FRAGMENTS_E)); } if (EXPECT_FAIL()) break; } return EXPECT_RESULT(); } static void test_wolfSSL_dtls_send_alert(WOLFSSL* ssl) { int fd, ret; byte alert_msg[] = { 0x15, /* alert type */ 0xfe, 0xfd, /* version */ 0x00, 0x00, /* epoch */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* seq number */ 0x00, 0x02, /* length */ 0x02, /* level: fatal */ 0x46 /* protocol version */ }; fd = wolfSSL_get_wfd(ssl); AssertIntGE(fd, 0); ret = (int)send(fd, (MESSAGE_TYPE_CAST)alert_msg, sizeof(alert_msg), 0); AssertIntGT(ret, 0); } static int _test_wolfSSL_ignore_alert_before_cookie(byte version12) { callback_functions client_cbs, server_cbs; XMEMSET(&client_cbs, 0, sizeof(client_cbs)); XMEMSET(&server_cbs, 0, sizeof(server_cbs)); client_cbs.doUdp = server_cbs.doUdp = 1; if (version12) { #if !defined(WOLFSSL_NO_TLS12) client_cbs.method = wolfDTLSv1_2_client_method; server_cbs.method = wolfDTLSv1_2_server_method; #else return TEST_SKIPPED; #endif } else { #ifdef WOLFSSL_DTLS13 client_cbs.method = wolfDTLSv1_3_client_method; server_cbs.method = wolfDTLSv1_3_server_method; #else return TEST_SKIPPED; #endif /* WOLFSSL_DTLS13 */ } client_cbs.ssl_ready = test_wolfSSL_dtls_send_alert; test_wolfSSL_client_server_nofail(&client_cbs, &server_cbs); if (!client_cbs.return_code) return TEST_FAIL; if (!server_cbs.return_code) return TEST_FAIL; return TEST_SUCCESS; } static int test_wolfSSL_ignore_alert_before_cookie(void) { int ret; ret =_test_wolfSSL_ignore_alert_before_cookie(0); if (ret != 0) return ret; ret =_test_wolfSSL_ignore_alert_before_cookie(1); if (ret != 0) return ret; return 0; } static void test_wolfSSL_send_bad_record(WOLFSSL* ssl) { int ret; int fd; byte bad_msg[] = { 0x17, /* app data */ 0xaa, 0xfd, /* bad version */ 0x00, 0x01, /* epoch 1 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, /* not seen seq number */ 0x00, 0x26, /* length: 38 bytes */ 0xae, 0x30, 0x31, 0xb1, 0xf1, 0xb9, 0x6f, 0xda, 0x17, 0x19, 0xd9, 0x57, 0xa9, 0x9d, 0x5c, 0x51, 0x9b, 0x53, 0x63, 0xa5, 0x24, 0x70, 0xa1, 0xae, 0xdf, 0x1c, 0xb9, 0xfc, 0xe3, 0xd7, 0x77, 0x6d, 0xb6, 0x89, 0x0f, 0x03, 0x18, 0x72 }; fd = wolfSSL_get_wfd(ssl); AssertIntGE(fd, 0); ret = (int)send(fd, (MESSAGE_TYPE_CAST)bad_msg, sizeof(bad_msg), 0); AssertIntEQ(ret, sizeof(bad_msg)); ret = wolfSSL_write(ssl, "badrecordtest", sizeof("badrecordtest")); AssertIntEQ(ret, sizeof("badrecordtest")); } static void test_wolfSSL_read_string(WOLFSSL* ssl) { byte buf[100]; int ret; ret = wolfSSL_read(ssl, buf, sizeof(buf)); AssertIntGT(ret, 0); AssertIntEQ(strcmp((char*)buf, "badrecordtest"), 0); } static int _test_wolfSSL_dtls_bad_record( method_provider client_method, method_provider server_method) { callback_functions client_cbs, server_cbs; XMEMSET(&client_cbs, 0, sizeof(client_cbs)); XMEMSET(&server_cbs, 0, sizeof(server_cbs)); client_cbs.doUdp = server_cbs.doUdp = 1; client_cbs.method = client_method; server_cbs.method = server_method; client_cbs.on_result = test_wolfSSL_send_bad_record; server_cbs.on_result = test_wolfSSL_read_string; test_wolfSSL_client_server_nofail(&client_cbs, &server_cbs); if (!client_cbs.return_code) return TEST_FAIL; if (!server_cbs.return_code) return TEST_FAIL; return TEST_SUCCESS; } static int test_wolfSSL_dtls_bad_record(void) { int ret = TEST_SUCCESS; #if !defined(WOLFSSL_NO_TLS12) ret = _test_wolfSSL_dtls_bad_record(wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method); #endif #ifdef WOLFSSL_DTLS13 if (ret == TEST_SUCCESS) { ret = _test_wolfSSL_dtls_bad_record(wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method); } #endif /* WOLFSSL_DTLS13 */ return ret; } #else static int test_wolfSSL_dtls_fragments(void) { return TEST_SKIPPED; } static int test_wolfSSL_ignore_alert_before_cookie(void) { return TEST_SKIPPED; } static int test_wolfSSL_dtls_bad_record(void) { return TEST_SKIPPED; } #endif #if defined(WOLFSSL_DTLS13) && !defined(WOLFSSL_TLS13_IGNORE_AEAD_LIMITS) && \ !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) && \ defined(HAVE_IO_TESTS_DEPENDENCIES) static volatile int test_AEAD_seq_num = 0; #ifdef WOLFSSL_NO_ATOMICS static volatile int test_AEAD_done = 0; #else wolfSSL_Atomic_Int test_AEAD_done = WOLFSSL_ATOMIC_INITIALIZER(0); #endif #ifdef WOLFSSL_MUTEX_INITIALIZER static wolfSSL_Mutex test_AEAD_mutex = WOLFSSL_MUTEX_INITIALIZER(test_AEAD_mutex); #endif static int test_AEAD_fail_decryption = 0; static int test_AEAD_cbiorecv(WOLFSSL *ssl, char *buf, int sz, void *ctx) { int fd = wolfSSL_get_fd(ssl); int ret = -1; if (fd >= 0 && (ret = (int)recv(fd, buf, sz, 0)) > 0) { if (test_AEAD_fail_decryption) { /* Modify the packet to trigger a decryption failure */ buf[ret/2] ^= 0xFF; if (test_AEAD_fail_decryption == 1) test_AEAD_fail_decryption = 0; } } (void)ctx; return ret; } static void test_AEAD_get_limits(WOLFSSL* ssl, w64wrapper* hardLimit, w64wrapper* keyUpdateLimit, w64wrapper* sendLimit) { if (sendLimit) w64Zero(sendLimit); switch (ssl->specs.bulk_cipher_algorithm) { case wolfssl_aes_gcm: if (sendLimit) *sendLimit = AEAD_AES_LIMIT; FALL_THROUGH; case wolfssl_chacha: if (hardLimit) *hardLimit = DTLS_AEAD_AES_GCM_CHACHA_FAIL_LIMIT; if (keyUpdateLimit) *keyUpdateLimit = DTLS_AEAD_AES_GCM_CHACHA_FAIL_KU_LIMIT; break; case wolfssl_aes_ccm: if (sendLimit) *sendLimit = DTLS_AEAD_AES_CCM_LIMIT; if (ssl->specs.aead_mac_size == AES_CCM_8_AUTH_SZ) { if (hardLimit) *hardLimit = DTLS_AEAD_AES_CCM_8_FAIL_LIMIT; if (keyUpdateLimit) *keyUpdateLimit = DTLS_AEAD_AES_CCM_8_FAIL_KU_LIMIT; } else { if (hardLimit) *hardLimit = DTLS_AEAD_AES_CCM_FAIL_LIMIT; if (keyUpdateLimit) *keyUpdateLimit = DTLS_AEAD_AES_CCM_FAIL_KU_LIMIT; } break; default: fprintf(stderr, "Unrecognized bulk cipher"); AssertFalse(1); break; } } static void test_AEAD_limit_client(WOLFSSL* ssl) { int ret; int i; int didReKey = 0; char msgBuf[20]; w64wrapper hardLimit; w64wrapper keyUpdateLimit; w64wrapper counter; w64wrapper sendLimit; test_AEAD_get_limits(ssl, &hardLimit, &keyUpdateLimit, &sendLimit); w64Zero(&counter); AssertTrue(w64Equal(Dtls13GetEpoch(ssl, ssl->dtls13Epoch)->dropCount, counter)); wolfSSL_SSLSetIORecv(ssl, test_AEAD_cbiorecv); for (i = 0; i < 10; i++) { /* Test some failed decryptions */ test_AEAD_fail_decryption = 1; w64Increment(&counter); ret = wolfSSL_read(ssl, msgBuf, sizeof(msgBuf)); /* Should succeed since decryption failures are dropped */ AssertIntGT(ret, 0); AssertTrue(w64Equal(Dtls13GetEpoch(ssl, ssl->dtls13PeerEpoch)->dropCount, counter)); } test_AEAD_fail_decryption = 1; Dtls13GetEpoch(ssl, ssl->dtls13PeerEpoch)->dropCount = keyUpdateLimit; w64Increment(&Dtls13GetEpoch(ssl, ssl->dtls13PeerEpoch)->dropCount); /* 100 read calls should be enough to complete the key update */ w64Zero(&counter); for (i = 0; i < 100; i++) { /* Key update should be sent and negotiated */ ret = wolfSSL_read(ssl, msgBuf, sizeof(msgBuf)); AssertIntGT(ret, 0); /* Epoch after one key update is 4 */ if (w64Equal(ssl->dtls13PeerEpoch, w64From32(0, 4)) && w64Equal(Dtls13GetEpoch(ssl, ssl->dtls13PeerEpoch)->dropCount, counter)) { didReKey = 1; break; } } AssertTrue(didReKey); if (!w64IsZero(sendLimit)) { /* Test the sending limit for AEAD ciphers */ #ifdef WOLFSSL_MUTEX_INITIALIZER (void)wc_LockMutex(&test_AEAD_mutex); #endif Dtls13GetEpoch(ssl, ssl->dtls13Epoch)->nextSeqNumber = sendLimit; test_AEAD_seq_num = 1; XMEMSET(msgBuf, 0, sizeof(msgBuf)); ret = wolfSSL_write(ssl, msgBuf, sizeof(msgBuf)); AssertIntGT(ret, 0); didReKey = 0; w64Zero(&counter); #ifdef WOLFSSL_MUTEX_INITIALIZER wc_UnLockMutex(&test_AEAD_mutex); #endif /* 100 read calls should be enough to complete the key update */ for (i = 0; i < 100; i++) { /* Key update should be sent and negotiated */ ret = wolfSSL_read(ssl, msgBuf, sizeof(msgBuf)); AssertIntGT(ret, 0); /* Epoch after another key update is 5 */ if (w64Equal(ssl->dtls13Epoch, w64From32(0, 5)) && w64Equal(Dtls13GetEpoch(ssl, ssl->dtls13Epoch)->dropCount, counter)) { didReKey = 1; break; } } AssertTrue(didReKey); } test_AEAD_fail_decryption = 2; Dtls13GetEpoch(ssl, ssl->dtls13PeerEpoch)->dropCount = hardLimit; w64Decrement(&Dtls13GetEpoch(ssl, ssl->dtls13PeerEpoch)->dropCount); /* Connection should fail with a DECRYPT_ERROR */ ret = wolfSSL_read(ssl, msgBuf, sizeof(msgBuf)); AssertIntEQ(ret, WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)); AssertIntEQ(wolfSSL_get_error(ssl, ret), WC_NO_ERR_TRACE(DECRYPT_ERROR)); #ifdef WOLFSSL_ATOMIC_INITIALIZER WOLFSSL_ATOMIC_STORE(test_AEAD_done, 1); #else test_AEAD_done = 1; #endif } int counter = 0; static void test_AEAD_limit_server(WOLFSSL* ssl) { char msgBuf[] = "Sending data"; int ret = WOLFSSL_SUCCESS; w64wrapper sendLimit; SOCKET_T fd = wolfSSL_get_fd(ssl); struct timespec delay; XMEMSET(&delay, 0, sizeof(delay)); delay.tv_nsec = 100000000; /* wait 0.1 seconds */ tcp_set_nonblocking(&fd); /* So that read doesn't block */ wolfSSL_dtls_set_using_nonblock(ssl, 1); test_AEAD_get_limits(ssl, NULL, NULL, &sendLimit); while (! #ifdef WOLFSSL_ATOMIC_INITIALIZER WOLFSSL_ATOMIC_LOAD(test_AEAD_done) #else test_AEAD_done #endif && ret > 0) { counter++; #ifdef WOLFSSL_MUTEX_INITIALIZER (void)wc_LockMutex(&test_AEAD_mutex); #endif if (test_AEAD_seq_num) { /* We need to update the seq number so that we can understand the * peer. Otherwise we will incorrectly interpret the seq number. */ Dtls13Epoch* e = Dtls13GetEpoch(ssl, ssl->dtls13PeerEpoch); AssertNotNull(e); e->nextPeerSeqNumber = sendLimit; test_AEAD_seq_num = 0; } #ifdef WOLFSSL_MUTEX_INITIALIZER wc_UnLockMutex(&test_AEAD_mutex); #endif (void)wolfSSL_read(ssl, msgBuf, sizeof(msgBuf)); ret = wolfSSL_write(ssl, msgBuf, sizeof(msgBuf)); nanosleep(&delay, NULL); } } static int test_wolfSSL_dtls_AEAD_limit(void) { callback_functions func_cb_client; callback_functions func_cb_server; XMEMSET(&func_cb_client, 0, sizeof(callback_functions)); XMEMSET(&func_cb_server, 0, sizeof(callback_functions)); func_cb_client.doUdp = func_cb_server.doUdp = 1; func_cb_server.method = wolfDTLSv1_3_server_method; func_cb_client.method = wolfDTLSv1_3_client_method; func_cb_server.on_result = test_AEAD_limit_server; func_cb_client.on_result = test_AEAD_limit_client; test_wolfSSL_client_server_nofail(&func_cb_client, &func_cb_server); if (!func_cb_client.return_code) return TEST_FAIL; if (!func_cb_server.return_code) return TEST_FAIL; return TEST_SUCCESS; } #else static int test_wolfSSL_dtls_AEAD_limit(void) { return TEST_SKIPPED; } #endif #if defined(WOLFSSL_DTLS) && \ defined(HAVE_IO_TESTS_DEPENDENCIES) && !defined(SINGLE_THREADED) && \ !defined(DEBUG_VECTOR_REGISTER_ACCESS_FUZZING) static void test_wolfSSL_dtls_send_ch(WOLFSSL* ssl) { int fd, ret; byte ch_msg[] = { 0x16, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfa, 0x01, 0x00, 0x01, 0xee, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xee, 0xfe, 0xfd, 0xc0, 0xca, 0xb5, 0x6f, 0x3d, 0x23, 0xcc, 0x53, 0x9a, 0x67, 0x17, 0x70, 0xd3, 0xfb, 0x23, 0x16, 0x9e, 0x4e, 0xd6, 0x7e, 0x29, 0xab, 0xfa, 0x4c, 0xa5, 0x84, 0x95, 0xc3, 0xdb, 0x21, 0x9a, 0x52, 0x00, 0x00, 0x00, 0x36, 0x13, 0x01, 0x13, 0x02, 0x13, 0x03, 0xc0, 0x2c, 0xc0, 0x2b, 0xc0, 0x30, 0xc0, 0x2f, 0x00, 0x9f, 0x00, 0x9e, 0xcc, 0xa9, 0xcc, 0xa8, 0xcc, 0xaa, 0xc0, 0x27, 0xc0, 0x23, 0xc0, 0x28, 0xc0, 0x24, 0xc0, 0x0a, 0xc0, 0x09, 0xc0, 0x14, 0xc0, 0x13, 0x00, 0x6b, 0x00, 0x67, 0x00, 0x39, 0x00, 0x33, 0xcc, 0x14, 0xcc, 0x13, 0xcc, 0x15, 0x01, 0x00, 0x01, 0x8e, 0x00, 0x2b, 0x00, 0x03, 0x02, 0xfe, 0xfc, 0x00, 0x0d, 0x00, 0x20, 0x00, 0x1e, 0x06, 0x03, 0x05, 0x03, 0x04, 0x03, 0x02, 0x03, 0x08, 0x06, 0x08, 0x0b, 0x08, 0x05, 0x08, 0x0a, 0x08, 0x04, 0x08, 0x09, 0x06, 0x01, 0x05, 0x01, 0x04, 0x01, 0x03, 0x01, 0x02, 0x01, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x0a, 0x00, 0x19, 0x00, 0x18, 0x00, 0x17, 0x00, 0x15, 0x01, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x33, 0x01, 0x4b, 0x01, 0x49, 0x00, 0x17, 0x00, 0x41, 0x04, 0x96, 0xcb, 0x2e, 0x4e, 0xd9, 0x88, 0x71, 0xc7, 0xf3, 0x1a, 0x16, 0xdd, 0x7a, 0x7c, 0xf7, 0x67, 0x8a, 0x5d, 0x9a, 0x55, 0xa6, 0x4a, 0x90, 0xd9, 0xfb, 0xc7, 0xfb, 0xbe, 0x09, 0xa9, 0x8a, 0xb5, 0x7a, 0xd1, 0xde, 0x83, 0x74, 0x27, 0x31, 0x1c, 0xaa, 0xae, 0xef, 0x58, 0x43, 0x13, 0x7d, 0x15, 0x4d, 0x7f, 0x68, 0xf6, 0x8a, 0x38, 0xef, 0x0e, 0xb3, 0xcf, 0xb8, 0x4a, 0xa9, 0xb4, 0xd7, 0xcb, 0x01, 0x00, 0x01, 0x00, 0x1d, 0x0a, 0x22, 0x8a, 0xd1, 0x78, 0x85, 0x1e, 0x5a, 0xe1, 0x1d, 0x1e, 0xb7, 0x2d, 0xbc, 0x5f, 0x52, 0xbc, 0x97, 0x5d, 0x8b, 0x6a, 0x8b, 0x9d, 0x1e, 0xb1, 0xfc, 0x8a, 0xb2, 0x56, 0xcd, 0xed, 0x4b, 0xfb, 0x66, 0x3f, 0x59, 0x3f, 0x15, 0x5d, 0x09, 0x9e, 0x2f, 0x60, 0x5b, 0x31, 0x81, 0x27, 0xf0, 0x1c, 0xda, 0xcd, 0x48, 0x66, 0xc6, 0xbb, 0x25, 0xf0, 0x5f, 0xda, 0x4c, 0xcf, 0x1d, 0x88, 0xc8, 0xda, 0x1b, 0x53, 0xea, 0xbd, 0xce, 0x6d, 0xf6, 0x4a, 0x76, 0xdb, 0x75, 0x99, 0xaf, 0xcf, 0x76, 0x4a, 0xfb, 0xe3, 0xef, 0xb2, 0xcb, 0xae, 0x4a, 0xc0, 0xe8, 0x63, 0x1f, 0xd6, 0xe8, 0xe6, 0x45, 0xf9, 0xea, 0x0d, 0x06, 0x19, 0xfc, 0xb1, 0xfd, 0x5d, 0x92, 0x89, 0x7b, 0xc7, 0x9f, 0x1a, 0xb3, 0x2b, 0xc7, 0xad, 0x0e, 0xfb, 0x13, 0x41, 0x83, 0x84, 0x58, 0x3a, 0x25, 0xb9, 0x49, 0x35, 0x1c, 0x23, 0xcb, 0xd6, 0xe7, 0xc2, 0x8c, 0x4b, 0x2a, 0x73, 0xa1, 0xdf, 0x4f, 0x73, 0x9b, 0xb3, 0xd2, 0xb2, 0x95, 0x00, 0x3c, 0x26, 0x09, 0x89, 0x71, 0x05, 0x39, 0xc8, 0x98, 0x8f, 0xed, 0x32, 0x15, 0x78, 0xcd, 0xd3, 0x7e, 0xfb, 0x5a, 0x78, 0x2a, 0xdc, 0xca, 0x20, 0x09, 0xb5, 0x14, 0xf9, 0xd4, 0x58, 0xf6, 0x69, 0xf8, 0x65, 0x9f, 0xb7, 0xe4, 0x93, 0xf1, 0xa3, 0x84, 0x7e, 0x1b, 0x23, 0x5d, 0xea, 0x59, 0x3e, 0x4d, 0xca, 0xfd, 0xa5, 0x55, 0xdd, 0x99, 0xb5, 0x02, 0xf8, 0x0d, 0xe5, 0xf4, 0x06, 0xb0, 0x43, 0x9e, 0x2e, 0xbf, 0x05, 0x33, 0x65, 0x7b, 0x13, 0x8c, 0xf9, 0x16, 0x4d, 0xc5, 0x15, 0x0b, 0x40, 0x2f, 0x66, 0x94, 0xf2, 0x43, 0x95, 0xe7, 0xa9, 0xb6, 0x39, 0x99, 0x73, 0xb3, 0xb0, 0x06, 0xfe, 0x52, 0x9e, 0x57, 0xba, 0x75, 0xfd, 0x76, 0x7b, 0x20, 0x31, 0x68, 0x4c }; fd = wolfSSL_get_wfd(ssl); AssertIntGE(fd, 0); ret = (int)send(fd, (MESSAGE_TYPE_CAST)ch_msg, sizeof(ch_msg), 0); AssertIntGT(ret, 0); /* consume the HRR otherwise handshake will fail */ ret = (int)recv(fd, (MESSAGE_TYPE_CAST)ch_msg, sizeof(ch_msg), 0); AssertIntGT(ret, 0); } #if defined(WOLFSSL_DTLS13) && defined(WOLFSSL_SEND_HRR_COOKIE) static void test_wolfSSL_dtls_send_ch_with_invalid_cookie(WOLFSSL* ssl) { int fd, ret; byte ch_msh_invalid_cookie[] = { 0x16, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x4e, 0x01, 0x00, 0x02, 0x42, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x42, 0xfe, 0xfd, 0x69, 0xca, 0x77, 0x60, 0x6f, 0xfc, 0xd1, 0x5b, 0x60, 0x5d, 0xf1, 0xa6, 0x5c, 0x44, 0x71, 0xae, 0xca, 0x62, 0x19, 0x0c, 0xb6, 0xf7, 0x2c, 0xa6, 0xd5, 0xd2, 0x99, 0x9d, 0x18, 0xae, 0xac, 0x11, 0x00, 0x00, 0x00, 0x36, 0x13, 0x01, 0x13, 0x02, 0x13, 0x03, 0xc0, 0x2c, 0xc0, 0x2b, 0xc0, 0x30, 0xc0, 0x2f, 0x00, 0x9f, 0x00, 0x9e, 0xcc, 0xa9, 0xcc, 0xa8, 0xcc, 0xaa, 0xc0, 0x27, 0xc0, 0x23, 0xc0, 0x28, 0xc0, 0x24, 0xc0, 0x0a, 0xc0, 0x09, 0xc0, 0x14, 0xc0, 0x13, 0x00, 0x6b, 0x00, 0x67, 0x00, 0x39, 0x00, 0x33, 0xcc, 0x14, 0xcc, 0x13, 0xcc, 0x15, 0x01, 0x00, 0x01, 0xe2, 0x00, 0x2b, 0x00, 0x03, 0x02, 0xfe, 0xfc, 0x00, 0x0d, 0x00, 0x20, 0x00, 0x1e, 0x06, 0x03, 0x05, 0x03, 0x04, 0x03, 0x02, 0x03, 0x08, 0x06, 0x08, 0x0b, 0x08, 0x05, 0x08, 0x0a, 0x08, 0x04, 0x08, 0x09, 0x06, 0x01, 0x05, 0x01, 0x04, 0x01, 0x03, 0x01, 0x02, 0x01, 0x00, 0x2c, 0x00, 0x45, 0x00, 0x43, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x2d, 0x00, 0x03, 0x02, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x0a, 0x00, 0x19, 0x00, 0x18, 0x00, 0x17, 0x00, 0x15, 0x01, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x33, 0x01, 0x4b, 0x01, 0x49, 0x00, 0x17, 0x00, 0x41, 0x04, 0x7c, 0x5a, 0xc2, 0x5a, 0xfd, 0xcd, 0x2b, 0x08, 0xb2, 0xeb, 0x8e, 0xc0, 0x02, 0x03, 0x9d, 0xb1, 0xc1, 0x0d, 0x7b, 0x7f, 0x46, 0x43, 0xdf, 0xf3, 0xee, 0x2b, 0x78, 0x0e, 0x29, 0x8c, 0x42, 0x11, 0x2c, 0xde, 0xd7, 0x41, 0x0f, 0x28, 0x94, 0x80, 0x41, 0x70, 0xc4, 0x17, 0xfd, 0x6d, 0xfa, 0xee, 0x9a, 0xf2, 0xc4, 0x15, 0x4c, 0x5f, 0x54, 0xb6, 0x78, 0x6e, 0xf9, 0x63, 0x27, 0x33, 0xb8, 0x7b, 0x01, 0x00, 0x01, 0x00, 0xd4, 0x46, 0x62, 0x9c, 0xbf, 0x8f, 0x1b, 0x65, 0x9b, 0xf0, 0x29, 0x64, 0xd8, 0x50, 0x0e, 0x74, 0xf1, 0x58, 0x10, 0xc9, 0xd9, 0x82, 0x5b, 0xd9, 0xbe, 0x14, 0xdf, 0xde, 0x86, 0xb4, 0x2e, 0x15, 0xee, 0x4f, 0xf6, 0x74, 0x9e, 0x59, 0x11, 0x36, 0x2d, 0xb9, 0x67, 0xaa, 0x5a, 0x09, 0x9b, 0x45, 0xf1, 0x01, 0x4c, 0x4e, 0xf6, 0xda, 0x6a, 0xae, 0xa7, 0x73, 0x7b, 0x2e, 0xb6, 0x24, 0x89, 0x99, 0xb7, 0x52, 0x16, 0x62, 0x0a, 0xab, 0x58, 0xf8, 0x3f, 0x10, 0x5b, 0x83, 0xfd, 0x7b, 0x81, 0x77, 0x81, 0x8d, 0xef, 0x24, 0x56, 0x6d, 0xba, 0x49, 0xd4, 0x8b, 0xb5, 0xa0, 0xb1, 0xc9, 0x8c, 0x32, 0x95, 0x1c, 0x5e, 0x0a, 0x4b, 0xf6, 0x00, 0x50, 0x0a, 0x87, 0x99, 0x59, 0xcf, 0x6f, 0x9d, 0x02, 0xd0, 0x1b, 0xa1, 0x96, 0x45, 0x28, 0x76, 0x40, 0x33, 0x28, 0xc9, 0xa1, 0xfd, 0x46, 0xab, 0x2c, 0x9e, 0x5e, 0xc6, 0x74, 0x19, 0x9a, 0xf5, 0x9b, 0x51, 0x11, 0x4f, 0xc8, 0xb9, 0x99, 0x6b, 0x4e, 0x3e, 0x31, 0x64, 0xb4, 0x92, 0xf4, 0x0d, 0x41, 0x4b, 0x2c, 0x65, 0x23, 0xf7, 0x47, 0xe3, 0xa5, 0x2e, 0xe4, 0x9c, 0x2b, 0xc9, 0x41, 0x22, 0x83, 0x8a, 0x23, 0xef, 0x29, 0x7e, 0x4f, 0x3f, 0xa3, 0xbf, 0x73, 0x2b, 0xd7, 0xcc, 0xc8, 0xc6, 0xe9, 0xbc, 0x01, 0xb7, 0x32, 0x63, 0xd4, 0x7e, 0x7f, 0x9a, 0xaf, 0x5f, 0x05, 0x31, 0x53, 0xd6, 0x1f, 0xa2, 0xd0, 0xdf, 0x67, 0x56, 0xf1, 0x9c, 0x4a, 0x9d, 0x83, 0xb4, 0xef, 0xb3, 0xf2, 0xcc, 0xf1, 0x91, 0x6c, 0x47, 0xc3, 0x8b, 0xd0, 0x92, 0x79, 0x3d, 0xa0, 0xc0, 0x3a, 0x57, 0x26, 0x6d, 0x0a, 0xad, 0x5f, 0xad, 0xb4, 0x74, 0x48, 0x4a, 0x51, 0xe1, 0xb5, 0x82, 0x0a, 0x4c, 0x4f, 0x9d, 0xaf, 0xee, 0x5a, 0xa2, 0x4d, 0x4d, 0x5f, 0xe0, 0x17, 0x00, 0x23, 0x00, 0x00 }; byte alert_reply[50]; byte expected_alert_reply[] = { 0x15, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, 0x2f }; fd = wolfSSL_get_wfd(ssl); if (fd >= 0) { ret = (int)send(fd, (MESSAGE_TYPE_CAST)ch_msh_invalid_cookie, sizeof(ch_msh_invalid_cookie), 0); AssertIntGT(ret, 0); /* should reply with an illegal_parameter reply */ ret = (int)recv(fd, (MESSAGE_TYPE_CAST)alert_reply, sizeof(alert_reply), 0); AssertIntEQ(ret, sizeof(expected_alert_reply)); AssertIntEQ(XMEMCMP(alert_reply, expected_alert_reply, sizeof(expected_alert_reply)), 0); } } #endif static word32 test_wolfSSL_dtls_stateless_HashWOLFSSL(const WOLFSSL* ssl) { #ifndef NO_MD5 enum wc_HashType hashType = WC_HASH_TYPE_MD5; #elif !defined(NO_SHA) enum wc_HashType hashType = WC_HASH_TYPE_SHA; #elif !defined(NO_SHA256) enum wc_HashType hashType = WC_HASH_TYPE_SHA256; #else #error "We need a digest to hash the WOLFSSL object" #endif byte hashBuf[WC_MAX_DIGEST_SIZE]; wc_HashAlg hash; const TLSX* exts = ssl->extensions; WOLFSSL sslCopy; /* Use a copy to omit certain fields */ #ifndef WOLFSSL_SMALL_STACK_CACHE HS_Hashes* hsHashes = ssl->hsHashes; /* Is re-allocated in * InitHandshakeHashes */ #endif XMEMCPY(&sslCopy, ssl, sizeof(*ssl)); XMEMSET(hashBuf, 0, sizeof(hashBuf)); /* Following fields are not important to compare */ XMEMSET(sslCopy.buffers.inputBuffer.staticBuffer, 0, STATIC_BUFFER_LEN); sslCopy.buffers.inputBuffer.buffer = NULL; sslCopy.buffers.inputBuffer.bufferSize = 0; sslCopy.buffers.inputBuffer.dynamicFlag = 0; sslCopy.buffers.inputBuffer.offset = 0; XMEMSET(sslCopy.buffers.outputBuffer.staticBuffer, 0, STATIC_BUFFER_LEN); sslCopy.buffers.outputBuffer.buffer = NULL; sslCopy.buffers.outputBuffer.bufferSize = 0; sslCopy.buffers.outputBuffer.dynamicFlag = 0; sslCopy.buffers.outputBuffer.offset = 0; sslCopy.error = 0; sslCopy.curSize = 0; sslCopy.curStartIdx = 0; sslCopy.keys.curSeq_lo = 0; XMEMSET(&sslCopy.curRL, 0, sizeof(sslCopy.curRL)); #ifdef WOLFSSL_DTLS13 XMEMSET(&sslCopy.keys.curSeq, 0, sizeof(sslCopy.keys.curSeq)); sslCopy.dtls13FastTimeout = 0; #endif sslCopy.keys.dtls_peer_handshake_number = 0; XMEMSET(&sslCopy.alert_history, 0, sizeof(sslCopy.alert_history)); sslCopy.hsHashes = NULL; #if !defined(WOLFSSL_NO_CLIENT_AUTH) && \ ((defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)) || \ (defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \ (defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH))) sslCopy.options.cacheMessages = 0; #endif #ifdef WOLFSSL_ASYNC_IO #ifdef WOLFSSL_ASYNC_CRYPT sslCopy.asyncDev = NULL; #endif sslCopy.async = NULL; #endif AssertIntEQ(wc_HashInit(&hash, hashType), 0); AssertIntEQ(wc_HashUpdate(&hash, hashType, (byte*)&sslCopy, sizeof(sslCopy)), 0); /* hash extension list */ while (exts != NULL) { AssertIntEQ(wc_HashUpdate(&hash, hashType, (byte*)exts, sizeof(*exts)), 0); exts = exts->next; } /* Hash suites */ if (sslCopy.suites != NULL) { AssertIntEQ(wc_HashUpdate(&hash, hashType, (byte*)sslCopy.suites, sizeof(struct Suites)), 0); } #ifdef WOLFSSL_SMALL_STACK_CACHE /* with WOLFSSL_SMALL_STACK_CACHE, the SHA-2 objects always differ after * initialization because of cached W and (for SHA512) X buffers. */ #else /* Hash hsHashes */ AssertIntEQ(wc_HashUpdate(&hash, hashType, (byte*)hsHashes, sizeof(*hsHashes)), 0); #endif AssertIntEQ(wc_HashFinal(&hash, hashType, hashBuf), 0); AssertIntEQ(wc_HashFree(&hash, hashType), 0); return MakeWordFromHash(hashBuf); } static CallbackIORecv test_wolfSSL_dtls_compare_stateless_cb; static int test_wolfSSL_dtls_compare_stateless_cb_call_once; static int test_wolfSSL_dtls_compare_stateless_read_cb_once(WOLFSSL *ssl, char *buf, int sz, void *ctx) { if (test_wolfSSL_dtls_compare_stateless_cb_call_once) { test_wolfSSL_dtls_compare_stateless_cb_call_once = 0; return test_wolfSSL_dtls_compare_stateless_cb(ssl, buf, sz, ctx); } else { return WOLFSSL_CBIO_ERR_WANT_READ; } } static void test_wolfSSL_dtls_compare_stateless(WOLFSSL* ssl) { /* Compare the ssl object before and after one ClientHello msg */ SOCKET_T fd = wolfSSL_get_fd(ssl); int res; int err; word32 initHash; test_wolfSSL_dtls_compare_stateless_cb = ssl->CBIORecv; test_wolfSSL_dtls_compare_stateless_cb_call_once = 1; wolfSSL_dtls_set_using_nonblock(ssl, 1); ssl->CBIORecv = test_wolfSSL_dtls_compare_stateless_read_cb_once; initHash = test_wolfSSL_dtls_stateless_HashWOLFSSL(ssl); (void)initHash; res = tcp_select(fd, 5); /* We are expecting a msg. A timeout indicates failure. */ AssertIntEQ(res, TEST_RECV_READY); res = wolfSSL_accept(ssl); err = wolfSSL_get_error(ssl, res); AssertIntEQ(res, WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)); AssertIntEQ(err, WOLFSSL_ERROR_WANT_READ); AssertIntEQ(initHash, test_wolfSSL_dtls_stateless_HashWOLFSSL(ssl)); wolfSSL_dtls_set_using_nonblock(ssl, 0); ssl->CBIORecv = test_wolfSSL_dtls_compare_stateless_cb; } #if defined(WOLFSSL_DTLS13) && defined(WOLFSSL_SEND_HRR_COOKIE) static void test_wolfSSL_dtls_enable_hrrcookie(WOLFSSL* ssl) { int ret; ret = wolfSSL_send_hrr_cookie(ssl, NULL, 0); AssertIntEQ(ret, WOLFSSL_SUCCESS); test_wolfSSL_dtls_compare_stateless(ssl); } #endif static int test_wolfSSL_dtls_stateless(void) { callback_functions client_cbs, server_cbs; size_t i; struct { method_provider client_meth; method_provider server_meth; ssl_callback client_ssl_ready; ssl_callback server_ssl_ready; } test_params[] = { #if !defined(WOLFSSL_NO_TLS12) {wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method, test_wolfSSL_dtls_send_ch, test_wolfSSL_dtls_compare_stateless}, #endif #if defined(WOLFSSL_DTLS13) && defined(WOLFSSL_SEND_HRR_COOKIE) {wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method, test_wolfSSL_dtls_send_ch, test_wolfSSL_dtls_enable_hrrcookie}, {wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method, test_wolfSSL_dtls_send_ch_with_invalid_cookie, test_wolfSSL_dtls_enable_hrrcookie}, #endif }; if (0 == sizeof(test_params)){ return TEST_SKIPPED; } for (i = 0; i < sizeof(test_params)/sizeof(*test_params); i++) { XMEMSET(&client_cbs, 0, sizeof(client_cbs)); XMEMSET(&server_cbs, 0, sizeof(server_cbs)); client_cbs.doUdp = server_cbs.doUdp = 1; client_cbs.method = test_params[i].client_meth; server_cbs.method = test_params[i].server_meth; client_cbs.ssl_ready = test_params[i].client_ssl_ready; server_cbs.ssl_ready = test_params[i].server_ssl_ready; test_wolfSSL_client_server_nofail(&client_cbs, &server_cbs); if (!client_cbs.return_code) return TEST_FAIL; if (!server_cbs.return_code) return TEST_FAIL; } return TEST_SUCCESS; } /* DTLS stateless API handling multiple CHs with different HRR groups */ static int test_wolfSSL_dtls_stateless_hrr_group(void) { EXPECT_DECLS; #if defined(WOLFSSL_SEND_HRR_COOKIE) size_t i; word32 initHash; struct { method_provider client_meth; method_provider server_meth; } params[] = { #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_DTLS13) { wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method }, #endif #if !defined(WOLFSSL_NO_TLS12) && defined(WOLFSSL_DTLS) { wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method }, #endif }; for (i = 0; i < XELEM_CNT(params) && !EXPECT_FAIL(); i++) { WOLFSSL_CTX *ctx_s = NULL, *ctx_c = NULL; WOLFSSL *ssl_s = NULL, *ssl_c = NULL, *ssl_c2 = NULL; struct test_memio_ctx test_ctx; int groups_1[] = { WOLFSSL_ECC_SECP256R1, WOLFSSL_ECC_SECP384R1, WOLFSSL_ECC_SECP521R1 }; int groups_2[] = { WOLFSSL_ECC_SECP384R1, WOLFSSL_ECC_SECP521R1 }; char hrrBuf[1000]; int hrrSz = sizeof(hrrBuf); XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, params[i].client_meth, params[i].server_meth), 0); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, NULL, &ssl_c2, NULL, params[i].client_meth, params[i].server_meth), 0); wolfSSL_SetLoggingPrefix("server"); wolfSSL_dtls_set_using_nonblock(ssl_s, 1); initHash = test_wolfSSL_dtls_stateless_HashWOLFSSL(ssl_s); /* Set groups and disable key shares. This ensures that only the given * groups are in the SupportedGroups extension and that an empty key * share extension is sent in the initial ClientHello of each session. * This triggers the server to send a HelloRetryRequest with the first * group in the SupportedGroups extension selected. */ wolfSSL_SetLoggingPrefix("client1"); ExpectIntEQ(wolfSSL_set_groups(ssl_c, groups_1, 3), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_NoKeyShares(ssl_c), WOLFSSL_SUCCESS); wolfSSL_SetLoggingPrefix("client2"); ExpectIntEQ(wolfSSL_set_groups(ssl_c2, groups_2, 2), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_NoKeyShares(ssl_c2), WOLFSSL_SUCCESS); /* Start handshake, send first ClientHello */ wolfSSL_SetLoggingPrefix("client1"); ExpectIntEQ(wolfSSL_connect(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); /* Read first ClientHello, send HRR with WOLFSSL_ECC_SECP256R1 */ wolfSSL_SetLoggingPrefix("server"); ExpectIntEQ(wolfDTLS_accept_stateless(ssl_s), 0); ExpectIntEQ(test_memio_copy_message(&test_ctx, 1, hrrBuf, &hrrSz, 0), 0); ExpectIntGT(hrrSz, 0); ExpectIntEQ(initHash, test_wolfSSL_dtls_stateless_HashWOLFSSL(ssl_s)); test_memio_clear_buffer(&test_ctx, 1); /* Send second ClientHello */ wolfSSL_SetLoggingPrefix("client2"); ExpectIntEQ(wolfSSL_connect(ssl_c2), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c2, -1), WOLFSSL_ERROR_WANT_READ); /* Read second ClientHello, send HRR now with WOLFSSL_ECC_SECP384R1 */ wolfSSL_SetLoggingPrefix("server"); ExpectIntEQ(wolfDTLS_accept_stateless(ssl_s), 0); ExpectIntEQ(initHash, test_wolfSSL_dtls_stateless_HashWOLFSSL(ssl_s)); test_memio_clear_buffer(&test_ctx, 1); /* Complete first handshake with WOLFSSL_ECC_SECP256R1 */ wolfSSL_SetLoggingPrefix("client1"); ExpectIntEQ(test_memio_inject_message(&test_ctx, 1, hrrBuf, hrrSz), 0); ExpectIntEQ(wolfSSL_connect(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); wolfSSL_SetLoggingPrefix("server"); ExpectIntEQ(wolfDTLS_accept_stateless(ssl_s), WOLFSSL_SUCCESS); ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); wolfSSL_free(ssl_s); wolfSSL_free(ssl_c); wolfSSL_free(ssl_c2); wolfSSL_CTX_free(ctx_s); wolfSSL_CTX_free(ctx_c); } #endif /* WOLFSSL_SEND_HRR_COOKIE */ return EXPECT_RESULT(); } #else static int test_wolfSSL_dtls_stateless(void) { return TEST_SKIPPED; } static int test_wolfSSL_dtls_stateless_hrr_group(void) { return TEST_SKIPPED; } #endif /* WOLFSSL_DTLS13 && WOLFSSL_SEND_HRR_COOKIE && * HAVE_IO_TESTS_DEPENDENCIES && !SINGLE_THREADED */ #if defined(HAVE_KEYING_MATERIAL) && defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) static int test_export_keying_material_cb(WOLFSSL_CTX *ctx, WOLFSSL *ssl) { EXPECT_DECLS; byte ekm[100] = {0}; (void)ctx; /* Success Cases */ ExpectIntEQ(wolfSSL_export_keying_material(ssl, ekm, sizeof(ekm), "Test label", XSTR_SIZEOF("Test label"), NULL, 0, 0), 1); ExpectIntEQ(wolfSSL_export_keying_material(ssl, ekm, sizeof(ekm), "Test label", XSTR_SIZEOF("Test label"), NULL, 0, 1), 1); /* Use some random context */ ExpectIntEQ(wolfSSL_export_keying_material(ssl, ekm, sizeof(ekm), "Test label", XSTR_SIZEOF("Test label"), ekm, 10, 1), 1); /* Failure cases */ ExpectIntEQ(wolfSSL_export_keying_material(ssl, ekm, sizeof(ekm), "client finished", XSTR_SIZEOF("client finished"), NULL, 0, 0), 0); ExpectIntEQ(wolfSSL_export_keying_material(ssl, ekm, sizeof(ekm), "server finished", XSTR_SIZEOF("server finished"), NULL, 0, 0), 0); ExpectIntEQ(wolfSSL_export_keying_material(ssl, ekm, sizeof(ekm), "master secret", XSTR_SIZEOF("master secret"), NULL, 0, 0), 0); ExpectIntEQ(wolfSSL_export_keying_material(ssl, ekm, sizeof(ekm), "extended master secret", XSTR_SIZEOF("extended master secret"), NULL, 0, 0), 0); ExpectIntEQ(wolfSSL_export_keying_material(ssl, ekm, sizeof(ekm), "key expansion", XSTR_SIZEOF("key expansion"), NULL, 0, 0), 0); /* contextLen overflow: values exceeding UINT16_MAX must be rejected to * prevent integer overflow in seedLen calculation (ZD #21242). */ ExpectIntEQ(wolfSSL_export_keying_material(ssl, ekm, sizeof(ekm), "Test label", XSTR_SIZEOF("Test label"), ekm, (size_t)0xFFFF + 1, 1), 0); return EXPECT_RESULT(); } static int test_export_keying_material_ssl_cb(WOLFSSL* ssl) { wolfSSL_KeepArrays(ssl); return TEST_SUCCESS; } static int test_export_keying_material(void) { EXPECT_DECLS; test_ssl_cbf serverCb; test_ssl_cbf clientCb; XMEMSET(&serverCb, 0, sizeof(serverCb)); XMEMSET(&clientCb, 0, sizeof(clientCb)); clientCb.ssl_ready = test_export_keying_material_ssl_cb; ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&clientCb, &serverCb, test_export_keying_material_cb), TEST_SUCCESS); return EXPECT_RESULT(); } #endif /* HAVE_KEYING_MATERIAL */ static int test_wolfSSL_THREADID_hash(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) CRYPTO_THREADID id; CRYPTO_THREADID_current(NULL); /* Hash result is word32. */ ExpectTrue(CRYPTO_THREADID_hash(NULL) == 0UL); XMEMSET(&id, 0, sizeof(id)); ExpectTrue(CRYPTO_THREADID_hash(&id) == 0UL); #endif /* OPENSSL_EXTRA */ return EXPECT_RESULT(); } static int test_wolfSSL_set_ecdh_auto(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) WOLFSSL* ssl = NULL; ExpectIntEQ(SSL_set_ecdh_auto(NULL,0), 1); ExpectIntEQ(SSL_set_ecdh_auto(NULL,1), 1); ExpectIntEQ(SSL_set_ecdh_auto(ssl,0), 1); ExpectIntEQ(SSL_set_ecdh_auto(ssl,1), 1); #endif /* OPENSSL_EXTRA */ return EXPECT_RESULT(); } static int test_wolfSSL_CTX_set_ecdh_auto(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) WOLFSSL_CTX* ctx = NULL; ExpectIntEQ(SSL_CTX_set_ecdh_auto(NULL,0), 1); ExpectIntEQ(SSL_CTX_set_ecdh_auto(NULL,1), 1); ExpectIntEQ(SSL_CTX_set_ecdh_auto(ctx,0), 1); ExpectIntEQ(SSL_CTX_set_ecdh_auto(ctx,1), 1); #endif /* OPENSSL_EXTRA */ return EXPECT_RESULT(); } #if defined(OPENSSL_EXTRA) && defined(WOLFSSL_ERROR_CODE_OPENSSL) && \ defined(HAVE_IO_TESTS_DEPENDENCIES) && !defined(WOLFSSL_NO_TLS12) static THREAD_RETURN WOLFSSL_THREAD SSL_read_test_server_thread(void* args) { EXPECT_DECLS; callback_functions* callbacks = NULL; WOLFSSL_CTX* ctx = NULL; WOLFSSL* ssl = NULL; SOCKET_T sfd = 0; SOCKET_T cfd = 0; word16 port; char msg[] = "I hear you fa shizzle!"; int len = (int) XSTRLEN(msg); char input[1024]; int ret = 0; int err = 0; if (!args) WOLFSSL_RETURN_FROM_THREAD(0); ((func_args*)args)->return_code = TEST_FAIL; callbacks = ((func_args*)args)->callbacks; ctx = wolfSSL_CTX_new(callbacks->method()); #if defined(USE_WINDOWS_API) port = ((func_args*)args)->signal->port; #else /* Let tcp_listen assign port */ port = 0; #endif #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); #endif ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_use_certificate_file(ctx, svrCertFile, WOLFSSL_FILETYPE_PEM)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, WOLFSSL_FILETYPE_PEM)); #if !defined(NO_FILESYSTEM) && !defined(NO_DH) ExpectIntEQ(wolfSSL_CTX_SetTmpDH_file(ctx, dhParamFile, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); #elif !defined(NO_DH) SetDHCtx(ctx); /* will repick suites with DHE, higher priority than PSK */ #endif if (callbacks->ctx_ready) callbacks->ctx_ready(ctx); ssl = wolfSSL_new(ctx); ExpectNotNull(ssl); /* listen and accept */ tcp_accept(&sfd, &cfd, (func_args*)args, port, 0, 0, 0, 0, 1, 0, 0); CloseSocket(sfd); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_set_fd(ssl, cfd)); if (callbacks->ssl_ready) callbacks->ssl_ready(ssl); if (EXPECT_SUCCESS()) { do { err = 0; /* Reset error */ ret = wolfSSL_accept(ssl); if (ret != WOLFSSL_SUCCESS) { err = wolfSSL_get_error(ssl, 0); } } while (ret != WOLFSSL_SUCCESS && err == WC_NO_ERR_TRACE(WC_PENDING_E)); } ExpectIntEQ(ret, WOLFSSL_SUCCESS); /* read and write data */ XMEMSET(input, 0, sizeof(input)); while (EXPECT_SUCCESS()) { ret = wolfSSL_read(ssl, input, sizeof(input)); if (ret > 0) { break; } else { err = wolfSSL_get_error(ssl,ret); if (err == WOLFSSL_ERROR_WANT_READ) { continue; } break; } } if (EXPECT_SUCCESS() && (err == WOLFSSL_ERROR_ZERO_RETURN)) { do { ret = wolfSSL_write(ssl, msg, len); if (ret > 0) { break; } } while (ret < 0); } /* bidirectional shutdown */ while (EXPECT_SUCCESS()) { ret = wolfSSL_shutdown(ssl); ExpectIntNE(ret, WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)); if (ret == WOLFSSL_SUCCESS) { break; } } if (EXPECT_SUCCESS()) { /* wait for the peer to disconnect the tcp connection */ do { ret = wolfSSL_read(ssl, input, sizeof(input)); err = wolfSSL_get_error(ssl, ret); } while (ret > 0 || err != WOLFSSL_ERROR_ZERO_RETURN); } /* detect TCP disconnect */ ExpectIntLE(ret,WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_get_error(ssl, ret), WOLFSSL_ERROR_ZERO_RETURN); ((func_args*)args)->return_code = EXPECT_RESULT(); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); CloseSocket(cfd); #if defined(HAVE_ECC) && defined(FP_ECC) && defined(HAVE_THREAD_LS) wc_ecc_fp_free(); /* free per thread cache */ #endif WOLFSSL_RETURN_FROM_THREAD(0); } static THREAD_RETURN WOLFSSL_THREAD SSL_read_test_client_thread(void* args) { EXPECT_DECLS; callback_functions* callbacks = NULL; WOLFSSL_CTX* ctx = NULL; WOLFSSL* ssl = NULL; SOCKET_T sfd = 0; char msg[] = "hello wolfssl server!"; int len = (int) XSTRLEN(msg); char input[1024]; int idx = 0; int ret = 0, err = 0; if (!args) WOLFSSL_RETURN_FROM_THREAD(0); ((func_args*)args)->return_code = TEST_FAIL; callbacks = ((func_args*)args)->callbacks; ctx = wolfSSL_CTX_new(callbacks->method()); #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); #endif ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_use_certificate_file(ctx, cliCertFile, WOLFSSL_FILETYPE_PEM)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_use_PrivateKey_file(ctx, cliKeyFile, WOLFSSL_FILETYPE_PEM)); ExpectNotNull((ssl = wolfSSL_new(ctx))); tcp_connect(&sfd, wolfSSLIP, ((func_args*)args)->signal->port, 0, 0, ssl); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_set_fd(ssl, sfd)); if (EXPECT_SUCCESS()) { do { err = 0; /* Reset error */ ret = wolfSSL_connect(ssl); if (ret != WOLFSSL_SUCCESS) { err = wolfSSL_get_error(ssl, 0); } } while (ret != WOLFSSL_SUCCESS && err == WC_NO_ERR_TRACE(WC_PENDING_E)); } ExpectIntGE(wolfSSL_write(ssl, msg, len), 0); if (EXPECT_SUCCESS()) { if (0 < (idx = wolfSSL_read(ssl, input, sizeof(input)-1))) { input[idx] = 0; } } if (EXPECT_SUCCESS()) { ret = wolfSSL_shutdown(ssl); if (ret == WC_NO_ERR_TRACE(WOLFSSL_SHUTDOWN_NOT_DONE)) { ret = wolfSSL_shutdown(ssl); } } ExpectIntEQ(ret, WOLFSSL_SUCCESS); ((func_args*)args)->return_code = EXPECT_RESULT(); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); CloseSocket(sfd); #if defined(HAVE_ECC) && defined(FP_ECC) && defined(HAVE_THREAD_LS) wc_ecc_fp_free(); /* free per thread cache */ #endif WOLFSSL_RETURN_FROM_THREAD(0); } #endif /* OPENSSL_EXTRA && WOLFSSL_ERROR_CODE_OPENSSL && HAVE_IO_TESTS_DEPENDENCIES && !WOLFSSL_NO_TLS12 */ /* This test is to check wolfSSL_read behaves as same as * openSSL when it is called after SSL_shutdown completes. */ static int test_wolfSSL_read_detect_TCP_disconnect(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && defined(WOLFSSL_ERROR_CODE_OPENSSL) && \ defined(HAVE_IO_TESTS_DEPENDENCIES) && !defined(WOLFSSL_NO_TLS12) tcp_ready ready; func_args client_args; func_args server_args; THREAD_TYPE serverThread; THREAD_TYPE clientThread; callback_functions server_cbf; callback_functions client_cbf; #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); #endif StartTCP(); InitTcpReady(&ready); XMEMSET(&client_args, 0, sizeof(func_args)); XMEMSET(&server_args, 0, sizeof(func_args)); XMEMSET(&server_cbf, 0, sizeof(callback_functions)); XMEMSET(&client_cbf, 0, sizeof(callback_functions)); server_cbf.method = wolfTLSv1_2_server_method; client_cbf.method = wolfTLSv1_2_client_method; server_args.callbacks = &server_cbf; client_args.callbacks = &client_cbf; server_args.signal = &ready; client_args.signal = &ready; start_thread(SSL_read_test_server_thread, &server_args, &serverThread); wait_tcp_ready(&server_args); start_thread(SSL_read_test_client_thread, &client_args, &clientThread); join_thread(clientThread); join_thread(serverThread); ExpectTrue(client_args.return_code); ExpectTrue(server_args.return_code); FreeTcpReady(&ready); #endif return EXPECT_RESULT(); } static int test_wolfSSL_CTX_get_min_proto_version(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_TLS) WOLFSSL_CTX *ctx = NULL; ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_method())); ExpectIntEQ(wolfSSL_CTX_set_min_proto_version(ctx, SSL3_VERSION), WOLFSSL_SUCCESS); #ifdef WOLFSSL_ALLOW_SSLV3 ExpectIntEQ(wolfSSL_CTX_get_min_proto_version(ctx), SSL3_VERSION); #else ExpectIntGT(wolfSSL_CTX_get_min_proto_version(ctx), SSL3_VERSION); #endif wolfSSL_CTX_free(ctx); ctx = NULL; #ifndef NO_OLD_TLS #ifdef WOLFSSL_ALLOW_TLSV10 ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_method())); #else ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_method())); #endif ExpectIntEQ(wolfSSL_CTX_set_min_proto_version(ctx, TLS1_VERSION), WOLFSSL_SUCCESS); #ifdef WOLFSSL_ALLOW_TLSV10 ExpectIntEQ(wolfSSL_CTX_get_min_proto_version(ctx), TLS1_VERSION); #else ExpectIntGT(wolfSSL_CTX_get_min_proto_version(ctx), TLS1_VERSION); #endif wolfSSL_CTX_free(ctx); ctx = NULL; #endif ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_method())); ExpectIntEQ(wolfSSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION), WOLFSSL_SUCCESS); #ifndef NO_OLD_TLS ExpectIntEQ(wolfSSL_CTX_get_min_proto_version(ctx), TLS1_1_VERSION); #else ExpectIntGT(wolfSSL_CTX_get_min_proto_version(ctx), TLS1_1_VERSION); #endif wolfSSL_CTX_free(ctx); ctx = NULL; #ifndef WOLFSSL_NO_TLS12 ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_2_method())); ExpectIntEQ(wolfSSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_get_min_proto_version(ctx), TLS1_2_VERSION); wolfSSL_CTX_free(ctx); ctx = NULL; #endif #ifdef WOLFSSL_TLS13 ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_method())); ExpectIntEQ(wolfSSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_get_min_proto_version(ctx), TLS1_3_VERSION); wolfSSL_CTX_free(ctx); ctx = NULL; #endif #endif return EXPECT_RESULT(); } #if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && \ (defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \ defined(HAVE_LIGHTY) || defined(WOLFSSL_HAPROXY) || \ defined(WOLFSSL_OPENSSH) || defined(HAVE_SBLIM_SFCB))) static int test_wolfSSL_set_SSL_CTX(void) { EXPECT_DECLS; #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) \ && !defined(WOLFSSL_NO_TLS12) && defined(WOLFSSL_TLS13) && \ !defined(NO_RSA) && !defined(NO_WOLFSSL_SERVER) WOLFSSL_CTX *ctx1 = NULL; WOLFSSL_CTX *ctx2 = NULL; WOLFSSL *ssl = NULL; const byte *session_id1 = (const byte *)"CTX1"; const byte *session_id2 = (const byte *)"CTX2"; ExpectNotNull(ctx1 = wolfSSL_CTX_new(wolfTLS_server_method())); ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx1, svrCertFile, WOLFSSL_FILETYPE_PEM)); ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx1, svrKeyFile, WOLFSSL_FILETYPE_PEM)); ExpectIntEQ(wolfSSL_CTX_set_min_proto_version(ctx1, TLS1_2_VERSION), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_get_min_proto_version(ctx1), TLS1_2_VERSION); ExpectIntEQ(wolfSSL_CTX_get_max_proto_version(ctx1), TLS1_3_VERSION); ExpectIntEQ(wolfSSL_CTX_set_session_id_context(ctx1, session_id1, 4), WOLFSSL_SUCCESS); ExpectNotNull(ctx2 = wolfSSL_CTX_new(wolfTLS_server_method())); ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx2, svrCertFile, WOLFSSL_FILETYPE_PEM)); ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx2, svrKeyFile, WOLFSSL_FILETYPE_PEM)); ExpectIntEQ(wolfSSL_CTX_set_min_proto_version(ctx2, TLS1_2_VERSION), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_set_max_proto_version(ctx2, TLS1_2_VERSION), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_get_min_proto_version(ctx2), TLS1_2_VERSION); ExpectIntEQ(wolfSSL_CTX_get_max_proto_version(ctx2), TLS1_2_VERSION); ExpectIntEQ(wolfSSL_CTX_set_session_id_context(ctx2, session_id2, 4), WOLFSSL_SUCCESS); #ifdef HAVE_SESSION_TICKET ExpectIntEQ((wolfSSL_CTX_get_options(ctx1) & SSL_OP_NO_TICKET), 0); wolfSSL_CTX_set_options(ctx2, SSL_OP_NO_TICKET); ExpectIntNE((wolfSSL_CTX_get_options(ctx2) & SSL_OP_NO_TICKET), 0); #endif ExpectNotNull(ssl = wolfSSL_new(ctx2)); ExpectIntNE((wolfSSL_get_options(ssl) & WOLFSSL_OP_NO_TLSv1_3), 0); #ifdef WOLFSSL_INT_H #ifdef WOLFSSL_SESSION_ID_CTX ExpectIntEQ(XMEMCMP(ssl->sessionCtx, session_id2, 4), 0); #endif #ifdef WOLFSSL_COPY_CERT if (ctx2 != NULL && ctx2->certificate != NULL) { ExpectFalse(ssl->buffers.certificate == ctx2->certificate); } if (ctx2 != NULL && ctx2->certChain != NULL) { ExpectFalse(ssl->buffers.certChain == ctx2->certChain); } #else ExpectTrue(ssl->buffers.certificate == ctx2->certificate); ExpectTrue(ssl->buffers.certChain == ctx2->certChain); #endif #endif #ifdef HAVE_SESSION_TICKET ExpectIntNE((wolfSSL_get_options(ssl) & SSL_OP_NO_TICKET), 0); #endif /* Set the ctx1 that has TLSv1.3 as max proto version */ ExpectNotNull(wolfSSL_set_SSL_CTX(ssl, ctx1)); /* MUST not change proto versions of ssl */ ExpectIntNE((wolfSSL_get_options(ssl) & WOLFSSL_OP_NO_TLSv1_3), 0); #ifdef HAVE_SESSION_TICKET /* MUST not change */ ExpectIntNE((wolfSSL_get_options(ssl) & SSL_OP_NO_TICKET), 0); #endif /* MUST change */ #ifdef WOLFSSL_INT_H #ifdef WOLFSSL_COPY_CERT if (ctx1 != NULL && ctx1->certificate != NULL) { ExpectFalse(ssl->buffers.certificate == ctx1->certificate); } if (ctx1 != NULL && ctx1->certChain != NULL) { ExpectFalse(ssl->buffers.certChain == ctx1->certChain); } #else ExpectTrue(ssl->buffers.certificate == ctx1->certificate); ExpectTrue(ssl->buffers.certChain == ctx1->certChain); #endif #ifdef WOLFSSL_SESSION_ID_CTX ExpectIntEQ(XMEMCMP(ssl->sessionCtx, session_id1, 4), 0); #endif #endif wolfSSL_free(ssl); wolfSSL_CTX_free(ctx1); wolfSSL_CTX_free(ctx2); #endif /* defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) */ return EXPECT_RESULT(); } #endif /* defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && \ (defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \ defined(HAVE_LIGHTY) || defined(WOLFSSL_HAPROXY) || \ defined(WOLFSSL_OPENSSH) || defined(HAVE_SBLIM_SFCB))) */ static int test_wolfSSL_security_level(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) SSL_CTX *ctx = NULL; #ifdef WOLFSSL_TLS13 #ifdef NO_WOLFSSL_SERVER ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method())); #else ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method())); #endif SSL_CTX_set_security_level(NULL, 1); SSL_CTX_set_security_level(ctx, 1); #if defined(WOLFSSL_SYS_CRYPTO_POLICY) ExpectIntEQ(SSL_CTX_get_security_level(NULL), BAD_FUNC_ARG); #else ExpectIntEQ(SSL_CTX_get_security_level(NULL), 0); #endif /* WOLFSSL_SYS_CRYPTO_POLICY */ /* Stub so nothing happens. */ ExpectIntEQ(SSL_CTX_get_security_level(ctx), 0); SSL_CTX_free(ctx); #else (void)ctx; #endif #endif return EXPECT_RESULT(); } /* System wide crypto-policy test. * * Loads three different policies (legacy, default, future), * then tests crypt_policy api. * */ static int test_wolfSSL_crypto_policy(void) { EXPECT_DECLS; #if defined(WOLFSSL_SYS_CRYPTO_POLICY) && !defined(NO_TLS) int rc = WC_NO_ERR_TRACE(WOLFSSL_FAILURE); const char * policy_list[] = { "examples/crypto_policies/legacy/wolfssl.txt", "examples/crypto_policies/default/wolfssl.txt", "examples/crypto_policies/future/wolfssl.txt", }; const char * ciphers_list[] = { "@SECLEVEL=1:EECDH:kRSA:EDH:PSK:DHEPSK:ECDHEPSK:RSAPSK" ":!eNULL:!aNULL", "@SECLEVEL=2:EECDH:kRSA:EDH:PSK:DHEPSK:ECDHEPSK:RSAPSK" ":!RC4:!eNULL:!aNULL", "@SECLEVEL=3:EECDH:EDH:PSK:DHEPSK:ECDHEPSK:!RSAPSK:!kRSA" ":!AES128:!RC4:!eNULL:!aNULL:!SHA1", }; int seclevel_list[] = { 1, 2, 3 }; int i = 0; for (i = 0; i < 3; ++i) { const char * ciphers = NULL; int n_diff = 0; WOLFSSL_CTX * ctx = NULL; WOLFSSL * ssl = NULL; /* Enable crypto policy. */ rc = wolfSSL_crypto_policy_enable(policy_list[i]); ExpectIntEQ(rc, WOLFSSL_SUCCESS); rc = wolfSSL_crypto_policy_is_enabled(); ExpectIntEQ(rc, 1); /* Trying to enable while already enabled should return * forbidden. */ rc = wolfSSL_crypto_policy_enable(policy_list[i]); ExpectIntEQ(rc, CRYPTO_POLICY_FORBIDDEN); /* Security level and ciphers should match what is expected. */ rc = wolfSSL_crypto_policy_get_level(); ExpectIntEQ(rc, seclevel_list[i]); ciphers = wolfSSL_crypto_policy_get_ciphers(); ExpectNotNull(ciphers); if (ciphers != NULL) { n_diff = XSTRNCMP(ciphers, ciphers_list[i], strlen(ciphers)); #ifdef DEBUG_WOLFSSL if (n_diff) { printf("error: got \n%s, expected \n%s\n", ciphers, ciphers_list[i]); } #endif /* DEBUG_WOLFSSL */ ExpectIntEQ(n_diff, 0); } /* TLSv1_2_method should work for all policies. */ ctx = wolfSSL_CTX_new(wolfTLSv1_2_method()); ExpectNotNull(ctx); if (ctx != NULL) { ssl = wolfSSL_new(ctx); ExpectNotNull(ssl); /* These API should be rejected while enabled. */ rc = wolfSSL_CTX_SetMinVersion(ctx, WOLFSSL_TLSV1_3); ExpectIntEQ(rc, CRYPTO_POLICY_FORBIDDEN); rc = wolfSSL_SetMinVersion(ssl, WOLFSSL_TLSV1_3); ExpectIntEQ(rc, CRYPTO_POLICY_FORBIDDEN); } if (ctx != NULL) { wolfSSL_CTX_free(ctx); ctx = NULL; } if (ssl != NULL) { wolfSSL_free(ssl); ssl = NULL; } wolfSSL_crypto_policy_disable(); /* Do the same test by buffer. */ rc = wolfSSL_crypto_policy_enable_buffer(ciphers_list[i]); ExpectIntEQ(rc, WOLFSSL_SUCCESS); rc = wolfSSL_crypto_policy_is_enabled(); ExpectIntEQ(rc, 1); /* Security level and ciphers should match what is expected. */ rc = wolfSSL_crypto_policy_get_level(); ExpectIntEQ(rc, seclevel_list[i]); ciphers = wolfSSL_crypto_policy_get_ciphers(); ExpectNotNull(ciphers); if (ciphers != NULL) { n_diff = XSTRNCMP(ciphers, ciphers_list[i], strlen(ciphers)); #ifdef DEBUG_WOLFSSL if (n_diff) { printf("error: got \n%s, expected \n%s\n", ciphers, ciphers_list[i]); } #endif /* DEBUG_WOLFSSL */ ExpectIntEQ(n_diff, 0); } wolfSSL_crypto_policy_disable(); } wolfSSL_crypto_policy_disable(); #endif /* WOLFSSL_SYS_CRYPTO_POLICY && !NO_TLS */ return EXPECT_RESULT(); } /* System wide crypto-policy test: certs and keys. * * Loads three different policies (legacy, default, future), * then tests loading different certificates and keys of * varying strength. * */ static int test_wolfSSL_crypto_policy_certs_and_keys(void) { EXPECT_DECLS; #if defined(WOLFSSL_SYS_CRYPTO_POLICY) && !defined(NO_TLS) int rc = WC_NO_ERR_TRACE(WOLFSSL_FAILURE); const char * policy_list[] = { "examples/crypto_policies/legacy/wolfssl.txt", "examples/crypto_policies/default/wolfssl.txt", "examples/crypto_policies/future/wolfssl.txt", }; int i = 0; for (i = 0; i < 3; ++i) { WOLFSSL_CTX * ctx = NULL; WOLFSSL * ssl = NULL; int is_legacy = 0; int is_future = 0; /* certs */ const char * cert1024 = "certs/1024/client-cert.pem"; const char * cert2048 = "certs/client-cert.pem"; const char * cert3072 = "certs/3072/client-cert.pem"; const char * cert256 = "certs/client-ecc-cert.pem"; const char * cert384 = "certs/client-ecc384-cert.pem"; /* keys */ const char * key1024 = "certs/1024/client-key.pem"; const char * key2048 = "certs/client-key.pem"; const char * key3072 = "certs/3072/client-key.pem"; const char * key256 = "certs/ecc-key.pem"; const char * key384 = "certs/client-ecc384-key.pem"; is_legacy = (XSTRSTR(policy_list[i], "legacy") != NULL) ? 1 : 0; is_future = (XSTRSTR(policy_list[i], "future") != NULL) ? 1 : 0; /* Enable crypto policy. */ rc = wolfSSL_crypto_policy_enable(policy_list[i]); ExpectIntEQ(rc, WOLFSSL_SUCCESS); rc = wolfSSL_crypto_policy_is_enabled(); ExpectIntEQ(rc, 1); /* TLSv1_2_method should work for all policies. */ ctx = wolfSSL_CTX_new(wolfTLSv1_2_method()); ExpectNotNull(ctx); /* Test certs of varying strength. */ if (ctx != NULL) { /* VERIFY_PEER must be set for key/cert checks to be done. */ wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, NULL); /* Test loading a cert with 1024 RSA key size. * This should fail for all but legacy. */ rc = wolfSSL_CTX_use_certificate_chain_file(ctx, cert1024); if (is_legacy) { ExpectIntEQ(rc, WOLFSSL_SUCCESS); } else { ExpectIntEQ(rc, WOLFSSL_FAILURE); } /* Test loading a cert with 2048 RSA key size. * Future crypto-policy is min 3072 RSA and DH key size, * and should fail. */ rc = wolfSSL_CTX_use_certificate_chain_file(ctx, cert2048); if (is_future) { /* Future crypto-policy is min 3072 RSA and DH key size, this * and should fail. */ ExpectIntEQ(rc, WOLFSSL_FAILURE); /* Set to VERIFY_NONE. This will disable key size checks, * it should now succeed. */ wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_NONE, NULL); rc = wolfSSL_CTX_use_certificate_chain_file(ctx, cert2048); ExpectIntEQ(rc, WOLFSSL_SUCCESS); /* Set back to verify peer. */ wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, NULL); } else { ExpectIntEQ(rc, WOLFSSL_SUCCESS); } /* Test loading a CA cert with 3072 RSA key size. * This should succeed for all policies. */ rc = wolfSSL_CTX_use_certificate_chain_file(ctx, cert3072); ExpectIntEQ(rc, WOLFSSL_SUCCESS); /* Test loading an ecc cert with 256 key size. * This should succeed for all policies. */ rc = wolfSSL_CTX_use_certificate_chain_file(ctx, cert256); ExpectIntEQ(rc, WOLFSSL_SUCCESS); /* Test loading an ecc cert with 384 key size. * This should succeed for all policies. */ rc = wolfSSL_CTX_use_certificate_chain_file(ctx, cert384); ExpectIntEQ(rc, WOLFSSL_SUCCESS); /* cleanup */ wolfSSL_CTX_free(ctx); ctx = NULL; } /* TLSv1_2_method should work for all policies. */ ctx = wolfSSL_CTX_new(wolfTLSv1_2_method()); ExpectNotNull(ctx); /* Repeat same tests for keys of varying strength. */ if (ctx != NULL) { /* 1024 RSA */ rc = SSL_CTX_use_PrivateKey_file(ctx, key1024, SSL_FILETYPE_PEM); if (is_legacy) { ExpectIntEQ(rc, WOLFSSL_SUCCESS); } else { ExpectIntEQ(rc, WOLFSSL_FAILURE); } /* 2048 RSA */ rc = SSL_CTX_use_PrivateKey_file(ctx, key2048, SSL_FILETYPE_PEM); if (!is_future) { ExpectIntEQ(rc, WOLFSSL_SUCCESS); } else { ExpectIntEQ(rc, WOLFSSL_FAILURE); } /* 3072 RSA */ rc = SSL_CTX_use_PrivateKey_file(ctx, key3072, SSL_FILETYPE_PEM); ExpectIntEQ(rc, WOLFSSL_SUCCESS); /* 256 ecc */ rc = SSL_CTX_use_PrivateKey_file(ctx, key256, SSL_FILETYPE_PEM); ExpectIntEQ(rc, WOLFSSL_SUCCESS); /* 384 ecc */ rc = SSL_CTX_use_PrivateKey_file(ctx, key384, SSL_FILETYPE_PEM); ExpectIntEQ(rc, WOLFSSL_SUCCESS); /* cleanup */ wolfSSL_CTX_free(ctx); ctx = NULL; } #ifdef HAVE_ECC /* Test set ecc min key size. */ ctx = wolfSSL_CTX_new(wolfTLSv1_2_method()); ExpectNotNull(ctx); if (ctx != NULL) { ssl = SSL_new(ctx); ExpectNotNull(ssl); /* Test setting ctx. */ rc = wolfSSL_CTX_SetMinEccKey_Sz(ctx, 160); if (is_legacy) { ExpectIntEQ(rc, WOLFSSL_SUCCESS); } else { ExpectIntEQ(rc, CRYPTO_POLICY_FORBIDDEN); } rc = wolfSSL_CTX_SetMinEccKey_Sz(ctx, 224); if (!is_future) { ExpectIntEQ(rc, WOLFSSL_SUCCESS); } else { ExpectIntEQ(rc, CRYPTO_POLICY_FORBIDDEN); } rc = wolfSSL_CTX_SetMinEccKey_Sz(ctx, 256); ExpectIntEQ(rc, WOLFSSL_SUCCESS); /* Test setting ssl. */ if (ssl != NULL) { rc = wolfSSL_SetMinEccKey_Sz(ssl, 160); if (is_legacy) { ExpectIntEQ(rc, WOLFSSL_SUCCESS); } else { ExpectIntEQ(rc, CRYPTO_POLICY_FORBIDDEN); } rc = wolfSSL_SetMinEccKey_Sz(ssl, 224); if (!is_future) { ExpectIntEQ(rc, WOLFSSL_SUCCESS); } else { ExpectIntEQ(rc, CRYPTO_POLICY_FORBIDDEN); } rc = wolfSSL_SetMinEccKey_Sz(ssl, 256); ExpectIntEQ(rc, WOLFSSL_SUCCESS); wolfSSL_free(ssl); ssl = NULL; } /* cleanup */ wolfSSL_CTX_free(ctx); ctx = NULL; } #endif /* HAVE_ECC */ #if !defined(NO_RSA) /* Test set rsa min key size. */ ctx = wolfSSL_CTX_new(wolfTLSv1_2_method()); ExpectNotNull(ctx); if (ctx != NULL) { ssl = SSL_new(ctx); ExpectNotNull(ssl); /* Test setting ctx. */ rc = wolfSSL_CTX_SetMinRsaKey_Sz(ctx, 1024); if (is_legacy) { ExpectIntEQ(rc, WOLFSSL_SUCCESS); } else { ExpectIntEQ(rc, CRYPTO_POLICY_FORBIDDEN); } rc = wolfSSL_CTX_SetMinRsaKey_Sz(ctx, 2048); if (!is_future) { ExpectIntEQ(rc, WOLFSSL_SUCCESS); } else { ExpectIntEQ(rc, CRYPTO_POLICY_FORBIDDEN); } rc = wolfSSL_CTX_SetMinRsaKey_Sz(ctx, 3072); ExpectIntEQ(rc, WOLFSSL_SUCCESS); /* Test setting ssl. */ if (ssl != NULL) { rc = wolfSSL_SetMinRsaKey_Sz(ssl, 1024); if (is_legacy) { ExpectIntEQ(rc, WOLFSSL_SUCCESS); } else { ExpectIntEQ(rc, CRYPTO_POLICY_FORBIDDEN); } rc = wolfSSL_SetMinRsaKey_Sz(ssl, 2048); if (!is_future) { ExpectIntEQ(rc, WOLFSSL_SUCCESS); } else { ExpectIntEQ(rc, CRYPTO_POLICY_FORBIDDEN); } rc = wolfSSL_SetMinRsaKey_Sz(ssl, 3072); ExpectIntEQ(rc, WOLFSSL_SUCCESS); wolfSSL_free(ssl); ssl = NULL; } /* cleanup */ wolfSSL_CTX_free(ctx); ctx = NULL; } #endif /* !NO_RSA */ wolfSSL_crypto_policy_disable(); } wolfSSL_crypto_policy_disable(); #endif /* WOLFSSL_SYS_CRYPTO_POLICY && !NO_TLS */ return EXPECT_RESULT(); } /* System wide crypto-policy test: tls and dtls methods. * */ static int test_wolfSSL_crypto_policy_tls_methods(void) { EXPECT_DECLS; #if defined(WOLFSSL_SYS_CRYPTO_POLICY) && !defined(NO_TLS) int rc = WC_NO_ERR_TRACE(WOLFSSL_FAILURE); const char * policy_list[] = { "examples/crypto_policies/legacy/wolfssl.txt", "examples/crypto_policies/default/wolfssl.txt", "examples/crypto_policies/future/wolfssl.txt", }; int i = 0; for (i = 0; i < 3; ++i) { WOLFSSL_CTX * ctx = NULL; int is_legacy = 0; is_legacy = (XSTRSTR(policy_list[i], "legacy") != NULL) ? 1 : 0; /* Enable crypto policy. */ rc = wolfSSL_crypto_policy_enable(policy_list[i]); ExpectIntEQ(rc, WOLFSSL_SUCCESS); rc = wolfSSL_crypto_policy_is_enabled(); ExpectIntEQ(rc, 1); /* Try to use old TLS methods. Only allowed with legacy. */ #if !defined(NO_OLD_TLS) ctx = wolfSSL_CTX_new(wolfTLSv1_1_method()); if (is_legacy) { ExpectNotNull(ctx); } else { ExpectNull(ctx); } if (ctx != NULL) { wolfSSL_CTX_free(ctx); ctx = NULL; } #if defined(WOLFSSL_ALLOW_TLSV10) ctx = wolfSSL_CTX_new(wolfTLSv1_method()); if (is_legacy) { ExpectNotNull(ctx); } else { ExpectNull(ctx); } if (ctx != NULL) { wolfSSL_CTX_free(ctx); ctx = NULL; } #endif /* WOLFSSL_ALLOW_TLSV10 */ #else (void) is_legacy; #endif /* !NO_OLD_TLS */ /* TLSv1_2_method should work for all policies. */ ctx = wolfSSL_CTX_new(wolfTLSv1_2_method()); ExpectNotNull(ctx); if (ctx != NULL) { wolfSSL_CTX_free(ctx); ctx = NULL; } ctx = wolfSSL_CTX_new(wolfTLSv1_3_method()); ExpectNotNull(ctx); if (ctx != NULL) { wolfSSL_CTX_free(ctx); ctx = NULL; } ctx = wolfSSL_CTX_new(TLS_method()); ExpectNotNull(ctx); if (ctx != NULL) { wolfSSL_CTX_free(ctx); ctx = NULL; } #ifdef WOLFSSL_DTLS ctx = wolfSSL_CTX_new(DTLS_method()); ExpectNotNull(ctx); if (ctx != NULL) { wolfSSL_CTX_free(ctx); ctx = NULL; } ctx = wolfSSL_CTX_new(wolfDTLSv1_2_method()); ExpectNotNull(ctx); if (ctx != NULL) { wolfSSL_CTX_free(ctx); ctx = NULL; } #ifndef NO_OLD_TLS /* Only allowed with legacy. */ ctx = wolfSSL_CTX_new(wolfDTLSv1_method()); if (is_legacy) { ExpectNotNull(ctx); } else { ExpectNull(ctx); } if (ctx != NULL) { wolfSSL_CTX_free(ctx); ctx = NULL; } #endif /* !NO_OLD_TLS */ #endif /* WOLFSSL_DTLS */ wolfSSL_crypto_policy_disable(); } wolfSSL_crypto_policy_disable(); #endif /* WOLFSSL_SYS_CRYPTO_POLICY && !NO_TLS */ return EXPECT_RESULT(); } #if defined(WOLFSSL_SYS_CRYPTO_POLICY) && !defined(NO_TLS) /* Helper function for test_wolfSSL_crypto_policy_ciphers. * Searches ssl suites for cipher string. * * Returns 1 if found. * Returns 0 if not found. * Returns < 0 if error. * */ static int crypto_policy_cipher_found(const WOLFSSL * ssl, const char * cipher, int match) { WOLF_STACK_OF(WOLFSSL_CIPHER) * sk = NULL; WOLFSSL_CIPHER * current = NULL; const char * suite; int found = 0; int i = 0; if (ssl == NULL || cipher == NULL || *cipher == '\0') { return -1; } sk = wolfSSL_get_ciphers_compat(ssl); if (sk == NULL) { return -1; } do { current = wolfSSL_sk_SSL_CIPHER_value(sk, i++); if (current) { suite = wolfSSL_CIPHER_get_name(current); if (suite) { if (match == 1) { /* prefix match */ if (XSTRNCMP(suite, cipher, XSTRLEN(cipher)) == 0) { found = 1; break; } } else if (match == -1) { /* postfix match */ if (XSTRLEN(suite) > XSTRLEN(cipher)) { const char * postfix = suite + XSTRLEN(suite) - XSTRLEN(cipher); if (XSTRNCMP(postfix, cipher, XSTRLEN(cipher)) == 0) { found = 1; break; } } } else { /* needle in haystack match */ if (XSTRSTR(suite, cipher)) { found = 1; break; } } } } } while (current); return found == 1; } #endif /* WOLFSSL_SYS_CRYPTO_POLICY && !NO_TLS */ /* System wide crypto-policy test: ciphers. * */ static int test_wolfSSL_crypto_policy_ciphers(void) { EXPECT_DECLS; #if defined(WOLFSSL_SYS_CRYPTO_POLICY) && !defined(NO_TLS) int rc = WC_NO_ERR_TRACE(WOLFSSL_FAILURE); const char * policy_list[] = { "examples/crypto_policies/legacy/wolfssl.txt", "examples/crypto_policies/default/wolfssl.txt", "examples/crypto_policies/future/wolfssl.txt", }; int seclevel_list[] = { 1, 2, 3 }; int i = 0; int is_legacy = 0; int is_future = 0; for (i = 0; i < 3; ++i) { WOLFSSL_CTX * ctx = NULL; WOLFSSL * ssl = NULL; int found = 0; is_legacy = (XSTRSTR(policy_list[i], "legacy") != NULL) ? 1 : 0; is_future = (XSTRSTR(policy_list[i], "future") != NULL) ? 1 : 0; (void) is_legacy; /* Enable crypto policy. */ rc = wolfSSL_crypto_policy_enable(policy_list[i]); ExpectIntEQ(rc, WOLFSSL_SUCCESS); rc = wolfSSL_crypto_policy_is_enabled(); ExpectIntEQ(rc, 1); ctx = wolfSSL_CTX_new(TLS_method()); ExpectNotNull(ctx); ssl = SSL_new(ctx); ExpectNotNull(ssl); rc = wolfSSL_CTX_get_security_level(ctx); ExpectIntEQ(rc, seclevel_list[i]); rc = wolfSSL_get_security_level(ssl); ExpectIntEQ(rc, seclevel_list[i]); found = crypto_policy_cipher_found(ssl, "RC4", 0); ExpectIntEQ(found, is_legacy); /* We return a different cipher string depending on build settings. */ #if !defined(WOLFSSL_CIPHER_INTERNALNAME) && \ !defined(NO_ERROR_STRINGS) && !defined(WOLFSSL_QT) found = crypto_policy_cipher_found(ssl, "AES_128", 0); ExpectIntEQ(found, !is_future); found = crypto_policy_cipher_found(ssl, "TLS_DHE_RSA_WITH_AES", 1); ExpectIntEQ(found, !is_future); found = crypto_policy_cipher_found(ssl, "_SHA", -1); ExpectIntEQ(found, !is_future); #else found = crypto_policy_cipher_found(ssl, "AES128", 0); ExpectIntEQ(found, !is_future); found = crypto_policy_cipher_found(ssl, "DHE-RSA-AES", 1); ExpectIntEQ(found, !is_future); found = crypto_policy_cipher_found(ssl, "-SHA", -1); ExpectIntEQ(found, !is_future); #endif if (ssl != NULL) { SSL_free(ssl); ssl = NULL; } if (ctx != NULL) { wolfSSL_CTX_free(ctx); ctx = NULL; } wolfSSL_crypto_policy_disable(); } wolfSSL_crypto_policy_disable(); #endif /* WOLFSSL_SYS_CRYPTO_POLICY && !NO_TLS */ return EXPECT_RESULT(); } static int test_wolfSSL_SSL_in_init(void) { EXPECT_DECLS; #if defined(OPENSSL_ALL) && !defined(NO_BIO) && !defined(NO_TLS) SSL_CTX* ctx = NULL; SSL* ssl = NULL; const char* testCertFile; const char* testKeyFile; #ifdef WOLFSSL_TLS13 #ifdef NO_WOLFSSL_SERVER ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method())); #else ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method())); #endif #else #ifdef NO_WOLFSSL_SERVER ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); #else ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); #endif #endif #ifndef NO_RSA testCertFile = svrCertFile; testKeyFile = svrKeyFile; #elif defined(HAVE_ECC) testCertFile = eccCertFile; testKeyFile = eccKeyFile; #else testCertFile = NULL; testKeyFile = NULL; #endif if ((testCertFile != NULL) && (testKeyFile != NULL)) { ExpectTrue(SSL_CTX_use_certificate_file(ctx, testCertFile, SSL_FILETYPE_PEM)); ExpectTrue(SSL_CTX_use_PrivateKey_file(ctx, testKeyFile, SSL_FILETYPE_PEM)); } ExpectNotNull(ssl = SSL_new(ctx)); ExpectIntEQ(SSL_in_init(ssl), 1); SSL_CTX_free(ctx); SSL_free(ssl); #endif return EXPECT_RESULT(); } static int test_wolfSSL_CTX_set_timeout(void) { EXPECT_DECLS; #if !defined(NO_WOLFSSL_SERVER) && !defined(NO_TLS) && \ !defined(NO_SESSION_CACHE) WOLFSSL_CTX* ctx = NULL; #if defined(WOLFSSL_ERROR_CODE_OPENSSL) int timeout; #endif ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); #if defined(WOLFSSL_ERROR_CODE_OPENSSL) /* in WOLFSSL_ERROR_CODE_OPENSSL macro guard, * wolfSSL_CTX_set_timeout returns previous timeout value on success. */ ExpectIntEQ(wolfSSL_CTX_set_timeout(NULL, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* giving 0 as timeout value sets default timeout */ timeout = wolfSSL_CTX_set_timeout(ctx, 0); ExpectIntEQ(wolfSSL_CTX_set_timeout(ctx, 20), timeout); ExpectIntEQ(wolfSSL_CTX_set_timeout(ctx, 30), 20); #else ExpectIntEQ(wolfSSL_CTX_set_timeout(NULL, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_CTX_set_timeout(ctx, 100), 1); ExpectIntEQ(wolfSSL_CTX_set_timeout(ctx, 0), 1); #endif wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } static int test_wolfSSL_OpenSSL_version(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) const char* ver; #if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L ExpectNotNull(ver = OpenSSL_version(0)); #else ExpectNotNull(ver = OpenSSL_version()); #endif ExpectIntEQ(XMEMCMP(ver, "wolfSSL " LIBWOLFSSL_VERSION_STRING, XSTRLEN("wolfSSL " LIBWOLFSSL_VERSION_STRING)), 0); #endif return EXPECT_RESULT(); } static int test_CONF_CTX_CMDLINE(void) { EXPECT_DECLS; #if defined(OPENSSL_ALL) && !defined(NO_TLS) && !defined(NO_WOLFSSL_SERVER) SSL_CTX* ctx = NULL; SSL_CONF_CTX* cctx = NULL; ExpectNotNull(cctx = SSL_CONF_CTX_new()); ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); SSL_CONF_CTX_set_ssl_ctx(cctx, ctx); /* set flags */ ExpectIntEQ(SSL_CONF_CTX_set_flags(cctx, WOLFSSL_CONF_FLAG_CMDLINE), WOLFSSL_CONF_FLAG_CMDLINE); ExpectIntEQ(SSL_CONF_CTX_set_flags(cctx, WOLFSSL_CONF_FLAG_CERTIFICATE), WOLFSSL_CONF_FLAG_CMDLINE | WOLFSSL_CONF_FLAG_CERTIFICATE); /* cmd invalid command */ ExpectIntEQ(SSL_CONF_cmd(cctx, "foo", "foobar"), -2); ExpectIntEQ(SSL_CONF_cmd(cctx, "foo", NULL), -2); ExpectIntEQ(SSL_CONF_cmd(cctx, NULL, NULL), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(SSL_CONF_cmd(cctx, NULL, "foobar"), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(SSL_CONF_cmd(NULL, "-curves", "foobar"), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); /* cmd Certificate and Private Key*/ { #if !defined(NO_CERTS) && !defined(NO_RSA) const char* ourCert = svrCertFile; const char* ourKey = svrKeyFile; ExpectIntEQ(SSL_CONF_cmd(cctx, "-cert", NULL), -3); ExpectIntEQ(SSL_CONF_cmd(cctx, "-cert", ourCert), WOLFSSL_SUCCESS); ExpectIntEQ(SSL_CONF_cmd(cctx, "-key", NULL), -3); ExpectIntEQ(SSL_CONF_cmd(cctx, "-key", ourKey), WOLFSSL_SUCCESS); ExpectIntEQ(SSL_CONF_CTX_finish(cctx), WOLFSSL_SUCCESS); #endif } /* cmd curves */ { #if defined(HAVE_ECC) const char* curve = "secp256r1"; ExpectIntEQ(SSL_CONF_cmd(cctx, "-curves", NULL), -3); ExpectIntEQ(SSL_CONF_cmd(cctx, "-curves", curve), WOLFSSL_SUCCESS); ExpectIntEQ(SSL_CONF_CTX_finish(cctx), WOLFSSL_SUCCESS); #endif } /* cmd CipherString */ { char* cipher = wolfSSL_get_cipher_list(0/*top priority*/); ExpectIntEQ(SSL_CONF_cmd(cctx, "-cipher", NULL), -3); ExpectIntEQ(SSL_CONF_cmd(cctx, "-cipher", cipher), WOLFSSL_SUCCESS); ExpectIntEQ(SSL_CONF_CTX_finish(cctx), WOLFSSL_SUCCESS); } /* cmd DH parameter */ { #if !defined(NO_DH) && !defined(NO_BIO) const char* ourdhcert = "./certs/dh2048.pem"; ExpectIntEQ(SSL_CONF_cmd(cctx, "-dhparam", NULL), -3); ExpectIntEQ(SSL_CONF_cmd(cctx, "-dhparam", ourdhcert), WOLFSSL_SUCCESS); ExpectIntEQ(SSL_CONF_CTX_finish(cctx), WOLFSSL_SUCCESS); #endif } SSL_CTX_free(ctx); SSL_CONF_CTX_free(cctx); #endif /* OPENSSL_EXTRA */ return EXPECT_RESULT(); } static int test_CONF_CTX_FILE(void) { EXPECT_DECLS; #if defined(OPENSSL_ALL) && !defined(NO_TLS) && !defined(NO_WOLFSSL_SERVER) SSL_CTX* ctx = NULL; SSL_CONF_CTX* cctx = NULL; ExpectNotNull(cctx = SSL_CONF_CTX_new()); ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); SSL_CONF_CTX_set_ssl_ctx(cctx, ctx); /* set flags */ ExpectIntEQ(SSL_CONF_CTX_set_flags(cctx, WOLFSSL_CONF_FLAG_FILE), WOLFSSL_CONF_FLAG_FILE); ExpectIntEQ(SSL_CONF_CTX_set_flags(cctx, WOLFSSL_CONF_FLAG_CERTIFICATE), WOLFSSL_CONF_FLAG_FILE | WOLFSSL_CONF_FLAG_CERTIFICATE); /* sanity check */ ExpectIntEQ(SSL_CONF_cmd(cctx, "foo", "foobar"), -2); ExpectIntEQ(SSL_CONF_cmd(cctx, "foo", NULL), -2); ExpectIntEQ(SSL_CONF_cmd(cctx, NULL, NULL), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(SSL_CONF_cmd(cctx, NULL, "foobar"), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(SSL_CONF_cmd(NULL, "-curves", "foobar"), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); /* cmd Certificate and Private Key*/ { #if !defined(NO_CERTS) && !defined(NO_RSA) const char* ourCert = svrCertFile; const char* ourKey = svrKeyFile; ExpectIntEQ(SSL_CONF_cmd(cctx, "Certificate", NULL), -3); ExpectIntEQ(SSL_CONF_cmd(cctx, "PrivateKey", NULL), -3); ExpectIntEQ(SSL_CONF_cmd(cctx, "Certificate", ourCert), WOLFSSL_SUCCESS); ExpectIntEQ(SSL_CONF_cmd(cctx, "PrivateKey", ourKey), WOLFSSL_SUCCESS); ExpectIntEQ(SSL_CONF_CTX_finish(cctx), WOLFSSL_SUCCESS); #endif } /* cmd curves */ { #if defined(HAVE_ECC) const char* curve = "secp256r1"; ExpectIntEQ(SSL_CONF_cmd(cctx, "Curves", NULL), -3); ExpectIntEQ(SSL_CONF_cmd(cctx, "Curves", curve), WOLFSSL_SUCCESS); ExpectIntEQ(SSL_CONF_CTX_finish(cctx), WOLFSSL_SUCCESS); #endif } /* cmd CipherString */ { char* cipher = wolfSSL_get_cipher_list(0/*top priority*/); ExpectIntEQ(SSL_CONF_cmd(cctx, "CipherString", NULL), -3); ExpectIntEQ(SSL_CONF_cmd(cctx, "CipherString", cipher), WOLFSSL_SUCCESS); ExpectIntEQ(SSL_CONF_CTX_finish(cctx), WOLFSSL_SUCCESS); } /* cmd DH parameter */ { #if !defined(NO_DH) && !defined(NO_BIO) && defined(HAVE_FFDHE_3072) const char* ourdhcert = "./certs/dh3072.pem"; ExpectIntEQ(SSL_CONF_cmd(cctx, "DHParameters", NULL), -3); ExpectIntEQ(SSL_CONF_cmd(cctx, "DHParameters", ourdhcert), WOLFSSL_SUCCESS); ExpectIntEQ(SSL_CONF_CTX_finish(cctx), WOLFSSL_SUCCESS); #endif } SSL_CTX_free(ctx); SSL_CONF_CTX_free(cctx); #endif /* OPENSSL_EXTRA */ return EXPECT_RESULT(); } static int test_wolfSSL_CRYPTO_get_ex_new_index(void) { EXPECT_DECLS; #ifdef HAVE_EX_DATA_CRYPTO int idx1, idx2; /* test for unsupported class index */ ExpectIntEQ(wolfSSL_CRYPTO_get_ex_new_index(WOLF_CRYPTO_EX_INDEX_X509_STORE, 0,NULL, NULL, NULL, NULL ), -1); ExpectIntEQ(wolfSSL_CRYPTO_get_ex_new_index( WOLF_CRYPTO_EX_INDEX_X509_STORE_CTX, 0,NULL, NULL, NULL, NULL ), -1); ExpectIntEQ(wolfSSL_CRYPTO_get_ex_new_index(WOLF_CRYPTO_EX_INDEX_DH, 0,NULL, NULL, NULL, NULL ), -1); ExpectIntEQ(wolfSSL_CRYPTO_get_ex_new_index(WOLF_CRYPTO_EX_INDEX_DSA, 0,NULL, NULL, NULL, NULL ), -1); ExpectIntEQ(wolfSSL_CRYPTO_get_ex_new_index(WOLF_CRYPTO_EX_INDEX_EC_KEY, 0,NULL, NULL, NULL, NULL ), -1); ExpectIntEQ(wolfSSL_CRYPTO_get_ex_new_index(WOLF_CRYPTO_EX_INDEX_RSA, 0,NULL, NULL, NULL, NULL ), -1); ExpectIntEQ(wolfSSL_CRYPTO_get_ex_new_index(WOLF_CRYPTO_EX_INDEX_ENGINE, 0,NULL, NULL, NULL, NULL ), -1); ExpectIntEQ(wolfSSL_CRYPTO_get_ex_new_index(WOLF_CRYPTO_EX_INDEX_UI, 0,NULL, NULL, NULL, NULL ), -1); ExpectIntEQ(wolfSSL_CRYPTO_get_ex_new_index(WOLF_CRYPTO_EX_INDEX_BIO, 0,NULL, NULL, NULL, NULL ), -1); ExpectIntEQ(wolfSSL_CRYPTO_get_ex_new_index(WOLF_CRYPTO_EX_INDEX_APP, 0,NULL, NULL, NULL, NULL ), -1); ExpectIntEQ(wolfSSL_CRYPTO_get_ex_new_index(WOLF_CRYPTO_EX_INDEX_UI_METHOD, 0,NULL, NULL, NULL, NULL ), -1); ExpectIntEQ(wolfSSL_CRYPTO_get_ex_new_index(WOLF_CRYPTO_EX_INDEX_DRBG, 0,NULL, NULL, NULL, NULL ), -1); ExpectIntEQ(wolfSSL_CRYPTO_get_ex_new_index(20, 0,NULL, NULL, NULL, NULL ), -1); /* test for supported class index */ idx1 = wolfSSL_CRYPTO_get_ex_new_index(WOLF_CRYPTO_EX_INDEX_SSL, 0,NULL, NULL, NULL, NULL ); idx2 = wolfSSL_CRYPTO_get_ex_new_index(WOLF_CRYPTO_EX_INDEX_SSL, 0,NULL, NULL, NULL, NULL ); ExpectIntNE(idx1, -1); ExpectIntNE(idx2, -1); ExpectIntNE(idx1, idx2); idx1 = wolfSSL_CRYPTO_get_ex_new_index(WOLF_CRYPTO_EX_INDEX_SSL_CTX, 0,NULL, NULL, NULL, NULL ); idx2 = wolfSSL_CRYPTO_get_ex_new_index(WOLF_CRYPTO_EX_INDEX_SSL_CTX, 0,NULL, NULL, NULL, NULL ); ExpectIntNE(idx1, -1); ExpectIntNE(idx2, -1); ExpectIntNE(idx1, idx2); idx1 = wolfSSL_CRYPTO_get_ex_new_index(WOLF_CRYPTO_EX_INDEX_X509, 0,NULL, NULL, NULL, NULL ); idx2 = wolfSSL_CRYPTO_get_ex_new_index(WOLF_CRYPTO_EX_INDEX_X509, 0,NULL, NULL, NULL, NULL ); ExpectIntNE(idx1, -1); ExpectIntNE(idx2, -1); ExpectIntNE(idx1, idx2); idx1 = wolfSSL_CRYPTO_get_ex_new_index(WOLF_CRYPTO_EX_INDEX_SSL_SESSION, 0,NULL, NULL, NULL, NULL ); idx2 = wolfSSL_CRYPTO_get_ex_new_index(WOLF_CRYPTO_EX_INDEX_SSL_SESSION, 0,NULL, NULL, NULL, NULL ); ExpectIntNE(idx1, -1); ExpectIntNE(idx2, -1); ExpectIntNE(idx1, idx2); #endif /* HAVE_EX_DATA_CRYPTO */ return EXPECT_RESULT(); } #if defined(HAVE_EX_DATA_CRYPTO) && defined(OPENSSL_EXTRA) #define SESSION_NEW_IDX_LONG 0xDEADBEEF #define SESSION_NEW_IDX_VAL ((void*)0xAEADAEAD) #define SESSION_DUP_IDX_VAL ((void*)0xDEDEDEDE) #define SESSION_NEW_IDX_PTR "Testing" static void test_wolfSSL_SESSION_get_ex_new_index_new_cb(void* p, void* ptr, CRYPTO_EX_DATA* a, int idx, long argValue, void* arg) { AssertNotNull(p); AssertNull(ptr); AssertIntEQ(CRYPTO_set_ex_data(a, idx, SESSION_NEW_IDX_VAL), SSL_SUCCESS); AssertIntEQ(argValue, SESSION_NEW_IDX_LONG); AssertStrEQ(arg, SESSION_NEW_IDX_PTR); } static int test_wolfSSL_SESSION_get_ex_new_index_dup_cb(CRYPTO_EX_DATA* out, const CRYPTO_EX_DATA* in, void* inPtr, int idx, long argV, void* arg) { EXPECT_DECLS; ExpectNotNull(out); ExpectNotNull(in); ExpectPtrEq(*(void**)inPtr, SESSION_NEW_IDX_VAL); ExpectPtrEq(CRYPTO_get_ex_data(in, idx), SESSION_NEW_IDX_VAL); ExpectPtrEq(CRYPTO_get_ex_data(out, idx), SESSION_NEW_IDX_VAL); ExpectIntEQ(argV, SESSION_NEW_IDX_LONG); ExpectStrEQ(arg, SESSION_NEW_IDX_PTR); *(void**)inPtr = SESSION_DUP_IDX_VAL; if (EXPECT_SUCCESS()) { return SSL_SUCCESS; } else { return SSL_FAILURE; } } static int test_wolfSSL_SESSION_get_ex_new_index_free_cb_called = 0; static void test_wolfSSL_SESSION_get_ex_new_index_free_cb(void* p, void* ptr, CRYPTO_EX_DATA* a, int idx, long argValue, void* arg) { EXPECT_DECLS; ExpectNotNull(p); ExpectNull(ptr); ExpectPtrNE(CRYPTO_get_ex_data(a, idx), 0); ExpectIntEQ(argValue, SESSION_NEW_IDX_LONG); ExpectStrEQ(arg, SESSION_NEW_IDX_PTR); if (EXPECT_SUCCESS()) { test_wolfSSL_SESSION_get_ex_new_index_free_cb_called++; } } static int test_wolfSSL_SESSION_get_ex_new_index(void) { EXPECT_DECLS; int idx = SSL_SESSION_get_ex_new_index(SESSION_NEW_IDX_LONG, (void*)SESSION_NEW_IDX_PTR, test_wolfSSL_SESSION_get_ex_new_index_new_cb, test_wolfSSL_SESSION_get_ex_new_index_dup_cb, test_wolfSSL_SESSION_get_ex_new_index_free_cb); SSL_SESSION* s = SSL_SESSION_new(); SSL_SESSION* d = NULL; ExpectNotNull(s); ExpectPtrEq(SSL_SESSION_get_ex_data(s, idx), SESSION_NEW_IDX_VAL); ExpectNotNull(d = SSL_SESSION_dup(s)); ExpectPtrEq(SSL_SESSION_get_ex_data(d, idx), SESSION_DUP_IDX_VAL); SSL_SESSION_free(s); ExpectIntEQ(test_wolfSSL_SESSION_get_ex_new_index_free_cb_called, 1); SSL_SESSION_free(d); ExpectIntEQ(test_wolfSSL_SESSION_get_ex_new_index_free_cb_called, 2); crypto_ex_cb_free(crypto_ex_cb_ctx_session); crypto_ex_cb_ctx_session = NULL; return EXPECT_RESULT(); } #else static int test_wolfSSL_SESSION_get_ex_new_index(void) { return TEST_SKIPPED; } #endif static int test_wolfSSL_set_psk_use_session_callback(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_PSK) && !defined(NO_TLS) SSL_CTX* ctx = NULL; SSL* ssl = NULL; const char* testCertFile; const char* testKeyFile; #ifdef WOLFSSL_TLS13 #ifdef NO_WOLFSSL_SERVER ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method())); #else ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method())); #endif #else #ifdef NO_WOLFSSL_SERVER ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); #else ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); #endif #endif #ifndef NO_RSA testCertFile = svrCertFile; testKeyFile = svrKeyFile; #elif defined(HAVE_ECC) testCertFile = eccCertFile; testKeyFile = eccKeyFile; #else testCertFile = NULL; testKeyFile = NULL; #endif if ((testCertFile != NULL) && (testKeyFile != NULL)) { ExpectTrue(SSL_CTX_use_certificate_file(ctx, testCertFile, SSL_FILETYPE_PEM)); ExpectTrue(SSL_CTX_use_PrivateKey_file(ctx, testKeyFile, SSL_FILETYPE_PEM)); } ExpectNotNull(ssl = SSL_new(ctx)); SSL_set_psk_use_session_callback(ssl, my_psk_use_session_cb); SSL_CTX_free(ctx); SSL_free(ssl); #endif return EXPECT_RESULT(); } /* similar to error_test() in wolfcrypt/test/test.c, but adding error codes from * TLS layer. */ static int error_test(void) { EXPECT_DECLS; const char* errStr; const char* unknownStr = wc_GetErrorString(WC_LAST_E - 1); #ifdef NO_ERROR_STRINGS /* Ensure a valid error code's string matches an invalid code's. * The string is that error strings are not available. */ errStr = wc_GetErrorString(OPEN_RAN_E); ExpectIntEQ(XSTRCMP(errStr, unknownStr), 0); if (EXPECT_FAIL()) return OPEN_RAN_E; #else int start_idx = 0; int i; int j = 0; /* Values that are not or no longer error codes. */ static const struct { int first; int last; } missing[] = { #ifndef OPENSSL_EXTRA { 0, 0 }, #endif #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \ defined(HAVE_WEBSERVER) || defined(HAVE_MEMCACHED) {11, 11}, {17, 15}, {19, 19}, {24, 24}, {27, 26 }, {61, 30}, {63, 63}, {78, 65}, #endif { -9, WC_SPAN1_FIRST_E + 1 }, { -300, -300 }, { -335, -336 }, { -346, -349 }, { -356, -356 }, { -358, -358 }, { -384, -384 }, { -466, -499 }, { WOLFSSL_LAST_E - 1, WC_SPAN2_FIRST_E + 1 }, { WC_SPAN2_LAST_E - 1, MIN_CODE_E } }; /* Check that all errors have a string and it's the same through the two * APIs. Check that the values that are not errors map to the unknown * string. */ #if defined(OPENSSL_EXTRA) start_idx = WC_OSSL_V509_V_ERR_MAX - 1; #endif for (i = start_idx; i >= MIN_CODE_E; i--) { int this_missing = 0; for (j = 0; j < (int)XELEM_CNT(missing); ++j) { if ((i <= missing[j].first) && (i >= missing[j].last)) { this_missing = 1; break; } } errStr = wolfSSL_ERR_reason_error_string((word32)i); if (! this_missing) { ExpectIntNE(XSTRCMP(errStr, unknownStr), 0); if (EXPECT_FAIL()) { return i; } ExpectTrue(XSTRLEN(errStr) < WOLFSSL_MAX_ERROR_SZ); if (EXPECT_FAIL()) { return i; } } else { j++; ExpectIntEQ(XSTRCMP(errStr, unknownStr), 0); if (EXPECT_FAIL()) { return i; } } } #endif return 1; } static int test_wolfSSL_ERR_strings(void) { EXPECT_DECLS; #if !defined(NO_ERROR_STRINGS) const char* err1 = "unsupported cipher suite"; const char* err2 = "wolfSSL PEM routines"; const char* err = NULL; (void)err; (void)err1; (void)err2; #if defined(OPENSSL_EXTRA) ExpectNotNull(err = ERR_reason_error_string(WC_NO_ERR_TRACE(UNSUPPORTED_SUITE))); ExpectIntEQ(XSTRNCMP(err, err1, XSTRLEN(err1)), 0); ExpectNotNull(err = ERR_func_error_string(WC_NO_ERR_TRACE(UNSUPPORTED_SUITE))); ExpectIntEQ((*err == '\0'), 1); ExpectNotNull(err = ERR_lib_error_string(PEM_R_PROBLEMS_GETTING_PASSWORD)); ExpectIntEQ(XSTRNCMP(err, err2, XSTRLEN(err2)), 0); #else ExpectNotNull(err = wolfSSL_ERR_reason_error_string(WC_NO_ERR_TRACE((word32)UNSUPPORTED_SUITE))); ExpectIntEQ(XSTRNCMP(err, err1, XSTRLEN(err1)), 0); ExpectNotNull(err = wolfSSL_ERR_func_error_string(WC_NO_ERR_TRACE((word32)UNSUPPORTED_SUITE))); ExpectIntEQ((*err == '\0'), 1); ExpectNotNull(err = wolfSSL_ERR_lib_error_string(-WOLFSSL_PEM_R_PROBLEMS_GETTING_PASSWORD_E)); ExpectIntEQ((*err == '\0'), 1); #endif #endif ExpectIntEQ(error_test(), 1); return EXPECT_RESULT(); } static int test_SSL_CIPHER_get_xxx(void) { EXPECT_DECLS; #if defined(OPENSSL_ALL) && !defined(NO_CERTS) && \ !defined(NO_FILESYSTEM) && !defined(NO_TLS) const SSL_CIPHER* cipher = NULL; STACK_OF(SSL_CIPHER) *supportedCiphers = NULL; int i, numCiphers = 0; SSL_CTX* ctx = NULL; SSL* ssl = NULL; const char* testCertFile; const char* testKeyFile; char buf[256] = {0}; const char* cipher_id = NULL; int expect_nid1 = NID_undef; int expect_nid2 = NID_undef; int expect_nid3 = NID_undef; int expect_nid4 = NID_undef; int expect_nid5 = 0; const char* cipher_id2 = NULL; int expect_nid21 = NID_undef; int expect_nid22 = NID_undef; int expect_nid23 = NID_undef; int expect_nid24 = NID_undef; int expect_nid25 = 0; (void)cipher; (void)supportedCiphers; (void)i; (void)numCiphers; (void)ctx; (void)ssl; (void)testCertFile; (void)testKeyFile; #if defined(WOLFSSL_TLS13) cipher_id = "TLS13-AES128-GCM-SHA256"; expect_nid1 = NID_auth_rsa; expect_nid2 = NID_aes_128_gcm; expect_nid3 = NID_sha256; expect_nid4 = NID_kx_any; expect_nid5 = 1; #if !defined(WOLFSSL_NO_TLS12) cipher_id2 = "ECDHE-RSA-AES256-GCM-SHA384"; expect_nid21 = NID_auth_rsa; expect_nid22 = NID_aes_256_gcm; expect_nid23 = NID_sha384; expect_nid24 = NID_kx_ecdhe; expect_nid25 = 1; #endif #endif #ifdef NO_WOLFSSL_SERVER ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); #else ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); #endif if (cipher_id) { #ifndef NO_RSA testCertFile = svrCertFile; testKeyFile = svrKeyFile; #elif defined(HAVE_ECC) testCertFile = eccCertFile; testKeyFile = eccKeyFile; #else testCertFile = NULL; testKeyFile = NULL; #endif if (testCertFile != NULL && testKeyFile != NULL) { ExpectTrue(SSL_CTX_use_certificate_file(ctx, testCertFile, SSL_FILETYPE_PEM)); ExpectTrue(SSL_CTX_use_PrivateKey_file(ctx, testKeyFile, SSL_FILETYPE_PEM)); } ExpectNotNull(ssl = SSL_new(ctx)); ExpectIntEQ(SSL_in_init(ssl), 1); supportedCiphers = SSL_get_ciphers(ssl); numCiphers = sk_num(supportedCiphers); for (i = 0; i < numCiphers; ++i) { if ((cipher = (const WOLFSSL_CIPHER*)sk_value(supportedCiphers, i))) { SSL_CIPHER_description(cipher, buf, sizeof(buf)); } if (XMEMCMP(cipher_id, buf, XSTRLEN(cipher_id)) == 0) { break; } } /* test case for */ if (i != numCiphers) { ExpectIntEQ(wolfSSL_CIPHER_get_auth_nid(cipher), expect_nid1); ExpectIntEQ(wolfSSL_CIPHER_get_cipher_nid(cipher), expect_nid2); ExpectIntEQ(wolfSSL_CIPHER_get_digest_nid(cipher), expect_nid3); ExpectIntEQ(wolfSSL_CIPHER_get_kx_nid(cipher), expect_nid4); ExpectIntEQ(wolfSSL_CIPHER_is_aead(cipher), expect_nid5); } if (cipher_id2) { for (i = 0; i < numCiphers; ++i) { if ((cipher = (const WOLFSSL_CIPHER*)sk_value(supportedCiphers, i))) { SSL_CIPHER_description(cipher, buf, sizeof(buf)); } if (XMEMCMP(cipher_id2, buf, XSTRLEN(cipher_id2)) == 0) { break; } } /* test case for */ if (i != numCiphers) { ExpectIntEQ(wolfSSL_CIPHER_get_auth_nid(cipher), expect_nid21); ExpectIntEQ(wolfSSL_CIPHER_get_cipher_nid(cipher), expect_nid22); ExpectIntEQ(wolfSSL_CIPHER_get_digest_nid(cipher), expect_nid23); ExpectIntEQ(wolfSSL_CIPHER_get_kx_nid(cipher), expect_nid24); ExpectIntEQ(wolfSSL_CIPHER_is_aead(cipher), expect_nid25); } } } SSL_CTX_free(ctx); SSL_free(ssl); #endif return EXPECT_RESULT(); } #if defined(WOLF_CRYPTO_CB) && defined(HAVE_IO_TESTS_DEPENDENCIES) && \ (!defined(WOLF_CRYPTO_CB_ONLY_SHA256) && !defined(WOLF_CRYPTO_CB_ONLY_AES) && \ !defined(WOLF_CRYPTO_CB_ONLY_ECC) && !defined(WOLF_CRYPTO_CB_ONLY_RSA)) static int load_pem_key_file_as_der(const char* privKeyFile, DerBuffer** pDer, int* keyFormat) { int ret; byte* key_buf = NULL; size_t key_sz = 0; EncryptedInfo encInfo; XMEMSET(&encInfo, 0, sizeof(encInfo)); ret = load_file(privKeyFile, &key_buf, &key_sz); if (ret == 0) { ret = wc_PemToDer(key_buf, key_sz, PRIVATEKEY_TYPE, pDer, NULL, &encInfo, keyFormat); } if (key_buf != NULL) { XFREE(key_buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); key_buf = NULL; } (void)encInfo; /* not used in this test */ #ifdef DEBUG_WOLFSSL fprintf(stderr, "%s (%d): Loading PEM %s (len %d) to DER (len %d)\n", (ret == 0) ? "Success" : "Failure", ret, privKeyFile, (int)key_sz, (*pDer)->length); #endif return ret; } static int test_CryptoCb_Func(int thisDevId, wc_CryptoInfo* info, void* ctx) { int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); const char* privKeyFile = (const char*)ctx; DerBuffer* pDer = NULL; int keyFormat = 0; if (info->algo_type == WC_ALGO_TYPE_PK) { #ifdef DEBUG_WOLFSSL fprintf(stderr, "test_CryptoCb_Func: Pk Type %d\n", info->pk.type); #endif #ifndef NO_RSA if (info->pk.type == WC_PK_TYPE_RSA) { switch (info->pk.rsa.type) { case RSA_PUBLIC_ENCRYPT: case RSA_PUBLIC_DECRYPT: /* perform software based RSA public op */ ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); /* fallback to software */ break; case RSA_PRIVATE_ENCRYPT: case RSA_PRIVATE_DECRYPT: { RsaKey key; /* perform software based RSA private op */ #ifdef DEBUG_WOLFSSL fprintf(stderr, "test_CryptoCb_Func: RSA Priv\n"); #endif ret = load_pem_key_file_as_der(privKeyFile, &pDer, &keyFormat); if (ret != 0) { return ret; } ret = wc_InitRsaKey(&key, HEAP_HINT); if (ret == 0) { word32 keyIdx = 0; /* load RSA private key and perform private transform */ ret = wc_RsaPrivateKeyDecode(pDer->buffer, &keyIdx, &key, pDer->length); if (ret == 0) { ret = wc_RsaFunction( info->pk.rsa.in, info->pk.rsa.inLen, info->pk.rsa.out, info->pk.rsa.outLen, info->pk.rsa.type, &key, info->pk.rsa.rng); } else { /* if decode fails, then fall-back to software based crypto */ fprintf(stderr, "test_CryptoCb_Func: RSA private " "key decode failed %d, falling back to " "software\n", ret); ret = CRYPTOCB_UNAVAILABLE; } wc_FreeRsaKey(&key); } wc_FreeDer(&pDer); pDer = NULL; break; } } #ifdef DEBUG_WOLFSSL fprintf(stderr, "test_CryptoCb_Func: RSA Type %d, Ret %d, Out %d\n", info->pk.rsa.type, ret, *info->pk.rsa.outLen); #endif } #ifdef WOLF_CRYPTO_CB_RSA_PAD else if (info->pk.type == WC_PK_TYPE_RSA_PKCS || info->pk.type == WC_PK_TYPE_RSA_PSS || info->pk.type == WC_PK_TYPE_RSA_OAEP) { RsaKey key; if (info->pk.rsa.type == RSA_PUBLIC_ENCRYPT || info->pk.rsa.type == RSA_PUBLIC_DECRYPT) { /* Have all public key ops fall back to SW */ return CRYPTOCB_UNAVAILABLE; } if (info->pk.rsa.padding == NULL) { return BAD_FUNC_ARG; } /* Initialize key */ ret = load_pem_key_file_as_der(privKeyFile, &pDer, &keyFormat); if (ret != 0) { return ret; } ret = wc_InitRsaKey(&key, HEAP_HINT); if (ret == 0) { word32 keyIdx = 0; /* load RSA private key and perform private transform */ ret = wc_RsaPrivateKeyDecode(pDer->buffer, &keyIdx, &key, pDer->length); } /* Perform RSA operation */ if ((ret == 0) && (info->pk.type == WC_PK_TYPE_RSA_PKCS)) { #if !defined(WOLFSSL_RSA_PUBLIC_ONLY) && !defined(WOLFSSL_RSA_VERIFY_ONLY) ret = wc_RsaSSL_Sign(info->pk.rsa.in, info->pk.rsa.inLen, info->pk.rsa.out, *info->pk.rsa.outLen, &key, info->pk.rsa.rng); #else ret = CRYPTOCB_UNAVAILABLE; #endif } if ((ret == 0) && (info->pk.type == WC_PK_TYPE_RSA_PSS)) { #ifdef WC_RSA_PSS ret = wc_RsaPSS_Sign_ex(info->pk.rsa.in, info->pk.rsa.inLen, info->pk.rsa.out, *info->pk.rsa.outLen, info->pk.rsa.padding->hash, info->pk.rsa.padding->mgf, info->pk.rsa.padding->saltLen, &key, info->pk.rsa.rng); #else ret = CRYPTOCB_UNAVAILABLE; #endif } if ((ret == 0) && (info->pk.type == WC_PK_TYPE_RSA_OAEP)) { #if !defined(WC_NO_RSA_OAEP) || defined(WC_RSA_NO_PADDING) ret = wc_RsaPrivateDecrypt_ex( info->pk.rsa.in, info->pk.rsa.inLen, info->pk.rsa.out, *info->pk.rsa.outLen, &key, WC_RSA_OAEP_PAD, info->pk.rsa.padding->hash, info->pk.rsa.padding->mgf, info->pk.rsa.padding->label, info->pk.rsa.padding->labelSz); #else ret = CRYPTOCB_UNAVAILABLE; #endif } if (ret > 0) { *info->pk.rsa.outLen = ret; } wc_FreeRsaKey(&key); wc_FreeDer(&pDer); pDer = NULL; } #endif /* ifdef WOLF_CRYPTO_CB_RSA_PAD */ #endif /* !NO_RSA */ #ifdef HAVE_ECC if (info->pk.type == WC_PK_TYPE_EC_KEYGEN) { /* mark this key as ephemeral */ if (info->pk.eckg.key != NULL) { XSTRNCPY(info->pk.eckg.key->label, "ephemeral", sizeof(info->pk.eckg.key->label)); info->pk.eckg.key->labelLen = (int)XSTRLEN(info->pk.eckg.key->label); } } else if (info->pk.type == WC_PK_TYPE_ECDSA_SIGN) { ecc_key key; /* perform software based ECC sign */ #ifdef DEBUG_WOLFSSL fprintf(stderr, "test_CryptoCb_Func: ECC Sign\n"); #endif if (info->pk.eccsign.key != NULL && XSTRCMP(info->pk.eccsign.key->label, "ephemeral") == 0) { /* this is an empheral key */ #ifdef DEBUG_WOLFSSL fprintf(stderr, "test_CryptoCb_Func: skipping signing op on " "ephemeral key\n"); #endif return CRYPTOCB_UNAVAILABLE; } ret = load_pem_key_file_as_der(privKeyFile, &pDer, &keyFormat); if (ret != 0) { return ret; } ret = wc_ecc_init(&key); if (ret == 0) { word32 keyIdx = 0; /* load ECC private key and perform private transform */ ret = wc_EccPrivateKeyDecode(pDer->buffer, &keyIdx, &key, pDer->length); if (ret == 0) { ret = wc_ecc_sign_hash( info->pk.eccsign.in, info->pk.eccsign.inlen, info->pk.eccsign.out, info->pk.eccsign.outlen, info->pk.eccsign.rng, &key); } else { /* if decode fails, then fall-back to software based crypto */ fprintf(stderr, "test_CryptoCb_Func: ECC private key " "decode failed %d, falling back to software\n", ret); ret = CRYPTOCB_UNAVAILABLE; } wc_ecc_free(&key); } wc_FreeDer(&pDer); pDer = NULL; #ifdef DEBUG_WOLFSSL fprintf(stderr, "test_CryptoCb_Func: ECC Ret %d, Out %d\n", ret, *info->pk.eccsign.outlen); #endif } else if (info->pk.type == WC_PK_TYPE_EC_GET_SIZE) { WC_DECLARE_VAR(tmpEcc, ecc_key, 1, NULL); WC_ALLOC_VAR(tmpEcc, ecc_key, 1, NULL); if (!WC_VAR_OK(tmpEcc)) { ret = MEMORY_E; } else { XMEMCPY(tmpEcc, info->pk.ecc_get_size.key, sizeof(ecc_key)); tmpEcc->devId = INVALID_DEVID; *info->pk.ecc_get_size.keySize = wc_ecc_size(tmpEcc); WC_FREE_VAR(tmpEcc, NULL); ret = 0; } } else if (info->pk.type == WC_PK_TYPE_EC_GET_SIG_SIZE) { WC_DECLARE_VAR(tmpEcc, ecc_key, 1, NULL); WC_ALLOC_VAR(tmpEcc, ecc_key, 1, NULL); if (!WC_VAR_OK(tmpEcc)) { ret = MEMORY_E; } else { XMEMCPY(tmpEcc, info->pk.ecc_get_sig_size.key, sizeof(ecc_key)); tmpEcc->devId = INVALID_DEVID; *info->pk.ecc_get_sig_size.sigSize = wc_ecc_sig_size(tmpEcc); WC_FREE_VAR(tmpEcc, NULL); ret = 0; } } #endif /* HAVE_ECC */ #ifdef HAVE_ED25519 if (info->pk.type == WC_PK_TYPE_ED25519_SIGN) { ed25519_key key; /* perform software based ED25519 sign */ #ifdef DEBUG_WOLFSSL fprintf(stderr, "test_CryptoCb_Func: ED25519 Sign\n"); #endif ret = load_pem_key_file_as_der(privKeyFile, &pDer, &keyFormat); if (ret != 0) { return ret; } ret = wc_ed25519_init(&key); if (ret == 0) { word32 keyIdx = 0; /* load ED25519 private key and perform private transform */ ret = wc_Ed25519PrivateKeyDecode(pDer->buffer, &keyIdx, &key, pDer->length); if (ret == 0) { /* calculate public key */ ret = wc_ed25519_make_public(&key, key.p, ED25519_PUB_KEY_SIZE); if (ret == 0) { key.pubKeySet = 1; ret = wc_ed25519_sign_msg_ex( info->pk.ed25519sign.in, info->pk.ed25519sign.inLen, info->pk.ed25519sign.out, info->pk.ed25519sign.outLen, &key, info->pk.ed25519sign.type, info->pk.ed25519sign.context, info->pk.ed25519sign.contextLen); } } else { /* if decode fails, then fall-back to software based crypto */ fprintf(stderr, "test_CryptoCb_Func: ED25519 private key " "decode failed %d, falling back to software\n", ret); ret = CRYPTOCB_UNAVAILABLE; } wc_ed25519_free(&key); } wc_FreeDer(&pDer); pDer = NULL; #ifdef DEBUG_WOLFSSL fprintf(stderr, "test_CryptoCb_Func: ED25519 Ret %d, Out %d\n", ret, *info->pk.ed25519sign.outLen); #endif } #endif /* HAVE_ED25519 */ } #ifdef WOLF_CRYPTO_CB_COPY else if (info->algo_type == WC_ALGO_TYPE_COPY) { #ifdef DEBUG_WOLFSSL fprintf(stderr, "test_CryptoCb_Func: Copy Algo=%d Type=%d\n", info->copy.algo, info->copy.type); #endif if (info->copy.algo == WC_ALGO_TYPE_HASH) { switch (info->copy.type) { #ifndef NO_SHA case WC_HASH_TYPE_SHA: { wc_Sha* src = (wc_Sha*)info->copy.src; wc_Sha* dst = (wc_Sha*)info->copy.dst; src->devId = INVALID_DEVID; ret = wc_ShaCopy(src, dst); src->devId = thisDevId; if (ret == 0) { dst->devId = thisDevId; } break; } #endif #ifdef WOLFSSL_SHA224 case WC_HASH_TYPE_SHA224: { wc_Sha224* src = (wc_Sha224*)info->copy.src; wc_Sha224* dst = (wc_Sha224*)info->copy.dst; src->devId = INVALID_DEVID; ret = wc_Sha224Copy(src, dst); src->devId = thisDevId; if (ret == 0) { dst->devId = thisDevId; } break; } #endif #ifndef NO_SHA256 case WC_HASH_TYPE_SHA256: { wc_Sha256* src = (wc_Sha256*)info->copy.src; wc_Sha256* dst = (wc_Sha256*)info->copy.dst; /* set devId to invalid, so software is used */ src->devId = INVALID_DEVID; ret = wc_Sha256Copy(src, dst); /* reset devId */ src->devId = thisDevId; if (ret == 0) { /* Set the devId of the destination to the same */ /* since we used the software implementation of copy */ /* so dst would have been set to INVALID_DEVID */ dst->devId = thisDevId; } break; } #endif /* !NO_SHA256 */ #ifdef WOLFSSL_SHA384 case WC_HASH_TYPE_SHA384: { wc_Sha384* src = (wc_Sha384*)info->copy.src; wc_Sha384* dst = (wc_Sha384*)info->copy.dst; src->devId = INVALID_DEVID; ret = wc_Sha384Copy(src, dst); src->devId = thisDevId; if (ret == 0) { dst->devId = thisDevId; } break; } #endif #ifdef WOLFSSL_SHA512 case WC_HASH_TYPE_SHA512: { wc_Sha512* src = (wc_Sha512*)info->copy.src; wc_Sha512* dst = (wc_Sha512*)info->copy.dst; src->devId = INVALID_DEVID; ret = wc_Sha512Copy(src, dst); src->devId = thisDevId; if (ret == 0) { dst->devId = thisDevId; } break; } #endif #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224) case WC_HASH_TYPE_SHA3_224: { wc_Sha3* src = (wc_Sha3*)info->copy.src; wc_Sha3* dst = (wc_Sha3*)info->copy.dst; src->devId = INVALID_DEVID; ret = wc_Sha3_224_Copy(src, dst); src->devId = thisDevId; if (ret == 0) { dst->devId = thisDevId; } break; } #endif #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256) case WC_HASH_TYPE_SHA3_256: { wc_Sha3* src = (wc_Sha3*)info->copy.src; wc_Sha3* dst = (wc_Sha3*)info->copy.dst; src->devId = INVALID_DEVID; ret = wc_Sha3_256_Copy(src, dst); src->devId = thisDevId; if (ret == 0) { dst->devId = thisDevId; } break; } #endif #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_384) case WC_HASH_TYPE_SHA3_384: { wc_Sha3* src = (wc_Sha3*)info->copy.src; wc_Sha3* dst = (wc_Sha3*)info->copy.dst; src->devId = INVALID_DEVID; ret = wc_Sha3_384_Copy(src, dst); src->devId = thisDevId; if (ret == 0) { dst->devId = thisDevId; } break; } #endif #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_512) case WC_HASH_TYPE_SHA3_512: { wc_Sha3* src = (wc_Sha3*)info->copy.src; wc_Sha3* dst = (wc_Sha3*)info->copy.dst; src->devId = INVALID_DEVID; ret = wc_Sha3_512_Copy(src, dst); src->devId = thisDevId; if (ret == 0) { dst->devId = thisDevId; } break; } #endif default: ret = WC_NO_ERR_TRACE(NOT_COMPILED_IN); break; } } else { ret = WC_NO_ERR_TRACE(NOT_COMPILED_IN); } } #endif /* WOLF_CRYPTO_CB_COPY */ #ifdef WOLF_CRYPTO_CB_FREE else if (info->algo_type == WC_ALGO_TYPE_FREE) { #ifdef DEBUG_WOLFSSL fprintf(stderr, "test_CryptoCb_Func: Free Algo=%d Type=%d\n", info->free.algo, info->free.type); #endif if (info->free.algo == WC_ALGO_TYPE_HASH) { switch (info->free.type) { #ifndef NO_SHA case WC_HASH_TYPE_SHA: { wc_Sha* sha = (wc_Sha*)info->free.obj; sha->devId = INVALID_DEVID; wc_ShaFree(sha); ret = 0; break; } #endif #ifdef WOLFSSL_SHA224 case WC_HASH_TYPE_SHA224: { wc_Sha224* sha = (wc_Sha224*)info->free.obj; sha->devId = INVALID_DEVID; wc_Sha224Free(sha); ret = 0; break; } #endif #ifndef NO_SHA256 case WC_HASH_TYPE_SHA256: { wc_Sha256* sha = (wc_Sha256*)info->free.obj; /* set devId to invalid, so software is used */ sha->devId = INVALID_DEVID; /* Call the actual free function */ wc_Sha256Free(sha); /* Note: devId doesn't need to be restored as object is freed */ ret = 0; break; } #endif #ifdef WOLFSSL_SHA384 case WC_HASH_TYPE_SHA384: { wc_Sha384* sha = (wc_Sha384*)info->free.obj; sha->devId = INVALID_DEVID; wc_Sha384Free(sha); ret = 0; break; } #endif #ifdef WOLFSSL_SHA512 case WC_HASH_TYPE_SHA512: { wc_Sha512* sha = (wc_Sha512*)info->free.obj; sha->devId = INVALID_DEVID; wc_Sha512Free(sha); ret = 0; break; } #endif #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224) case WC_HASH_TYPE_SHA3_224: { wc_Sha3* sha = (wc_Sha3*)info->free.obj; sha->devId = INVALID_DEVID; wc_Sha3_224_Free(sha); ret = 0; break; } #endif #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256) case WC_HASH_TYPE_SHA3_256: { wc_Sha3* sha = (wc_Sha3*)info->free.obj; sha->devId = INVALID_DEVID; wc_Sha3_256_Free(sha); ret = 0; break; } #endif #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_384) case WC_HASH_TYPE_SHA3_384: { wc_Sha3* sha = (wc_Sha3*)info->free.obj; sha->devId = INVALID_DEVID; wc_Sha3_384_Free(sha); ret = 0; break; } #endif #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_512) case WC_HASH_TYPE_SHA3_512: { wc_Sha3* sha = (wc_Sha3*)info->free.obj; sha->devId = INVALID_DEVID; wc_Sha3_512_Free(sha); ret = 0; break; } #endif default: ret = WC_NO_ERR_TRACE(NOT_COMPILED_IN); break; } } else if (info->free.algo == WC_ALGO_TYPE_CIPHER) { switch (info->free.type) { #ifndef NO_AES case WC_CIPHER_AES: { Aes* aes = (Aes*)info->free.obj; aes->devId = INVALID_DEVID; wc_AesFree(aes); ret = 0; break; } #endif default: ret = WC_NO_ERR_TRACE(NOT_COMPILED_IN); break; } } else { ret = WC_NO_ERR_TRACE(NOT_COMPILED_IN); } } #endif /* WOLF_CRYPTO_CB_FREE */ #ifdef WOLF_CRYPTO_CB_SETKEY else if (info->algo_type == WC_ALGO_TYPE_SETKEY) { #ifdef DEBUG_WOLFSSL fprintf(stderr, "test_CryptoCb_Func: SetKey Type=%d\n", info->setkey.type); #endif switch (info->setkey.type) { #ifndef NO_AES case WC_SETKEY_AES: { Aes* aes = (Aes*)info->setkey.obj; aes->devId = INVALID_DEVID; ret = wc_AesSetKey(aes, (const byte*)info->setkey.key, info->setkey.keySz, (const byte*)info->setkey.aux, info->setkey.flags); aes->devId = thisDevId; break; } #endif /* !NO_AES */ #ifndef NO_HMAC case WC_SETKEY_HMAC: { Hmac* hmac = (Hmac*)info->setkey.obj; hmac->devId = INVALID_DEVID; ret = wc_HmacSetKey(hmac, hmac->macType, (const byte*)info->setkey.key, info->setkey.keySz); hmac->devId = thisDevId; break; } #endif /* !NO_HMAC */ #if !defined(NO_RSA) && defined(WOLFSSL_KEY_TO_DER) case WC_SETKEY_RSA_PUB: { RsaKey* rsaObj = (RsaKey*)info->setkey.obj; RsaKey* rsaTmp = (RsaKey*)info->setkey.key; int derSz; word32 idx = 0; byte* der = NULL; derSz = wc_RsaPublicKeyDerSize(rsaTmp, 1); if (derSz <= 0) { ret = derSz; break; } der = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (der == NULL) { ret = MEMORY_E; break; } derSz = wc_RsaKeyToPublicDer_ex(rsaTmp, der, (word32)derSz, 1); if (derSz <= 0) { XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); ret = derSz; break; } rsaObj->devId = INVALID_DEVID; ret = wc_RsaPublicKeyDecode(der, &idx, rsaObj, (word32)derSz); rsaObj->devId = thisDevId; XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); break; } case WC_SETKEY_RSA_PRIV: { RsaKey* rsaObj = (RsaKey*)info->setkey.obj; RsaKey* rsaTmp = (RsaKey*)info->setkey.key; int derSz; word32 idx = 0; byte* der = NULL; derSz = wc_RsaKeyToDer(rsaTmp, NULL, 0); if (derSz <= 0) { ret = derSz; break; } der = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (der == NULL) { ret = MEMORY_E; break; } derSz = wc_RsaKeyToDer(rsaTmp, der, (word32)derSz); if (derSz <= 0) { XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); ret = derSz; break; } rsaObj->devId = INVALID_DEVID; ret = wc_RsaPrivateKeyDecode(der, &idx, rsaObj, (word32)derSz); rsaObj->devId = thisDevId; XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); break; } #endif /* !NO_RSA && WOLFSSL_KEY_TO_DER */ #if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) && \ defined(HAVE_ECC_KEY_IMPORT) case WC_SETKEY_ECC_PUB: { ecc_key* eccObj = (ecc_key*)info->setkey.obj; ecc_key* eccTmp = (ecc_key*)info->setkey.key; word32 bufSz = ECC_BUFSIZE; int curveId; WC_DECLARE_VAR(buf, byte, ECC_BUFSIZE, NULL); WC_ALLOC_VAR(buf, byte, ECC_BUFSIZE, NULL); if (!WC_VAR_OK(buf)) { ret = MEMORY_E; break; } ret = wc_ecc_export_x963(eccTmp, buf, &bufSz); if (ret != 0) { WC_FREE_VAR(buf, NULL); break; } curveId = wc_ecc_get_curve_id(eccTmp->idx); eccObj->devId = INVALID_DEVID; ret = wc_ecc_import_x963_ex2(buf, bufSz, eccObj, curveId, 0); eccObj->devId = thisDevId; WC_FREE_VAR(buf, NULL); break; } case WC_SETKEY_ECC_PRIV: { ecc_key* eccObj = (ecc_key*)info->setkey.obj; ecc_key* eccTmp = (ecc_key*)info->setkey.key; word32 pubSz = ECC_BUFSIZE; word32 privSz = MAX_ECC_BYTES; byte* pubPtr = NULL; int curveId; WC_DECLARE_VAR(pubBuf, byte, ECC_BUFSIZE, NULL); WC_DECLARE_VAR(privBuf, byte, MAX_ECC_BYTES, NULL); WC_ALLOC_VAR(pubBuf, byte, ECC_BUFSIZE, NULL); WC_ALLOC_VAR(privBuf, byte, MAX_ECC_BYTES, NULL); if (!WC_VAR_OK(pubBuf) || !WC_VAR_OK(privBuf)) { WC_FREE_VAR(pubBuf, NULL); WC_FREE_VAR(privBuf, NULL); ret = MEMORY_E; break; } /* Export public key from temp (if available) */ if (eccTmp->type != ECC_PRIVATEKEY_ONLY) { ret = wc_ecc_export_x963(eccTmp, pubBuf, &pubSz); if (ret != 0) { WC_FREE_VAR(pubBuf, NULL); WC_FREE_VAR(privBuf, NULL); break; } pubPtr = pubBuf; } ret = wc_ecc_export_private_only(eccTmp, privBuf, &privSz); if (ret != 0) { WC_FREE_VAR(pubBuf, NULL); WC_FREE_VAR(privBuf, NULL); break; } curveId = wc_ecc_get_curve_id(eccTmp->idx); eccObj->devId = INVALID_DEVID; ret = wc_ecc_import_private_key_ex(privBuf, privSz, pubPtr, (pubPtr != NULL) ? pubSz : 0, eccObj, curveId); eccObj->devId = thisDevId; WC_FREE_VAR(pubBuf, NULL); WC_FREE_VAR(privBuf, NULL); break; } #endif /* HAVE_ECC && HAVE_ECC_KEY_EXPORT && HAVE_ECC_KEY_IMPORT */ default: ret = WC_NO_ERR_TRACE(NOT_COMPILED_IN); break; } } #endif /* WOLF_CRYPTO_CB_SETKEY */ #ifdef WOLF_CRYPTO_CB_EXPORT_KEY else if (info->algo_type == WC_ALGO_TYPE_EXPORT_KEY) { #ifdef DEBUG_WOLFSSL fprintf(stderr, "test_CryptoCb_Func: ExportKey Type=%d\n", info->export_key.type); #endif switch (info->export_key.type) { #if !defined(NO_RSA) && defined(WOLFSSL_KEY_TO_DER) case WC_PK_TYPE_RSA: { RsaKey* src = (RsaKey*)info->export_key.obj; RsaKey* dst = (RsaKey*)info->export_key.out; int derSz; word32 idx = 0; byte* der = NULL; /* Try private key export first, fall back to public */ derSz = wc_RsaKeyToDer(src, NULL, 0); if (derSz > 0) { der = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (der == NULL) { ret = MEMORY_E; break; } derSz = wc_RsaKeyToDer(src, der, (word32)derSz); if (derSz > 0) { ret = wc_RsaPrivateKeyDecode(der, &idx, dst, (word32)derSz); } else { ret = derSz; } XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); } else { /* Public key only */ derSz = wc_RsaPublicKeyDerSize(src, 1); if (derSz <= 0) { ret = derSz; break; } der = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (der == NULL) { ret = MEMORY_E; break; } derSz = wc_RsaKeyToPublicDer_ex(src, der, (word32)derSz, 1); if (derSz > 0) { ret = wc_RsaPublicKeyDecode(der, &idx, dst, (word32)derSz); } else { ret = derSz; } XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); } break; } #endif /* !NO_RSA && WOLFSSL_KEY_TO_DER */ #if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) && \ defined(HAVE_ECC_KEY_IMPORT) case WC_PK_TYPE_ECDSA_SIGN: /* ECC key */ { ecc_key* src = (ecc_key*)info->export_key.obj; ecc_key* dst = (ecc_key*)info->export_key.out; word32 pubSz = ECC_BUFSIZE; word32 privSz = MAX_ECC_BYTES; byte* pubPtr = NULL; int curveId; WC_DECLARE_VAR(pubBuf, byte, ECC_BUFSIZE, NULL); WC_DECLARE_VAR(privBuf, byte, MAX_ECC_BYTES, NULL); WC_ALLOC_VAR(pubBuf, byte, ECC_BUFSIZE, NULL); WC_ALLOC_VAR(privBuf, byte, MAX_ECC_BYTES, NULL); if (!WC_VAR_OK(pubBuf) || !WC_VAR_OK(privBuf)) { WC_FREE_VAR(pubBuf, NULL); WC_FREE_VAR(privBuf, NULL); ret = MEMORY_E; break; } /* Use software to export from src - prevent recursion */ { int savedDevId = src->devId; src->devId = INVALID_DEVID; /* Export public key if available */ if (src->type != ECC_PRIVATEKEY_ONLY) { ret = wc_ecc_export_x963(src, pubBuf, &pubSz); if (ret != 0) { src->devId = savedDevId; WC_FREE_VAR(pubBuf, NULL); WC_FREE_VAR(privBuf, NULL); break; } pubPtr = pubBuf; } /* Export private key if available */ if (src->type != ECC_PUBLICKEY) { ret = wc_ecc_export_private_only(src, privBuf, &privSz); if (ret != 0) { src->devId = savedDevId; WC_FREE_VAR(pubBuf, NULL); WC_FREE_VAR(privBuf, NULL); break; } curveId = wc_ecc_get_curve_id(src->idx); ret = wc_ecc_import_private_key_ex(privBuf, privSz, pubPtr, (pubPtr != NULL) ? pubSz : 0, dst, curveId); } else { /* Public key only */ curveId = wc_ecc_get_curve_id(src->idx); ret = wc_ecc_import_x963_ex2(pubBuf, pubSz, dst, curveId, 0); } src->devId = savedDevId; } WC_FREE_VAR(pubBuf, NULL); WC_FREE_VAR(privBuf, NULL); break; } #endif /* HAVE_ECC && HAVE_ECC_KEY_EXPORT && HAVE_ECC_KEY_IMPORT */ default: ret = WC_NO_ERR_TRACE(NOT_COMPILED_IN); break; } } #endif /* WOLF_CRYPTO_CB_EXPORT_KEY */ (void)thisDevId; (void)keyFormat; return ret; } /* tlsVer: WOLFSSL_TLSV1_2 or WOLFSSL_TLSV1_3 */ static int test_wc_CryptoCb_TLS(int tlsVer, const char* cliCaPemFile, const char* cliCertPemFile, const char* cliPrivKeyPemFile, const char* cliPubKeyPemFile, const char* svrCaPemFile, const char* svrCertPemFile, const char* svrPrivKeyPemFile, const char* svrPubKeyPemFile) { EXPECT_DECLS; callback_functions client_cbf; callback_functions server_cbf; XMEMSET(&client_cbf, 0, sizeof(client_cbf)); XMEMSET(&server_cbf, 0, sizeof(server_cbf)); if (tlsVer == WOLFSSL_TLSV1_3) { #ifdef WOLFSSL_TLS13 server_cbf.method = wolfTLSv1_3_server_method; client_cbf.method = wolfTLSv1_3_client_method; #endif } else if (tlsVer == WOLFSSL_TLSV1_2) { #ifndef WOLFSSL_NO_TLS12 server_cbf.method = wolfTLSv1_2_server_method; client_cbf.method = wolfTLSv1_2_client_method; #endif } else if (tlsVer == WOLFSSL_TLSV1_1) { #ifndef NO_OLD_TLS server_cbf.method = wolfTLSv1_1_server_method; client_cbf.method = wolfTLSv1_1_client_method; #endif } else if (tlsVer == WOLFSSL_TLSV1) { #if !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_TLSV10) server_cbf.method = wolfTLSv1_server_method; client_cbf.method = wolfTLSv1_client_method; #endif } else if (tlsVer == WOLFSSL_SSLV3) { #if !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_SSLV3) && \ defined(WOLFSSL_STATIC_RSA) server_cbf.method = wolfSSLv3_server_method; client_cbf.method = wolfSSLv3_client_method; #endif } else if (tlsVer == WOLFSSL_DTLSV1_2) { #if defined(WOLFSSL_DTLS) && !defined(WOLFSSL_NO_TLS12) server_cbf.method = wolfDTLSv1_2_server_method; client_cbf.method = wolfDTLSv1_2_client_method; #endif } else if (tlsVer == WOLFSSL_DTLSV1) { #if defined(WOLFSSL_DTLS) && !defined(NO_OLD_TLS) server_cbf.method = wolfDTLSv1_server_method; client_cbf.method = wolfDTLSv1_client_method; #endif } if (server_cbf.method == NULL) { /* not enabled */ return TEST_SUCCESS; } /* Setup the keys for the TLS test */ client_cbf.certPemFile = cliCertPemFile; client_cbf.keyPemFile = cliPubKeyPemFile; client_cbf.caPemFile = cliCaPemFile; server_cbf.certPemFile = svrCertPemFile; server_cbf.keyPemFile = svrPubKeyPemFile; server_cbf.caPemFile = svrCaPemFile; /* Setup a crypto callback with pointer to private key file for testing */ client_cbf.devId = 1; wc_CryptoCb_RegisterDevice(client_cbf.devId, test_CryptoCb_Func, (void*)cliPrivKeyPemFile); server_cbf.devId = 2; wc_CryptoCb_RegisterDevice(server_cbf.devId, test_CryptoCb_Func, (void*)svrPrivKeyPemFile); /* Perform TLS server and client test */ /* First test is at WOLFSSL_CTX level */ test_wolfSSL_client_server(&client_cbf, &server_cbf); /* Check for success */ ExpectIntEQ(server_cbf.return_code, TEST_SUCCESS); ExpectIntEQ(client_cbf.return_code, TEST_SUCCESS); if (EXPECT_SUCCESS()) { /* Second test is a WOLFSSL object level */ client_cbf.loadToSSL = 1; server_cbf.loadToSSL = 1; test_wolfSSL_client_server(&client_cbf, &server_cbf); } /* Check for success */ ExpectIntEQ(server_cbf.return_code, TEST_SUCCESS); ExpectIntEQ(client_cbf.return_code, TEST_SUCCESS); /* Un register the devId's */ wc_CryptoCb_UnRegisterDevice(client_cbf.devId); client_cbf.devId = INVALID_DEVID; wc_CryptoCb_UnRegisterDevice(server_cbf.devId); server_cbf.devId = INVALID_DEVID; return EXPECT_RESULT(); } #endif /* WOLF_CRYPTO_CB && HAVE_IO_TESTS_DEPENDENCIES */ static int test_wc_CryptoCb(void) { EXPECT_DECLS; #if defined(WOLF_CRYPTO_CB) && \ (!defined(WOLF_CRYPTO_CB_ONLY_SHA256) && !defined(WOLF_CRYPTO_CB_ONLY_AES) && \ !defined(WOLF_CRYPTO_CB_ONLY_ECC) && !defined(WOLF_CRYPTO_CB_ONLY_RSA)) /* TODO: Add crypto callback API tests */ #ifdef HAVE_IO_TESTS_DEPENDENCIES #if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) int tlsVer; #endif #ifndef NO_RSA for (tlsVer = WOLFSSL_SSLV3; tlsVer <= WOLFSSL_DTLSV1; tlsVer++) { ExpectIntEQ(test_wc_CryptoCb_TLS(tlsVer, svrCertFile, cliCertFile, cliKeyFile, cliKeyPubFile, cliCertFile, svrCertFile, svrKeyFile, svrKeyPubFile), TEST_SUCCESS); } #endif #ifdef HAVE_ECC for (tlsVer = WOLFSSL_TLSV1; tlsVer <= WOLFSSL_DTLSV1; tlsVer++) { ExpectIntEQ(test_wc_CryptoCb_TLS(tlsVer, caEccCertFile, cliEccCertFile, cliEccKeyFile, cliEccKeyPubFile, cliEccCertFile, eccCertFile, eccKeyFile, eccKeyPubFile), TEST_SUCCESS); } #endif #ifdef HAVE_ED25519 for (tlsVer = WOLFSSL_TLSV1_2; tlsVer <= WOLFSSL_DTLSV1_2; tlsVer++) { if (tlsVer == WOLFSSL_DTLSV1) continue; ExpectIntEQ(test_wc_CryptoCb_TLS(tlsVer, caEdCertFile, cliEdCertFile, cliEdKeyFile, cliEdKeyPubFile, cliEdCertFile, edCertFile, edKeyFile, edKeyPubFile), TEST_SUCCESS); } #endif #endif /* HAVE_IO_TESTS_DEPENDENCIES */ #endif /* WOLF_CRYPTO_CB */ return EXPECT_RESULT(); } #if defined(WOLFSSL_STATIC_MEMORY) && defined(HAVE_IO_TESTS_DEPENDENCIES) /* tlsVer: Example: WOLFSSL_TLSV1_2 or WOLFSSL_TLSV1_3 */ static int test_wolfSSL_CTX_StaticMemory_TLS(int tlsVer, const char* cliCaPemFile, const char* cliCertPemFile, const char* cliPrivKeyPemFile, const char* svrCaPemFile, const char* svrCertPemFile, const char* svrPrivKeyPemFile, byte* cliMem, word32 cliMemSz, byte* svrMem, word32 svrMemSz) { EXPECT_DECLS; callback_functions client_cbf; callback_functions server_cbf; XMEMSET(&client_cbf, 0, sizeof(client_cbf)); XMEMSET(&server_cbf, 0, sizeof(server_cbf)); if (tlsVer == WOLFSSL_TLSV1_3) { #ifdef WOLFSSL_TLS13 server_cbf.method_ex = wolfTLSv1_3_server_method_ex; client_cbf.method_ex = wolfTLSv1_3_client_method_ex; #endif } else if (tlsVer == WOLFSSL_TLSV1_2) { #ifndef WOLFSSL_NO_TLS12 server_cbf.method_ex = wolfTLSv1_2_server_method_ex; client_cbf.method_ex = wolfTLSv1_2_client_method_ex; #endif } else if (tlsVer == WOLFSSL_TLSV1_1) { #ifndef NO_OLD_TLS server_cbf.method_ex = wolfTLSv1_1_server_method_ex; client_cbf.method_ex = wolfTLSv1_1_client_method_ex; #endif } else if (tlsVer == WOLFSSL_TLSV1) { #if !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_TLSV10) server_cbf.method_ex = wolfTLSv1_server_method_ex; client_cbf.method_ex = wolfTLSv1_client_method_ex; #endif } else if (tlsVer == WOLFSSL_SSLV3) { #if !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_SSLV3) && \ defined(WOLFSSL_STATIC_RSA) server_cbf.method_ex = wolfSSLv3_server_method_ex; client_cbf.method_ex = wolfSSLv3_client_method_ex; #endif } else if (tlsVer == WOLFSSL_DTLSV1_2) { #if defined(WOLFSSL_DTLS) && !defined(WOLFSSL_NO_TLS12) server_cbf.method_ex = wolfDTLSv1_2_server_method_ex; client_cbf.method_ex = wolfDTLSv1_2_client_method_ex; #endif } else if (tlsVer == WOLFSSL_DTLSV1) { #if defined(WOLFSSL_DTLS) && !defined(NO_OLD_TLS) server_cbf.method_ex = wolfDTLSv1_server_method_ex; client_cbf.method_ex = wolfDTLSv1_client_method_ex; #endif } if (server_cbf.method_ex == NULL) { /* not enabled */ return TEST_SUCCESS; } /* Setup the keys for the TLS test */ client_cbf.certPemFile = cliCertPemFile; client_cbf.keyPemFile = cliPrivKeyPemFile; client_cbf.caPemFile = cliCaPemFile; server_cbf.certPemFile = svrCertPemFile; server_cbf.keyPemFile = svrPrivKeyPemFile; server_cbf.caPemFile = svrCaPemFile; client_cbf.mem = cliMem; client_cbf.memSz = cliMemSz; server_cbf.mem = svrMem; server_cbf.memSz = svrMemSz; client_cbf.devId = INVALID_DEVID; server_cbf.devId = INVALID_DEVID; /* Perform TLS server and client test */ /* First test is at WOLFSSL_CTX level */ test_wolfSSL_client_server(&client_cbf, &server_cbf); /* Check for success */ ExpectIntEQ(server_cbf.return_code, TEST_SUCCESS); ExpectIntEQ(client_cbf.return_code, TEST_SUCCESS); if (EXPECT_SUCCESS()) { /* Second test is a WOLFSSL object level */ client_cbf.loadToSSL = 1; server_cbf.loadToSSL = 1; test_wolfSSL_client_server(&client_cbf, &server_cbf); } /* Check for success */ ExpectIntEQ(server_cbf.return_code, TEST_SUCCESS); ExpectIntEQ(client_cbf.return_code, TEST_SUCCESS); return EXPECT_RESULT(); } #endif /* WOLFSSL_STATIC_MEMORY && HAVE_IO_TESTS_DEPENDENCIES */ #if defined(WOLFSSL_STATIC_MEMORY) && !defined(WOLFCRYPT_ONLY) static int test_wolfSSL_CTX_StaticMemory_SSL(WOLFSSL_CTX* ctx) { EXPECT_DECLS; WOLFSSL *ssl1 = NULL, *ssl2 = NULL, *ssl3 = NULL; WOLFSSL_MEM_STATS mem_stats; WOLFSSL_MEM_CONN_STATS ssl_stats; #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_RSA) ExpectIntEQ(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); #endif ExpectNotNull((ssl1 = wolfSSL_new(ctx))); ExpectNotNull((ssl2 = wolfSSL_new(ctx))); #ifndef WOLFSSL_STATIC_MEMORY_LEAN /* this should fail because kMaxCtxClients == 2 */ ExpectNull((ssl3 = wolfSSL_new(ctx))); #else (void)ssl3; #endif if (wolfSSL_is_static_memory(ssl1, &ssl_stats) == 1) { #if defined(DEBUG_WOLFSSL) && !defined(WOLFSSL_STATIC_MEMORY_LEAN) wolfSSL_PrintStatsConn(&ssl_stats); #endif (void)ssl_stats; } /* display collected statistics */ if (wolfSSL_CTX_is_static_memory(ctx, &mem_stats) == 1) { #if defined(DEBUG_WOLFSSL) && !defined(WOLFSSL_STATIC_MEMORY_LEAN) wolfSSL_PrintStats(&mem_stats); #endif (void)mem_stats; } wolfSSL_free(ssl1); wolfSSL_free(ssl2); return EXPECT_RESULT(); } #endif /* WOLFSSL_STATIC_MEMORY && !WOLFCRYPT_ONLY */ static int test_wolfSSL_CTX_StaticMemory(void) { EXPECT_DECLS; #if defined(WOLFSSL_STATIC_MEMORY) && !defined(WOLFCRYPT_ONLY) wolfSSL_method_func method_func; WOLFSSL_CTX* ctx; const int kMaxCtxClients = 2; #ifdef HAVE_IO_TESTS_DEPENDENCIES #if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) int tlsVer; byte cliMem[TEST_TLS_STATIC_MEMSZ]; #endif #endif byte svrMem[TEST_TLS_STATIC_MEMSZ]; #ifndef NO_WOLFSSL_SERVER #ifndef WOLFSSL_NO_TLS12 method_func = wolfTLSv1_2_server_method_ex; #else method_func = wolfTLSv1_3_server_method_ex; #endif #else #ifndef WOLFSSL_NO_TLS12 method_func = wolfTLSv1_2_client_method_ex; #else method_func = wolfTLSv1_3_client_method_ex; #endif #endif /* Test creating CTX directly from static memory pool */ ctx = NULL; ExpectIntEQ(wolfSSL_CTX_load_static_memory(&ctx, method_func, svrMem, sizeof(svrMem), 0, kMaxCtxClients), WOLFSSL_SUCCESS); ExpectIntEQ(test_wolfSSL_CTX_StaticMemory_SSL(ctx), TEST_SUCCESS); wolfSSL_CTX_free(ctx); ctx = NULL; /* Test for heap allocated CTX, then assigning static pool to it */ ExpectNotNull(ctx = wolfSSL_CTX_new(method_func(NULL))); ExpectIntEQ(wolfSSL_CTX_load_static_memory(&ctx, NULL, svrMem, sizeof(svrMem), 0, kMaxCtxClients), WOLFSSL_SUCCESS); ExpectIntEQ(test_wolfSSL_CTX_StaticMemory_SSL(ctx), TEST_SUCCESS); wolfSSL_CTX_free(ctx); /* TLS Level Tests using static memory */ #ifdef HAVE_IO_TESTS_DEPENDENCIES #ifndef NO_RSA for (tlsVer = WOLFSSL_SSLV3; tlsVer <= WOLFSSL_DTLSV1; tlsVer++) { ExpectIntEQ(test_wolfSSL_CTX_StaticMemory_TLS(tlsVer, svrCertFile, cliCertFile, cliKeyFile, cliCertFile, svrCertFile, svrKeyFile, cliMem, (word32)sizeof(cliMem), svrMem, (word32)sizeof(svrMem)), TEST_SUCCESS); } #endif #ifdef HAVE_ECC for (tlsVer = WOLFSSL_TLSV1; tlsVer <= WOLFSSL_DTLSV1; tlsVer++) { ExpectIntEQ(test_wolfSSL_CTX_StaticMemory_TLS(tlsVer, caEccCertFile, cliEccCertFile, cliEccKeyFile, cliEccCertFile, eccCertFile, eccKeyFile, cliMem, (word32)sizeof(cliMem), svrMem, (word32)sizeof(svrMem)), TEST_SUCCESS); } #endif #ifdef HAVE_ED25519 for (tlsVer = WOLFSSL_TLSV1_2; tlsVer <= WOLFSSL_DTLSV1_2; tlsVer++) { if (tlsVer == WOLFSSL_DTLSV1) continue; ExpectIntEQ(test_wolfSSL_CTX_StaticMemory_TLS(tlsVer, caEdCertFile, cliEdCertFile, cliEdKeyFile, cliEdCertFile, edCertFile, edKeyFile, cliMem, (word32)sizeof(cliMem), svrMem, (word32)sizeof(svrMem)), TEST_SUCCESS); } #endif #endif /* HAVE_IO_TESTS_DEPENDENCIES */ #endif /* WOLFSSL_STATIC_MEMORY && !WOLFCRYPT_ONLY */ return EXPECT_RESULT(); } static int test_openssl_FIPS_drbg(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(WC_NO_RNG) && defined(HAVE_HASHDRBG) DRBG_CTX* dctx = NULL; byte data1[32], data2[32], zeroData[32]; byte testSeed[16]; size_t dlen = sizeof(data1); int i; XMEMSET(data1, 0, dlen); XMEMSET(data2, 0, dlen); XMEMSET(zeroData, 0, sizeof(zeroData)); for (i = 0; i < (int)sizeof(testSeed); i++) { testSeed[i] = (byte)i; } ExpectNotNull(dctx = FIPS_get_default_drbg()); ExpectIntEQ(FIPS_drbg_init(dctx, 0, 0), WOLFSSL_SUCCESS); ExpectIntEQ(FIPS_drbg_set_callbacks(dctx, NULL, NULL, 20, NULL, NULL), WOLFSSL_SUCCESS); ExpectIntEQ(FIPS_drbg_instantiate(dctx, NULL, 0), WOLFSSL_SUCCESS); ExpectIntEQ(FIPS_drbg_generate(dctx, data1, dlen, 0, NULL, 0), WOLFSSL_SUCCESS); ExpectIntNE(XMEMCMP(data1, zeroData, dlen), 0); ExpectIntEQ(FIPS_drbg_reseed(dctx, testSeed, sizeof(testSeed)), WOLFSSL_SUCCESS); ExpectIntEQ(FIPS_drbg_generate(dctx, data2, dlen, 0, NULL, 0), WOLFSSL_SUCCESS); ExpectIntNE(XMEMCMP(data1, zeroData, dlen), 0); ExpectIntNE(XMEMCMP(data1, data2, dlen), 0); ExpectIntEQ(FIPS_drbg_uninstantiate(dctx), WOLFSSL_SUCCESS); #ifndef HAVE_GLOBAL_RNG /* gets freed by wolfSSL_Cleanup() when HAVE_GLOBAL_RNG defined */ wolfSSL_FIPS_drbg_free(dctx); #endif #endif return EXPECT_RESULT(); } static int test_wolfSSL_FIPS_mode(void) { EXPECT_DECLS; #if defined(OPENSSL_ALL) #ifdef HAVE_FIPS ExpectIntEQ(wolfSSL_FIPS_mode(), 1); ExpectIntEQ(wolfSSL_FIPS_mode_set(0), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(wolfSSL_FIPS_mode_set(1), WOLFSSL_SUCCESS); #else ExpectIntEQ(wolfSSL_FIPS_mode(), 0); ExpectIntEQ(wolfSSL_FIPS_mode_set(0), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_FIPS_mode_set(1), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); #endif #endif return EXPECT_RESULT(); } #ifdef WOLFSSL_DTLS /* Prints out the current window */ static void DUW_TEST_print_window_binary(word32 h, word32 l, word32* w) { #ifdef WOLFSSL_DEBUG_DTLS_WINDOW int i; for (i = WOLFSSL_DTLS_WINDOW_WORDS - 1; i >= 0; i--) { word32 b = w[i]; int j; /* Prints out a 32 bit binary number in big endian order */ for (j = 0; j < 32; j++, b <<= 1) { if (b & (((word32)1) << 31)) fprintf(stderr, "1"); else fprintf(stderr, "0"); } fprintf(stderr, " "); } fprintf(stderr, "cur_hi %u cur_lo %u\n", h, l); #else (void)h; (void)l; (void)w; #endif } /* a - cur_hi * b - cur_lo * c - next_hi * d - next_lo * e - window * f - expected next_hi * g - expected next_lo * h - expected window[1] * i - expected window[0] */ #define DUW_TEST(a,b,c,d,e,f,g,h,i) do { \ ExpectIntEQ(wolfSSL_DtlsUpdateWindow((a), (b), &(c), &(d), (e)), 1); \ DUW_TEST_print_window_binary((a), (b), (e)); \ ExpectIntEQ((c), (f)); \ ExpectIntEQ((d), (g)); \ ExpectIntEQ((e)[1], (h)); \ ExpectIntEQ((e)[0], (i)); \ } while (0) static int test_wolfSSL_DtlsUpdateWindow(void) { EXPECT_DECLS; word32 window[WOLFSSL_DTLS_WINDOW_WORDS]; word32 next_lo = 0; word16 next_hi = 0; #ifdef WOLFSSL_DEBUG_DTLS_WINDOW fprintf(stderr, "\n"); #endif XMEMSET(window, 0, sizeof window); DUW_TEST(0, 0, next_hi, next_lo, window, 0, 1, 0, 0x01); DUW_TEST(0, 1, next_hi, next_lo, window, 0, 2, 0, 0x03); DUW_TEST(0, 5, next_hi, next_lo, window, 0, 6, 0, 0x31); DUW_TEST(0, 4, next_hi, next_lo, window, 0, 6, 0, 0x33); DUW_TEST(0, 100, next_hi, next_lo, window, 0, 101, 0, 0x01); DUW_TEST(0, 101, next_hi, next_lo, window, 0, 102, 0, 0x03); DUW_TEST(0, 133, next_hi, next_lo, window, 0, 134, 0x03, 0x01); DUW_TEST(0, 200, next_hi, next_lo, window, 0, 201, 0, 0x01); DUW_TEST(0, 264, next_hi, next_lo, window, 0, 265, 0, 0x01); DUW_TEST(0, 0xFFFFFFFF, next_hi, next_lo, window, 1, 0, 0, 0x01); DUW_TEST(0, 0xFFFFFFFD, next_hi, next_lo, window, 1, 0, 0, 0x05); DUW_TEST(0, 0xFFFFFFFE, next_hi, next_lo, window, 1, 0, 0, 0x07); DUW_TEST(1, 3, next_hi, next_lo, window, 1, 4, 0, 0x71); DUW_TEST(1, 0, next_hi, next_lo, window, 1, 4, 0, 0x79); DUW_TEST(1, 0xFFFFFFFF, next_hi, next_lo, window, 2, 0, 0, 0x01); DUW_TEST(2, 3, next_hi, next_lo, window, 2, 4, 0, 0x11); DUW_TEST(2, 0, next_hi, next_lo, window, 2, 4, 0, 0x19); DUW_TEST(2, 25, next_hi, next_lo, window, 2, 26, 0, 0x6400001); DUW_TEST(2, 27, next_hi, next_lo, window, 2, 28, 0, 0x19000005); DUW_TEST(2, 29, next_hi, next_lo, window, 2, 30, 0, 0x64000015); DUW_TEST(2, 33, next_hi, next_lo, window, 2, 34, 6, 0x40000151); DUW_TEST(2, 60, next_hi, next_lo, window, 2, 61, 0x3200000A, 0x88000001); DUW_TEST(1, 0xFFFFFFF0, next_hi, next_lo, window, 2, 61, 0x3200000A, 0x88000001); DUW_TEST(2, 0xFFFFFFFD, next_hi, next_lo, window, 2, 0xFFFFFFFE, 0, 0x01); DUW_TEST(3, 1, next_hi, next_lo, window, 3, 2, 0, 0x11); DUW_TEST(99, 66, next_hi, next_lo, window, 99, 67, 0, 0x01); DUW_TEST(50, 66, next_hi, next_lo, window, 99, 67, 0, 0x01); DUW_TEST(100, 68, next_hi, next_lo, window, 100, 69, 0, 0x01); DUW_TEST(99, 50, next_hi, next_lo, window, 100, 69, 0, 0x01); DUW_TEST(99, 0xFFFFFFFF, next_hi, next_lo, window, 100, 69, 0, 0x01); DUW_TEST(150, 0xFFFFFFFF, next_hi, next_lo, window, 151, 0, 0, 0x01); DUW_TEST(152, 0xFFFFFFFF, next_hi, next_lo, window, 153, 0, 0, 0x01); return EXPECT_RESULT(); } #endif /* WOLFSSL_DTLS */ #ifdef WOLFSSL_DTLS static int DFB_TEST(WOLFSSL* ssl, word32 seq, word32 len, word32 f_offset, word32 f_len, word32 f_count, byte ready, word32 bytesReceived) { EXPECT_DECLS; DtlsMsg* cur = NULL; static byte msg[100]; static byte msgInit = 0; if (!msgInit) { int i; for (i = 0; i < 100; i++) msg[i] = i + 1; msgInit = 1; } /* Sanitize test parameters */ ExpectIntLE(len, sizeof(msg)); ExpectIntLE(f_offset + f_len, sizeof(msg)); if (EXPECT_SUCCESS()) DtlsMsgStore(ssl, 0, seq, msg + f_offset, len, certificate, f_offset, f_len, NULL); ExpectNotNull(ssl->dtls_rx_msg_list); ExpectNotNull(cur = DtlsMsgFind(ssl->dtls_rx_msg_list, 0, seq)); ExpectIntEQ(cur->fragBucketListCount, f_count); ExpectIntEQ(cur->ready, ready); ExpectIntEQ(cur->bytesReceived, bytesReceived); if (ready) { ExpectNull(cur->fragBucketList); ExpectBufEQ(cur->fullMsg, msg, cur->sz); } else { DtlsFragBucket* fb; ExpectNotNull(cur->fragBucketList); for (fb = cur != NULL ? cur->fragBucketList : NULL; EXPECT_SUCCESS() && fb != NULL; fb = fb->m.m.next) ExpectBufEQ(fb->buf, msg + fb->m.m.offset, fb->m.m.sz); } if (EXPECT_FAIL()) { printf("Test parameters: seq %u len %u f_offset %u f_len %u f_count %u ready %u bytesReceived %u\n", seq, len, f_offset, f_len, f_count, ready, bytesReceived); } return EXPECT_RESULT(); } static int test_wolfSSL_DTLS_fragment_buckets(void) { EXPECT_DECLS; WOLFSSL ssl[1]; XMEMSET(ssl, 0, sizeof(*ssl)); EXPECT_TEST(DFB_TEST(ssl, 0, 100, 0, 100, 0, 1, 100)); /* 0-100 */ EXPECT_TEST(DFB_TEST(ssl, 1, 100, 0, 20, 1, 0, 20)); /* 0-20 */ EXPECT_TEST(DFB_TEST(ssl, 1, 100, 20, 20, 1, 0, 40)); /* 20-40 */ EXPECT_TEST(DFB_TEST(ssl, 1, 100, 40, 20, 1, 0, 60)); /* 40-60 */ EXPECT_TEST(DFB_TEST(ssl, 1, 100, 60, 20, 1, 0, 80)); /* 60-80 */ EXPECT_TEST(DFB_TEST(ssl, 1, 100, 80, 20, 0, 1, 100)); /* 80-100 */ /* Test all permutations of 3 regions */ /* 1 2 3 */ EXPECT_TEST(DFB_TEST(ssl, 2, 100, 0, 30, 1, 0, 30)); /* 0-30 */ EXPECT_TEST(DFB_TEST(ssl, 2, 100, 30, 30, 1, 0, 60)); /* 30-60 */ EXPECT_TEST(DFB_TEST(ssl, 2, 100, 60, 40, 0, 1, 100)); /* 60-100 */ /* 1 3 2 */ EXPECT_TEST(DFB_TEST(ssl, 3, 100, 0, 30, 1, 0, 30)); /* 0-30 */ EXPECT_TEST(DFB_TEST(ssl, 3, 100, 60, 40, 2, 0, 70)); /* 60-100 */ EXPECT_TEST(DFB_TEST(ssl, 3, 100, 30, 30, 0, 1, 100)); /* 30-60 */ /* 2 1 3 */ EXPECT_TEST(DFB_TEST(ssl, 4, 100, 30, 30, 1, 0, 30)); /* 30-60 */ EXPECT_TEST(DFB_TEST(ssl, 4, 100, 0, 30, 1, 0, 60)); /* 0-30 */ EXPECT_TEST(DFB_TEST(ssl, 4, 100, 60, 40, 0, 1, 100)); /* 60-100 */ /* 2 3 1 */ EXPECT_TEST(DFB_TEST(ssl, 5, 100, 30, 30, 1, 0, 30)); /* 30-60 */ EXPECT_TEST(DFB_TEST(ssl, 5, 100, 60, 40, 1, 0, 70)); /* 60-100 */ EXPECT_TEST(DFB_TEST(ssl, 5, 100, 0, 30, 0, 1, 100)); /* 0-30 */ /* 3 1 2 */ EXPECT_TEST(DFB_TEST(ssl, 6, 100, 60, 40, 1, 0, 40)); /* 60-100 */ EXPECT_TEST(DFB_TEST(ssl, 6, 100, 0, 30, 2, 0, 70)); /* 0-30 */ EXPECT_TEST(DFB_TEST(ssl, 6, 100, 30, 30, 0, 1, 100)); /* 30-60 */ /* 3 2 1 */ EXPECT_TEST(DFB_TEST(ssl, 7, 100, 60, 40, 1, 0, 40)); /* 60-100 */ EXPECT_TEST(DFB_TEST(ssl, 7, 100, 30, 30, 1, 0, 70)); /* 30-60 */ EXPECT_TEST(DFB_TEST(ssl, 7, 100, 0, 30, 0, 1, 100)); /* 0-30 */ /* Test overlapping regions */ EXPECT_TEST(DFB_TEST(ssl, 8, 100, 0, 30, 1, 0, 30)); /* 0-30 */ EXPECT_TEST(DFB_TEST(ssl, 8, 100, 20, 10, 1, 0, 30)); /* 20-30 */ EXPECT_TEST(DFB_TEST(ssl, 8, 100, 70, 10, 2, 0, 40)); /* 70-80 */ EXPECT_TEST(DFB_TEST(ssl, 8, 100, 20, 30, 2, 0, 60)); /* 20-50 */ EXPECT_TEST(DFB_TEST(ssl, 8, 100, 40, 60, 0, 1, 100)); /* 40-100 */ /* Test overlapping multiple regions */ EXPECT_TEST(DFB_TEST(ssl, 9, 100, 0, 20, 1, 0, 20)); /* 0-20 */ EXPECT_TEST(DFB_TEST(ssl, 9, 100, 30, 5, 2, 0, 25)); /* 30-35 */ EXPECT_TEST(DFB_TEST(ssl, 9, 100, 40, 5, 3, 0, 30)); /* 40-45 */ EXPECT_TEST(DFB_TEST(ssl, 9, 100, 50, 5, 4, 0, 35)); /* 50-55 */ EXPECT_TEST(DFB_TEST(ssl, 9, 100, 60, 5, 5, 0, 40)); /* 60-65 */ EXPECT_TEST(DFB_TEST(ssl, 9, 100, 70, 5, 6, 0, 45)); /* 70-75 */ EXPECT_TEST(DFB_TEST(ssl, 9, 100, 30, 25, 4, 0, 55)); /* 30-55 */ EXPECT_TEST(DFB_TEST(ssl, 9, 100, 55, 15, 2, 0, 65)); /* 55-70 */ EXPECT_TEST(DFB_TEST(ssl, 9, 100, 75, 25, 2, 0, 90)); /* 75-100 */ EXPECT_TEST(DFB_TEST(ssl, 9, 100, 10, 25, 0, 1, 100)); /* 10-35 */ EXPECT_TEST(DFB_TEST(ssl,10, 100, 0, 20, 1, 0, 20)); /* 0-20 */ EXPECT_TEST(DFB_TEST(ssl,10, 100, 30, 20, 2, 0, 40)); /* 30-50 */ EXPECT_TEST(DFB_TEST(ssl,10, 100, 0, 40, 1, 0, 50)); /* 0-40 */ EXPECT_TEST(DFB_TEST(ssl,10, 100, 50, 50, 0, 1, 100)); /* 50-100 */ /* Test region between other regions */ EXPECT_TEST(DFB_TEST(ssl,11, 100, 0, 20, 1, 0, 20)); /* 0-20 */ EXPECT_TEST(DFB_TEST(ssl,11, 100, 80, 20, 2, 0, 40)); /* 80-100 */ EXPECT_TEST(DFB_TEST(ssl,11, 100, 40, 20, 3, 0, 60)); /* 40-60 */ EXPECT_TEST(DFB_TEST(ssl,11, 100, 20, 20, 2, 0, 80)); /* 20-40 */ EXPECT_TEST(DFB_TEST(ssl,11, 100, 60, 20, 0, 1, 100)); /* 60-80 */ /* Test gap before first bucket (prev==NULL in gap-before branch) */ EXPECT_TEST(DFB_TEST(ssl,12, 100, 50, 20, 1, 0, 20)); /* 50-70 */ EXPECT_TEST(DFB_TEST(ssl,12, 100, 0, 20, 2, 0, 40)); /* 0-20 gap before first */ EXPECT_TEST(DFB_TEST(ssl,12, 100, 20, 30, 1, 0, 70)); /* 20-50 bridges gap */ EXPECT_TEST(DFB_TEST(ssl,12, 100, 70, 30, 0, 1, 100)); /* 70-100 */ /* Test fragment after message is already complete (ready early return) */ EXPECT_TEST(DFB_TEST(ssl,13, 100, 0,100, 0, 1, 100)); /* 0-100 complete */ EXPECT_TEST(DFB_TEST(ssl,13, 100, 0, 50, 0, 1, 100)); /* 0-50 dup on ready */ /* Test combine where next bucket is larger than cur (chosenBucket=&next) */ EXPECT_TEST(DFB_TEST(ssl,14, 100, 0, 10, 1, 0, 10)); /* 0-10 */ EXPECT_TEST(DFB_TEST(ssl,14, 100, 30, 50, 2, 0, 60)); /* 30-80 */ EXPECT_TEST(DFB_TEST(ssl,14, 100, 5, 30, 1, 0, 80)); /* 5-35 next>cur */ EXPECT_TEST(DFB_TEST(ssl,14, 100, 80, 20, 0, 1, 100)); /* 80-100 */ /* Test super fragment covering all existing buckets */ EXPECT_TEST(DFB_TEST(ssl,15, 100, 10, 10, 1, 0, 10)); /* 10-20 */ EXPECT_TEST(DFB_TEST(ssl,15, 100, 30, 10, 2, 0, 20)); /* 30-40 */ EXPECT_TEST(DFB_TEST(ssl,15, 100, 60, 10, 3, 0, 30)); /* 60-70 */ EXPECT_TEST(DFB_TEST(ssl,15, 100, 0,100, 0, 1, 100)); /* 0-100 super frag */ /* Test exact duplicate fragment */ EXPECT_TEST(DFB_TEST(ssl,16, 100, 20, 40, 1, 0, 40)); /* 20-60 */ EXPECT_TEST(DFB_TEST(ssl,16, 100, 20, 40, 1, 0, 40)); /* 20-60 exact dup */ EXPECT_TEST(DFB_TEST(ssl,16, 100, 0, 20, 1, 0, 60)); /* 0-20 */ EXPECT_TEST(DFB_TEST(ssl,16, 100, 60, 40, 0, 1, 100)); /* 60-100 */ /* Test combine bridging two buckets (combineNext, cur->data) */ EXPECT_TEST(DFB_TEST(ssl,17, 100, 0, 30, 1, 0, 30)); /* 0-30 */ EXPECT_TEST(DFB_TEST(ssl,17, 100, 60, 20, 2, 0, 50)); /* 60-80 */ EXPECT_TEST(DFB_TEST(ssl,17, 100, 20, 45, 1, 0, 80)); /* 20-65 bridge */ EXPECT_TEST(DFB_TEST(ssl,17, 100, 80, 20, 0, 1, 100)); /* 80-100 */ /* Test progressive left-extension with partial overlaps */ EXPECT_TEST(DFB_TEST(ssl,18, 100, 70, 30, 1, 0, 30)); /* 70-100 */ EXPECT_TEST(DFB_TEST(ssl,18, 100, 50, 30, 1, 0, 50)); /* 50-80 extend left */ EXPECT_TEST(DFB_TEST(ssl,18, 100, 30, 30, 1, 0, 70)); /* 30-60 extend left */ EXPECT_TEST(DFB_TEST(ssl,18, 100, 0, 40, 0, 1, 100)); /* 0-40 complete left */ DtlsMsgListDelete(ssl->dtls_rx_msg_list, ssl->heap); ssl->dtls_rx_msg_list = NULL; ssl->dtls_rx_msg_list_sz = 0; return EXPECT_RESULT(); } #endif #if !defined(NO_FILESYSTEM) && \ defined(WOLFSSL_DTLS) && !defined(WOLFSSL_NO_TLS12) && \ defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && !defined(NO_RSA) static int test_wolfSSL_dtls_stateless2(void) { EXPECT_DECLS; WOLFSSL *ssl_c = NULL; WOLFSSL *ssl_c2 = NULL; WOLFSSL *ssl_s = NULL; struct test_memio_ctx test_ctx; WOLFSSL_CTX *ctx_c = NULL; WOLFSSL_CTX *ctx_s = NULL; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method), 0); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, NULL, &ssl_c2, NULL, wolfDTLSv1_2_client_method, NULL), 0); ExpectFalse(wolfSSL_is_stateful(ssl_s)); /* send CH */ ExpectTrue((wolfSSL_connect(ssl_c2) == WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)) && (ssl_c2->error == WC_NO_ERR_TRACE(WANT_READ))); ExpectIntEQ(wolfDTLS_accept_stateless(ssl_s), WOLFSSL_FAILURE); ExpectFalse(wolfSSL_is_stateful(ssl_s)); ExpectIntNE(test_ctx.c_len, 0); /* consume HRR */ test_memio_clear_buffer(&test_ctx, 1); /* send CH1 */ ExpectIntEQ(wolfSSL_connect(ssl_c), WOLFSSL_FATAL_ERROR); ExpectIntEQ(wolfSSL_get_error(ssl_c, WOLFSSL_FATAL_ERROR), WOLFSSL_ERROR_WANT_READ); /* send HRR */ ExpectIntEQ(wolfDTLS_accept_stateless(ssl_s), WOLFSSL_FAILURE); /* send CH2 */ ExpectIntEQ(wolfSSL_connect(ssl_c), WOLFSSL_FATAL_ERROR); ExpectIntEQ(wolfSSL_get_error(ssl_c, WOLFSSL_FATAL_ERROR), WOLFSSL_ERROR_WANT_READ); /* send HRR */ ExpectIntEQ(wolfDTLS_accept_stateless(ssl_s), WOLFSSL_SUCCESS); ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); ExpectTrue(wolfSSL_is_stateful(ssl_s)); wolfSSL_free(ssl_c2); wolfSSL_free(ssl_c); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_c); wolfSSL_CTX_free(ctx_s); return EXPECT_RESULT(); } #ifdef HAVE_MAX_FRAGMENT static int test_wolfSSL_dtls_stateless_maxfrag(void) { EXPECT_DECLS; WOLFSSL *ssl_c = NULL; WOLFSSL *ssl_c2 = NULL; WOLFSSL *ssl_s = NULL; struct test_memio_ctx test_ctx; WOLFSSL_CTX *ctx_c = NULL; WOLFSSL_CTX *ctx_s = NULL; word16 max_fragment = 0; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method), 0); ExpectNotNull(ssl_s); ExpectNotNull(ssl_c2 = wolfSSL_new(ctx_c)); ExpectIntEQ(wolfSSL_UseMaxFragment(ssl_c2, WOLFSSL_MFL_2_8), WOLFSSL_SUCCESS); wolfSSL_SetIOWriteCtx(ssl_c2, &test_ctx); wolfSSL_SetIOReadCtx(ssl_c2, &test_ctx); if (EXPECT_SUCCESS()) { max_fragment = ssl_s->max_fragment; } /* send CH */ ExpectTrue((wolfSSL_connect(ssl_c2) == WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)) && (ssl_c2->error == WC_NO_ERR_TRACE(WANT_READ))); ExpectTrue((wolfSSL_accept(ssl_s) == WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)) && (ssl_s->error == WC_NO_ERR_TRACE(WANT_READ))); /* CH without cookie shouldn't change state */ ExpectIntEQ(ssl_s->max_fragment, max_fragment); ExpectIntNE(test_ctx.c_len, 0); /* consume HRR from buffer */ test_memio_clear_buffer(&test_ctx, 1); ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); wolfSSL_free(ssl_c2); wolfSSL_free(ssl_c); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_c); wolfSSL_CTX_free(ctx_s); return EXPECT_RESULT(); } #endif /* HAVE_MAX_FRAGMENT */ #if defined(WOLFSSL_DTLS_NO_HVR_ON_RESUME) #define ROUNDS_WITH_HVR 4 #define ROUNDS_WITHOUT_HVR 2 #define HANDSHAKE_TYPE_OFFSET DTLS_RECORD_HEADER_SZ static int buf_is_hvr(const byte *data, int len) { if (len < DTLS_RECORD_HEADER_SZ + DTLS_HANDSHAKE_HEADER_SZ) return 0; return data[HANDSHAKE_TYPE_OFFSET] == hello_verify_request; } static int _test_wolfSSL_dtls_stateless_resume(byte useticket, byte bad) { EXPECT_DECLS; struct test_memio_ctx test_ctx; WOLFSSL_CTX *ctx_c = NULL; WOLFSSL_CTX *ctx_s = NULL; WOLFSSL *ssl_c = NULL; WOLFSSL *ssl_s = NULL; WOLFSSL_SESSION *sess = NULL; int round_trips; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method), 0); #ifdef HAVE_SESSION_TICKET if (useticket) { ExpectIntEQ(wolfSSL_UseSessionTicket(ssl_c), WOLFSSL_SUCCESS); } #endif round_trips = ROUNDS_WITH_HVR; ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, round_trips, &round_trips), 0); ExpectIntEQ(round_trips, ROUNDS_WITH_HVR); ExpectNotNull(sess = wolfSSL_get1_session(ssl_c)); wolfSSL_shutdown(ssl_c); wolfSSL_shutdown(ssl_s); wolfSSL_free(ssl_c); ssl_c = NULL; wolfSSL_free(ssl_s); ssl_s = NULL; test_memio_clear_buffer(&test_ctx, 1); test_memio_clear_buffer(&test_ctx, 0); /* make resumption invalid */ if (bad && (sess != NULL)) { if (useticket) { #ifdef HAVE_SESSION_TICKET if (sess->ticket != NULL) { sess->ticket[0] = !sess->ticket[0]; } #endif /* HAVE_SESSION_TICKET */ } else { sess->sessionID[0] = !sess->sessionID[0]; } } ExpectNotNull(ssl_c = wolfSSL_new(ctx_c)); ExpectNotNull(ssl_s = wolfSSL_new(ctx_s)); wolfSSL_SetIOWriteCtx(ssl_c, &test_ctx); wolfSSL_SetIOReadCtx(ssl_c, &test_ctx); wolfSSL_SetIOWriteCtx(ssl_s, &test_ctx); wolfSSL_SetIOReadCtx(ssl_s, &test_ctx); ExpectIntEQ(wolfSSL_set_session(ssl_c, sess), WOLFSSL_SUCCESS); ExpectTrue((wolfSSL_connect(ssl_c) == WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)) && (ssl_c->error == WC_NO_ERR_TRACE(WANT_READ))); ExpectTrue((wolfSSL_accept(ssl_s) == WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)) && (ssl_s->error == WC_NO_ERR_TRACE(WANT_READ))); ExpectFalse(bad && !buf_is_hvr(test_ctx.c_buff, test_ctx.c_len)); ExpectFalse(!bad && buf_is_hvr(test_ctx.c_buff, test_ctx.c_len)); if (!useticket) { ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, &round_trips), 0); ExpectFalse(bad && round_trips != ROUNDS_WITH_HVR - 1); ExpectFalse(!bad && round_trips != ROUNDS_WITHOUT_HVR - 1); } wolfSSL_SESSION_free(sess); wolfSSL_free(ssl_c); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_c); wolfSSL_CTX_free(ctx_s); return EXPECT_RESULT(); } static int test_wolfSSL_dtls_stateless_resume(void) { EXPECT_DECLS; #ifdef HAVE_SESSION_TICKET ExpectIntEQ(_test_wolfSSL_dtls_stateless_resume(1, 0), TEST_SUCCESS); ExpectIntEQ(_test_wolfSSL_dtls_stateless_resume(1, 1), TEST_SUCCESS); #endif /* HAVE_SESION_TICKET */ ExpectIntEQ(_test_wolfSSL_dtls_stateless_resume(0, 0), TEST_SUCCESS); ExpectIntEQ(_test_wolfSSL_dtls_stateless_resume(0, 1), TEST_SUCCESS); return EXPECT_RESULT(); } #endif /* WOLFSSL_DTLS_NO_HVR_ON_RESUME */ #if !defined(NO_OLD_TLS) static int test_wolfSSL_dtls_stateless_downgrade(void) { EXPECT_DECLS; WOLFSSL_CTX *ctx_c = NULL; WOLFSSL_CTX *ctx_c2 = NULL; WOLFSSL_CTX *ctx_s = NULL; WOLFSSL *ssl_c = NULL; WOLFSSL *ssl_c2 = NULL; WOLFSSL *ssl_s = NULL; struct test_memio_ctx test_ctx; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method), 0); ExpectIntEQ(wolfSSL_CTX_SetMinVersion(ctx_s, WOLFSSL_DTLSV1), WOLFSSL_SUCCESS); ExpectNotNull(ctx_c2 = wolfSSL_CTX_new(wolfDTLSv1_client_method())); wolfSSL_SetIORecv(ctx_c2, test_memio_read_cb); wolfSSL_SetIOSend(ctx_c2, test_memio_write_cb); ExpectNotNull(ssl_c2 = wolfSSL_new(ctx_c2)); wolfSSL_SetIOWriteCtx(ssl_c2, &test_ctx); wolfSSL_SetIOReadCtx(ssl_c2, &test_ctx); /* send CH */ ExpectTrue((wolfSSL_connect(ssl_c2) == WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)) && (ssl_c2->error == WC_NO_ERR_TRACE(WANT_READ))); ExpectTrue((wolfSSL_accept(ssl_s) == WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)) && (ssl_s->error == WC_NO_ERR_TRACE(WANT_READ))); ExpectIntNE(test_ctx.c_len, 0); /* consume HRR */ test_memio_clear_buffer(&test_ctx, 1); ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); wolfSSL_free(ssl_c2); wolfSSL_free(ssl_c); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_c); wolfSSL_CTX_free(ctx_c2); wolfSSL_CTX_free(ctx_s); return EXPECT_RESULT(); } #endif /* !defined(NO_OLD_TLS) */ #endif /* defined(WOLFSSL_DTLS) && !defined(WOLFSSL_NO_TLS12) && \ !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER)*/ #if defined(WOLFSSL_DTLS) && !defined(WOLFSSL_NO_TLS12) && \ !defined(NO_OLD_TLS) && defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) static int test_WOLFSSL_dtls_version_alert(void) { EXPECT_DECLS; struct test_memio_ctx test_ctx; WOLFSSL_CTX *ctx_c = NULL; WOLFSSL_CTX *ctx_s = NULL; WOLFSSL *ssl_c = NULL; WOLFSSL *ssl_s = NULL; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, wolfDTLSv1_2_client_method, wolfDTLSv1_server_method), 0); /* client hello */ ExpectTrue((wolfSSL_connect(ssl_c) == WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)) && (ssl_c->error == WC_NO_ERR_TRACE(WANT_READ))); /* hrr */ ExpectTrue((wolfSSL_accept(ssl_s) == WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)) && (ssl_s->error == WC_NO_ERR_TRACE(WANT_READ))); /* client hello 1 */ ExpectTrue((wolfSSL_connect(ssl_c) == WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)) && (ssl_c->error == WC_NO_ERR_TRACE(WANT_READ))); /* server hello */ ExpectTrue((wolfSSL_accept(ssl_s) == WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)) && (ssl_s->error == WC_NO_ERR_TRACE(WANT_READ))); /* should fail */ ExpectTrue((wolfSSL_connect(ssl_c) == WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)) && (ssl_c->error == WC_NO_ERR_TRACE(VERSION_ERROR))); /* shuould fail */ ExpectTrue((wolfSSL_accept(ssl_s) == WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)) && (ssl_s->error == WC_NO_ERR_TRACE(VERSION_ERROR) || ssl_s->error == WC_NO_ERR_TRACE(FATAL_ERROR))); wolfSSL_free(ssl_c); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_c); wolfSSL_CTX_free(ctx_s); return EXPECT_RESULT(); } #else static int test_WOLFSSL_dtls_version_alert(void) { return TEST_SKIPPED; } #endif /* defined(WOLFSSL_DTLS) && !defined(WOLFSSL_NO_TLS12) && * !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) && * !defined(NO_OLD_TLS) && !defined(NO_RSA) */ #if defined(WOLFSSL_TICKET_NONCE_MALLOC) && defined(HAVE_SESSION_TICKET) \ && defined(WOLFSSL_TLS13) && \ (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3)))\ && defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) static int send_new_session_ticket(WOLFSSL *ssl, byte nonceLength, byte filler) { struct test_memio_ctx *test_ctx; byte buf[2048]; int idx, sz; word32 tmp; int ret; idx = 5; /* space for record header */ buf[idx] = session_ticket; /* type */ idx++; tmp = OPAQUE32_LEN + OPAQUE32_LEN + OPAQUE8_LEN + nonceLength + OPAQUE16_LEN + OPAQUE8_LEN + OPAQUE16_LEN; c32to24(tmp, buf + idx); idx += OPAQUE24_LEN; c32toa((word32)12345, buf+idx); /* lifetime */ idx += OPAQUE32_LEN; c32toa((word32)12345, buf+idx); /* add */ idx += OPAQUE32_LEN; buf[idx] = nonceLength; /* nonce length */ idx++; XMEMSET(&buf[idx], filler, nonceLength); /* nonce */ idx += nonceLength; tmp = 1; /* ticket len */ c16toa((word16)tmp, buf+idx); idx += 2; buf[idx] = 0xFF; /* ticket */ idx++; tmp = 0; /* ext len */ c16toa((word16)tmp, buf+idx); idx += 2; sz = BuildTls13Message(ssl, buf, 2048, buf+5, idx - 5, handshake, 0, 0, 0); AssertIntGT(sz, 0); test_ctx = (struct test_memio_ctx*)wolfSSL_GetIOWriteCtx(ssl); AssertNotNull(test_ctx); ret = test_memio_write_cb(ssl, (char*)buf, sz, test_ctx); return !(ret == sz); } static int test_ticket_nonce_check(WOLFSSL_SESSION *sess, byte len) { int ret = 0; if ((sess == NULL) || (sess->ticketNonce.len != len)) { ret = -1; } else { int i; for (i = 0; i < len; i++) { if (sess->ticketNonce.data[i] != len) { ret = -1; break; } } } return ret; } static int test_ticket_nonce_malloc_do(WOLFSSL *ssl_s, WOLFSSL *ssl_c, byte len) { EXPECT_DECLS; char *buf[1024]; ExpectIntEQ(send_new_session_ticket(ssl_s, len, len), 0); ExpectTrue((wolfSSL_recv(ssl_c, buf, 1024, 0) == WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)) && (ssl_c->error == WC_NO_ERR_TRACE(WANT_READ))); ExpectIntEQ(test_ticket_nonce_check(ssl_c->session, len), 0); return EXPECT_RESULT(); } static int test_ticket_nonce_cache(WOLFSSL *ssl_s, WOLFSSL *ssl_c, byte len) { EXPECT_DECLS; WOLFSSL_SESSION *sess = NULL; WOLFSSL_SESSION *cached = NULL; WOLFSSL_CTX *ctx = ssl_c->ctx; ExpectIntEQ(test_ticket_nonce_malloc_do(ssl_s, ssl_c, len), TEST_SUCCESS); ExpectNotNull(sess = wolfSSL_get1_session(ssl_c)); ExpectIntEQ(AddSessionToCache(ctx, sess, sess->sessionID, sess->sessionIDSz, NULL, ssl_c->options.side, 1,NULL), 0); ExpectNotNull(cached = wolfSSL_SESSION_new()); ExpectIntEQ(wolfSSL_GetSessionFromCache(ssl_c, cached), WOLFSSL_SUCCESS); ExpectIntEQ(test_ticket_nonce_check(cached, len), 0); wolfSSL_SESSION_free(cached); wolfSSL_SESSION_free(sess); return EXPECT_RESULT(); } static int test_ticket_nonce_malloc(void) { EXPECT_DECLS; struct test_memio_ctx test_ctx; WOLFSSL_CTX *ctx_c = NULL; WOLFSSL_CTX *ctx_s = NULL; WOLFSSL *ssl_c = NULL; WOLFSSL *ssl_s = NULL; byte small; byte medium; byte big; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0); /* will send ticket manually */ ExpectIntEQ(wolfSSL_no_ticket_TLSv13(ssl_s), 0); wolfSSL_set_verify(ssl_s, WOLFSSL_VERIFY_NONE, 0); wolfSSL_set_verify(ssl_c, WOLFSSL_VERIFY_NONE, 0); while (EXPECT_SUCCESS() && (ssl_c->options.handShakeDone == 0) && (ssl_s->options.handShakeDone == 0)) { ExpectTrue((wolfSSL_connect(ssl_c) == WOLFSSL_SUCCESS) || (ssl_c->error == WC_NO_ERR_TRACE(WANT_READ))); ExpectTrue((wolfSSL_accept(ssl_s) == WOLFSSL_SUCCESS) || (ssl_s->error == WC_NO_ERR_TRACE(WANT_READ))); } small = TLS13_TICKET_NONCE_STATIC_SZ; #if TLS13_TICKET_NONCE_STATIC_SZ + 20 <= 255 medium = small + 20; #else medium = 255; #endif #if TLS13_TICKET_NONCE_STATIC_SZ + 20 + 20 <= 255 big = small + 20; #else big = 255; #endif ExpectIntEQ(test_ticket_nonce_malloc_do(ssl_s, ssl_c, small), TEST_SUCCESS); ExpectPtrEq(ssl_c->session->ticketNonce.data, ssl_c->session->ticketNonce.dataStatic); ExpectIntEQ(test_ticket_nonce_malloc_do(ssl_s, ssl_c, medium), TEST_SUCCESS); ExpectIntEQ(test_ticket_nonce_malloc_do(ssl_s, ssl_c, big), TEST_SUCCESS); ExpectIntEQ(test_ticket_nonce_malloc_do(ssl_s, ssl_c, medium), TEST_SUCCESS); ExpectIntEQ(test_ticket_nonce_malloc_do(ssl_s, ssl_c, small), TEST_SUCCESS); ExpectIntEQ(test_ticket_nonce_cache(ssl_s, ssl_c, small), TEST_SUCCESS); ExpectIntEQ(test_ticket_nonce_cache(ssl_s, ssl_c, medium), TEST_SUCCESS); ExpectIntEQ(test_ticket_nonce_cache(ssl_s, ssl_c, big), TEST_SUCCESS); ExpectIntEQ(test_ticket_nonce_cache(ssl_s, ssl_c, medium), TEST_SUCCESS); ExpectIntEQ(test_ticket_nonce_cache(ssl_s, ssl_c, small), TEST_SUCCESS); wolfSSL_free(ssl_c); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_c); wolfSSL_CTX_free(ctx_s); return EXPECT_RESULT(); } #endif /* WOLFSSL_TICKET_NONCE_MALLOC */ #if defined(HAVE_SESSION_TICKET) && !defined(WOLFSSL_NO_TLS12) && \ !defined(WOLFSSL_TICKET_DECRYPT_NO_CREATE) && \ !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) && \ !defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) && !defined(NO_RSA) && \ defined(HAVE_ECC) && defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) static int test_ticket_ret_create(void) { EXPECT_DECLS; WOLFSSL_CTX *ctx_c = NULL; WOLFSSL_CTX *ctx_s = NULL; WOLFSSL *ssl_c = NULL; WOLFSSL *ssl_s = NULL; byte ticket[SESSION_TICKET_LEN]; struct test_memio_ctx test_ctx; WOLFSSL_SESSION *sess = NULL; word16 ticketLen = 0; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, wolfTLSv1_2_client_method, wolfTLSv1_2_server_method), 0); wolfSSL_set_verify(ssl_s, WOLFSSL_VERIFY_NONE, 0); wolfSSL_set_verify(ssl_c, WOLFSSL_VERIFY_NONE, 0); ExpectIntEQ(wolfSSL_CTX_UseSessionTicket(ctx_c), WOLFSSL_SUCCESS); ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); ExpectNotNull(sess = wolfSSL_get1_session(ssl_c)); ExpectIntLE(sess->ticketLen, SESSION_TICKET_LEN); if (sess != NULL) { ticketLen = sess->ticketLen; XMEMCPY(ticket, sess->ticket, sess->ticketLen); } wolfSSL_free(ssl_c); ssl_c = NULL; wolfSSL_free(ssl_s); ssl_s = NULL; ExpectNotNull(ssl_s = wolfSSL_new(ctx_s)); wolfSSL_SetIOWriteCtx(ssl_s, &test_ctx); wolfSSL_SetIOReadCtx(ssl_s, &test_ctx); ExpectNotNull(ssl_c = wolfSSL_new(ctx_c)); wolfSSL_SetIOWriteCtx(ssl_c, &test_ctx); wolfSSL_SetIOReadCtx(ssl_c, &test_ctx); ExpectIntEQ(wolfSSL_set_session(ssl_c, sess), WOLFSSL_SUCCESS); ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); ExpectIntLE(ssl_c->session->ticketLen, SESSION_TICKET_LEN); ExpectIntEQ(ssl_c->session->ticketLen, ticketLen); ExpectTrue(XMEMCMP(ssl_c->session->ticket, ticket, ticketLen) != 0); wolfSSL_SESSION_free(sess); wolfSSL_free(ssl_c); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_c); wolfSSL_CTX_free(ctx_s); return EXPECT_RESULT(); } #else static int test_ticket_ret_create(void) { return TEST_SKIPPED; } #endif /* Build a valid TLS 1.2 ticket by completing an initial handshake, then tamper * with enc_len so it is larger than the true encrypted payload. */ #if defined(HAVE_SESSION_TICKET) && !defined(WOLFSSL_NO_TLS12) && \ !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) && \ !defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) && \ !defined(NO_RSA) && defined(HAVE_ECC) && \ defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) static int test_ticket_enc_corrupted_cb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], byte iv[WOLFSSL_TICKET_IV_SZ], byte mac[WOLFSSL_TICKET_MAC_SZ], int enc, byte* ticket, int inLen, int* outLen, void* userCtx) { (void)ssl; (void)key_name; (void)iv; (void)mac; (void)userCtx; (void)outLen; if (!enc) { XMEMSET(ticket, 0, (size_t)inLen); return WOLFSSL_TICKET_RET_REJECT; /* keep handshake progressing */ } return WOLFSSL_TICKET_RET_CREATE; } static int test_ticket_enc_corrupted(void) { EXPECT_DECLS; struct test_memio_ctx test_ctx; WOLFSSL_CTX* ctx_c = NULL; WOLFSSL_CTX* ctx_s = NULL; WOLFSSL* ssl_c = NULL; WOLFSSL* ssl_s = NULL; WOLFSSL_SESSION* sess = NULL; ExternalTicket* et; word16 encLen; int actualEncLen; int craftedBadLen = 0; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, wolfTLSv1_2_client_method, wolfTLSv1_2_server_method), 0); wolfSSL_set_verify(ssl_s, WOLFSSL_VERIFY_NONE, 0); wolfSSL_set_verify(ssl_c, WOLFSSL_VERIFY_NONE, 0); ExpectIntEQ(wolfSSL_CTX_UseSessionTicket(ctx_c), WOLFSSL_SUCCESS); ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); ExpectNotNull(sess = wolfSSL_get1_session(ssl_c)); if (sess != NULL) { ExpectIntGT(sess->ticketLen, WOLFSSL_TICKET_FIXED_SZ); /* Force enc_len to exceed actual encrypted ticket payload while still * staying <= WOLFSSL_TICKET_ENC_SZ, so callback is reached. */ et = (ExternalTicket*)sess->ticket; ato16(et->enc_len, &encLen); actualEncLen = (int)(sess->ticketLen - WOLFSSL_TICKET_FIXED_SZ); if (actualEncLen + 100 <= (int)WOLFSSL_TICKET_ENC_SZ) { encLen = (word16)(actualEncLen + 100); c16toa(encLen, et->enc_len); craftedBadLen = 1; } else if (actualEncLen + 1 <= (int)WOLFSSL_TICKET_ENC_SZ) { encLen = (word16)(actualEncLen + 1); c16toa(encLen, et->enc_len); craftedBadLen = 1; } } wolfSSL_free(ssl_c); ssl_c = NULL; wolfSSL_free(ssl_s); ssl_s = NULL; test_memio_clear_buffer(&test_ctx, 1); test_memio_clear_buffer(&test_ctx, 0); ExpectNotNull(ssl_s = wolfSSL_new(ctx_s)); wolfSSL_SetIOWriteCtx(ssl_s, &test_ctx); wolfSSL_SetIOReadCtx(ssl_s, &test_ctx); ExpectNotNull(ssl_c = wolfSSL_new(ctx_c)); wolfSSL_SetIOWriteCtx(ssl_c, &test_ctx); wolfSSL_SetIOReadCtx(ssl_c, &test_ctx); wolfSSL_set_verify(ssl_s, WOLFSSL_VERIFY_NONE, 0); wolfSSL_set_verify(ssl_c, WOLFSSL_VERIFY_NONE, 0); if (sess != NULL) { if (!craftedBadLen) { wolfSSL_SESSION_free(sess); wolfSSL_free(ssl_c); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_c); wolfSSL_CTX_free(ctx_s); return TEST_SKIPPED; } ExpectIntEQ(wolfSSL_set_session(ssl_c, sess), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_set_TicketEncCb(ctx_s, test_ticket_enc_corrupted_cb), WOLFSSL_SUCCESS); ExpectTrue((wolfSSL_connect(ssl_c) == WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)) && (ssl_c->error == WC_NO_ERR_TRACE(WANT_READ))); ExpectTrue((wolfSSL_accept(ssl_s) == WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)) && (ssl_s->error == WC_NO_ERR_TRACE(WANT_READ))); } wolfSSL_SESSION_free(sess); wolfSSL_free(ssl_c); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_c); wolfSSL_CTX_free(ctx_s); return EXPECT_RESULT(); } #else static int test_ticket_enc_corrupted(void) { return TEST_SKIPPED; } #endif #if defined(WOLFSSL_TLS13) && !defined(NO_PSK) && \ defined(HAVE_SESSION_TICKET) && defined(OPENSSL_EXTRA) && \ defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(HAVE_AESGCM) && \ !defined(NO_SHA256) && defined(WOLFSSL_AES_128) && \ defined(WOLFSSL_SHA384) && defined(WOLFSSL_AES_256) static void test_ticket_and_psk_mixing_on_result(WOLFSSL* ssl) { int ret; WOLFSSL_SESSION* session = NULL; AssertIntEQ(wolfSSL_get_current_cipher_suite(ssl), 0x1301); if (!wolfSSL_is_server(ssl)) { session = wolfSSL_SESSION_dup(wolfSSL_get_session(ssl)); AssertNotNull(session); } do { ret = wolfSSL_shutdown(ssl); } while (ret == WC_NO_ERR_TRACE(WOLFSSL_SHUTDOWN_NOT_DONE)); AssertIntEQ(wolfSSL_clear(ssl), WOLFSSL_SUCCESS); wolfSSL_set_psk_callback_ctx(ssl, (void*)"TLS13-AES256-GCM-SHA384"); #ifndef OPENSSL_COMPATIBLE_DEFAULTS /* OpenSSL considers PSK to be verified. We error out with NO_PEER_CERT. */ wolfSSL_set_verify(ssl, WOLFSSL_VERIFY_NONE, NULL); #endif if (!wolfSSL_is_server(ssl)) { /* client */ AssertIntEQ(wolfSSL_set_cipher_list(ssl, "TLS13-AES256-GCM-SHA384:" "TLS13-AES128-GCM-SHA256"), WOLFSSL_SUCCESS); wolfSSL_set_session(ssl, session); wolfSSL_SESSION_free(session); wolfSSL_set_psk_client_tls13_callback(ssl, my_psk_client_tls13_cb); AssertIntEQ(wolfSSL_connect(ssl), WOLFSSL_SUCCESS); } else { /* server */ /* Different ciphersuite so that the ticket will be invalidated based on * the ciphersuite */ AssertIntEQ(wolfSSL_set_cipher_list(ssl, "TLS13-AES256-GCM-SHA384"), WOLFSSL_SUCCESS); wolfSSL_set_psk_server_tls13_callback(ssl, my_psk_server_tls13_cb); AssertIntEQ(wolfSSL_accept(ssl), WOLFSSL_SUCCESS); } } static void test_ticket_and_psk_mixing_ssl_ready(WOLFSSL* ssl) { AssertIntEQ(wolfSSL_UseSessionTicket(ssl), WOLFSSL_SUCCESS); AssertIntEQ(wolfSSL_set_cipher_list(ssl, "TLS13-AES128-GCM-SHA256"), WOLFSSL_SUCCESS); } static int test_ticket_and_psk_mixing(void) { EXPECT_DECLS; /* Test mixing tickets and regular PSK */ callback_functions client_cbs, server_cbs; XMEMSET(&client_cbs, 0, sizeof(client_cbs)); XMEMSET(&server_cbs, 0, sizeof(server_cbs)); client_cbs.method = wolfTLSv1_3_client_method; server_cbs.method = wolfTLSv1_3_server_method; client_cbs.ssl_ready = test_ticket_and_psk_mixing_ssl_ready; client_cbs.on_result = test_ticket_and_psk_mixing_on_result; server_cbs.on_result = test_ticket_and_psk_mixing_on_result; test_wolfSSL_client_server_nofail(&client_cbs, &server_cbs); ExpectIntEQ(client_cbs.return_code, TEST_SUCCESS); ExpectIntEQ(server_cbs.return_code, TEST_SUCCESS); return EXPECT_RESULT(); } #else static int test_ticket_and_psk_mixing(void) { return TEST_SKIPPED; } #endif #if defined(WOLFSSL_TLS13) && !defined(NO_PSK) && defined(HAVE_SESSION_TICKET) \ && defined(OPENSSL_EXTRA) && defined(HAVE_IO_TESTS_DEPENDENCIES) && \ defined(HAVE_AESGCM) && !defined(NO_SHA256) && defined(WOLFSSL_AES_128) && \ defined(WOLFSSL_SHA384) && defined(WOLFSSL_AES_256) static int test_prioritize_psk_cb_called = FALSE; static unsigned int test_prioritize_psk_cb(WOLFSSL* ssl, const char* identity, unsigned char* key, unsigned int key_max_len, const char** ciphersuite) { test_prioritize_psk_cb_called = TRUE; return my_psk_server_tls13_cb(ssl, identity, key, key_max_len, ciphersuite); } static void test_prioritize_psk_on_result(WOLFSSL* ssl) { int ret; WOLFSSL_SESSION* session = NULL; AssertIntEQ(wolfSSL_get_current_cipher_suite(ssl), 0x1301); if (!wolfSSL_is_server(ssl)) { session = wolfSSL_SESSION_dup(wolfSSL_get_session(ssl)); AssertNotNull(session); } do { ret = wolfSSL_shutdown(ssl); } while (ret == WC_NO_ERR_TRACE(WOLFSSL_SHUTDOWN_NOT_DONE)); AssertIntEQ(wolfSSL_clear(ssl), WOLFSSL_SUCCESS); wolfSSL_set_psk_callback_ctx(ssl, (void*)"TLS13-AES256-GCM-SHA384"); /* Previous connection was made with TLS13-AES128-GCM-SHA256. Order is * important. */ AssertIntEQ(wolfSSL_set_cipher_list(ssl, "TLS13-AES256-GCM-SHA384:" "TLS13-AES128-GCM-SHA256"), WOLFSSL_SUCCESS); #ifndef OPENSSL_COMPATIBLE_DEFAULTS /* OpenSSL considers PSK to be verified. We error out with NO_PEER_CERT. */ wolfSSL_set_verify(ssl, WOLFSSL_VERIFY_NONE, NULL); #endif if (!wolfSSL_is_server(ssl)) { /* client */ wolfSSL_set_psk_client_tls13_callback(ssl, my_psk_client_tls13_cb); wolfSSL_set_session(ssl, session); wolfSSL_SESSION_free(session); AssertIntEQ(wolfSSL_connect(ssl), WOLFSSL_SUCCESS); } else { /* server */ wolfSSL_set_psk_server_tls13_callback(ssl, test_prioritize_psk_cb); AssertIntEQ(wolfSSL_accept(ssl), WOLFSSL_SUCCESS); #ifdef WOLFSSL_PRIORITIZE_PSK /* The ticket should be first tried with all ciphersuites and chosen */ AssertFalse(test_prioritize_psk_cb_called); #else /* Ciphersuites should be tried with each PSK. This triggers the PSK * callback that sets this var. */ AssertTrue(test_prioritize_psk_cb_called); #endif } } static void test_prioritize_psk_ssl_ready(WOLFSSL* ssl) { if (!wolfSSL_is_server(ssl)) AssertIntEQ(wolfSSL_set_cipher_list(ssl, "TLS13-AES128-GCM-SHA256"), WOLFSSL_SUCCESS); else AssertIntEQ(wolfSSL_set_cipher_list(ssl, "TLS13-AES256-GCM-SHA384:" "TLS13-AES128-GCM-SHA256"), WOLFSSL_SUCCESS); } static int test_prioritize_psk(void) { EXPECT_DECLS; /* We always send the ticket first. With WOLFSSL_PRIORITIZE_PSK the order * of the PSK's will be followed instead of the ciphersuite. */ callback_functions client_cbs, server_cbs; XMEMSET(&client_cbs, 0, sizeof(client_cbs)); XMEMSET(&server_cbs, 0, sizeof(server_cbs)); client_cbs.method = wolfTLSv1_3_client_method; server_cbs.method = wolfTLSv1_3_server_method; client_cbs.ssl_ready = test_prioritize_psk_ssl_ready; server_cbs.ssl_ready = test_prioritize_psk_ssl_ready; client_cbs.on_result = test_prioritize_psk_on_result; server_cbs.on_result = test_prioritize_psk_on_result; test_wolfSSL_client_server_nofail(&client_cbs, &server_cbs); ExpectIntEQ(client_cbs.return_code, TEST_SUCCESS); ExpectIntEQ(server_cbs.return_code, TEST_SUCCESS); return EXPECT_RESULT(); } #else static int test_prioritize_psk(void) { return TEST_SKIPPED; } #endif #if defined(WOLFSSL_TLS13) && defined(OPENSSL_EXTRA) && \ defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && defined(HAVE_AESGCM) && \ !defined(NO_SHA256) && defined(WOLFSSL_AES_128) && \ !defined(WOLFSSL_NO_TLS12) static int test_wolfSSL_CTX_set_ciphersuites_ctx_ready_server(WOLFSSL_CTX* ctx) { EXPECT_DECLS; ExpectTrue(SSL_CTX_set_cipher_list(ctx, "DEFAULT")); /* Set TLS 1.3 specific suite */ ExpectTrue(SSL_CTX_set_ciphersuites(ctx, "TLS13-AES128-GCM-SHA256")); return EXPECT_RESULT(); } static int test_wolfSSL_CTX_set_ciphersuites(void) { EXPECT_DECLS; /* Test using SSL_CTX_set_cipher_list and SSL_CTX_set_ciphersuites and then * do a 1.2 connection. */ test_ssl_cbf client_cbs, server_cbs; XMEMSET(&client_cbs, 0, sizeof(client_cbs)); XMEMSET(&server_cbs, 0, sizeof(server_cbs)); client_cbs.method = wolfTLSv1_2_client_method; server_cbs.method = wolfTLS_server_method; /* Allow downgrade */ server_cbs.ctx_ready = test_wolfSSL_CTX_set_ciphersuites_ctx_ready_server; ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&client_cbs, &server_cbs, NULL), TEST_SUCCESS); return EXPECT_RESULT(); } #else static int test_wolfSSL_CTX_set_ciphersuites(void) { return TEST_SKIPPED; } #endif #if defined(HAVE_CRL) && defined(WOLFSSL_CHECK_ALERT_ON_ERR) && \ defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) static int test_wolfSSL_CRL_CERT_REVOKED_alert_ctx_ready(WOLFSSL_CTX* ctx) { wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, NULL); return TEST_SUCCESS; } static int test_wolfSSL_CRL_CERT_REVOKED_alert_on_cleanup(WOLFSSL* ssl) { EXPECT_DECLS; WOLFSSL_ALERT_HISTORY h; ExpectIntEQ(wolfSSL_get_alert_history(ssl, &h), WOLFSSL_SUCCESS); ExpectIntEQ(h.last_rx.level, alert_fatal); ExpectIntEQ(h.last_rx.code, certificate_revoked); return EXPECT_RESULT(); } static int test_wolfSSL_CRL_CERT_REVOKED_alert(void) { EXPECT_DECLS; test_ssl_cbf client_cbs, server_cbs; XMEMSET(&client_cbs, 0, sizeof(client_cbs)); XMEMSET(&server_cbs, 0, sizeof(server_cbs)); server_cbs.certPemFile = "./certs/server-revoked-cert.pem"; server_cbs.keyPemFile = "./certs/server-revoked-key.pem"; client_cbs.crlPemFile = "./certs/crl/crl.revoked"; client_cbs.ctx_ready = test_wolfSSL_CRL_CERT_REVOKED_alert_ctx_ready; server_cbs.on_cleanup = test_wolfSSL_CRL_CERT_REVOKED_alert_on_cleanup; ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&client_cbs, &server_cbs, NULL), -1001); return EXPECT_RESULT(); } #else static int test_wolfSSL_CRL_CERT_REVOKED_alert(void) { return TEST_SKIPPED; } #endif #if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) \ && defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && defined(HAVE_AESGCM) && \ !defined(NO_SHA256) && defined(WOLFSSL_AES_128) && \ defined(WOLFSSL_SHA384) && defined(WOLFSSL_AES_256) && \ !defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) static WOLFSSL_CTX* test_TLS_13_ticket_different_ciphers_ctx = NULL; static WOLFSSL_SESSION* test_TLS_13_ticket_different_ciphers_session = NULL; static int test_TLS_13_ticket_different_ciphers_run = 0; static int test_TLS_13_ticket_different_ciphers_ssl_ready(WOLFSSL* ssl) { EXPECT_DECLS; switch (test_TLS_13_ticket_different_ciphers_run) { case 0: /* First run */ ExpectIntEQ(wolfSSL_set_cipher_list(ssl, "TLS13-AES128-GCM-SHA256"), WOLFSSL_SUCCESS); if (wolfSSL_is_server(ssl)) { ExpectNotNull(test_TLS_13_ticket_different_ciphers_ctx = wolfSSL_get_SSL_CTX(ssl)); ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_up_ref( test_TLS_13_ticket_different_ciphers_ctx)); } break; case 1: /* Second run */ ExpectIntEQ(wolfSSL_set_cipher_list(ssl, "TLS13-AES256-GCM-SHA384:" "TLS13-AES128-GCM-SHA256"), WOLFSSL_SUCCESS); if (!wolfSSL_is_server(ssl)) { ExpectIntEQ(wolfSSL_set_session(ssl, test_TLS_13_ticket_different_ciphers_session), WOLFSSL_SUCCESS); } break; default: /* Bad state? */ Fail(("Should not enter here"), ("Should not enter here")); } return EXPECT_RESULT(); } static int test_TLS_13_ticket_different_ciphers_on_result(WOLFSSL* ssl) { EXPECT_DECLS; switch (test_TLS_13_ticket_different_ciphers_run) { case 0: /* First run */ ExpectNotNull(test_TLS_13_ticket_different_ciphers_session = wolfSSL_get1_session(ssl)); break; case 1: /* Second run */ ExpectTrue(wolfSSL_session_reused(ssl)); break; default: /* Bad state? */ Fail(("Should not enter here"), ("Should not enter here")); } return EXPECT_RESULT(); } static int test_TLS_13_ticket_different_ciphers(void) { EXPECT_DECLS; /* Check that we handle the connection when the ticket doesn't match * the first ciphersuite. */ test_ssl_cbf client_cbs, server_cbs; struct test_params { method_provider client_meth; method_provider server_meth; int doUdp; } params[] = { #ifdef WOLFSSL_DTLS13 /* Test that the stateless code handles sessions correctly */ {wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method, 1}, #endif {wolfTLSv1_3_client_method, wolfTLSv1_3_server_method, 0}, }; size_t i; for (i = 0; i < sizeof(params)/sizeof(*params); i++) { XMEMSET(&client_cbs, 0, sizeof(client_cbs)); XMEMSET(&server_cbs, 0, sizeof(server_cbs)); test_TLS_13_ticket_different_ciphers_run = 0; client_cbs.doUdp = server_cbs.doUdp = params[i].doUdp; client_cbs.method = params[i].client_meth; server_cbs.method = params[i].server_meth; client_cbs.ssl_ready = test_TLS_13_ticket_different_ciphers_ssl_ready; server_cbs.ssl_ready = test_TLS_13_ticket_different_ciphers_ssl_ready; client_cbs.on_result = test_TLS_13_ticket_different_ciphers_on_result; server_cbs.ticNoInit = 1; ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&client_cbs, &server_cbs, NULL), TEST_SUCCESS); test_TLS_13_ticket_different_ciphers_run++; server_cbs.ctx = test_TLS_13_ticket_different_ciphers_ctx; ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&client_cbs, &server_cbs, NULL), TEST_SUCCESS); wolfSSL_SESSION_free(test_TLS_13_ticket_different_ciphers_session); test_TLS_13_ticket_different_ciphers_session = NULL; wolfSSL_CTX_free(test_TLS_13_ticket_different_ciphers_ctx); test_TLS_13_ticket_different_ciphers_ctx = NULL; } return EXPECT_RESULT(); } #else static int test_TLS_13_ticket_different_ciphers(void) { return TEST_SKIPPED; } #endif #if defined(WOLFSSL_EXTRA_ALERTS) && !defined(WOLFSSL_NO_TLS12) && \ defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) #define TEST_WRONG_CS_CLIENT "DHE-RSA-AES128-SHA" /* AKA TLS_DHE_RSA_WITH_AES_128_CBC_SHA */ byte test_extra_alerts_wrong_cs_sh[] = { 0x16, 0x03, 0x03, 0x00, 0x56, 0x02, 0x00, 0x00, 0x52, 0x03, 0x03, 0xef, 0x0c, 0x30, 0x98, 0xa2, 0xac, 0xfa, 0x68, 0xe9, 0x3e, 0xaa, 0x5c, 0xcf, 0xa7, 0x42, 0x72, 0xaf, 0xa0, 0xe8, 0x39, 0x2b, 0x3e, 0x81, 0xa7, 0x7a, 0xa5, 0x62, 0x8a, 0x0e, 0x41, 0xba, 0xda, 0x20, 0x18, 0x9f, 0xe1, 0x8c, 0x1d, 0xc0, 0x37, 0x9c, 0xf4, 0x90, 0x5d, 0x8d, 0xa0, 0x79, 0xa7, 0x4b, 0xa8, 0x79, 0xdf, 0xcd, 0x8d, 0xf5, 0xb5, 0x50, 0x5f, 0xf1, 0xdb, 0x4d, 0xbb, 0x07, 0x54, 0x1c, 0x00, 0x02, /* TLS_RSA_WITH_NULL_SHA */ 0x00, 0x00, 0x0a, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x17, 0x00, 0x00 }; static int test_extra_alerts_wrong_cs(void) { EXPECT_DECLS; #ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA struct test_memio_ctx test_ctx; WOLFSSL_CTX *ctx_c = NULL; WOLFSSL_ALERT_HISTORY h; WOLFSSL *ssl_c = NULL; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, NULL, &ssl_c, NULL, wolfTLSv1_2_client_method, NULL), 0); ExpectIntEQ(wolfSSL_set_cipher_list(ssl_c, TEST_WRONG_CS_CLIENT), WOLFSSL_SUCCESS); /* CH */ ExpectIntNE(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_get_error(ssl_c, WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)), WOLFSSL_ERROR_WANT_READ); /* consume CH */ test_memio_clear_buffer(&test_ctx, 0); /* inject SH */ ExpectIntEQ(test_memio_inject_message(&test_ctx, 1, (const char *)test_extra_alerts_wrong_cs_sh, sizeof(test_extra_alerts_wrong_cs_sh)), 0); ExpectIntNE(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS); ExpectIntNE(wolfSSL_get_error(ssl_c, WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)), WOLFSSL_ERROR_WANT_READ); ExpectIntEQ(wolfSSL_get_alert_history(ssl_c, &h), WOLFSSL_SUCCESS); ExpectIntEQ(h.last_tx.code, handshake_failure); ExpectIntEQ(h.last_tx.level, alert_fatal); wolfSSL_free(ssl_c); wolfSSL_CTX_free(ctx_c); #endif return EXPECT_RESULT(); } #else static int test_extra_alerts_wrong_cs(void) { return TEST_SKIPPED; } #endif #if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_NO_TLS12) && \ defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_AES_256) #define TEST_CS_DOWNGRADE_CLIENT "ECDHE-RSA-AES256-GCM-SHA384" byte test_wrong_cs_downgrade_sh[] = { 0x16, 0x03, 0x03, 0x00, 0x56, 0x02, 0x00, 0x00, 0x52, 0x03, 0x03, 0x10, 0x2c, 0x88, 0xd9, 0x7a, 0x23, 0xc9, 0xbd, 0x11, 0x3b, 0x64, 0x24, 0xab, 0x5b, 0x45, 0x33, 0xf6, 0x2c, 0x34, 0xe4, 0xcf, 0xf4, 0x78, 0xc8, 0x62, 0x06, 0xc7, 0xe5, 0x30, 0x39, 0xbf, 0xa1, 0x20, 0xa3, 0x06, 0x74, 0xc3, 0xa9, 0x74, 0x52, 0x8a, 0xfb, 0xae, 0xf0, 0xd8, 0x6f, 0xb2, 0x9d, 0xfe, 0x78, 0xf0, 0x3f, 0x51, 0x8f, 0x9c, 0xcf, 0xbe, 0x61, 0x43, 0x9d, 0xf8, 0x85, 0xe5, 0x2f, 0x54, 0xc0, 0x2f, /* ECDHE-RSA-AES128-GCM-SHA256 */ 0x00, 0x00, 0x0a, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x17, 0x00, 0x00 }; static int test_wrong_cs_downgrade(void) { EXPECT_DECLS; #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 struct test_memio_ctx test_ctx; WOLFSSL_CTX *ctx_c = NULL; WOLFSSL *ssl_c = NULL; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, NULL, &ssl_c, NULL, wolfSSLv23_client_method, NULL), 0); ExpectIntEQ(wolfSSL_set_cipher_list(ssl_c, TEST_CS_DOWNGRADE_CLIENT), WOLFSSL_SUCCESS); /* CH */ ExpectIntNE(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_get_error(ssl_c, WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)), WOLFSSL_ERROR_WANT_READ); /* consume CH */ test_memio_clear_buffer(&test_ctx, 0); /* inject SH */ ExpectIntEQ(test_memio_inject_message(&test_ctx, 1, (const char *)test_wrong_cs_downgrade_sh, sizeof(test_wrong_cs_downgrade_sh)), 0); ExpectIntNE(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS); #ifdef OPENSSL_EXTRA ExpectIntEQ(wolfSSL_get_error(ssl_c, WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)), WC_NO_ERR_TRACE(WOLFSSL_ERROR_SYSCALL)); #else ExpectIntEQ(wolfSSL_get_error(ssl_c, WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)), WC_NO_ERR_TRACE(MATCH_SUITE_ERROR)); #endif /* OPENSSL_EXTRA */ wolfSSL_free(ssl_c); wolfSSL_CTX_free(ctx_c); #endif return EXPECT_RESULT(); } #else static int test_wrong_cs_downgrade(void) { return TEST_SKIPPED; } #endif #if !defined(WOLFSSL_NO_TLS12) && defined(WOLFSSL_EXTRA_ALERTS) && \ defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && !defined(WOLFSSL_SP_MATH) static int test_remove_hs_msg_from_buffer(struct test_memio_ctx *test_ctx, byte type, byte *found) { const unsigned int _HANDSHAKE_HEADER_SZ = 4; const unsigned int _RECORD_HEADER_SZ = 5; const int _change_cipher_hs = 55; const int _change_cipher = 20; const int _handshake = 22; unsigned int tail_len; byte *idx; int curr; word8 currType; word16 rLength; word32 hLength; idx = test_ctx->c_buff; tail_len = (unsigned int)test_ctx->c_len; *found = 0; while (tail_len > _RECORD_HEADER_SZ) { curr = (int)(idx - test_ctx->c_buff); currType = *idx; ato16(idx + 3, &rLength); idx += _RECORD_HEADER_SZ; tail_len -= _RECORD_HEADER_SZ; if (tail_len < rLength) return -1; if (type == _change_cipher_hs && currType == _change_cipher) { if (rLength != 1) return -1; /* match */ test_memio_remove_from_buffer(test_ctx, 1, curr, _RECORD_HEADER_SZ + rLength); *found = 1; return 0; } if (currType != _handshake) { idx += rLength; tail_len -= rLength; continue; } if (rLength < _HANDSHAKE_HEADER_SZ) return -1; currType = *idx; ato24(idx+1, &hLength); hLength += _HANDSHAKE_HEADER_SZ; if (tail_len < hLength) return -1; if (currType != type) { idx += hLength; tail_len -= hLength; continue; } /* match */ test_memio_remove_from_buffer(test_ctx, 1, curr, hLength + _RECORD_HEADER_SZ); *found = 1; return 0; } /* not found */ return 0; } static int test_remove_hs_message(byte hs_message_type, int extra_round, byte alert_type) { EXPECT_DECLS; WOLFSSL_CTX *ctx_c = NULL; WOLFSSL_CTX *ctx_s = NULL; WOLFSSL *ssl_c = NULL; WOLFSSL *ssl_s = NULL; struct test_memio_ctx test_ctx; WOLFSSL_ALERT_HISTORY h; byte found = 0; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, wolfTLSv1_2_client_method, wolfTLSv1_2_server_method), 0); ExpectIntNE(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_get_error(ssl_c, WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)), WOLFSSL_ERROR_WANT_READ); ExpectIntNE(wolfSSL_accept(ssl_s), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_get_error(ssl_c, WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)), WOLFSSL_ERROR_WANT_READ); if (extra_round) { ExpectIntNE(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_get_error(ssl_c, WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)), WOLFSSL_ERROR_WANT_READ); /* this will complete handshake from server side */ ExpectIntEQ(wolfSSL_accept(ssl_s), WOLFSSL_SUCCESS); } ExpectIntEQ(test_remove_hs_msg_from_buffer(&test_ctx, hs_message_type, &found), 0); if (!found) { wolfSSL_free(ssl_c); wolfSSL_CTX_free(ctx_c); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_s); return TEST_SKIPPED; } ExpectIntNE(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS); ExpectIntNE(wolfSSL_get_error(ssl_c, WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)), WOLFSSL_ERROR_WANT_READ); ExpectIntEQ(wolfSSL_get_alert_history(ssl_c, &h), WOLFSSL_SUCCESS); ExpectTrue(alert_type == 0xff || h.last_tx.code == alert_type); ExpectIntEQ(h.last_tx.level, alert_fatal); wolfSSL_free(ssl_c); wolfSSL_CTX_free(ctx_c); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_s); return EXPECT_RESULT(); } static int test_extra_alerts_skip_hs(void) { EXPECT_DECLS; const byte _server_key_exchange = 12; const byte _server_hello = 2; const byte _certificate = 11; /* server_hello */ ExpectIntNE(test_remove_hs_message(_server_hello, 0, unexpected_message), TEST_FAIL); ExpectIntNE(test_remove_hs_message(_certificate, 0, 0xff), TEST_FAIL); ExpectIntNE(test_remove_hs_message(_server_key_exchange, 0, unexpected_message), TEST_FAIL); return EXPECT_RESULT(); } #else static int test_extra_alerts_skip_hs(void) { return TEST_SKIPPED; } #endif #if !defined(WOLFSSL_NO_TLS12) && defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES)\ && defined(WOLFSSL_EXTRA_ALERTS) && !defined(NO_PSK) && !defined(NO_DH) static unsigned int test_server_psk_cb(WOLFSSL* ssl, const char* id, unsigned char* key, unsigned int key_max_len) { (void)ssl; (void)id; (void)key_max_len; /* zero means error */ key[0] = 0x10; return 1; } static int test_extra_alerts_bad_psk(void) { EXPECT_DECLS; WOLFSSL_CTX *ctx_c = NULL; WOLFSSL_CTX *ctx_s = NULL; WOLFSSL *ssl_c = NULL; WOLFSSL *ssl_s = NULL; struct test_memio_ctx test_ctx; WOLFSSL_ALERT_HISTORY h; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, wolfTLSv1_2_client_method, wolfTLSv1_2_server_method), 0); ExpectIntEQ(wolfSSL_set_cipher_list(ssl_c, "DHE-PSK-AES128-GCM-SHA256"), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_set_cipher_list(ssl_s, "DHE-PSK-AES128-GCM-SHA256"), WOLFSSL_SUCCESS); wolfSSL_set_psk_server_callback(ssl_s, test_server_psk_cb); ExpectIntNE(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_get_error(ssl_c, WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)), WOLFSSL_ERROR_WANT_READ); ExpectIntNE(wolfSSL_accept(ssl_s), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_get_error(ssl_s, WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)), WOLFSSL_ERROR_WANT_READ); ExpectIntNE(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS); ExpectIntNE(wolfSSL_get_error(ssl_c, WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)), WOLFSSL_ERROR_WANT_READ); ExpectIntEQ(wolfSSL_get_alert_history(ssl_c, &h), WOLFSSL_SUCCESS); ExpectIntEQ(h.last_tx.code, handshake_failure); ExpectIntEQ(h.last_tx.level, alert_fatal); wolfSSL_free(ssl_c); wolfSSL_CTX_free(ctx_c); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_s); return EXPECT_RESULT(); } #else static int test_extra_alerts_bad_psk(void) { return TEST_SKIPPED; } #endif #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && !defined(WOLFSSL_NO_TLS12) static int test_multiple_shutdown_nonblocking(void) { EXPECT_DECLS; size_t size_of_last_packet = 0; int dummy_recv_buffer; /* declare wolfSSL objects */ struct test_memio_ctx test_ctx; WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL; WOLFSSL *ssl_c = NULL, *ssl_s = NULL; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); /* Create and initialize WOLFSSL_CTX and WOLFSSL objects */ ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, wolfTLSv1_2_client_method, wolfTLSv1_2_server_method), 0); ExpectNotNull(ctx_c); ExpectNotNull(ssl_c); ExpectNotNull(ctx_s); ExpectNotNull(ssl_s); ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); /* buffers should be empty now */ ExpectIntEQ(test_ctx.c_len, 0); ExpectIntEQ(test_ctx.s_len, 0); ExpectIntEQ(ssl_c->buffers.outputBuffer.length, 0); test_memio_simulate_want_write(&test_ctx, 1, 1); /* * We call wolfSSL_shutdown multiple times to to check that it doesn't add * the CLOSE_NOTIFY packet multiple times on the output buffer. * */ ExpectIntEQ(wolfSSL_shutdown(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, 0), WOLFSSL_ERROR_WANT_WRITE); /* store the size of the packet */ if (ssl_c != NULL) { size_of_last_packet = ssl_c->buffers.outputBuffer.length; } /* invoke it multiple times shouldn't change the wolfssl internal output buffer size */ ExpectIntEQ(wolfSSL_shutdown(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, 0), WOLFSSL_ERROR_WANT_WRITE); ExpectIntEQ(wolfSSL_shutdown(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, 0), WOLFSSL_ERROR_WANT_WRITE); ExpectIntEQ(ssl_c->buffers.outputBuffer.length, size_of_last_packet); /* now send the CLOSE_NOTIFY to the server for real, expecting shutdown not done */ test_memio_simulate_want_write(&test_ctx, 1, 0); ExpectIntEQ(wolfSSL_shutdown(ssl_c), WOLFSSL_SHUTDOWN_NOT_DONE); /* output buffer should be empty and socket buffer should contain the message */ ExpectIntEQ(ssl_c->buffers.outputBuffer.length, 0); ExpectIntEQ(test_ctx.s_len, size_of_last_packet); /* this should try to read from the socket */ ExpectIntEQ(wolfSSL_shutdown(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); /* complete the bidirectional shutdown */ /* check that server received the shutdown alert */ ExpectIntEQ(wolfSSL_recv(ssl_s, &dummy_recv_buffer, 0, 0), 0); ExpectIntEQ(wolfSSL_get_error(ssl_s, 0), WOLFSSL_ERROR_ZERO_RETURN); /* send the shutdown from the server side */ ExpectIntEQ(wolfSSL_shutdown(ssl_s), WOLFSSL_SUCCESS); /* This should return success and zero return */ ExpectIntEQ(wolfSSL_shutdown(ssl_c), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_get_error(ssl_c, 0), WOLFSSL_ERROR_ZERO_RETURN); /* Cleanup and return */ wolfSSL_CTX_free(ctx_c); wolfSSL_free(ssl_c); wolfSSL_CTX_free(ctx_s); wolfSSL_free(ssl_s); return EXPECT_RESULT(); } #else static int test_multiple_shutdown_nonblocking(void) { return TEST_SKIPPED; } #endif #if defined(WOLFSSL_HARDEN_TLS) && !defined(WOLFSSL_NO_TLS12) && \ defined(HAVE_IO_TESTS_DEPENDENCIES) static int test_harden_no_secure_renegotiation_io_cb(WOLFSSL *ssl, char *buf, int sz, void *ctx) { static int sentServerHello = FALSE; if (!sentServerHello) { byte renegExt[] = { 0xFF, 0x01, 0x00, 0x01, 0x00 }; size_t i; if (sz < (int)sizeof(renegExt)) return WOLFSSL_CBIO_ERR_GENERAL; /* Remove SCR from ServerHello */ for (i = 0; i < sz - sizeof(renegExt); i++) { if (XMEMCMP(buf + i, renegExt, sizeof(renegExt)) == 0) { /* Found the extension. Change it to something unrecognized. */ buf[i+1] = 0x11; break; } } sentServerHello = TRUE; } return EmbedSend(ssl, buf, sz, ctx); } static void test_harden_no_secure_renegotiation_ssl_ready(WOLFSSL* ssl) { wolfSSL_SSLSetIOSend(ssl, test_harden_no_secure_renegotiation_io_cb); } static void test_harden_no_secure_renegotiation_on_cleanup(WOLFSSL* ssl) { WOLFSSL_ALERT_HISTORY h; AssertIntEQ(wolfSSL_get_alert_history(ssl, &h), WOLFSSL_SUCCESS); AssertIntEQ(h.last_rx.code, handshake_failure); AssertIntEQ(h.last_rx.level, alert_fatal); } static int test_harden_no_secure_renegotiation(void) { EXPECT_DECLS; callback_functions client_cbs, server_cbs; XMEMSET(&client_cbs, 0, sizeof(client_cbs)); XMEMSET(&server_cbs, 0, sizeof(server_cbs)); client_cbs.method = wolfTLSv1_2_client_method; server_cbs.method = wolfTLSv1_2_server_method; server_cbs.ssl_ready = test_harden_no_secure_renegotiation_ssl_ready; server_cbs.on_cleanup = test_harden_no_secure_renegotiation_on_cleanup; test_wolfSSL_client_server_nofail(&client_cbs, &server_cbs); ExpectIntEQ(client_cbs.return_code, TEST_FAIL); ExpectIntEQ(client_cbs.last_err, WC_NO_ERR_TRACE(SECURE_RENEGOTIATION_E)); ExpectIntEQ(server_cbs.return_code, TEST_FAIL); ExpectTrue(server_cbs.last_err == WC_NO_ERR_TRACE(SOCKET_ERROR_E) || server_cbs.last_err == WC_NO_ERR_TRACE(FATAL_ERROR)); return EXPECT_RESULT(); } #else static int test_harden_no_secure_renegotiation(void) { return TEST_SKIPPED; } #endif #if defined(HAVE_OCSP) && defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) static int test_override_alt_cert_chain_cert_cb(int preverify, WOLFSSL_X509_STORE_CTX* store) { fprintf(stderr, "preverify: %d\n", preverify); fprintf(stderr, "store->error: %d\n", store->error); fprintf(stderr, "error reason: %s\n", wolfSSL_ERR_reason_error_string(store->error)); if (store->error == WC_NO_ERR_TRACE(OCSP_INVALID_STATUS)) { fprintf(stderr, "Overriding OCSP error\n"); return 1; } #ifndef WOLFSSL_ALT_CERT_CHAINS else if ((store->error == WC_NO_ERR_TRACE(ASN_NO_SIGNER_E) || store->error == WC_NO_ERR_TRACE(ASN_SELF_SIGNED_E) #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \ defined(HAVE_WEBSERVER) || store->error == WOLFSSL_X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY #endif ) && store->error_depth == store->totalCerts - 1) { fprintf(stderr, "Overriding no signer error only for root cert\n"); return 1; } #endif else return preverify; } static int test_override_alt_cert_chain_ocsp_cb(void* ioCtx, const char* url, int urlSz, unsigned char* request, int requestSz, unsigned char** response) { (void)ioCtx; (void)url; (void)urlSz; (void)request; (void)requestSz; (void)response; return WOLFSSL_CBIO_ERR_GENERAL; } static int test_override_alt_cert_chain_client_ctx_ready(WOLFSSL_CTX* ctx) { EXPECT_DECLS; wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, test_override_alt_cert_chain_cert_cb); ExpectIntEQ(wolfSSL_CTX_EnableOCSP(ctx, WOLFSSL_OCSP_CHECKALL | WOLFSSL_OCSP_URL_OVERRIDE), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_SetOCSP_Cb(ctx, test_override_alt_cert_chain_ocsp_cb, NULL, NULL), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_SetOCSP_OverrideURL(ctx, "not a url"), WOLFSSL_SUCCESS); return EXPECT_RESULT(); } static int test_override_alt_cert_chain_client_ctx_ready2(WOLFSSL_CTX* ctx) { EXPECT_DECLS; wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, NULL); ExpectIntEQ(wolfSSL_CTX_EnableOCSP(ctx, WOLFSSL_OCSP_CHECKALL | WOLFSSL_OCSP_URL_OVERRIDE), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_SetOCSP_Cb(ctx, test_override_alt_cert_chain_ocsp_cb, NULL, NULL), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_SetOCSP_OverrideURL(ctx, "not a url"), WOLFSSL_SUCCESS); return EXPECT_RESULT(); } static int test_override_alt_cert_chain_server_ctx_ready(WOLFSSL_CTX* ctx) { EXPECT_DECLS; ExpectIntEQ(wolfSSL_CTX_use_certificate_chain_file(ctx, "./certs/intermediate/server-chain-alt.pem"), WOLFSSL_SUCCESS); return EXPECT_RESULT(); } static int test_override_alt_cert_chain(void) { EXPECT_DECLS; size_t i; struct test_params { ctx_cb client_ctx_cb; ctx_cb server_ctx_cb; int result; } params[] = { {test_override_alt_cert_chain_client_ctx_ready, test_override_alt_cert_chain_server_ctx_ready, TEST_SUCCESS}, {test_override_alt_cert_chain_client_ctx_ready2, test_override_alt_cert_chain_server_ctx_ready, -1001}, }; for (i = 0; i < sizeof(params)/sizeof(*params); i++) { test_ssl_cbf client_cbs, server_cbs; XMEMSET(&client_cbs, 0, sizeof(client_cbs)); XMEMSET(&server_cbs, 0, sizeof(server_cbs)); fprintf(stderr, "test config: %d\n", (int)i); client_cbs.ctx_ready = params[i].client_ctx_cb; server_cbs.ctx_ready = params[i].server_ctx_cb; ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&client_cbs, &server_cbs, NULL), params[i].result); ExpectIntEQ(client_cbs.return_code, params[i].result <= 0 ? -1000 : TEST_SUCCESS); ExpectIntEQ(server_cbs.return_code, params[i].result <= 0 ? -1000 : TEST_SUCCESS); } return EXPECT_RESULT(); } #else static int test_override_alt_cert_chain(void) { return TEST_SKIPPED; } #endif static int test_rpk_set_xxx_cert_type(void) { EXPECT_DECLS; #if defined(HAVE_RPK) && !defined(NO_TLS) && !defined(NO_WOLFSSL_CLIENT) char ctype[MAX_CLIENT_CERT_TYPE_CNT + 1]; /* prepare bigger buffer */ WOLFSSL_CTX* ctx = NULL; WOLFSSL* ssl = NULL; int tp; ctx = wolfSSL_CTX_new(wolfTLS_client_method()); ExpectNotNull(ctx); ssl = wolfSSL_new(ctx); ExpectNotNull(ssl); XMEMSET(ctype, 0, sizeof(ctype)); /*--------------------------------------------*/ /* tests for wolfSSL_CTX_set_client_cert_type */ /*--------------------------------------------*/ /* illegal parameter test caces */ ExpectIntEQ(wolfSSL_CTX_set_client_cert_type(NULL, ctype, MAX_CLIENT_CERT_TYPE_CNT), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_CTX_set_client_cert_type(ctx, ctype, sizeof(ctype)), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ctype[0] = WOLFSSL_CERT_TYPE_RPK; /* set an identical cert type */ ctype[1] = WOLFSSL_CERT_TYPE_RPK; ExpectIntEQ(wolfSSL_CTX_set_client_cert_type(ctx, ctype, MAX_CLIENT_CERT_TYPE_CNT), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ctype[0] = WOLFSSL_CERT_TYPE_X509; ctype[1] = 10; /* set unknown cert type */ ExpectIntEQ(wolfSSL_CTX_set_client_cert_type(ctx, ctype, MAX_CLIENT_CERT_TYPE_CNT), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* pass larger type count */ ctype[0] = WOLFSSL_CERT_TYPE_RPK; ctype[1] = WOLFSSL_CERT_TYPE_X509; ctype[2] = 1; /* pass unacceptable type count */ ExpectIntEQ(wolfSSL_CTX_set_client_cert_type(ctx, ctype, MAX_CLIENT_CERT_TYPE_CNT + 1), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* should accept NULL for type buffer */ ExpectIntEQ(wolfSSL_CTX_set_client_cert_type(ctx, NULL, MAX_CLIENT_CERT_TYPE_CNT), WOLFSSL_SUCCESS); /* should accept zero for type count */ ExpectIntEQ(wolfSSL_CTX_set_client_cert_type(ctx, ctype, 0), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_set_client_cert_type(ctx, ctype, MAX_CLIENT_CERT_TYPE_CNT), WOLFSSL_SUCCESS); /*--------------------------------------------*/ /* tests for wolfSSL_CTX_set_server_cert_type */ /*--------------------------------------------*/ ExpectIntEQ(wolfSSL_CTX_set_server_cert_type(NULL, ctype, MAX_SERVER_CERT_TYPE_CNT), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_CTX_set_server_cert_type(ctx, ctype, sizeof(ctype)), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ctype[0] = WOLFSSL_CERT_TYPE_RPK; /* set an identical cert type */ ctype[1] = WOLFSSL_CERT_TYPE_RPK; ExpectIntEQ(wolfSSL_CTX_set_server_cert_type(ctx, ctype, MAX_SERVER_CERT_TYPE_CNT), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ctype[0] = WOLFSSL_CERT_TYPE_X509; ctype[1] = 10; /* set unknown cert type */ ExpectIntEQ(wolfSSL_CTX_set_server_cert_type(ctx, ctype, MAX_SERVER_CERT_TYPE_CNT), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* pass larger type count */ ctype[0] = WOLFSSL_CERT_TYPE_RPK; ctype[1] = WOLFSSL_CERT_TYPE_X509; ctype[2] = 1; /* pass unacceptable type count */ ExpectIntEQ(wolfSSL_CTX_set_server_cert_type(ctx, ctype, MAX_SERVER_CERT_TYPE_CNT + 1), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* should accept NULL for type buffer */ ExpectIntEQ(wolfSSL_CTX_set_server_cert_type(ctx, NULL, MAX_SERVER_CERT_TYPE_CNT), WOLFSSL_SUCCESS); /* should accept zero for type count */ ExpectIntEQ(wolfSSL_CTX_set_server_cert_type(ctx, ctype, 0), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_set_server_cert_type(ctx, ctype, MAX_CLIENT_CERT_TYPE_CNT), WOLFSSL_SUCCESS); /*--------------------------------------------*/ /* tests for wolfSSL_set_client_cert_type */ /*--------------------------------------------*/ ExpectIntEQ(wolfSSL_set_client_cert_type(NULL, ctype, MAX_CLIENT_CERT_TYPE_CNT), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_set_client_cert_type(ssl, ctype, sizeof(ctype)), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ctype[0] = WOLFSSL_CERT_TYPE_RPK; /* set an identical cert type */ ctype[1] = WOLFSSL_CERT_TYPE_RPK; ExpectIntEQ(wolfSSL_set_client_cert_type(ssl, ctype, MAX_CLIENT_CERT_TYPE_CNT), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ctype[0] = WOLFSSL_CERT_TYPE_X509; ctype[1] = 10; /* set unknown cert type */ ExpectIntEQ(wolfSSL_set_client_cert_type(ssl, ctype, MAX_CLIENT_CERT_TYPE_CNT), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* pass larger type count */ ctype[0] = WOLFSSL_CERT_TYPE_RPK; ctype[1] = WOLFSSL_CERT_TYPE_X509; ctype[2] = 1; /* pass unacceptable type count */ ExpectIntEQ(wolfSSL_set_client_cert_type(ssl, ctype, MAX_CLIENT_CERT_TYPE_CNT + 1), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* should accept NULL for type buffer */ ExpectIntEQ(wolfSSL_set_client_cert_type(ssl, NULL, MAX_CLIENT_CERT_TYPE_CNT), WOLFSSL_SUCCESS); /* should accept zero for type count */ ExpectIntEQ(wolfSSL_set_client_cert_type(ssl, ctype, 0), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_set_client_cert_type(ssl, ctype, MAX_CLIENT_CERT_TYPE_CNT), WOLFSSL_SUCCESS); /*--------------------------------------------*/ /* tests for wolfSSL_CTX_set_server_cert_type */ /*--------------------------------------------*/ ExpectIntEQ(wolfSSL_set_server_cert_type(NULL, ctype, MAX_SERVER_CERT_TYPE_CNT), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_set_server_cert_type(ssl, ctype, sizeof(ctype)), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ctype[0] = WOLFSSL_CERT_TYPE_RPK; /* set an identical cert type */ ctype[1] = WOLFSSL_CERT_TYPE_RPK; ExpectIntEQ(wolfSSL_set_server_cert_type(ssl, ctype, MAX_SERVER_CERT_TYPE_CNT), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ctype[0] = WOLFSSL_CERT_TYPE_X509; ctype[1] = 10; /* set unknown cert type */ ExpectIntEQ(wolfSSL_set_server_cert_type(ssl, ctype, MAX_SERVER_CERT_TYPE_CNT), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* pass larger type count */ ctype[0] = WOLFSSL_CERT_TYPE_RPK; ctype[1] = WOLFSSL_CERT_TYPE_X509; ctype[2] = 1; /* pass unacceptable type count */ ExpectIntEQ(wolfSSL_set_server_cert_type(ssl, ctype, MAX_SERVER_CERT_TYPE_CNT + 1), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* should accept NULL for type buffer */ ExpectIntEQ(wolfSSL_set_server_cert_type(ssl, NULL, MAX_SERVER_CERT_TYPE_CNT), WOLFSSL_SUCCESS); /* should accept zero for type count */ ExpectIntEQ(wolfSSL_set_server_cert_type(ssl, ctype, 0), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_set_server_cert_type(ssl, ctype, MAX_SERVER_CERT_TYPE_CNT), WOLFSSL_SUCCESS); /*------------------------------------------------*/ /* tests for wolfSSL_get_negotiated_xxx_cert_type */ /*------------------------------------------------*/ ExpectIntEQ(wolfSSL_get_negotiated_client_cert_type(NULL, &tp), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_get_negotiated_client_cert_type(ssl, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_get_negotiated_server_cert_type(NULL, &tp), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_get_negotiated_server_cert_type(ssl, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* clean up */ wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13) static int test_dtls13_bad_epoch_ch(void) { EXPECT_DECLS; WOLFSSL_CTX *ctx_c = NULL; WOLFSSL_CTX *ctx_s = NULL; WOLFSSL *ssl_c = NULL; WOLFSSL *ssl_s = NULL; struct test_memio_ctx test_ctx; const int EPOCH_OFF = 3; int groups[] = { WOLFSSL_ECC_SECP256R1, WOLFSSL_ECC_SECP384R1, }; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method), 0); /* disable hrr cookie so we can later check msgsReceived.got_client_hello * with just one message */ ExpectIntEQ(wolfSSL_disable_hrr_cookie(ssl_s), WOLFSSL_SUCCESS); /* Set client groups to traditional only to avoid CH fragmentation */ ExpectIntEQ(wolfSSL_set_groups(ssl_c, groups, 2), WOLFSSL_SUCCESS); ExpectIntNE(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_get_error(ssl_c, WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)), WOLFSSL_ERROR_WANT_READ); ExpectIntGE(test_ctx.s_len, EPOCH_OFF + 2); /* first CH should use epoch 0x0 */ ExpectTrue((test_ctx.s_buff[EPOCH_OFF] == 0x0) && (test_ctx.s_buff[EPOCH_OFF + 1] == 0x0)); /* change epoch to 2 */ test_ctx.s_buff[EPOCH_OFF + 1] = 0x2; ExpectIntNE(wolfSSL_accept(ssl_s), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_get_error(ssl_s, WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)), WOLFSSL_ERROR_WANT_READ); ExpectIntNE(ssl_s->msgsReceived.got_client_hello, 1); /* resend the CH */ ExpectIntEQ(wolfSSL_dtls_got_timeout(ssl_c), WOLFSSL_SUCCESS); ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); wolfSSL_free(ssl_c); wolfSSL_CTX_free(ctx_c); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_s); return EXPECT_RESULT(); } #else static int test_dtls13_bad_epoch_ch(void) { return TEST_SKIPPED; } #endif #if ((defined(WOLFSSL_TLS13) && !defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) && \ defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_TICKET_HAVE_ID) && \ !defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT)) || \ (!defined(NO_OLD_TLS) && ((!defined(NO_AES) && !defined(NO_AES_CBC)) || \ !defined(NO_DES3))) || !defined(WOLFSSL_NO_TLS12)) && \ !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) && \ defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && \ !defined(NO_SESSION_CACHE) && !defined(NO_SHA256) static int test_short_session_id_ssl_ready(WOLFSSL* ssl) { EXPECT_DECLS; WOLFSSL_SESSION *sess = NULL; /* Setup the session to avoid errors */ ssl->session->timeout = (word32)-1; ssl->session->side = WOLFSSL_CLIENT_END; ssl->session->version = ssl->version; /* Force a short session ID to be sent */ ssl->session->sessionIDSz = 4; #ifndef NO_SESSION_CACHE_REF /* Allow the client cache to be used */ ssl->session->idLen = 4; #endif ssl->session->isSetup = 1; ExpectNotNull(sess = wolfSSL_get_session(ssl)); ExpectIntEQ(wolfSSL_set_session(ssl, sess), WOLFSSL_SUCCESS); return EXPECT_RESULT(); } static int test_short_session_id(void) { EXPECT_DECLS; test_ssl_cbf client_cbf; test_ssl_cbf server_cbf; size_t i; struct { method_provider client_meth; method_provider server_meth; const char* tls_version; } params[] = { #if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) && \ defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_TICKET_HAVE_ID) && \ !defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT) /* With WOLFSSL_TLS13_MIDDLEBOX_COMPAT a short ID will result in an error */ { wolfTLSv1_3_client_method, wolfTLSv1_3_server_method, "TLSv1_3" }, #ifdef WOLFSSL_DTLS13 { wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method, "DTLSv1_3" }, #endif #endif #ifndef WOLFSSL_NO_TLS12 { wolfTLSv1_2_client_method, wolfTLSv1_2_server_method, "TLSv1_2" }, #ifdef WOLFSSL_DTLS { wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method, "DTLSv1_2" }, #endif #endif #if !defined(NO_OLD_TLS) && ((!defined(NO_AES) && !defined(NO_AES_CBC)) || \ !defined(NO_DES3)) { wolfTLSv1_1_client_method, wolfTLSv1_1_server_method, "TLSv1_1" }, #ifdef WOLFSSL_DTLS { wolfDTLSv1_client_method, wolfDTLSv1_server_method, "DTLSv1_0" }, #endif #endif }; fprintf(stderr, "\n"); for (i = 0; i < sizeof(params)/sizeof(*params) && !EXPECT_FAIL(); i++) { XMEMSET(&client_cbf, 0, sizeof(client_cbf)); XMEMSET(&server_cbf, 0, sizeof(server_cbf)); fprintf(stderr, "\tTesting short ID with %s\n", params[i].tls_version); client_cbf.ssl_ready = test_short_session_id_ssl_ready; client_cbf.method = params[i].client_meth; server_cbf.method = params[i].server_meth; ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&client_cbf, &server_cbf, NULL), TEST_SUCCESS); } return EXPECT_RESULT(); } #else static int test_short_session_id(void) { return TEST_SKIPPED; } #endif #if defined(HAVE_NULL_CIPHER) && defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) \ && defined(WOLFSSL_DTLS13) static byte* test_find_string(const char *string, byte *buf, int buf_size) { int string_size, i; string_size = (int)XSTRLEN(string); for (i = 0; i < buf_size - string_size - 1; i++) { if (XSTRCMP((char*)&buf[i], string) == 0) return &buf[i]; } return NULL; } static int test_wolfSSL_dtls13_null_cipher(void) { EXPECT_DECLS; WOLFSSL_CTX *ctx_c = NULL; WOLFSSL_CTX *ctx_s = NULL; WOLFSSL *ssl_c = NULL; WOLFSSL *ssl_s = NULL; struct test_memio_ctx test_ctx; const char *test_str = "test"; int test_str_size; byte buf[255], *ptr = NULL; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); test_ctx.c_ciphers = test_ctx.s_ciphers = "TLS13-SHA256-SHA256"; ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method), 0); ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); test_str_size = XSTRLEN("test") + 1; ExpectIntEQ(wolfSSL_write(ssl_c, test_str, test_str_size), test_str_size); ExpectIntEQ(wolfSSL_read(ssl_s, buf, sizeof(buf)), test_str_size); ExpectIntEQ(XSTRCMP((char*)buf, test_str), 0); ExpectIntEQ(wolfSSL_write(ssl_c, test_str, test_str_size), test_str_size); /* check that the packet was sent cleartext */ ExpectNotNull(ptr = test_find_string(test_str, test_ctx.s_buff, test_ctx.s_len)); if (ptr != NULL) { /* modify the message */ *ptr = 'H'; /* bad messages should be ignored in DTLS */ ExpectIntEQ(wolfSSL_read(ssl_s, buf, sizeof(buf)), -1); ExpectIntEQ(ssl_s->error, WC_NO_ERR_TRACE(WANT_READ)); } ExpectIntEQ(wolfSSL_shutdown(ssl_c), WOLFSSL_SHUTDOWN_NOT_DONE); ExpectIntEQ(wolfSSL_shutdown(ssl_s), WOLFSSL_SHUTDOWN_NOT_DONE); ExpectIntEQ(wolfSSL_shutdown(ssl_c), 1); ExpectIntEQ(wolfSSL_shutdown(ssl_s), 1); wolfSSL_free(ssl_c); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_c); wolfSSL_CTX_free(ctx_s); return TEST_SUCCESS; } #else static int test_wolfSSL_dtls13_null_cipher(void) { return TEST_SKIPPED; } #endif #if defined(WOLFSSL_DTLS) && !defined(WOLFSSL_NO_TLS12) && \ !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) && \ !defined(SINGLE_THREADED) && !defined(NO_RSA) static int test_dtls_msg_get_connected_port(int fd, word16 *port) { SOCKADDR_S peer; XSOCKLENT len; int ret; XMEMSET((byte*)&peer, 0, sizeof(peer)); len = sizeof(peer); ret = getpeername(fd, (SOCKADDR*)&peer, &len); if (ret != 0 || len > (XSOCKLENT)sizeof(peer)) return -1; switch (peer.ss_family) { #ifdef WOLFSSL_IPV6 case WOLFSSL_IP6: { *port = ntohs(((SOCKADDR_IN6*)&peer)->sin6_port); break; } #endif /* WOLFSSL_IPV6 */ case WOLFSSL_IP4: *port = ntohs(((SOCKADDR_IN*)&peer)->sin_port); break; default: return -1; } return 0; } static int test_dtls_msg_from_other_peer_cb(WOLFSSL_CTX *ctx, WOLFSSL *ssl) { char buf[1] = {'t'}; SOCKADDR_IN_T addr; int sock_fd; word16 port; int err; (void)ssl; (void)ctx; if (ssl == NULL) return -1; err = test_dtls_msg_get_connected_port(wolfSSL_get_fd(ssl), &port); if (err != 0) return -1; sock_fd = socket(AF_INET_V, SOCK_DGRAM, 0); if (sock_fd == -1) return -1; build_addr(&addr, wolfSSLIP, port, 1, 0); /* send a packet to the server. Being another socket, the kernel will ensure * the source port will be different. */ err = (int)sendto(sock_fd, buf, sizeof(buf), 0, (SOCKADDR*)&addr, sizeof(addr)); close(sock_fd); if (err == -1) return -1; return 0; } /* setup a SSL session but just after the handshake send a packet to the server * with a source address different than the one of the connected client. The I/O * callback EmbedRecvFrom should just ignore the packet. Sending of the packet * is done in test_dtls_msg_from_other_peer_cb */ static int test_dtls_msg_from_other_peer(void) { EXPECT_DECLS; callback_functions client_cbs; callback_functions server_cbs; XMEMSET((byte*)&client_cbs, 0, sizeof(client_cbs)); XMEMSET((byte*)&server_cbs, 0, sizeof(server_cbs)); client_cbs.method = wolfDTLSv1_2_client_method; server_cbs.method = wolfDTLSv1_2_server_method; client_cbs.doUdp = 1; server_cbs.doUdp = 1; test_wolfSSL_client_server_nofail_ex(&client_cbs, &server_cbs, test_dtls_msg_from_other_peer_cb); ExpectIntEQ(client_cbs.return_code, WOLFSSL_SUCCESS); ExpectIntEQ(server_cbs.return_code, WOLFSSL_SUCCESS); return EXPECT_RESULT(); } #else static int test_dtls_msg_from_other_peer(void) { return TEST_SKIPPED; } #endif /* defined(WOLFSSL_DTLS) && !defined(WOLFSSL_NO_TLS12) && \ * !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) && \ * !defined(SINGLE_THREADED) && !defined(NO_RSA) */ #if defined(WOLFSSL_DTLS) && !defined(WOLFSSL_IPV6) && \ !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) && \ defined(HAVE_IO_TESTS_DEPENDENCIES) && !defined(WOLFSSL_NO_TLS12) \ && !defined(USE_WINDOWS_API) static int test_dtls_ipv6_check(void) { EXPECT_DECLS; WOLFSSL_CTX *ctx_c = NULL; WOLFSSL_CTX *ctx_s = NULL; WOLFSSL *ssl_c = NULL; WOLFSSL *ssl_s = NULL; SOCKADDR_IN fake_addr6; int sockfd = -1; ExpectNotNull(ctx_c = wolfSSL_CTX_new(wolfDTLSv1_2_client_method())); ExpectNotNull(ssl_c = wolfSSL_new(ctx_c)); ExpectNotNull(ctx_s = wolfSSL_CTX_new(wolfDTLSv1_2_server_method())); ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_file(ctx_s, svrKeyFile, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_use_certificate_file(ctx_s, svrCertFile, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); ExpectNotNull(ssl_s = wolfSSL_new(ctx_s)); XMEMSET((byte*)&fake_addr6, 0, sizeof(fake_addr6)); /* mimic a sockaddr_in6 struct, this way we can't test without * WOLFSSL_IPV6 */ fake_addr6.sin_family = WOLFSSL_IP6; ExpectIntNE(sockfd = socket(AF_INET, SOCK_DGRAM, 0), -1); ExpectIntEQ(wolfSSL_set_fd(ssl_c, sockfd), WOLFSSL_SUCCESS); /* can't return error here, as the peer is opaque for wolfssl library at * this point */ ExpectIntEQ(wolfSSL_dtls_set_peer(ssl_c, &fake_addr6, sizeof(fake_addr6)), WOLFSSL_SUCCESS); ExpectIntNE(fcntl(sockfd, F_SETFL, O_NONBLOCK), -1); wolfSSL_dtls_set_using_nonblock(ssl_c, 1); ExpectIntNE(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS); ExpectIntEQ(ssl_c->error, WC_NO_ERR_TRACE(SOCKET_ERROR_E)); ExpectIntEQ(wolfSSL_dtls_set_peer(ssl_s, &fake_addr6, sizeof(fake_addr6)), WOLFSSL_SUCCESS); /* reuse the socket */ ExpectIntEQ(wolfSSL_set_fd(ssl_c, sockfd), WOLFSSL_SUCCESS); wolfSSL_dtls_set_using_nonblock(ssl_s, 1); ExpectIntNE(wolfSSL_accept(ssl_s), WOLFSSL_SUCCESS); ExpectIntEQ(ssl_s->error, WC_NO_ERR_TRACE(SOCKET_ERROR_E)); if (sockfd != -1) close(sockfd); wolfSSL_free(ssl_c); wolfSSL_CTX_free(ctx_c); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_s); return EXPECT_RESULT(); } #else static int test_dtls_ipv6_check(void) { return TEST_SKIPPED; } #endif #if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) && \ defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(HAVE_SECURE_RENEGOTIATION) static WOLFSSL_SESSION* test_wolfSSL_SCR_after_resumption_session = NULL; static void test_wolfSSL_SCR_after_resumption_ctx_ready(WOLFSSL_CTX* ctx) { AssertIntEQ(wolfSSL_CTX_UseSecureRenegotiation(ctx), WOLFSSL_SUCCESS); } static void test_wolfSSL_SCR_after_resumption_on_result(WOLFSSL* ssl) { if (test_wolfSSL_SCR_after_resumption_session == NULL) { test_wolfSSL_SCR_after_resumption_session = wolfSSL_get1_session(ssl); AssertNotNull(test_wolfSSL_SCR_after_resumption_session); } else { char testMsg[] = "Message after SCR"; char msgBuf[sizeof(testMsg)]; int ret; if (!wolfSSL_is_server(ssl)) { AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_set_session(ssl, test_wolfSSL_SCR_after_resumption_session)); } AssertIntEQ(wolfSSL_Rehandshake(ssl), WOLFSSL_SUCCESS); AssertIntEQ(wolfSSL_write(ssl, testMsg, sizeof(testMsg)), sizeof(testMsg)); ret = wolfSSL_read(ssl, msgBuf, sizeof(msgBuf)); if (ret != sizeof(msgBuf)) /* Possibly APP_DATA_READY error. Retry. */ ret = wolfSSL_read(ssl, msgBuf, sizeof(msgBuf)); AssertIntEQ(ret, sizeof(msgBuf)); } } static void test_wolfSSL_SCR_after_resumption_ssl_ready(WOLFSSL* ssl) { AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_set_session(ssl, test_wolfSSL_SCR_after_resumption_session)); } static int test_wolfSSL_SCR_after_resumption(void) { EXPECT_DECLS; callback_functions func_cb_client; callback_functions func_cb_server; XMEMSET(&func_cb_client, 0, sizeof(func_cb_client)); XMEMSET(&func_cb_server, 0, sizeof(func_cb_server)); func_cb_client.method = wolfTLSv1_2_client_method; func_cb_client.ctx_ready = test_wolfSSL_SCR_after_resumption_ctx_ready; func_cb_client.on_result = test_wolfSSL_SCR_after_resumption_on_result; func_cb_server.method = wolfTLSv1_2_server_method; func_cb_server.ctx_ready = test_wolfSSL_SCR_after_resumption_ctx_ready; test_wolfSSL_client_server_nofail(&func_cb_client, &func_cb_server); ExpectIntEQ(func_cb_client.return_code, TEST_SUCCESS); ExpectIntEQ(func_cb_server.return_code, TEST_SUCCESS); if (EXPECT_SUCCESS()) { func_cb_client.ssl_ready = test_wolfSSL_SCR_after_resumption_ssl_ready; func_cb_server.on_result = test_wolfSSL_SCR_after_resumption_on_result; test_wolfSSL_client_server_nofail(&func_cb_client, &func_cb_server); ExpectIntEQ(func_cb_client.return_code, TEST_SUCCESS); ExpectIntEQ(func_cb_server.return_code, TEST_SUCCESS); } wolfSSL_SESSION_free(test_wolfSSL_SCR_after_resumption_session); return EXPECT_RESULT(); } #else static int test_wolfSSL_SCR_after_resumption(void) { return TEST_SKIPPED; } #endif static int test_wolfSSL_configure_args(void) { EXPECT_DECLS; #if defined(LIBWOLFSSL_CONFIGURE_ARGS) && defined(HAVE_WC_INTROSPECTION) ExpectNotNull(wolfSSL_configure_args()); #endif return EXPECT_RESULT(); } static int test_dtls_no_extensions(void) { EXPECT_DECLS; #if defined(WOLFSSL_DTLS) && defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \ !defined(WOLFSSL_NO_TLS12) WOLFSSL *ssl_s = NULL; WOLFSSL_CTX *ctx_s = NULL; struct test_memio_ctx test_ctx; const byte chNoExtensions[] = { /* Handshake type */ 0x16, /* Version */ 0xfe, 0xff, /* Epoch */ 0x00, 0x00, /* Seq number */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Length */ 0x00, 0x40, /* CH type */ 0x01, /* Length */ 0x00, 0x00, 0x34, /* Msg Seq */ 0x00, 0x00, /* Frag offset */ 0x00, 0x00, 0x00, /* Frag length */ 0x00, 0x00, 0x34, /* Version */ 0xfe, 0xff, /* Random */ 0x62, 0xfe, 0xbc, 0xfe, 0x2b, 0xfe, 0x3f, 0xeb, 0x03, 0xc4, 0xea, 0x37, 0xe7, 0x47, 0x7e, 0x8a, 0xd9, 0xbf, 0x77, 0x0f, 0x6c, 0xb6, 0x77, 0x0b, 0x03, 0x3f, 0x82, 0x2b, 0x21, 0x64, 0x57, 0x1d, /* Session Length */ 0x00, /* Cookie Length */ 0x00, /* CS Length */ 0x00, 0x0c, /* CS */ 0xc0, 0x0a, 0xc0, 0x09, 0xc0, 0x14, 0xc0, 0x13, 0x00, 0x39, 0x00, 0x33, /* Comp Meths Length */ 0x01, /* Comp Meths */ 0x00 /* And finally... no extensions */ }; int i; #ifdef OPENSSL_EXTRA int repeats = 2; #else int repeats = 1; #endif for (i = 0; i < repeats; i++) { XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ssl_s = NULL; ctx_s = NULL; ExpectIntEQ(test_memio_setup(&test_ctx, NULL, &ctx_s, NULL, &ssl_s, NULL, wolfDTLS_server_method), 0); test_memio_clear_buffer(&test_ctx, 0); ExpectIntEQ( test_memio_inject_message(&test_ctx, 1, (const char *)chNoExtensions, sizeof(chNoExtensions)), 0); #ifdef OPENSSL_EXTRA if (i > 0) { ExpectIntEQ(wolfSSL_set_max_proto_version(ssl_s, DTLS1_2_VERSION), WOLFSSL_SUCCESS); } #endif ExpectIntEQ(wolfSSL_accept(ssl_s), -1); ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ); /* Expecting a handshake msg. Either HVR or SH. */ ExpectIntGT(test_ctx.c_len, 0); ExpectIntEQ(test_ctx.c_buff[0], 0x16); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_s); } #endif return EXPECT_RESULT(); } static int test_tls_alert_no_server_hello(void) { EXPECT_DECLS; #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && !defined(WOLFSSL_NO_TLS12) WOLFSSL *ssl_c = NULL; WOLFSSL_CTX *ctx_c = NULL; struct test_memio_ctx test_ctx; unsigned char alert_msg[] = { 0x15, 0x03, 0x01, 0x00, 0x02, 0x02, 0x28 }; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ssl_c = NULL; ctx_c = NULL; ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, NULL, &ssl_c, NULL, wolfTLSv1_2_client_method, NULL), 0); test_memio_clear_buffer(&test_ctx, 1); ExpectIntEQ(test_memio_inject_message(&test_ctx, 1, (const char *)alert_msg, sizeof(alert_msg)), 0); ExpectIntEQ(wolfSSL_connect(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WC_NO_ERR_TRACE(FATAL_ERROR)); wolfSSL_free(ssl_c); wolfSSL_CTX_free(ctx_c); #endif return EXPECT_RESULT(); } static int test_TLSX_CA_NAMES_bad_extension(void) { EXPECT_DECLS; #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_TLS13) && \ !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES) && \ defined(OPENSSL_EXTRA) && defined(BUILD_TLS_CHACHA20_POLY1305_SHA256) && \ defined(HAVE_ECC) && !defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT) /* This test should only fail (with BUFFER_ERROR) when we actually try to * parse the CA Names extension. Otherwise it will return other non-related * errors. If CA Names will be parsed in more configurations, that should * be reflected in the macro guard above. */ WOLFSSL *ssl_c = NULL; WOLFSSL_CTX *ctx_c = NULL; struct test_memio_ctx test_ctx; /* HRR + SH using TLS_CHACHA20_POLY1305_SHA256 */ const byte shBadCaNamesExt[] = { 0x16, 0x03, 0x04, 0x00, 0x3f, 0x02, 0x00, 0x00, 0x3b, 0x03, 0x03, 0xcf, 0x21, 0xad, 0x74, 0xe5, 0x9a, 0x61, 0x11, 0xbe, 0x1d, 0x8c, 0x02, 0x1e, 0x65, 0xb8, 0x91, 0xc2, 0xa2, 0x11, 0x16, 0x7a, 0xbb, 0x8c, 0x5e, 0x07, 0x9e, 0x09, 0xe2, 0xc8, 0xa8, 0x33, 0x9c, 0x00, 0x13, 0x03, 0x00, 0x00, 0x13, 0x94, 0x7e, 0x00, 0x03, 0x0b, 0xf7, 0x03, 0x00, 0x2b, 0x00, 0x02, 0x03, 0x04, 0x00, 0x33, 0x00, 0x02, 0x00, 0x19, 0x16, 0x03, 0x03, 0x00, 0x5c, 0x02, 0x00, 0x00, 0x3b, 0x03, 0x03, 0x03, 0xcf, 0x21, 0xad, 0x74, 0x00, 0x00, 0x83, 0x3f, 0x3b, 0x80, 0x01, 0xac, 0x65, 0x8c, 0x19, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x02, 0x00, 0x9e, 0x09, 0x1c, 0xe8, 0xa8, 0x09, 0x9c, 0x00, 0x13, 0x03, 0x00, 0x00, 0x11, 0x8f, 0x00, 0x00, 0x03, 0x3f, 0x00, 0x0c, 0x00, 0x2b, 0x00, 0x02, 0x03, 0x04, 0x13, 0x05, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x11, 0x00, 0x00, 0x0d, 0x00, 0x2f, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x0d, 0x00, 0x00, 0x00, 0xad, 0x02 }; const byte shBadCaNamesExt2[] = { 0x16, 0x03, 0x04, 0x00, 0x3f, 0x02, 0x00, 0x00, 0x3b, 0x03, 0x03, 0xcf, 0x21, 0xad, 0x74, 0xe5, 0x9a, 0x61, 0x11, 0xbe, 0x1d, 0x8c, 0x02, 0x1e, 0x65, 0xb8, 0x91, 0xc2, 0xa2, 0x11, 0x16, 0x7a, 0xbb, 0x8c, 0x5e, 0x07, 0x9e, 0x09, 0xe2, 0xc8, 0xa8, 0x33, 0x9c, 0x00, 0x13, 0x03, 0x00, 0x00, 0x13, 0x94, 0x7e, 0x00, 0x03, 0x0b, 0xf7, 0x03, 0x00, 0x2b, 0x00, 0x02, 0x03, 0x04, 0x00, 0x33, 0x00, 0x02, 0x00, 0x19, 0x16, 0x03, 0x03, 0x00, 0x5e, 0x02, 0x00, 0x00, 0x3b, 0x03, 0x03, 0x7f, 0xd0, 0x2d, 0xea, 0x6e, 0x53, 0xa1, 0x6a, 0xc9, 0xc8, 0x54, 0xef, 0x75, 0xe4, 0xd9, 0xc6, 0x3e, 0x74, 0xcb, 0x30, 0x80, 0xcc, 0x83, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x5a, 0x00, 0x13, 0x03, 0x00, 0x00, 0x11, 0x8f, 0x00, 0x00, 0x03, 0x03, 0x00, 0x0c, 0x00, 0x2b, 0x00, 0x02, 0x03, 0x04, 0x53, 0x25, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x04, 0x02, 0x05, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x11, 0x00, 0x00, 0x0d, 0x00, 0x2f, 0x00, 0x06, 0x00, 0x04, 0x00, 0x03, 0x30, 0x00, 0x13, 0x94, 0x00, 0x06, 0x00, 0x04, 0x02 }; int groups[2] = { WOLFSSL_ECC_SECP256R1, WOLFSSL_ECC_SECP521R1, }; int i = 0; for (i = 0; i < 2; i++) { XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, NULL, &ssl_c, NULL, wolfTLSv1_3_client_method, NULL), 0); switch (i) { case 0: test_memio_clear_buffer(&test_ctx, 0); ExpectIntEQ(test_memio_inject_message(&test_ctx, 1, (const char *)shBadCaNamesExt, sizeof(shBadCaNamesExt)), 0); break; case 1: test_memio_clear_buffer(&test_ctx, 0); ExpectIntEQ(test_memio_inject_message(&test_ctx, 1, (const char *)shBadCaNamesExt2, sizeof(shBadCaNamesExt2)), 0); break; } /* Ensure the correct groups are used for the test */ ExpectIntEQ(wolfSSL_set_groups(ssl_c, groups, 2), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_connect(ssl_c), -1); #ifndef WOLFSSL_DISABLE_EARLY_SANITY_CHECKS ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WC_NO_ERR_TRACE(UNSUPPORTED_EXTENSION)); #else ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WC_NO_ERR_TRACE(BUFFER_ERROR)); #endif wolfSSL_free(ssl_c); ssl_c = NULL; wolfSSL_CTX_free(ctx_c); ctx_c = NULL; } #endif return EXPECT_RESULT(); } #if defined(WOLFSSL_DTLS) && !defined(WOLFSSL_NO_TLS12) && \ defined(HAVE_IO_TESTS_DEPENDENCIES) static void test_dtls_1_0_hvr_downgrade_ctx_ready(WOLFSSL_CTX* ctx) { AssertIntEQ(wolfSSL_CTX_SetMinVersion(ctx, WOLFSSL_DTLSV1_2), WOLFSSL_SUCCESS); } static int test_dtls_1_0_hvr_downgrade(void) { EXPECT_DECLS; callback_functions func_cb_client; callback_functions func_cb_server; XMEMSET(&func_cb_client, 0, sizeof(callback_functions)); XMEMSET(&func_cb_server, 0, sizeof(callback_functions)); func_cb_client.doUdp = func_cb_server.doUdp = 1; func_cb_client.method = wolfDTLS_client_method; func_cb_server.method = wolfDTLSv1_2_server_method; func_cb_client.ctx_ready = test_dtls_1_0_hvr_downgrade_ctx_ready; test_wolfSSL_client_server_nofail(&func_cb_client, &func_cb_server); ExpectIntEQ(func_cb_client.return_code, TEST_SUCCESS); ExpectIntEQ(func_cb_server.return_code, TEST_SUCCESS); return EXPECT_RESULT(); } #else static int test_dtls_1_0_hvr_downgrade(void) { EXPECT_DECLS; return EXPECT_RESULT(); } #endif #if defined(HAVE_IO_TESTS_DEPENDENCIES) && !defined(WOLFSSL_NO_TLS12) && \ defined(HAVE_SESSION_TICKET) static WOLFSSL_SESSION* test_session_ticket_no_id_session = NULL; static void test_session_ticket_no_id_on_result(WOLFSSL* ssl) { test_session_ticket_no_id_session = wolfSSL_get1_session(ssl); AssertNotNull(test_session_ticket_no_id_session); } static void test_session_ticket_no_id_ctx_ready(WOLFSSL_CTX* ctx) { AssertIntEQ(wolfSSL_CTX_UseSessionTicket(ctx), WOLFSSL_SUCCESS); } static void test_session_ticket_no_id_ssl_ready(WOLFSSL* ssl) { test_session_ticket_no_id_session->sessionIDSz = 0; AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_set_session(ssl, test_session_ticket_no_id_session)); } static int test_session_ticket_no_id(void) { /* We are testing an expired (invalid crypto context in out case since the * ctx changes) session ticket being sent with the session ID being 0 * length. */ EXPECT_DECLS; callback_functions func_cb_client; callback_functions func_cb_server; XMEMSET(&func_cb_client, 0, sizeof(func_cb_client)); XMEMSET(&func_cb_server, 0, sizeof(func_cb_server)); func_cb_client.method = wolfTLSv1_2_client_method; func_cb_client.ctx_ready = test_session_ticket_no_id_ctx_ready; func_cb_client.on_result = test_session_ticket_no_id_on_result; func_cb_server.method = wolfTLSv1_2_server_method; func_cb_server.ctx_ready = test_session_ticket_no_id_ctx_ready; test_wolfSSL_client_server_nofail(&func_cb_client, &func_cb_server); ExpectIntEQ(func_cb_client.return_code, TEST_SUCCESS); ExpectIntEQ(func_cb_server.return_code, TEST_SUCCESS); XMEMSET(&func_cb_client, 0, sizeof(func_cb_client)); XMEMSET(&func_cb_server, 0, sizeof(func_cb_server)); func_cb_client.method = wolfTLSv1_2_client_method; func_cb_client.ctx_ready = test_session_ticket_no_id_ctx_ready; func_cb_client.ssl_ready = test_session_ticket_no_id_ssl_ready; func_cb_server.method = wolfTLSv1_2_server_method; func_cb_server.ctx_ready = test_session_ticket_no_id_ctx_ready; test_wolfSSL_client_server_nofail(&func_cb_client, &func_cb_server); ExpectIntEQ(func_cb_client.return_code, TEST_SUCCESS); ExpectIntEQ(func_cb_server.return_code, TEST_SUCCESS); wolfSSL_SESSION_free(test_session_ticket_no_id_session); return EXPECT_RESULT(); } #else static int test_session_ticket_no_id(void) { EXPECT_DECLS; return EXPECT_RESULT(); } #endif static int test_session_ticket_hs_update(void) { EXPECT_DECLS; #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_TLS13) && \ defined(HAVE_SESSION_TICKET) && !defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) struct test_memio_ctx test_ctx; struct test_memio_ctx test_ctx2; struct test_memio_ctx test_ctx3; WOLFSSL_CTX *ctx_c = NULL; WOLFSSL_CTX *ctx_s = NULL; WOLFSSL *ssl_c = NULL; WOLFSSL *ssl_c2 = NULL; WOLFSSL *ssl_c3 = NULL; WOLFSSL *ssl_s = NULL; WOLFSSL *ssl_s2 = NULL; WOLFSSL *ssl_s3 = NULL; WOLFSSL_SESSION *sess = NULL; byte read_data[1]; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); XMEMSET(&test_ctx2, 0, sizeof(test_ctx2)); XMEMSET(&test_ctx3, 0, sizeof(test_ctx3)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0); /* Generate tickets */ ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); wolfSSL_SetLoggingPrefix("client"); /* Read the ticket msg */ ExpectIntEQ(wolfSSL_read(ssl_c, read_data, sizeof(read_data)), WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)); ExpectIntEQ(wolfSSL_get_error(ssl_c, WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)), WOLFSSL_ERROR_WANT_READ); wolfSSL_SetLoggingPrefix(NULL); ExpectIntEQ(test_memio_setup(&test_ctx2, &ctx_c, &ctx_s, &ssl_c2, &ssl_s2, wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0); ExpectIntEQ(test_memio_setup(&test_ctx3, &ctx_c, &ctx_s, &ssl_c3, &ssl_s3, wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0); ExpectNotNull(sess = wolfSSL_get1_session(ssl_c)); ExpectIntEQ(wolfSSL_set_session(ssl_c2, sess), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_set_session(ssl_c3, sess), WOLFSSL_SUCCESS); wolfSSL_SetLoggingPrefix("client"); /* Exchange initial flights for the second connection */ ExpectIntEQ(wolfSSL_connect(ssl_c2), WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)); ExpectIntEQ(wolfSSL_get_error(ssl_c2, WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)), WOLFSSL_ERROR_WANT_READ); wolfSSL_SetLoggingPrefix(NULL); wolfSSL_SetLoggingPrefix("server"); ExpectIntEQ(wolfSSL_accept(ssl_s2), WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)); ExpectIntEQ(wolfSSL_get_error(ssl_s2, WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)), WOLFSSL_ERROR_WANT_READ); wolfSSL_SetLoggingPrefix(NULL); /* Complete third connection so that new tickets are exchanged */ ExpectIntEQ(test_memio_do_handshake(ssl_c3, ssl_s3, 10, NULL), 0); /* Read the ticket msg */ wolfSSL_SetLoggingPrefix("client"); ExpectIntEQ(wolfSSL_read(ssl_c3, read_data, sizeof(read_data)), WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)); ExpectIntEQ(wolfSSL_get_error(ssl_c3, WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)), WOLFSSL_ERROR_WANT_READ); wolfSSL_SetLoggingPrefix(NULL); /* Complete second connection */ ExpectIntEQ(test_memio_do_handshake(ssl_c2, ssl_s2, 10, NULL), 0); ExpectIntEQ(wolfSSL_session_reused(ssl_c2), 1); ExpectIntEQ(wolfSSL_session_reused(ssl_c3), 1); wolfSSL_free(ssl_c); wolfSSL_free(ssl_c2); wolfSSL_free(ssl_c3); wolfSSL_free(ssl_s); wolfSSL_free(ssl_s2); wolfSSL_free(ssl_s3); wolfSSL_CTX_free(ctx_c); wolfSSL_CTX_free(ctx_s); wolfSSL_SESSION_free(sess); #endif return EXPECT_RESULT(); } #if defined(WOLFSSL_DTLS) && !defined(WOLFSSL_NO_TLS12) && \ defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(HAVE_SECURE_RENEGOTIATION) static void test_dtls_downgrade_scr_server_ctx_ready_server(WOLFSSL_CTX* ctx) { AssertIntEQ(wolfSSL_CTX_SetMinVersion(ctx, WOLFSSL_DTLSV1_2), WOLFSSL_SUCCESS); AssertIntEQ(wolfSSL_CTX_UseSecureRenegotiation(ctx), WOLFSSL_SUCCESS); } static void test_dtls_downgrade_scr_server_ctx_ready(WOLFSSL_CTX* ctx) { AssertIntEQ(wolfSSL_CTX_UseSecureRenegotiation(ctx), WOLFSSL_SUCCESS); } static void test_dtls_downgrade_scr_server_on_result(WOLFSSL* ssl) { char testMsg[] = "Message after SCR"; char msgBuf[sizeof(testMsg)]; if (wolfSSL_is_server(ssl)) { AssertIntEQ(wolfSSL_Rehandshake(ssl), WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)); AssertIntEQ(wolfSSL_get_error(ssl, -1), WC_NO_ERR_TRACE(APP_DATA_READY)); AssertIntEQ(wolfSSL_read(ssl, msgBuf, sizeof(msgBuf)), sizeof(msgBuf)); AssertIntEQ(wolfSSL_Rehandshake(ssl), WOLFSSL_SUCCESS); AssertIntEQ(wolfSSL_write(ssl, testMsg, sizeof(testMsg)), sizeof(testMsg)); } else { AssertIntEQ(wolfSSL_write(ssl, testMsg, sizeof(testMsg)), sizeof(testMsg)); AssertIntEQ(wolfSSL_read(ssl, msgBuf, sizeof(msgBuf)), sizeof(msgBuf)); } } static int test_dtls_downgrade_scr_server(void) { EXPECT_DECLS; callback_functions func_cb_client; callback_functions func_cb_server; XMEMSET(&func_cb_client, 0, sizeof(callback_functions)); XMEMSET(&func_cb_server, 0, sizeof(callback_functions)); func_cb_client.doUdp = func_cb_server.doUdp = 1; func_cb_client.method = wolfDTLSv1_2_client_method; func_cb_server.method = wolfDTLS_server_method; func_cb_client.ctx_ready = test_dtls_downgrade_scr_server_ctx_ready; func_cb_server.ctx_ready = test_dtls_downgrade_scr_server_ctx_ready_server; func_cb_client.on_result = test_dtls_downgrade_scr_server_on_result; func_cb_server.on_result = test_dtls_downgrade_scr_server_on_result; test_wolfSSL_client_server_nofail(&func_cb_client, &func_cb_server); ExpectIntEQ(func_cb_client.return_code, TEST_SUCCESS); ExpectIntEQ(func_cb_server.return_code, TEST_SUCCESS); return EXPECT_RESULT(); } #else static int test_dtls_downgrade_scr_server(void) { EXPECT_DECLS; return EXPECT_RESULT(); } #endif #if defined(WOLFSSL_DTLS) && !defined(WOLFSSL_NO_TLS12) && \ defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(HAVE_SECURE_RENEGOTIATION) static void test_dtls_downgrade_scr_ctx_ready(WOLFSSL_CTX* ctx) { AssertIntEQ(wolfSSL_CTX_SetMinVersion(ctx, WOLFSSL_DTLSV1_2), WOLFSSL_SUCCESS); AssertIntEQ(wolfSSL_CTX_UseSecureRenegotiation(ctx), WOLFSSL_SUCCESS); } static void test_dtls_downgrade_scr_on_result(WOLFSSL* ssl) { char testMsg[] = "Message after SCR"; char msgBuf[sizeof(testMsg)]; if (wolfSSL_is_server(ssl)) { AssertIntEQ(wolfSSL_Rehandshake(ssl), WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)); AssertIntEQ(wolfSSL_get_error(ssl, -1), WC_NO_ERR_TRACE(APP_DATA_READY)); AssertIntEQ(wolfSSL_read(ssl, msgBuf, sizeof(msgBuf)), sizeof(msgBuf)); AssertIntEQ(wolfSSL_Rehandshake(ssl), WOLFSSL_SUCCESS); AssertIntEQ(wolfSSL_write(ssl, testMsg, sizeof(testMsg)), sizeof(testMsg)); } else { AssertIntEQ(wolfSSL_write(ssl, testMsg, sizeof(testMsg)), sizeof(testMsg)); AssertIntEQ(wolfSSL_read(ssl, msgBuf, sizeof(msgBuf)), sizeof(msgBuf)); } } static int test_dtls_downgrade_scr(void) { EXPECT_DECLS; callback_functions func_cb_client; callback_functions func_cb_server; XMEMSET(&func_cb_client, 0, sizeof(callback_functions)); XMEMSET(&func_cb_server, 0, sizeof(callback_functions)); func_cb_client.doUdp = func_cb_server.doUdp = 1; func_cb_client.method = wolfDTLS_client_method; func_cb_server.method = wolfDTLSv1_2_server_method; func_cb_client.ctx_ready = test_dtls_downgrade_scr_ctx_ready; func_cb_client.on_result = test_dtls_downgrade_scr_on_result; func_cb_server.on_result = test_dtls_downgrade_scr_on_result; test_wolfSSL_client_server_nofail(&func_cb_client, &func_cb_server); ExpectIntEQ(func_cb_client.return_code, TEST_SUCCESS); ExpectIntEQ(func_cb_server.return_code, TEST_SUCCESS); return EXPECT_RESULT(); } #else static int test_dtls_downgrade_scr(void) { EXPECT_DECLS; return EXPECT_RESULT(); } #endif #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13) \ && !defined(WOLFSSL_NO_TLS12) static int test_dtls_client_hello_timeout_downgrade_read_cb(WOLFSSL *ssl, char *data, int sz, void *ctx) { static int call_counter = 0; call_counter++; (void)ssl; (void)data; (void)sz; (void)ctx; switch (call_counter) { case 1: case 2: return WOLFSSL_CBIO_ERR_TIMEOUT; case 3: return WOLFSSL_CBIO_ERR_WANT_READ; default: AssertIntLE(call_counter, 3); return -1; } } #endif /* Make sure we don't send acks before getting a server hello */ static int test_dtls_client_hello_timeout_downgrade(void) { EXPECT_DECLS; #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13) \ && !defined(WOLFSSL_NO_TLS12) WOLFSSL_CTX *ctx_c = NULL; WOLFSSL_CTX *ctx_s = NULL; WOLFSSL *ssl_c = NULL; WOLFSSL *ssl_s = NULL; struct test_memio_ctx test_ctx; DtlsRecordLayerHeader* dtlsRH; size_t len; byte sequence_number[8]; int i; for (i = 0; i < 2; i++) { XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, wolfDTLS_client_method, wolfDTLSv1_2_server_method), 0); if (i == 0) { /* First time simulate timeout in IO layer */ /* CH1 */ ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); /* HVR */ ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1); ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ); /* CH2 */ ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); /* SH flight */ ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1); ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ); /* Drop the SH */ if (EXPECT_SUCCESS()) { ExpectIntEQ(test_memio_drop_message(&test_ctx, 1, 0), 0); } /* Read the remainder of the flight */ ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); wolfSSL_SSLSetIORecv(ssl_c, test_dtls_client_hello_timeout_downgrade_read_cb); /* CH3 */ ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); wolfSSL_SSLSetIORecv(ssl_c, test_memio_read_cb); } else { /* Second time call wolfSSL_dtls_got_timeout */ /* CH1 */ ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); /* HVR */ ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1); ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ); /* CH2 */ ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); /* SH flight */ ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1); ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ); /* Drop the SH */ if (EXPECT_SUCCESS()) { ExpectIntEQ(test_memio_drop_message(&test_ctx, 1, 0), 0); } /* Read the remainder of the flight */ ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); /* Quick timeout should be set as we received at least one msg */ ExpectIntEQ(wolfSSL_dtls13_use_quick_timeout(ssl_c), 1); ExpectIntEQ(wolfSSL_dtls_got_timeout(ssl_c), WOLFSSL_SUCCESS); /* Quick timeout should be cleared after a quick timeout */ /* CH3 */ ExpectIntEQ(wolfSSL_dtls13_use_quick_timeout(ssl_c), 0); ExpectIntEQ(wolfSSL_dtls_got_timeout(ssl_c), WOLFSSL_SUCCESS); } /* Parse out to make sure we got exactly one ClientHello message */ XMEMSET(&sequence_number, 0, sizeof(sequence_number)); /* Second ClientHello after HVR */ sequence_number[7] = 2; dtlsRH = (DtlsRecordLayerHeader*)test_ctx.s_buff; ExpectIntEQ(dtlsRH->type, handshake); ExpectIntEQ(dtlsRH->pvMajor, DTLS_MAJOR); ExpectIntEQ(dtlsRH->pvMinor, DTLSv1_2_MINOR); ExpectIntEQ(XMEMCMP(sequence_number, dtlsRH->sequence_number, sizeof(sequence_number)), 0); len = (size_t)((dtlsRH->length[0] << 8) | dtlsRH->length[1]); ExpectIntEQ(sizeof(DtlsRecordLayerHeader) + len, test_ctx.s_len); /* Connection should be able to continue */ ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); wolfSSL_free(ssl_c); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_c); wolfSSL_CTX_free(ctx_s); ssl_c = NULL; ssl_s = NULL; ctx_c = NULL; ctx_s = NULL; if (!EXPECT_SUCCESS()) break; } #endif return EXPECT_RESULT(); } #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13) static int test_dtls_client_hello_timeout_read_cb(WOLFSSL *ssl, char *data, int sz, void *ctx) { static int call_counter = 0; call_counter++; (void)ssl; (void)data; (void)sz; (void)ctx; switch (call_counter) { case 1: return WOLFSSL_CBIO_ERR_TIMEOUT; case 2: return WOLFSSL_CBIO_ERR_WANT_READ; default: AssertIntLE(call_counter, 2); return -1; } } #endif /* Make sure we don't send acks before getting a server hello */ static int test_dtls_client_hello_timeout(void) { EXPECT_DECLS; #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13) WOLFSSL *ssl_c = NULL; WOLFSSL_CTX *ctx_c = NULL; struct test_memio_ctx test_ctx; DtlsRecordLayerHeader* dtlsRH; size_t idx; size_t len; byte sequence_number[8]; int i; for (i = 0; i < 2; i++) { XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, NULL, &ssl_c, NULL, wolfDTLSv1_3_client_method, NULL), 0); if (i == 0) { /* First time simulate timeout in IO layer */ wolfSSL_SSLSetIORecv(ssl_c, test_dtls_client_hello_timeout_read_cb); ExpectIntEQ(wolfSSL_connect(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); } else { /* Second time call wolfSSL_dtls_got_timeout */ ExpectIntEQ(wolfSSL_connect(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); ExpectIntEQ(wolfSSL_dtls_got_timeout(ssl_c), WOLFSSL_SUCCESS); } /* Parse out to make sure we got exactly two ClientHello messages */ idx = 0; XMEMSET(&sequence_number, 0, sizeof(sequence_number)); /* First ClientHello */ dtlsRH = (DtlsRecordLayerHeader*)(test_ctx.s_buff + idx); ExpectIntEQ(dtlsRH->type, handshake); ExpectIntEQ(dtlsRH->pvMajor, DTLS_MAJOR); ExpectIntEQ(dtlsRH->pvMinor, DTLSv1_2_MINOR); ExpectIntEQ(XMEMCMP(sequence_number, dtlsRH->sequence_number, sizeof(sequence_number)), 0); len = (size_t)((dtlsRH->length[0] << 8) | dtlsRH->length[1]); ExpectIntLT(idx + sizeof(DtlsRecordLayerHeader) + len, test_ctx.s_len); idx += sizeof(DtlsRecordLayerHeader) + len; /* Second ClientHello */ sequence_number[7] = 1; dtlsRH = (DtlsRecordLayerHeader*)(test_ctx.s_buff + idx); ExpectIntEQ(dtlsRH->type, handshake); ExpectIntEQ(dtlsRH->pvMajor, DTLS_MAJOR); ExpectIntEQ(dtlsRH->pvMinor, DTLSv1_2_MINOR); ExpectIntEQ(XMEMCMP(sequence_number, dtlsRH->sequence_number, sizeof(sequence_number)), 0); len = (size_t)((dtlsRH->length[0] << 8) | dtlsRH->length[1]); ExpectIntEQ(idx + sizeof(DtlsRecordLayerHeader) + len, test_ctx.s_len); wolfSSL_free(ssl_c); wolfSSL_CTX_free(ctx_c); ssl_c = NULL; ctx_c = NULL; if (!EXPECT_SUCCESS()) break; } #endif return EXPECT_RESULT(); } /* DTLS test when dropping the changed cipher spec message */ static int test_dtls_dropped_ccs(void) { EXPECT_DECLS; #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS) \ && !defined(WOLFSSL_NO_TLS12) WOLFSSL_CTX *ctx_c = NULL; WOLFSSL_CTX *ctx_s = NULL; WOLFSSL *ssl_c = NULL; WOLFSSL *ssl_s = NULL; struct test_memio_ctx test_ctx; DtlsRecordLayerHeader* dtlsRH; size_t len; byte data[1]; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method), 0); /* CH1 */ ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); /* HVR */ ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1); ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ); /* CH2 */ ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); /* Server first flight */ ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1); ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ); /* Client flight */ ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); /* Server ccs + finished */ ExpectIntEQ(wolfSSL_negotiate(ssl_s), 1); /* Drop the ccs */ dtlsRH = (DtlsRecordLayerHeader*)test_ctx.c_buff; len = (size_t)((dtlsRH->length[0] << 8) | dtlsRH->length[1]); ExpectIntEQ(len, 1); ExpectIntEQ(dtlsRH->type, change_cipher_spec); if (EXPECT_SUCCESS()) { ExpectIntEQ(test_memio_drop_message(&test_ctx, 1, 0), 0); } /* Client rtx flight */ ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); ExpectIntEQ(wolfSSL_dtls_got_timeout(ssl_c), WOLFSSL_SUCCESS); /* Server ccs + finished rtx */ ExpectIntEQ(wolfSSL_read(ssl_s, data, sizeof(data)), -1); ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ); /* Client processes finished */ ExpectIntEQ(wolfSSL_negotiate(ssl_c), 1); wolfSSL_free(ssl_c); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_c); wolfSSL_CTX_free(ctx_s); #endif return EXPECT_RESULT(); } #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS) \ && !defined(WOLFSSL_NO_TLS12) static int test_dtls_seq_num_downgrade_check_num(byte* ioBuf, int ioBufLen, byte seq_num) { EXPECT_DECLS; DtlsRecordLayerHeader* dtlsRH; byte sequence_number[8]; XMEMSET(&sequence_number, 0, sizeof(sequence_number)); ExpectIntGE(ioBufLen, sizeof(*dtlsRH)); dtlsRH = (DtlsRecordLayerHeader*)ioBuf; ExpectIntEQ(dtlsRH->type, handshake); ExpectIntEQ(dtlsRH->pvMajor, DTLS_MAJOR); ExpectIntEQ(dtlsRH->pvMinor, DTLSv1_2_MINOR); sequence_number[7] = seq_num; ExpectIntEQ(XMEMCMP(sequence_number, dtlsRH->sequence_number, sizeof(sequence_number)), 0); return EXPECT_RESULT(); } #endif /* * Make sure that we send the correct sequence number after a HelloVerifyRequest * and after a HelloRetryRequest. This is testing the server side as it is * operating statelessly and should copy the sequence number of the ClientHello. */ static int test_dtls_seq_num_downgrade(void) { EXPECT_DECLS; #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS) \ && !defined(WOLFSSL_NO_TLS12) WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL; WOLFSSL *ssl_c = NULL, *ssl_s = NULL; struct test_memio_ctx test_ctx; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, wolfDTLSv1_2_client_method, wolfDTLS_server_method), 0); /* CH1 */ ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); ExpectIntEQ(test_dtls_seq_num_downgrade_check_num(test_ctx.s_buff, test_ctx.s_len, 0), TEST_SUCCESS); /* HVR */ ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1); ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ); ExpectIntEQ(test_dtls_seq_num_downgrade_check_num(test_ctx.c_buff, test_ctx.c_len, 0), TEST_SUCCESS); /* CH2 */ ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); ExpectIntEQ(test_dtls_seq_num_downgrade_check_num(test_ctx.s_buff, test_ctx.s_len, 1), TEST_SUCCESS); /* Server first flight */ ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1); ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ); ExpectIntEQ(test_dtls_seq_num_downgrade_check_num(test_ctx.c_buff, test_ctx.c_len, 1), TEST_SUCCESS); ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); wolfSSL_free(ssl_c); wolfSSL_CTX_free(ctx_c); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_s); #endif return EXPECT_RESULT(); } /** * Make sure we don't send RSA Signature Hash Algorithms in the * CertificateRequest when we don't have any such ciphers set. * @return EXPECT_RESULT() */ static int test_certreq_sighash_algos(void) { EXPECT_DECLS; #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \ !defined(WOLFSSL_MAX_STRENGTH) && defined(HAVE_ECC) && \ !defined(NO_SHA256) && defined(WOLFSSL_SHA384) && \ defined(WOLFSSL_AES_256) && defined(HAVE_AES_CBC) && \ !defined(WOLFSSL_NO_TLS12) WOLFSSL_CTX *ctx_c = NULL; WOLFSSL_CTX *ctx_s = NULL; WOLFSSL *ssl_c = NULL; WOLFSSL *ssl_s = NULL; struct test_memio_ctx test_ctx; int idx = 0; int maxIdx = 0; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); test_ctx.c_ciphers = test_ctx.s_ciphers = "ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA384"; ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, wolfTLSv1_2_client_method, wolfTLSv1_2_server_method), 0); ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx_c, caEccCertFile, NULL), WOLFSSL_SUCCESS); wolfSSL_set_verify(ssl_s, WOLFSSL_VERIFY_PEER, NULL); ExpectIntEQ(wolfSSL_use_PrivateKey_file(ssl_s, eccKeyFile, CERT_FILETYPE), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_use_certificate_file(ssl_s, eccCertFile, CERT_FILETYPE), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_connect(ssl_c), WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)); ExpectIntEQ(wolfSSL_get_error(ssl_c, WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)), WOLFSSL_ERROR_WANT_READ); ExpectIntEQ(wolfSSL_accept(ssl_s), WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)); ExpectIntEQ(wolfSSL_get_error(ssl_s, WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)), WOLFSSL_ERROR_WANT_READ); /* Find the CertificateRequest message */ for (idx = 0; idx < test_ctx.c_len && EXPECT_SUCCESS();) { word16 len; ExpectIntEQ(test_ctx.c_buff[idx++], handshake); ExpectIntEQ(test_ctx.c_buff[idx++], SSLv3_MAJOR); ExpectIntEQ(test_ctx.c_buff[idx++], TLSv1_2_MINOR); ato16(test_ctx.c_buff + idx, &len); idx += OPAQUE16_LEN; if (test_ctx.c_buff[idx] == certificate_request) { idx++; /* length */ idx += OPAQUE24_LEN; /* cert types */ idx += 1 + test_ctx.c_buff[idx]; /* Sig algos */ ato16(test_ctx.c_buff + idx, &len); idx += OPAQUE16_LEN; maxIdx = idx + (int)len; for (; idx < maxIdx && EXPECT_SUCCESS(); idx += OPAQUE16_LEN) { if (test_ctx.c_buff[idx+1] == ED25519_SA_MINOR || test_ctx.c_buff[idx+1] == ED448_SA_MINOR || test_ctx.c_buff[idx+1] == ECDSA_BRAINPOOLP256R1TLS13_SHA256_MINOR || test_ctx.c_buff[idx+1] == ECDSA_BRAINPOOLP384R1TLS13_SHA384_MINOR || test_ctx.c_buff[idx+1] == ECDSA_BRAINPOOLP512R1TLS13_SHA512_MINOR) ExpectIntEQ(test_ctx.c_buff[idx], NEW_SA_MAJOR); else ExpectIntEQ(test_ctx.c_buff[idx+1], ecc_dsa_sa_algo); } break; } else { idx += (int)len; } } ExpectIntLT(idx, test_ctx.c_len); ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); wolfSSL_free(ssl_c); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_c); wolfSSL_CTX_free(ctx_s); #endif return EXPECT_RESULT(); } #if defined(HAVE_CRL) && defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && \ !defined(WOLFSSL_CRL_ALLOW_MISSING_CDP) static int test_revoked_loaded_int_cert_ctx_ready1(WOLFSSL_CTX* ctx) { EXPECT_DECLS; wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, myVerify); myVerifyAction = VERIFY_USE_PREVERIFY; ExpectIntEQ(wolfSSL_CTX_load_verify_locations_ex(ctx, "./certs/ca-cert.pem", NULL, 0), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_load_verify_locations_ex(ctx, "./certs/intermediate/ca-int-cert.pem", NULL, 0), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_EnableCRL(ctx, WOLFSSL_CRL_CHECKALL), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_LoadCRLFile(ctx, "./certs/crl/extra-crls/ca-int-cert-revoked.pem", WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_LoadCRLFile(ctx, "./certs/crl/ca-int.pem", WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); return EXPECT_RESULT(); } static int test_revoked_loaded_int_cert_ctx_ready2(WOLFSSL_CTX* ctx) { EXPECT_DECLS; wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, myVerify); myVerifyAction = VERIFY_USE_PREVERIFY; ExpectIntEQ(wolfSSL_CTX_load_verify_locations_ex(ctx, "./certs/ca-cert.pem", NULL, 0), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_load_verify_locations_ex(ctx, "./certs/intermediate/ca-int-cert.pem", NULL, 0), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_load_verify_locations_ex(ctx, "./certs/intermediate/ca-int2-cert.pem", NULL, 0), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_EnableCRL(ctx, WOLFSSL_CRL_CHECKALL), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_LoadCRLFile(ctx, "./certs/crl/ca-int2.pem", WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_LoadCRLFile(ctx, "./certs/crl/extra-crls/ca-int-cert-revoked.pem", WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_LoadCRLFile(ctx, "./certs/crl/ca-int.pem", WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); return EXPECT_RESULT(); } static int test_revoked_loaded_int_cert_ctx_ready3_crl_missing_cb(int ret, WOLFSSL_CRL* crl, WOLFSSL_CERT_MANAGER* cm, void* ctx) { (void)crl; (void)cm; (void)ctx; if (ret == WC_NO_ERR_TRACE(CRL_MISSING)) return 1; return 0; } /* Here we are allowing missing CRL's but want to error out when its revoked */ static int test_revoked_loaded_int_cert_ctx_ready3(WOLFSSL_CTX* ctx) { EXPECT_DECLS; wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, myVerify); myVerifyAction = VERIFY_USE_PREVERIFY; ExpectIntEQ(wolfSSL_CTX_load_verify_locations_ex(ctx, "./certs/ca-cert.pem", NULL, 0), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_load_verify_locations_ex(ctx, "./certs/intermediate/ca-int-cert.pem", NULL, 0), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_load_verify_locations_ex(ctx, "./certs/intermediate/ca-int2-cert.pem", NULL, 0), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_EnableCRL(ctx, WOLFSSL_CRL_CHECKALL), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_LoadCRLFile(ctx, "./certs/crl/extra-crls/ca-int-cert-revoked.pem", WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_SetCRL_ErrorCb(ctx, test_revoked_loaded_int_cert_ctx_ready3_crl_missing_cb, NULL), WOLFSSL_SUCCESS); return EXPECT_RESULT(); } #endif static int test_revoked_loaded_int_cert(void) { EXPECT_DECLS; #if defined(HAVE_CRL) && defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && \ !defined(WOLFSSL_CRL_ALLOW_MISSING_CDP) test_ssl_cbf client_cbf; test_ssl_cbf server_cbf; struct { const char* certPemFile; const char* keyPemFile; ctx_cb client_ctx_ready; } test_params[] = { {"./certs/intermediate/ca-int2-cert.pem", "./certs/intermediate/ca-int2-key.pem", test_revoked_loaded_int_cert_ctx_ready1}, {"./certs/intermediate/server-chain.pem", "./certs/server-key.pem", test_revoked_loaded_int_cert_ctx_ready2}, {"./certs/intermediate/server-chain-short.pem", "./certs/server-key.pem", test_revoked_loaded_int_cert_ctx_ready2}, {"./certs/intermediate/server-chain-short.pem", "./certs/server-key.pem", test_revoked_loaded_int_cert_ctx_ready3}, }; size_t i; printf("\n"); for (i = 0; i < XELEM_CNT(test_params); i++) { XMEMSET(&client_cbf, 0, sizeof(client_cbf)); XMEMSET(&server_cbf, 0, sizeof(server_cbf)); printf("\tTesting with %s...\n", test_params[i].certPemFile); server_cbf.certPemFile = test_params[i].certPemFile; server_cbf.keyPemFile = test_params[i].keyPemFile; client_cbf.ctx_ready = test_params[i].client_ctx_ready; ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&client_cbf, &server_cbf, NULL), -1001); ExpectIntEQ(client_cbf.last_err, WC_NO_ERR_TRACE(CRL_CERT_REVOKED)); ExpectIntEQ(server_cbf.last_err, WC_NO_ERR_TRACE(FATAL_ERROR)); if (!EXPECT_SUCCESS()) break; printf("\t%s passed\n", test_params[i].certPemFile); } #endif return EXPECT_RESULT(); } static int test_dtls13_frag_ch_pq(void) { EXPECT_DECLS; #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13) \ && defined(WOLFSSL_DTLS_CH_FRAG) && defined(WOLFSSL_HAVE_MLKEM) WOLFSSL_CTX *ctx_c = NULL; WOLFSSL_CTX *ctx_s = NULL; WOLFSSL *ssl_c = NULL; WOLFSSL *ssl_s = NULL; struct test_memio_ctx test_ctx; const char *test_str = "test"; int test_str_size; byte buf[255]; #if defined(WOLFSSL_MLKEM_KYBER) #if !defined(WOLFSSL_NO_KYBER1024) int group = WOLFSSL_KYBER_LEVEL5; const char *group_name = "KYBER_LEVEL5"; #elif !defined(WOLFSSL_NO_KYBER768) int group = WOLFSSL_KYBER_LEVEL3; const char *group_name = "KYBER_LEVEL3"; #else int group = WOLFSSL_KYBER_LEVEL1; const char *group_name = "KYBER_LEVEL1"; #endif #elif !defined(WOLFSSL_NO_ML_KEM) && !defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE) #if !defined(WOLFSSL_NO_ML_KEM_1024) int group = WOLFSSL_ML_KEM_1024; const char *group_name = "ML_KEM_1024"; #elif !defined(WOLFSSL_NO_ML_KEM_768) int group = WOLFSSL_ML_KEM_768; const char *group_name = "ML_KEM_768"; #else int group = WOLFSSL_ML_KEM_512; const char *group_name = "ML_KEM_512"; #endif #elif defined(WOLFSSL_PQC_HYBRIDS) #if defined(HAVE_CURVE25519) && !defined(WOLFSSL_NO_ML_KEM_768) int group = WOLFSSL_X25519MLKEM768; const char *group_name = "X25519MLKEM768"; #elif !defined(WOLFSSL_NO_ML_KEM_768) int group = WOLFSSL_SECP256R1MLKEM768; const char *group_name = "SecP256r1MLKEM768"; #else int group = WOLFSSL_SECP384R1MLKEM1024; const char *group_name = "SecP384r1MLKEM1024"; #endif #endif XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method), 0); /* Add in a large post-quantum key share to make the CH long. */ ExpectIntEQ(wolfSSL_set_groups(ssl_c, &group, 1), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_UseKeyShare(ssl_c, group), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_dtls13_allow_ch_frag(ssl_s, 1), WOLFSSL_SUCCESS); ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); ExpectStrEQ(wolfSSL_get_curve_name(ssl_c), group_name); ExpectStrEQ(wolfSSL_get_curve_name(ssl_s), group_name); test_str_size = XSTRLEN("test") + 1; ExpectIntEQ(wolfSSL_write(ssl_c, test_str, test_str_size), test_str_size); ExpectIntEQ(wolfSSL_read(ssl_s, buf, sizeof(buf)), test_str_size); ExpectIntEQ(XSTRCMP((char*)buf, test_str), 0); ExpectIntEQ(wolfSSL_write(ssl_c, test_str, test_str_size), test_str_size); wolfSSL_free(ssl_c); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_c); wolfSSL_CTX_free(ctx_s); #endif return EXPECT_RESULT(); } #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS) \ && defined(WOLFSSL_DTLS_MTU) && defined(WOLFSSL_DTLS_CH_FRAG) && \ defined(WOLFSSL_AES_256) static int test_dtls_frag_ch_count_records(byte* b, int len) { DtlsRecordLayerHeader* dtlsRH; int records = 0; size_t recordLen; while (len > 0) { records++; dtlsRH = (DtlsRecordLayerHeader*)b; recordLen = (dtlsRH->length[0] << 8) | dtlsRH->length[1]; if (recordLen > (size_t)len) break; b += sizeof(DtlsRecordLayerHeader) + recordLen; len -= sizeof(DtlsRecordLayerHeader) + recordLen; } return records; } #endif static int test_dtls_frag_ch(void) { EXPECT_DECLS; #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13) \ && defined(WOLFSSL_DTLS_MTU) && defined(WOLFSSL_DTLS_CH_FRAG) && \ defined(WOLFSSL_AES_256) WOLFSSL_CTX *ctx_c = NULL; WOLFSSL_CTX *ctx_s = NULL; WOLFSSL *ssl_c = NULL; WOLFSSL *ssl_s = NULL; struct test_memio_ctx test_ctx; static unsigned int DUMMY_MTU = 256; unsigned int len; unsigned char four_frag_CH[] = { 0x16, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xda, 0x01, 0x00, 0x02, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xce, 0xfe, 0xfd, 0xf3, 0x94, 0x01, 0x33, 0x2c, 0xcf, 0x2c, 0x47, 0xb1, 0xe5, 0xa1, 0x7b, 0x19, 0x3e, 0xac, 0x68, 0xdd, 0xe6, 0x17, 0x6b, 0x85, 0xad, 0x5f, 0xfc, 0x7f, 0x6e, 0xf0, 0xb9, 0xe0, 0x2e, 0xca, 0x47, 0x00, 0x00, 0x00, 0x36, 0x13, 0x01, 0x13, 0x02, 0x13, 0x03, 0xc0, 0x2c, 0xc0, 0x2b, 0xc0, 0x30, 0xc0, 0x2f, 0x00, 0x9f, 0x00, 0x9e, 0xcc, 0xa9, 0xcc, 0xa8, 0xcc, 0xaa, 0xc0, 0x27, 0xc0, 0x23, 0xc0, 0x28, 0xc0, 0x24, 0xc0, 0x0a, 0xc0, 0x09, 0xc0, 0x14, 0xc0, 0x13, 0x00, 0x6b, 0x00, 0x67, 0x00, 0x39, 0x00, 0x33, 0xcc, 0x14, 0xcc, 0x13, 0xcc, 0x15, 0x01, 0x00, 0x02, 0x7c, 0x00, 0x2b, 0x00, 0x03, 0x02, 0xfe, 0xfc, 0x00, 0x0d, 0x00, 0x20, 0x00, 0x1e, 0x06, 0x03, 0x05, 0x03, 0x04, 0x03, 0x02, 0x03, 0x08, 0x06, 0x08, 0x0b, 0x08, 0x05, 0x08, 0x0a, 0x08, 0x04, 0x08, 0x09, 0x06, 0x01, 0x05, 0x01, 0x04, 0x01, 0x03, 0x01, 0x02, 0x01, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x0a, 0x00, 0x19, 0x00, 0x18, 0x00, 0x17, 0x00, 0x15, 0x01, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x33, 0x02, 0x39, 0x02, 0x37, 0x00, 0x17, 0x00, 0x41, 0x04, 0x94, 0xdf, 0x36, 0xd7, 0xb3, 0x90, 0x6d, 0x01, 0xa1, 0xe6, 0xed, 0x67, 0xf4, 0xd9, 0x9d, 0x2c, 0xac, 0x57, 0x74, 0xff, 0x19, 0xbe, 0x5a, 0xc9, 0x30, 0x11, 0xb7, 0x2b, 0x59, 0x47, 0x80, 0x7c, 0xa9, 0xb7, 0x31, 0x8c, 0x16, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xda, 0x01, 0x00, 0x02, 0xdc, 0x00, 0x00, 0x00, 0x00, 0xce, 0x00, 0x00, 0xce, 0x9e, 0x13, 0x74, 0x3b, 0x86, 0xba, 0x69, 0x1f, 0x12, 0xf7, 0xcd, 0x78, 0x53, 0xe8, 0x50, 0x4d, 0x71, 0x3f, 0x4b, 0x4e, 0xeb, 0x3e, 0xe5, 0x43, 0x54, 0x78, 0x17, 0x6d, 0x00, 0x18, 0x00, 0x61, 0x04, 0xd1, 0x99, 0x66, 0x4f, 0xda, 0xc7, 0x12, 0x3b, 0xff, 0xb2, 0xd6, 0x2f, 0x35, 0xb6, 0x17, 0x1f, 0xb3, 0xd0, 0xb6, 0x52, 0xff, 0x97, 0x8b, 0x01, 0xe8, 0xd9, 0x68, 0x71, 0x40, 0x02, 0xd5, 0x68, 0x3a, 0x58, 0xb2, 0x5d, 0xee, 0xa4, 0xe9, 0x5f, 0xf4, 0xaf, 0x3e, 0x30, 0x9c, 0x3e, 0x2b, 0xda, 0x61, 0x43, 0x99, 0x02, 0x35, 0x33, 0x9f, 0xcf, 0xb5, 0xd3, 0x28, 0x19, 0x9d, 0x1c, 0xbe, 0x69, 0x07, 0x9e, 0xfc, 0xe4, 0x8e, 0xcd, 0x86, 0x4a, 0x1b, 0xf0, 0xfc, 0x17, 0x94, 0x66, 0x53, 0xda, 0x24, 0x5e, 0xaf, 0xce, 0xec, 0x62, 0x4c, 0x06, 0xb4, 0x52, 0x94, 0xb1, 0x4a, 0x7a, 0x8c, 0x4f, 0x00, 0x19, 0x00, 0x85, 0x04, 0x00, 0x27, 0xeb, 0x99, 0x49, 0x7f, 0xcb, 0x2c, 0x46, 0x54, 0x2d, 0x93, 0x5d, 0x25, 0x92, 0x58, 0x5e, 0x06, 0xc3, 0x7c, 0xfb, 0x9a, 0xa7, 0xec, 0xcd, 0x9f, 0xe1, 0x6b, 0x2d, 0x78, 0xf5, 0x16, 0xa9, 0x20, 0x52, 0x48, 0x19, 0x0f, 0x1a, 0xd0, 0xce, 0xd8, 0x68, 0xb1, 0x4e, 0x7f, 0x33, 0x03, 0x7d, 0x0c, 0x39, 0xdb, 0x9c, 0x4b, 0xf4, 0xe7, 0xc2, 0xf5, 0xdd, 0x51, 0x9b, 0x03, 0xa8, 0x53, 0x2b, 0xe6, 0x00, 0x15, 0x4b, 0xff, 0xd2, 0xa0, 0x16, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xda, 0x01, 0x00, 0x02, 0xdc, 0x00, 0x00, 0x00, 0x01, 0x9c, 0x00, 0x00, 0xce, 0x58, 0x30, 0x10, 0x3d, 0x46, 0xcc, 0xca, 0x1a, 0x44, 0xc8, 0x58, 0x9b, 0x27, 0x17, 0x67, 0x31, 0x96, 0x8a, 0x66, 0x39, 0xf4, 0xcc, 0xc1, 0x9f, 0x12, 0x1f, 0x01, 0x30, 0x50, 0x16, 0xd6, 0x89, 0x97, 0xa3, 0x66, 0xd7, 0x99, 0x50, 0x09, 0x6e, 0x80, 0x87, 0xe4, 0xa2, 0x88, 0xae, 0xb4, 0x23, 0x57, 0x2f, 0x12, 0x60, 0xe7, 0x7d, 0x44, 0x2d, 0xad, 0xbe, 0xe9, 0x0d, 0x01, 0x00, 0x01, 0x00, 0xd5, 0xdd, 0x62, 0xee, 0xf3, 0x0e, 0xd9, 0x30, 0x0e, 0x38, 0xf3, 0x48, 0xf4, 0xc9, 0x8f, 0x8c, 0x20, 0xf7, 0xd3, 0xa8, 0xb3, 0x87, 0x3c, 0x98, 0x5d, 0x70, 0xc5, 0x03, 0x76, 0xb7, 0xd5, 0x0b, 0x7b, 0x23, 0x97, 0x6b, 0xe3, 0xb5, 0x18, 0xeb, 0x64, 0x55, 0x18, 0xb2, 0x8a, 0x90, 0x1a, 0x8f, 0x0e, 0x15, 0xda, 0xb1, 0x8e, 0x7f, 0xee, 0x1f, 0xe0, 0x3b, 0xb9, 0xed, 0xfc, 0x4e, 0x3f, 0x78, 0x16, 0x39, 0x95, 0x5f, 0xb7, 0xcb, 0x65, 0x55, 0x72, 0x7b, 0x7d, 0x86, 0x2f, 0x8a, 0xe5, 0xee, 0xf7, 0x57, 0x40, 0xf3, 0xc4, 0x96, 0x4f, 0x11, 0x4d, 0x85, 0xf9, 0x56, 0xfa, 0x3d, 0xf0, 0xc9, 0xa4, 0xec, 0x1e, 0xaa, 0x47, 0x90, 0x53, 0xdf, 0xe1, 0xb7, 0x78, 0x18, 0xeb, 0xdd, 0x0d, 0x89, 0xb7, 0xf6, 0x15, 0x0e, 0x55, 0x12, 0xb3, 0x23, 0x17, 0x0b, 0x59, 0x6f, 0x83, 0x05, 0x6b, 0xa6, 0xf8, 0x6c, 0x3a, 0x9b, 0x1b, 0x50, 0x93, 0x51, 0xea, 0x95, 0x2d, 0x99, 0x96, 0x38, 0x16, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x7e, 0x01, 0x00, 0x02, 0xdc, 0x00, 0x00, 0x00, 0x02, 0x6a, 0x00, 0x00, 0x72, 0x2d, 0x66, 0x3e, 0xf2, 0x36, 0x5a, 0xf2, 0x23, 0x8f, 0x28, 0x09, 0xa9, 0x55, 0x8c, 0x8f, 0xc0, 0x0d, 0x61, 0x98, 0x33, 0x56, 0x87, 0x7a, 0xfd, 0xa7, 0x50, 0x71, 0x84, 0x2e, 0x41, 0x58, 0x00, 0x87, 0xd9, 0x27, 0xe5, 0x7b, 0xf4, 0x6d, 0x84, 0x4e, 0x2e, 0x0c, 0x80, 0x0c, 0xf3, 0x8a, 0x02, 0x4b, 0x99, 0x3a, 0x1f, 0x9f, 0x18, 0x7d, 0x1c, 0xec, 0xad, 0x60, 0x54, 0xa6, 0xa3, 0x2c, 0x82, 0x5e, 0xf8, 0x8f, 0xae, 0xe1, 0xc4, 0x82, 0x7e, 0x43, 0x43, 0xc5, 0x99, 0x49, 0x05, 0xd3, 0xf6, 0xdf, 0xa1, 0xb5, 0x2d, 0x0c, 0x13, 0x2f, 0x1e, 0xb6, 0x28, 0x7c, 0x5c, 0xa1, 0x02, 0x6b, 0x8d, 0xa3, 0xeb, 0xd4, 0x58, 0xe6, 0xa0, 0x7e, 0x6b, 0xaa, 0x09, 0x43, 0x67, 0x71, 0x87, 0xa5, 0xcb, 0x68, 0xf3 }; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method), 0); /* Fragment msgs */ ExpectIntEQ(wolfSSL_dtls_set_mtu(ssl_c, DUMMY_MTU), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_dtls_set_mtu(ssl_s, DUMMY_MTU), WOLFSSL_SUCCESS); /* Add in some key shares to make the CH long */ ExpectIntEQ(wolfSSL_UseKeyShare(ssl_c, WOLFSSL_ECC_SECP256R1), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_UseKeyShare(ssl_c, WOLFSSL_ECC_SECP384R1), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_UseKeyShare(ssl_c, WOLFSSL_ECC_SECP521R1), WOLFSSL_SUCCESS); #ifdef HAVE_FFDHE_2048 ExpectIntEQ(wolfSSL_UseKeyShare(ssl_c, WOLFSSL_FFDHE_2048), WOLFSSL_SUCCESS); #endif #ifdef HAVE_FFDHE_3072 ExpectIntEQ(wolfSSL_UseKeyShare(ssl_c, WOLFSSL_FFDHE_3072), WOLFSSL_SUCCESS); #endif #ifdef HAVE_FFDHE_4096 ExpectIntEQ(wolfSSL_UseKeyShare(ssl_c, WOLFSSL_FFDHE_4096), WOLFSSL_SUCCESS); #endif ExpectIntEQ(wolfSSL_dtls13_allow_ch_frag(ssl_s, 1), WOLFSSL_SUCCESS); /* Reject fragmented first CH */ ExpectIntEQ(test_dtls_frag_ch_count_records(four_frag_CH, sizeof(four_frag_CH)), 4); len = sizeof(four_frag_CH); test_memio_clear_buffer(&test_ctx, 0); while (len > 0 && EXPECT_SUCCESS()) { unsigned int inj_len = len > DUMMY_MTU ? DUMMY_MTU : len; unsigned char *idx = four_frag_CH + sizeof(four_frag_CH) - len; ExpectIntEQ(test_memio_inject_message(&test_ctx, 0, (const char *)idx, inj_len), 0); len -= inj_len; } ExpectIntEQ(test_ctx.s_len, sizeof(four_frag_CH)); while (test_ctx.s_len > 0 && EXPECT_SUCCESS()) { int s_len = test_ctx.s_len; ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1); ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ); /* Fail if we didn't advance the buffer to avoid infinite loops */ ExpectIntLT(test_ctx.s_len, s_len); } /* Expect all fragments read */ ExpectIntEQ(test_ctx.s_len, 0); /* Expect quietly dropping fragmented first CH */ ExpectIntEQ(test_ctx.c_len, 0); #if defined(WOLFSSL_TLS13) && defined(HAVE_ECH) /* Disable ECH as it pushes it over our MTU */ wolfSSL_SetEchEnable(ssl_c, 0); #endif /* Limit options to make the CH a fixed length */ /* See wolfSSL_parse_cipher_list for reason why we provide 1.3 AND 1.2 * ciphersuite. This is only necessary when building with OPENSSL_EXTRA. */ #ifdef OPENSSL_EXTRA ExpectTrue(wolfSSL_set_cipher_list(ssl_c, "TLS13-AES256-GCM-SHA384" ":DHE-RSA-AES256-GCM-SHA384")); #else ExpectTrue(wolfSSL_set_cipher_list(ssl_c, "TLS13-AES256-GCM-SHA384")); #endif /* CH1 */ ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); /* Count records. Expect 1 unfragmented CH */ ExpectIntEQ(test_dtls_frag_ch_count_records(test_ctx.s_buff, test_ctx.s_len), 1); /* HRR */ ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1); ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ); /* CH2 */ ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); /* Count records. Expect fragmented CH */ ExpectIntGT(test_dtls_frag_ch_count_records(test_ctx.s_buff, test_ctx.s_len), 1); ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); wolfSSL_free(ssl_c); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_c); wolfSSL_CTX_free(ctx_s); ssl_c = ssl_s = NULL; ctx_c = ctx_s = NULL; #endif return EXPECT_RESULT(); } static int test_dtls_empty_keyshare_with_cookie(void) { EXPECT_DECLS; #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13) WOLFSSL_CTX *ctx_s = NULL; WOLFSSL *ssl_s = NULL; struct test_memio_ctx test_ctx; unsigned char ch_empty_keyshare_with_cookie[] = { 0x16, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x12, 0x01, 0x00, 0x01, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0xfe, 0xfd, 0xfb, 0x8c, 0x9b, 0x28, 0xae, 0x50, 0x1c, 0x4d, 0xf3, 0xb8, 0xcf, 0x4d, 0xd8, 0x7e, 0x93, 0x13, 0x7b, 0x9e, 0xd9, 0xeb, 0xe9, 0x13, 0x4b, 0x0d, 0x7f, 0x2e, 0x43, 0x62, 0x8c, 0xe4, 0x57, 0x79, 0x00, 0x00, 0x00, 0x36, 0x13, 0x01, 0x13, 0x02, 0x13, 0x03, 0xc0, 0x2c, 0xc0, 0x2b, 0xc0, 0x30, 0xc0, 0x2f, 0x00, 0x9f, 0x00, 0x9e, 0xcc, 0xa9, 0xcc, 0xa8, 0xcc, 0xaa, 0xc0, 0x27, 0xc0, 0x23, 0xc0, 0x28, 0xc0, 0x24, 0xc0, 0x0a, 0xc0, 0x09, 0xc0, 0x14, 0xc0, 0x13, 0x00, 0x6b, 0x00, 0x67, 0x00, 0x39, 0x00, 0x33, 0xcc, 0x14, 0xcc, 0x13, 0xcc, 0x15, 0x01, 0x00, 0x00, 0xa6, 0x00, 0x2b, 0x00, 0x03, 0x02, 0xfe, 0xfc, 0x00, 0x2c, 0x00, 0x47, 0x00, 0x45, 0x20, 0xee, 0x4b, 0x17, 0x70, 0x63, 0xa0, 0x4c, 0x82, 0xbf, 0x43, 0x01, 0x7d, 0x8d, 0xc1, 0x1b, 0x4e, 0x9b, 0xa0, 0x3c, 0x53, 0x1f, 0xb7, 0xd1, 0x10, 0x81, 0xa8, 0xdf, 0xdf, 0x8c, 0x7f, 0xf3, 0x11, 0x13, 0x01, 0x02, 0x3d, 0x3b, 0x7d, 0x14, 0x2c, 0x31, 0xb3, 0x60, 0x72, 0x4d, 0xe5, 0x1a, 0xb2, 0xa3, 0x61, 0x77, 0x73, 0x03, 0x40, 0x0e, 0x5f, 0xc5, 0x61, 0x38, 0x43, 0x56, 0x21, 0x4a, 0x95, 0xd5, 0x35, 0xa8, 0x0d, 0x00, 0x0d, 0x00, 0x2a, 0x00, 0x28, 0x06, 0x03, 0x05, 0x03, 0x04, 0x03, 0x02, 0x03, 0xfe, 0x0b, 0xfe, 0x0e, 0xfe, 0xa0, 0xfe, 0xa3, 0xfe, 0xa5, 0x08, 0x06, 0x08, 0x0b, 0x08, 0x05, 0x08, 0x0a, 0x08, 0x04, 0x08, 0x09, 0x06, 0x01, 0x05, 0x01, 0x04, 0x01, 0x03, 0x01, 0x02, 0x01, 0x00, 0x0a, 0x00, 0x18, 0x00, 0x16, 0x00, 0x19, 0x00, 0x18, 0x00, 0x17, 0x00, 0x15, 0x01, 0x00, 0x02, 0x3a, 0x02, 0x3c, 0x02, 0x3d, 0x2f, 0x3a, 0x2f, 0x3c, 0x2f, 0x3d, 0x00, 0x16, 0x00, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x00 }; DtlsRecordLayerHeader* dtlsRH; byte sequence_number[8]; XMEMSET(&sequence_number, 0, sizeof(sequence_number)); XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, NULL, &ctx_s, NULL, &ssl_s, NULL, wolfDTLSv1_3_server_method), 0); ExpectIntEQ(test_memio_inject_message(&test_ctx, 0, (const char *)ch_empty_keyshare_with_cookie, sizeof(ch_empty_keyshare_with_cookie)), 0); /* CH1 */ ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1); ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ); /* Expect an alert. A plaintext alert should be exactly 15 bytes. */ ExpectIntEQ(test_ctx.c_len, 15); dtlsRH = (DtlsRecordLayerHeader*)test_ctx.c_buff; ExpectIntEQ(dtlsRH->type, alert); ExpectIntEQ(dtlsRH->pvMajor, DTLS_MAJOR); ExpectIntEQ(dtlsRH->pvMinor, DTLSv1_2_MINOR); sequence_number[7] = 1; ExpectIntEQ(XMEMCMP(sequence_number, dtlsRH->sequence_number, sizeof(sequence_number)), 0); ExpectIntEQ(dtlsRH->length[0], 0); ExpectIntEQ(dtlsRH->length[1], 2); ExpectIntEQ(test_ctx.c_buff[13], alert_fatal); ExpectIntEQ(test_ctx.c_buff[14], illegal_parameter); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_s); #endif return EXPECT_RESULT(); } static int test_dtls_old_seq_number(void) { EXPECT_DECLS; #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS) && \ !defined(WOLFSSL_NO_TLS12) WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL; WOLFSSL *ssl_c = NULL, *ssl_s = NULL; struct test_memio_ctx test_ctx; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method), 0); /* CH1 */ ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); /* HVR */ ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1); ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ); /* CH2 */ ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); /* Server first flight */ ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1); ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ); /* Client second flight */ ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); /* Modify the sequence number */ { DtlsRecordLayerHeader* dtlsRH = (DtlsRecordLayerHeader*)test_ctx.s_buff; XMEMSET(dtlsRH->sequence_number, 0, sizeof(dtlsRH->sequence_number)); } /* Server second flight */ ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1); ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ); /* Server should not do anything as a pkt was dropped */ ExpectIntEQ(test_ctx.c_len, 0); ExpectIntEQ(test_ctx.s_len, 0); /* Trigger rtx */ ExpectIntEQ(wolfSSL_dtls_got_timeout(ssl_c), WOLFSSL_SUCCESS); /* Complete connection */ ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); wolfSSL_free(ssl_c); wolfSSL_CTX_free(ctx_c); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_s); #endif return EXPECT_RESULT(); } static int test_dtls12_missing_finished(void) { EXPECT_DECLS; #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS) && \ !defined(WOLFSSL_NO_TLS12) WOLFSSL_CTX *ctx_c = NULL; WOLFSSL_CTX *ctx_s = NULL; WOLFSSL *ssl_c = NULL; WOLFSSL *ssl_s = NULL; struct test_memio_ctx test_ctx; const char test_str[] = "test string"; char test_buf[sizeof(test_str)]; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method), 0); /* CH1 */ ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); /* HVR */ ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1); ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ); /* CH2 */ ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); /* Server first flight */ ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1); ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ); /* Client second flight with finished */ ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); /* Server second flight with finished */ ExpectIntEQ(wolfSSL_negotiate(ssl_s), 1); /* Let's clear the output */ test_memio_clear_buffer(&test_ctx, 1); /* Let's send some app data */ ExpectIntEQ(wolfSSL_write(ssl_s, test_str, sizeof(test_str)), sizeof(test_str)); /* Client should not error out on a missing finished */ ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); /* Server rtx second flight with finished */ ExpectIntEQ(wolfSSL_dtls_got_timeout(ssl_s), 1); /* Client process rest of handshake */ ExpectIntEQ(wolfSSL_negotiate(ssl_c), 1); /* Let's send some app data */ ExpectIntEQ(wolfSSL_write(ssl_s, test_str, sizeof(test_str)), sizeof(test_str)); ExpectIntEQ(wolfSSL_read(ssl_c, test_buf, sizeof(test_buf)), sizeof(test_str)); ExpectBufEQ(test_buf, test_str, sizeof(test_str)); wolfSSL_free(ssl_c); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_c); wolfSSL_CTX_free(ctx_s); #endif return EXPECT_RESULT(); } static int test_dtls13_missing_finished_client(void) { EXPECT_DECLS; #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13) WOLFSSL_CTX *ctx_c = NULL; WOLFSSL_CTX *ctx_s = NULL; WOLFSSL *ssl_c = NULL; WOLFSSL *ssl_s = NULL; struct test_memio_ctx test_ctx; const char test_str[] = "test string"; char test_buf[sizeof(test_str)]; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method), 0); /* CH1 */ ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); /* HRR */ ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1); ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ); /* CH2 */ ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); /* Server first flight with finished */ ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1); ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ); /* Let's clear the output */ test_memio_clear_buffer(&test_ctx, 1); /* Let's send some app data */ ExpectIntEQ(wolfSSL_write(ssl_s, test_str, sizeof(test_str)), sizeof(test_str)); /* Client second flight with finished */ ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); /* Server should not error out on a missing finished */ ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1); ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ); /* Client rtx second flight with finished */ ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); /* Server */ ExpectIntEQ(wolfSSL_negotiate(ssl_s), 1); /* Client */ ExpectIntEQ(wolfSSL_negotiate(ssl_c), 1); /* Let's send some app data */ ExpectIntEQ(wolfSSL_write(ssl_s, test_str, sizeof(test_str)), sizeof(test_str)); ExpectIntEQ(wolfSSL_read(ssl_c, test_buf, sizeof(test_buf)), sizeof(test_str)); ExpectBufEQ(test_buf, test_str, sizeof(test_str)); wolfSSL_free(ssl_c); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_c); wolfSSL_CTX_free(ctx_s); #endif return EXPECT_RESULT(); } static int test_dtls13_missing_finished_server(void) { EXPECT_DECLS; #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13) WOLFSSL_CTX *ctx_c = NULL; WOLFSSL_CTX *ctx_s = NULL; WOLFSSL *ssl_c = NULL; WOLFSSL *ssl_s = NULL; struct test_memio_ctx test_ctx; const char test_str[] = "test string"; char test_buf[sizeof(test_str)]; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method), 0); /* CH1 */ ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); /* HRR */ ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1); ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ); /* CH2 */ ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); /* Server first flight with finished */ ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1); ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ); /* Client second flight with finished */ ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); /* Let's clear the output */ test_memio_clear_buffer(&test_ctx, 0); ExpectFalse(wolfSSL_is_init_finished(ssl_c)); /* Let's send some app data */ ExpectIntEQ(wolfSSL_write(ssl_c, test_str, sizeof(test_str)), sizeof(test_str)); /* Server should not error out on a missing finished */ ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1); ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ); /* Client rtx second flight with finished */ ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); /* Server first flight with finished */ ExpectIntEQ(wolfSSL_negotiate(ssl_s), 1); /* Let's send some app data */ ExpectIntEQ(wolfSSL_write(ssl_c, test_str, sizeof(test_str)), sizeof(test_str)); ExpectIntEQ(wolfSSL_read(ssl_s, test_buf, sizeof(test_buf)), sizeof(test_str)); ExpectBufEQ(test_buf, test_str, sizeof(test_str)); wolfSSL_free(ssl_c); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_c); wolfSSL_CTX_free(ctx_s); #endif return EXPECT_RESULT(); } static int test_dtls13_finished_send_error_propagation(void) { EXPECT_DECLS; #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13) WOLFSSL_CTX *ctx_c = NULL; WOLFSSL_CTX *ctx_s = NULL; WOLFSSL *ssl_c = NULL; WOLFSSL *ssl_s = NULL; struct test_memio_ctx test_ctx; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method), 0); /* CH1 */ ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); /* HRR */ ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1); ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ); /* CH2 */ ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); /* Server first flight with finished */ ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1); ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ); /* Client second flight with finished - block sends to force error */ test_ctx.s_len = TEST_MEMIO_BUF_SZ; ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); /* Verify the error is propagated, not silently swallowed as success */ ExpectIntNE(wolfSSL_get_error(ssl_c, -1), 0); wolfSSL_free(ssl_c); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_c); wolfSSL_CTX_free(ctx_s); #endif return EXPECT_RESULT(); } #if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) #ifdef HAVE_CERTIFICATE_STATUS_REQUEST static int test_self_signed_stapling_client_v1_ctx_ready(WOLFSSL_CTX* ctx) { EXPECT_DECLS; ExpectIntEQ(wolfSSL_CTX_EnableOCSPStapling(ctx), 1); ExpectIntEQ(wolfSSL_CTX_UseOCSPStapling(ctx, WOLFSSL_CSR_OCSP, WOLFSSL_CSR_OCSP_USE_NONCE), 1); return EXPECT_RESULT(); } #endif #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 static int test_self_signed_stapling_client_v2_ctx_ready(WOLFSSL_CTX* ctx) { EXPECT_DECLS; ExpectIntEQ(wolfSSL_CTX_EnableOCSPStapling(ctx), 1); ExpectIntEQ(wolfSSL_CTX_UseOCSPStaplingV2(ctx, WOLFSSL_CSR2_OCSP, WOLFSSL_CSR2_OCSP_USE_NONCE), 1); return EXPECT_RESULT(); } static int test_self_signed_stapling_client_v2_multi_ctx_ready(WOLFSSL_CTX* ctx) { EXPECT_DECLS; ExpectIntEQ(wolfSSL_CTX_EnableOCSPStapling(ctx), 1); ExpectIntEQ(wolfSSL_CTX_UseOCSPStaplingV2(ctx, WOLFSSL_CSR2_OCSP_MULTI, 0), 1); return EXPECT_RESULT(); } #endif #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) static int test_self_signed_stapling_server_ctx_ready(WOLFSSL_CTX* ctx) { EXPECT_DECLS; ExpectIntEQ(wolfSSL_CTX_EnableOCSPStapling(ctx), 1); return EXPECT_RESULT(); } #endif #endif static int test_self_signed_stapling(void) { EXPECT_DECLS; #if (defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \ defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)) && \ !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) test_ssl_cbf client_cbf; test_ssl_cbf server_cbf; size_t i; struct { method_provider client_meth; method_provider server_meth; ctx_cb client_ctx; const char* tls_version; } params[] = { #if defined(WOLFSSL_TLS13) && defined(HAVE_CERTIFICATE_STATUS_REQUEST) { wolfTLSv1_3_client_method, wolfTLSv1_3_server_method, test_self_signed_stapling_client_v1_ctx_ready, "TLSv1_3 v1" }, #endif #ifndef WOLFSSL_NO_TLS12 #ifdef HAVE_CERTIFICATE_STATUS_REQUEST { wolfTLSv1_2_client_method, wolfTLSv1_2_server_method, test_self_signed_stapling_client_v1_ctx_ready, "TLSv1_2 v1" }, #endif #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 { wolfTLSv1_2_client_method, wolfTLSv1_2_server_method, test_self_signed_stapling_client_v2_ctx_ready, "TLSv1_2 v2" }, { wolfTLSv1_2_client_method, wolfTLSv1_2_server_method, test_self_signed_stapling_client_v2_multi_ctx_ready, "TLSv1_2 v2 multi" }, #endif #endif }; for (i = 0; i < sizeof(params)/sizeof(*params) && !EXPECT_FAIL(); i++) { XMEMSET(&client_cbf, 0, sizeof(client_cbf)); XMEMSET(&server_cbf, 0, sizeof(server_cbf)); printf("\nTesting self-signed cert with status request: %s\n", params[i].tls_version); client_cbf.method = params[i].client_meth; client_cbf.ctx_ready = params[i].client_ctx; server_cbf.method = params[i].server_meth; server_cbf.certPemFile = "certs/ca-cert.pem"; server_cbf.keyPemFile = "certs/ca-key.pem"; server_cbf.ctx_ready = test_self_signed_stapling_server_ctx_ready; ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&client_cbf, &server_cbf, NULL), TEST_SUCCESS); } #endif return EXPECT_RESULT(); } static int test_tls_multi_handshakes_one_record(void) { EXPECT_DECLS; #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \ !defined(WOLFSSL_NO_TLS12) && !defined(NO_SHA256) struct test_memio_ctx test_ctx; WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL; WOLFSSL *ssl_c = NULL, *ssl_s = NULL; RecordLayerHeader* rh = NULL; byte *len ; int newRecIdx; int idx; byte buff[64 * 1024]; word16 recLen; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, wolfTLS_client_method, wolfTLSv1_2_server_method), 0); ExpectIntEQ(wolfSSL_connect(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); ExpectIntEQ(wolfSSL_accept(ssl_s), -1); ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ); XMEMSET(buff, 0, sizeof(buff)); rh = (RecordLayerHeader*)(test_ctx.c_buff); len = &rh->length[0]; ato16((const byte*)len, &recLen); ExpectIntLE(RECORD_HEADER_SZ + recLen, (int)sizeof(buff)); ExpectIntLE(RECORD_HEADER_SZ + recLen, test_ctx.c_len); if (EXPECT_SUCCESS()) { XMEMCPY(buff, test_ctx.c_buff, RECORD_HEADER_SZ + recLen); newRecIdx = idx = RECORD_HEADER_SZ + recLen; /* Combine server handshake msgs into one record */ while (idx < test_ctx.c_len) { rh = (RecordLayerHeader*)(test_ctx.c_buff + idx); len = &rh->length[0]; ato16((const byte*)len, &recLen); ExpectIntLE(idx + RECORD_HEADER_SZ + recLen, test_ctx.c_len); ExpectIntLE(newRecIdx + recLen, (int)sizeof(buff)); if (!EXPECT_SUCCESS()) { break; } idx += RECORD_HEADER_SZ; XMEMCPY(buff + newRecIdx, test_ctx.c_buff + idx, (size_t)recLen); newRecIdx += recLen; idx += recLen; } if (EXPECT_SUCCESS()) { rh = (RecordLayerHeader*)(buff); len = &rh->length[0]; c16toa((word16)newRecIdx - RECORD_HEADER_SZ, len); test_memio_clear_buffer(&test_ctx, 1); test_memio_inject_message(&test_ctx, 1, (const char*)buff, newRecIdx); ExpectIntEQ(wolfSSL_connect(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); } } wolfSSL_free(ssl_c); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_c); wolfSSL_CTX_free(ctx_s); #endif return EXPECT_RESULT(); } static int test_write_dup(void) { EXPECT_DECLS; #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(HAVE_WRITE_DUP) size_t i, j, k; char hiWorld[] = "dup message"; char readData[sizeof(hiWorld) + 5]; #ifdef WOLFSSL_TLS13 int required; #endif struct { method_provider client_meth; method_provider server_meth; const char* version_name; int version; } methods[] = { #ifndef WOLFSSL_NO_TLS12 {wolfTLSv1_2_client_method, wolfTLSv1_2_server_method, "TLS 1.2", WOLFSSL_TLSV1_2}, {wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method, "DTLS 1.2", WOLFSSL_TLSV1_2}, #endif #ifdef WOLFSSL_TLS13 {wolfTLSv1_3_client_method, wolfTLSv1_3_server_method, "TLS 1.3", WOLFSSL_TLSV1_3}, {wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method, "DTLS 1.3", WOLFSSL_TLSV1_3}, #endif }; struct { const char* cipher; int version; } ciphers[] = { /* For simplicity the macros are copied from internal.h */ /* TLS 1.2 */ #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) && !defined(NO_SHA256) #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) #ifndef NO_RSA {"ECDHE-RSA-CHACHA20-POLY1305", WOLFSSL_TLSV1_2}, #endif #endif #if !defined(NO_DH) && !defined(NO_RSA) && !defined(NO_TLS_DH) {"DHE-RSA-CHACHA20-POLY1305", WOLFSSL_TLSV1_2}, #endif #endif #if !defined(NO_DH) && !defined(NO_AES) && !defined(NO_TLS) && \ !defined(NO_RSA) && defined(HAVE_AESGCM) && !defined(NO_TLS_DH) #if !defined(NO_SHA256) && defined(WOLFSSL_AES_128) {"DHE-RSA-AES128-GCM-SHA256", WOLFSSL_TLSV1_2}, #endif #if defined(WOLFSSL_SHA384) && defined(WOLFSSL_AES_256) {"DHE-RSA-AES256-GCM-SHA384", WOLFSSL_TLSV1_2}, #endif #endif #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)) \ && !defined(NO_TLS) && !defined(NO_AES) #ifdef HAVE_AESGCM #if !defined(NO_SHA256) && defined(WOLFSSL_AES_128) #ifndef NO_RSA {"ECDHE-RSA-AES128-GCM-SHA256", WOLFSSL_TLSV1_2}, #endif #endif #if defined(WOLFSSL_SHA384) && defined(WOLFSSL_AES_256) #ifndef NO_RSA {"ECDHE-RSA-AES256-GCM-SHA384", WOLFSSL_TLSV1_2}, #endif #endif #endif #endif /* TLS 1.3 */ #ifdef WOLFSSL_TLS13 #ifdef HAVE_AESGCM #if !defined(NO_SHA256) && defined(WOLFSSL_AES_128) {"TLS13-AES128-GCM-SHA256", WOLFSSL_TLSV1_3}, #endif #if defined(WOLFSSL_SHA384) && defined(WOLFSSL_AES_256) {"TLS13-AES256-GCM-SHA384", WOLFSSL_TLSV1_3}, #endif #endif #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) #ifndef NO_SHA256 {"TLS13-CHACHA20-POLY1305-SHA256", WOLFSSL_TLSV1_3}, #endif #endif #ifdef HAVE_AESCCM #if !defined(NO_SHA256) && defined(WOLFSSL_AES_128) {"TLS13-AES128-CCM-SHA256", WOLFSSL_TLSV1_3}, #endif #endif #endif }; /* Macro capturing local variables for concise bidirectional data exchange. */ #define EXCHANGE_DATA do { \ ExpectIntEQ(wolfSSL_write(ssl_s, hiWorld, sizeof(hiWorld)), \ sizeof(hiWorld)); \ ExpectIntEQ(wolfSSL_read(ssl_c, readData, sizeof(readData)), \ sizeof(hiWorld)); \ ExpectIntEQ(wolfSSL_write(ssl_c2, hiWorld, sizeof(hiWorld)), \ sizeof(hiWorld)); \ ExpectIntEQ(wolfSSL_read(ssl_s, readData, sizeof(readData)), \ sizeof(hiWorld)); \ } while (0) for (i = 0; i < XELEM_CNT(methods); i++) { for (j = 0; j < XELEM_CNT(ciphers) && !EXPECT_FAIL(); j++) { struct test_memio_ctx test_ctx; WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL; WOLFSSL *ssl_c = NULL, *ssl_s = NULL; WOLFSSL *ssl_c2 = NULL; if (methods[i].version != ciphers[j].version) continue; if (i == 0 && j == 0) printf("\n"); printf("Testing %s with %s... ", methods[i].version_name, ciphers[j].cipher); XMEMSET(&test_ctx, 0, sizeof(test_ctx)); test_ctx.c_ciphers = test_ctx.s_ciphers = ciphers[j].cipher; ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, methods[i].client_meth, methods[i].server_meth), 0); #ifdef WOLFSSL_POST_HANDSHAKE_AUTH if (methods[i].version == WOLFSSL_TLSV1_3) { ExpectIntEQ(wolfSSL_CTX_use_certificate_file(ctx_c, cliCertFile, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_file(ctx_c, cliKeyFile, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_use_certificate_file(ssl_c, cliCertFile, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_use_PrivateKey_file(ssl_c, cliKeyFile, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_allow_post_handshake_auth(ssl_c), 0); ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx_s, caCertFile, NULL), WOLFSSL_SUCCESS); } #endif ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); ExpectNotNull(ssl_c2 = wolfSSL_write_dup(ssl_c)); ExpectIntEQ(wolfSSL_write(ssl_c, hiWorld, sizeof(hiWorld)), WC_NO_ERR_TRACE(WRITE_DUP_WRITE_E)); EXCHANGE_DATA; ExpectIntEQ(wolfSSL_read(ssl_c2, readData, sizeof(readData)), WC_NO_ERR_TRACE(WRITE_DUP_READ_E)); #ifdef WOLFSSL_DTLS13 /* The initial EXCHANGE_DATA above processes the post-handshake * NewSessionTicket (S2C part delegates ACK) and triggers the * ACK (C2S part sends it). Verify it completed. */ if (methods[i].client_meth == wolfDTLSv1_3_client_method) { ExpectNotNull(ssl_c->dupWrite); ExpectIntEQ(ssl_c->dupWrite->sendAcks, 0); ExpectNull(ssl_s->dtls13Rtx.rtxRecords); } #endif for (k = 0; k < 10; k++) EXCHANGE_DATA; #ifdef WOLFSSL_TLS13 if (methods[i].version == WOLFSSL_TLSV1_3) { /* Client-initiated key update. */ ExpectIntEQ(wolfSSL_update_keys(ssl_c2), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_key_update_response(ssl_c2, &required), 0); ExpectIntEQ(required, 1); for (k = 0; k < 10; k++) EXCHANGE_DATA; } if (methods[i].version == WOLFSSL_TLSV1_3) { /* Server-initiated key update. */ ExpectIntEQ(wolfSSL_update_keys(ssl_s), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_key_update_response(ssl_s, &required), 0); ExpectIntEQ(required, 1); for (k = 0; k < 10; k++) EXCHANGE_DATA; ExpectIntEQ(wolfSSL_key_update_response(ssl_s, &required), 0); ExpectIntEQ(required, 0); } #endif /* WOLFSSL_TLS13 */ #ifdef WOLFSSL_POST_HANDSHAKE_AUTH if (methods[i].version == WOLFSSL_TLSV1_3) { WOLFSSL_X509_CHAIN* chain = NULL; ExpectNotNull(chain = wolfSSL_get_peer_chain(ssl_s)); ExpectIntEQ(wolfSSL_get_chain_count(chain), 0); ExpectIntEQ(wolfSSL_request_certificate(ssl_s), WOLFSSL_SUCCESS); EXCHANGE_DATA; ExpectNotNull(chain = wolfSSL_get_peer_chain(ssl_s)); ExpectIntEQ(wolfSSL_get_chain_count(chain), 1); for (k = 0; k < 10; k++) EXCHANGE_DATA; } #endif if (EXPECT_SUCCESS()) printf("ok\n"); else printf("failed\n"); wolfSSL_free(ssl_c); wolfSSL_free(ssl_c2); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_c); wolfSSL_CTX_free(ctx_s); } } #undef EXCHANGE_DATA #endif return EXPECT_RESULT(); } static int test_write_dup_want_write(void) { EXPECT_DECLS; #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(HAVE_WRITE_DUP) size_t i, k; char hiWorld[] = "dup message"; char readData[sizeof(hiWorld) + 5]; #ifdef WOLFSSL_TLS13 int required; #endif struct { method_provider client_meth; method_provider server_meth; const char* version_name; int version; } methods[] = { #ifndef WOLFSSL_NO_TLS12 {wolfTLSv1_2_client_method, wolfTLSv1_2_server_method, "TLS 1.2", WOLFSSL_TLSV1_2}, {wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method, "DTLS 1.2", WOLFSSL_TLSV1_2}, #endif #ifdef WOLFSSL_TLS13 {wolfTLSv1_3_client_method, wolfTLSv1_3_server_method, "TLS 1.3", WOLFSSL_TLSV1_3}, {wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method, "DTLS 1.3", WOLFSSL_TLSV1_3}, #endif }; /* Same as test_write_dup's EXCHANGE_DATA but every client (write-dup side) * write is preceded by a simulated WANT_WRITE that must be retried. */ #define EXCHANGE_DATA do { \ ExpectIntEQ(wolfSSL_write(ssl_s, hiWorld, sizeof(hiWorld)), \ sizeof(hiWorld)); \ ExpectIntEQ(wolfSSL_read(ssl_c, readData, sizeof(readData)), \ sizeof(hiWorld)); \ test_memio_simulate_want_write(&test_ctx, 1, 1); \ ExpectIntEQ(wolfSSL_write(ssl_c2, hiWorld, sizeof(hiWorld)), \ WOLFSSL_FATAL_ERROR); \ ExpectIntEQ(wolfSSL_get_error(ssl_c2, WOLFSSL_FATAL_ERROR), \ WOLFSSL_ERROR_WANT_WRITE); \ test_memio_simulate_want_write(&test_ctx, 1, 0); \ ExpectIntEQ(wolfSSL_write(ssl_c2, hiWorld, sizeof(hiWorld)), \ sizeof(hiWorld)); \ ExpectIntEQ(wolfSSL_read(ssl_s, readData, sizeof(readData)), \ sizeof(hiWorld)); \ } while (0) for (i = 0; i < XELEM_CNT(methods) && !EXPECT_FAIL(); i++) { struct test_memio_ctx test_ctx; WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL; WOLFSSL *ssl_c = NULL, *ssl_s = NULL; WOLFSSL *ssl_c2 = NULL; if (i == 0) printf("\n"); printf("Testing write_dup WANT_WRITE %s... ", methods[i].version_name); XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, methods[i].client_meth, methods[i].server_meth), 0); #ifdef WOLFSSL_POST_HANDSHAKE_AUTH if (methods[i].version == WOLFSSL_TLSV1_3) { ExpectIntEQ(wolfSSL_CTX_use_certificate_file(ctx_c, cliCertFile, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_file(ctx_c, cliKeyFile, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_use_certificate_file(ssl_c, cliCertFile, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_use_PrivateKey_file(ssl_c, cliKeyFile, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_allow_post_handshake_auth(ssl_c), 0); ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx_s, caCertFile, NULL), WOLFSSL_SUCCESS); } #endif ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); ExpectNotNull(ssl_c2 = wolfSSL_write_dup(ssl_c)); for (k = 0; k < 10 && !EXPECT_FAIL(); k++) EXCHANGE_DATA; #ifdef WOLFSSL_TLS13 if (methods[i].version == WOLFSSL_TLSV1_3) { /* Client-initiated key update with WANT_WRITE. */ ExpectIntEQ(wolfSSL_update_keys(ssl_c2), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_key_update_response(ssl_c2, &required), 0); ExpectIntEQ(required, 1); for (k = 0; k < 10 && !EXPECT_FAIL(); k++) EXCHANGE_DATA; /* Server-initiated key update: response goes through write side * with WANT_WRITE. */ ExpectIntEQ(wolfSSL_update_keys(ssl_s), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_key_update_response(ssl_s, &required), 0); ExpectIntEQ(required, 1); for (k = 0; k < 10 && !EXPECT_FAIL(); k++) EXCHANGE_DATA; ExpectIntEQ(wolfSSL_key_update_response(ssl_s, &required), 0); ExpectIntEQ(required, 0); } #endif /* WOLFSSL_TLS13 */ #ifdef WOLFSSL_POST_HANDSHAKE_AUTH if (methods[i].version == WOLFSSL_TLSV1_3) { WOLFSSL_X509_CHAIN* chain = NULL; ExpectNotNull(chain = wolfSSL_get_peer_chain(ssl_s)); ExpectIntEQ(wolfSSL_get_chain_count(chain), 0); ExpectIntEQ(wolfSSL_request_certificate(ssl_s), WOLFSSL_SUCCESS); EXCHANGE_DATA; ExpectNotNull(chain = wolfSSL_get_peer_chain(ssl_s)); ExpectIntEQ(wolfSSL_get_chain_count(chain), 1); for (k = 0; k < 10 && !EXPECT_FAIL(); k++) EXCHANGE_DATA; } #endif /* WOLFSSL_POST_HANDSHAKE_AUTH */ if (EXPECT_SUCCESS()) printf("ok\n"); else printf("failed\n"); wolfSSL_free(ssl_c); wolfSSL_free(ssl_c2); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_c); wolfSSL_CTX_free(ctx_s); } #undef EXCHANGE_DATA #endif return EXPECT_RESULT(); } /* Simultaneous key update and cert req */ static int test_write_dup_want_write_simul(void) { EXPECT_DECLS; #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(HAVE_WRITE_DUP) && \ defined(WOLFSSL_POST_HANDSHAKE_AUTH) && defined(WOLFSSL_TLS13) size_t i, k; char hiWorld[] = "dup message"; char readData[sizeof(hiWorld) + 5]; int required; struct { method_provider client_meth; method_provider server_meth; const char* version_name; } methods[] = { #ifdef WOLFSSL_TLS13 {wolfTLSv1_3_client_method, wolfTLSv1_3_server_method, "TLS 1.3"}, {wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method, "DTLS 1.3"}, #endif }; /* Same as test_write_dup's EXCHANGE_DATA but every client (write-dup side) * write is preceded by a simulated WANT_WRITE that must be retried. */ #define EXCHANGE_DATA do { \ ExpectIntEQ(wolfSSL_write(ssl_s, hiWorld, sizeof(hiWorld)), \ sizeof(hiWorld)); \ ExpectIntEQ(wolfSSL_read(ssl_c, readData, sizeof(readData)), \ sizeof(hiWorld)); \ test_memio_simulate_want_write(&test_ctx, 1, 1); \ ExpectIntEQ(wolfSSL_write(ssl_c2, hiWorld, sizeof(hiWorld)), \ WOLFSSL_FATAL_ERROR); \ ExpectIntEQ(wolfSSL_get_error(ssl_c2, WOLFSSL_FATAL_ERROR), \ WOLFSSL_ERROR_WANT_WRITE); \ test_memio_simulate_want_write(&test_ctx, 1, 0); \ ExpectIntEQ(wolfSSL_write(ssl_c2, hiWorld, sizeof(hiWorld)), \ sizeof(hiWorld)); \ ExpectIntEQ(wolfSSL_read(ssl_s, readData, sizeof(readData)), \ sizeof(hiWorld)); \ } while (0) for (i = 0; i < XELEM_CNT(methods) && !EXPECT_FAIL(); i++) { struct test_memio_ctx test_ctx; WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL; WOLFSSL *ssl_c = NULL, *ssl_s = NULL; WOLFSSL *ssl_c2 = NULL; WOLFSSL_X509_CHAIN* chain = NULL; if (i == 0) printf("\n"); printf("Testing write_dup WANT_WRITE %s... ", methods[i].version_name); XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, methods[i].client_meth, methods[i].server_meth), 0); ExpectIntEQ(wolfSSL_CTX_use_certificate_file(ctx_c, cliCertFile, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_file(ctx_c, cliKeyFile, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_use_certificate_file(ssl_c, cliCertFile, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_use_PrivateKey_file(ssl_c, cliKeyFile, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_allow_post_handshake_auth(ssl_c), 0); ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx_s, caCertFile, NULL), WOLFSSL_SUCCESS); ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); ExpectNotNull(ssl_c2 = wolfSSL_write_dup(ssl_c)); for (k = 0; k < 10 && !EXPECT_FAIL(); k++) EXCHANGE_DATA; /* Server-initiated key update and cert req: response goes through * write side with WANT_WRITE. */ ExpectNotNull(chain = wolfSSL_get_peer_chain(ssl_s)); ExpectIntEQ(wolfSSL_get_chain_count(chain), 0); ExpectIntEQ(wolfSSL_update_keys(ssl_s), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_key_update_response(ssl_s, &required), 0); ExpectIntEQ(required, 1); ExpectIntEQ(wolfSSL_request_certificate(ssl_s), WOLFSSL_SUCCESS); for (k = 0; k < 10 && !EXPECT_FAIL(); k++) EXCHANGE_DATA; ExpectNotNull(chain = wolfSSL_get_peer_chain(ssl_s)); ExpectIntEQ(wolfSSL_get_chain_count(chain), 1); ExpectIntEQ(wolfSSL_key_update_response(ssl_s, &required), 0); ExpectIntEQ(required, 0); if (EXPECT_SUCCESS()) printf("ok\n"); else printf("failed\n"); wolfSSL_free(ssl_c); wolfSSL_free(ssl_c2); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_c); wolfSSL_CTX_free(ctx_s); } #undef EXCHANGE_DATA #endif return EXPECT_RESULT(); } #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(HAVE_WRITE_DUP) && \ defined(HAVE_CHACHA) && defined(HAVE_POLY1305) && !defined(NO_SHA256) && \ (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ defined(HAVE_CURVE448)) && \ !defined(NO_RSA) && defined(USE_WOLFSSL_MEMORY) && \ !defined(WOLFSSL_NO_MALLOC) && !defined(WOLFSSL_STATIC_MEMORY) && \ !defined(WOLFSSL_KERNEL_MODE) && !defined(WOLFSSL_NO_TLS12) && \ !defined(NO_TLS) #include /* Custom allocator state for test_write_dup_oom. * The allocator counts allocations of size oom_match_size (set to * sizeof(Poly1305) by the test). The Nth such allocation is forced to * fail if oom_fail_at_match == N; oom_failed is then set so callers can * confirm the fault was actually injected. The test runs in two phases: * 1) Measure: oom_fail_at_match = 0 (no failures), record oom_match_count * after a successful wolfSSL_write_dup(). The Poly1305 alloc in * DupSSL() is the LAST sizeof(Poly1305) allocation in the call path, * so that count is the index that targets it. * 2) Trigger: oom_fail_at_match = recorded count, run write_dup again on * a fresh handshake. The Nth match is the Poly1305 alloc, so the * failure exercises exactly the bug under test. */ static size_t oom_match_size = 0; static int oom_match_count = 0; static int oom_fail_at_match = 0; static int oom_failed = 0; #ifdef WOLFSSL_DEBUG_MEMORY static void* oom_malloc_cb(size_t size, const char* func, unsigned int line) { (void)func; (void)line; #else static void* oom_malloc_cb(size_t size) { #endif if (!oom_failed && oom_match_size != 0 && size == oom_match_size) { oom_match_count++; if (oom_fail_at_match != 0 && oom_match_count == oom_fail_at_match) { oom_failed = 1; return NULL; } } return malloc(size); } #ifdef WOLFSSL_DEBUG_MEMORY static void oom_free_cb(void* ptr, const char* func, unsigned int line) { (void)func; (void)line; #else static void oom_free_cb(void* ptr) { #endif free(ptr); } #ifdef WOLFSSL_DEBUG_MEMORY static void* oom_realloc_cb(void* ptr, size_t size, const char* func, unsigned int line) { (void)func; (void)line; #else static void* oom_realloc_cb(void* ptr, size_t size) { #endif return realloc(ptr, size); } #endif /* Regression test for the DupSSL() error-path bug: an allocation failure on * the Poly1305 alloc must not leave the original ssl object with a zeroed * encrypt context or a non-NULL ssl->dupWrite. * * Pass 0 measures the count of sizeof(Poly1305) allocations during a * successful wolfSSL_write_dup(); pass 1 fails the same-indexed allocation * on a fresh handshake to deterministically target the DupSSL() Poly1305 * alloc regardless of any incidental size collisions. */ static int test_write_dup_oom(void) { EXPECT_DECLS; #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(HAVE_WRITE_DUP) && \ defined(HAVE_CHACHA) && defined(HAVE_POLY1305) && !defined(NO_SHA256) && \ (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ defined(HAVE_CURVE448)) && \ !defined(NO_RSA) && defined(USE_WOLFSSL_MEMORY) && \ !defined(WOLFSSL_NO_MALLOC) && !defined(WOLFSSL_STATIC_MEMORY) && \ !defined(WOLFSSL_KERNEL_MODE) && !defined(WOLFSSL_NO_TLS12) && \ !defined(NO_TLS) char hiWorld[] = "dup message"; char readData[sizeof(hiWorld) + 5]; wolfSSL_Malloc_cb prev_mc = NULL; wolfSSL_Free_cb prev_fc = NULL; wolfSSL_Realloc_cb prev_rc = NULL; int allocators_set = 0; int target_match = 0; int pass; ExpectIntEQ(wolfSSL_GetAllocators(&prev_mc, &prev_fc, &prev_rc), 0); ExpectIntEQ(wolfSSL_SetAllocators(oom_malloc_cb, oom_free_cb, oom_realloc_cb), 0); if (EXPECT_SUCCESS()) allocators_set = 1; for (pass = 0; pass < 2 && EXPECT_SUCCESS(); pass++) { struct test_memio_ctx test_ctx; WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL; WOLFSSL *ssl_c = NULL, *ssl_s = NULL; WOLFSSL *ssl_c2 = NULL; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); test_ctx.c_ciphers = test_ctx.s_ciphers = "ECDHE-RSA-CHACHA20-POLY1305"; ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, wolfTLSv1_2_client_method, wolfTLSv1_2_server_method), 0); ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); /* Start counting sizeof(Poly1305) allocations only now, after the * handshake, so the count reflects only allocations on the * wolfSSL_write_dup() code path. */ oom_match_size = sizeof(Poly1305); oom_match_count = 0; oom_failed = 0; oom_fail_at_match = (pass == 0) ? 0 : target_match; if (pass == 0) { ExpectNotNull(ssl_c2 = wolfSSL_write_dup(ssl_c)); target_match = oom_match_count; /* Sanity: at least one Poly1305 alloc must occur on this path, * otherwise the test setup was wrong (feature compiled out, or * negotiated cipher does not use Poly1305). */ ExpectIntGE(target_match, 1); } else { ExpectNull(wolfSSL_write_dup(ssl_c)); /* Confirm the targeted Poly1305 allocation actually failed. */ ExpectIntEQ(oom_failed, 1); /* Stop further failures so the recovery path can run. */ oom_fail_at_match = 0; /* The original ssl_c must NOT be poisoned: the WriteDup must have * been cleaned up, the encrypt cipher context must still be * intact, and a fresh wolfSSL_write_dup() must succeed. */ ExpectNull(ssl_c->dupWrite); ExpectNotNull(ssl_c2 = wolfSSL_write_dup(ssl_c)); /* Round-trip data both directions to confirm both sides still * encrypt with the original ssl_c context preserved. */ ExpectIntEQ(wolfSSL_write(ssl_s, hiWorld, sizeof(hiWorld)), sizeof(hiWorld)); ExpectIntEQ(wolfSSL_read(ssl_c, readData, sizeof(readData)), sizeof(hiWorld)); ExpectIntEQ(wolfSSL_write(ssl_c2, hiWorld, sizeof(hiWorld)), sizeof(hiWorld)); ExpectIntEQ(wolfSSL_read(ssl_s, readData, sizeof(readData)), sizeof(hiWorld)); } /* Disable matching/failure during teardown so frees and any internal * allocations of the same size during cleanup are unaffected. */ oom_match_size = 0; oom_fail_at_match = 0; wolfSSL_free(ssl_c); wolfSSL_free(ssl_c2); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_c); wolfSSL_CTX_free(ctx_s); } /* Restore previous allocators only after every object allocated under the * test allocators has been freed, so allocator bookkeeping (in builds * that wrap the default allocators) is not desynchronised. */ if (allocators_set) (void)wolfSSL_SetAllocators(prev_mc, prev_fc, prev_rc); #endif return EXPECT_RESULT(); } static int test_read_write_hs(void) { EXPECT_DECLS; #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \ !defined(WOLFSSL_NO_TLS12) && !defined(NO_SHA256) WOLFSSL_CTX *ctx_s = NULL, *ctx_c = NULL; WOLFSSL *ssl_s = NULL, *ssl_c = NULL; struct test_memio_ctx test_ctx; byte test_buffer[16]; unsigned int test; /* test == 0 : client writes, server reads */ /* test == 1 : server writes, client reads */ for (test = 0; test < 2; test++) { XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, wolfTLSv1_2_client_method, wolfTLSv1_2_server_method), 0); ExpectIntEQ(wolfSSL_set_group_messages(ssl_s), WOLFSSL_SUCCESS); /* CH -> */ if (test == 0) { ExpectIntEQ(wolfSSL_write(ssl_c, "hello", 5), -1); } else { ExpectIntEQ(wolfSSL_read(ssl_c, test_buffer, sizeof(test_buffer)), -1); } ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); /* <- SH + SKE + SHD */ if (test == 0) { ExpectIntEQ(wolfSSL_read(ssl_s, test_buffer, sizeof(test_buffer)), -1); } else { ExpectIntEQ(wolfSSL_write(ssl_s, "hello", 5), -1); } ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ); /* -> CKE + CLIENT FINISHED */ if (test == 0) { ExpectIntEQ(wolfSSL_write(ssl_c, "hello", 5), -1); } else { ExpectIntEQ(wolfSSL_read(ssl_c, test_buffer, sizeof(test_buffer)), -1); } ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); /* abide clang static analyzer */ if (ssl_s != NULL) { /* disable group message to separate sending of ChangeCipherspec * from Finished */ ssl_s->options.groupMessages = 0; } /* allow writing of CS, but not FINISHED */ test_ctx.c_len = TEST_MEMIO_BUF_SZ - 6; /* <- CS */ if (test == 0) { ExpectIntEQ(wolfSSL_read(ssl_s, test_buffer, sizeof(test_buffer)), -1); } else { ExpectIntEQ(wolfSSL_write(ssl_s, "hello", 5), -1); } ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_WRITE); /* move CS message where the client can read it */ memmove(test_ctx.c_buff, (test_ctx.c_buff + TEST_MEMIO_BUF_SZ - 6), 6); test_ctx.c_len = 6; /* read CS */ if (test == 0) { ExpectIntEQ(wolfSSL_write(ssl_c, "hello", 5), -1); } else { ExpectIntEQ(wolfSSL_read(ssl_c, test_buffer, sizeof(test_buffer)), -1); } ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); ExpectIntEQ(test_ctx.c_len, 0); if (test == 0) { /* send SERVER FINISHED */ ExpectIntEQ(wolfSSL_read(ssl_s, test_buffer, sizeof(test_buffer)), -1); ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ); } else { /* send SERVER FINISHED + App Data */ ExpectIntEQ(wolfSSL_write(ssl_s, "hello", 5), 5); } ExpectIntGT(test_ctx.c_len, 0); /* Send and receive the data */ if (test == 0) { ExpectIntEQ(wolfSSL_write(ssl_c, "hello", 5), 5); ExpectIntEQ(wolfSSL_read(ssl_s, test_buffer, sizeof(test_buffer)), 5); } else { ExpectIntEQ(wolfSSL_read(ssl_c, test_buffer, sizeof(test_buffer)), 5); } ExpectBufEQ(test_buffer, "hello", 5); wolfSSL_free(ssl_c); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_c); wolfSSL_CTX_free(ctx_s); ssl_c = ssl_s = NULL; ctx_c = ctx_s = NULL; } #endif return EXPECT_RESULT(); } #if defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && defined(OPENSSL_EXTRA) static const char* test_get_signature_nid_siglag; static int test_get_signature_nid_sig; static int test_get_signature_nid_hash; static int test_get_signature_nid_ssl_ready(WOLFSSL* ssl) { EXPECT_DECLS; ExpectIntEQ(wolfSSL_set_cipher_list(ssl, "ALL"), WOLFSSL_SUCCESS); if (!wolfSSL_is_server(ssl)) { ExpectIntEQ(wolfSSL_set1_sigalgs_list(ssl, test_get_signature_nid_siglag), WOLFSSL_SUCCESS); } return EXPECT_RESULT(); } static int test_get_signature_nid_on_hs_client(WOLFSSL_CTX **ctx, WOLFSSL **ssl) { EXPECT_DECLS; int nid = 0; (void)ctx; if (XSTRSTR(wolfSSL_get_cipher(*ssl), "TLS_RSA_") == NULL) { ExpectIntEQ(SSL_get_peer_signature_type_nid(*ssl, &nid), WOLFSSL_SUCCESS); ExpectIntEQ(nid, test_get_signature_nid_sig); ExpectIntEQ(SSL_get_peer_signature_nid(*ssl, &nid), WOLFSSL_SUCCESS); ExpectIntEQ(nid, test_get_signature_nid_hash); } else /* No sigalg info on static ciphersuite */ return TEST_SUCCESS; return EXPECT_RESULT(); } static int test_get_signature_nid_on_hs_server(WOLFSSL_CTX **ctx, WOLFSSL **ssl) { EXPECT_DECLS; int nid = 0; (void)ctx; ExpectIntEQ(SSL_get_signature_type_nid(*ssl, &nid), WOLFSSL_SUCCESS); ExpectIntEQ(nid, test_get_signature_nid_sig); ExpectIntEQ(SSL_get_signature_nid(*ssl, &nid), WOLFSSL_SUCCESS); ExpectIntEQ(nid, test_get_signature_nid_hash); return EXPECT_RESULT(); } #endif static int test_get_signature_nid(void) { EXPECT_DECLS; #if defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && defined(OPENSSL_EXTRA) test_ssl_cbf client_cbf; test_ssl_cbf server_cbf; size_t i; #define TGSN_TLS12_RSA(sigalg, sig_nid, hash_nid) \ { sigalg, sig_nid, hash_nid, WOLFSSL_TLSV1_2, svrCertFile, svrKeyFile, \ caCertFile } #define TGSN_TLS12_ECDSA(sigalg, sig_nid, hash_nid) \ { sigalg, sig_nid, hash_nid, WOLFSSL_TLSV1_2, eccCertFile, eccKeyFile, \ caEccCertFile } #define TGSN_TLS13_RSA(sigalg, sig_nid, hash_nid) \ { sigalg, sig_nid, hash_nid, WOLFSSL_TLSV1_3, svrCertFile, svrKeyFile, \ caCertFile } #define TGSN_TLS13_ECDSA(sigalg, sig_nid, hash_nid) \ { sigalg, sig_nid, hash_nid, WOLFSSL_TLSV1_3, eccCertFile, eccKeyFile, \ caEccCertFile } #define TGSN_TLS13_ED25519(sigalg, sig_nid, hash_nid) \ { sigalg, sig_nid, hash_nid, WOLFSSL_TLSV1_3, edCertFile, edKeyFile, \ caEdCertFile } #define TGSN_TLS13_ED448(sigalg, sig_nid, hash_nid) \ { sigalg, sig_nid, hash_nid, WOLFSSL_TLSV1_3, ed448CertFile, ed448KeyFile, \ caEd448CertFile } struct { const char* siglag; int sig_nid; int hash_nid; int tls_ver; const char* server_cert; const char* server_key; const char* client_ca; } params[] = { #ifndef NO_RSA #ifndef NO_SHA256 TGSN_TLS12_RSA("RSA+SHA256", NID_rsaEncryption, NID_sha256), #ifdef WC_RSA_PSS TGSN_TLS12_RSA("RSA-PSS+SHA256", NID_rsassaPss, NID_sha256), TGSN_TLS13_RSA("RSA-PSS+SHA256", NID_rsassaPss, NID_sha256), #endif #endif #ifdef WOLFSSL_SHA512 TGSN_TLS12_RSA("RSA+SHA512", NID_rsaEncryption, NID_sha512), #ifdef WC_RSA_PSS TGSN_TLS12_RSA("RSA-PSS+SHA512", NID_rsassaPss, NID_sha512), TGSN_TLS13_RSA("RSA-PSS+SHA512", NID_rsassaPss, NID_sha512), #endif #endif #endif #ifdef HAVE_ECC #ifndef NO_SHA256 TGSN_TLS12_ECDSA("ECDSA+SHA256", NID_X9_62_id_ecPublicKey, NID_sha256), TGSN_TLS13_ECDSA("ECDSA+SHA256", NID_X9_62_id_ecPublicKey, NID_sha256), #endif #endif #ifdef HAVE_ED25519 TGSN_TLS13_ED25519("ED25519", NID_ED25519, NID_sha512), #endif #ifdef HAVE_ED448 TGSN_TLS13_ED448("ED448", NID_ED448, NID_sha512), #endif }; /* These correspond to WOLFSSL_SSLV3...WOLFSSL_DTLSV1_3 */ const char* tls_desc[] = { "SSLv3", "TLSv1.0", "TLSv1.1", "TLSv1.2", "TLSv1.3", "DTLSv1.0", "DTLSv1.2", "DTLSv1.3" }; printf("\n"); for (i = 0; i < XELEM_CNT(params) && !EXPECT_FAIL(); i++) { XMEMSET(&client_cbf, 0, sizeof(client_cbf)); XMEMSET(&server_cbf, 0, sizeof(server_cbf)); printf("Testing %s with %s...", tls_desc[params[i].tls_ver], params[i].siglag); switch (params[i].tls_ver) { #ifndef WOLFSSL_NO_TLS12 case WOLFSSL_TLSV1_2: client_cbf.method = wolfTLSv1_2_client_method; server_cbf.method = wolfTLSv1_2_server_method; break; #endif #ifdef WOLFSSL_TLS13 case WOLFSSL_TLSV1_3: client_cbf.method = wolfTLSv1_3_client_method; server_cbf.method = wolfTLSv1_3_server_method; break; #endif default: printf("skipping\n"); continue; } test_get_signature_nid_siglag = params[i].siglag; test_get_signature_nid_sig = params[i].sig_nid; test_get_signature_nid_hash = params[i].hash_nid; client_cbf.ssl_ready = test_get_signature_nid_ssl_ready; server_cbf.ssl_ready = test_get_signature_nid_ssl_ready; client_cbf.on_handshake = test_get_signature_nid_on_hs_client; server_cbf.on_handshake = test_get_signature_nid_on_hs_server; server_cbf.certPemFile = params[i].server_cert; server_cbf.keyPemFile = params[i].server_key; client_cbf.caPemFile = params[i].client_ca; ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&client_cbf, &server_cbf, NULL), TEST_SUCCESS); if (EXPECT_SUCCESS()) printf("passed\n"); } #endif return EXPECT_RESULT(); } #ifndef WOLFSSL_TEST_APPLE_NATIVE_CERT_VALIDATION #if !defined(NO_CERTS) && defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && \ !defined(NO_SHA256) static word32 test_tls_cert_store_unchanged_HashCaTable(Signer** caTable) { #ifndef NO_MD5 enum wc_HashType hashType = WC_HASH_TYPE_MD5; #elif !defined(NO_SHA) enum wc_HashType hashType = WC_HASH_TYPE_SHA; #elif !defined(NO_SHA256) enum wc_HashType hashType = WC_HASH_TYPE_SHA256; #else #error "We need a digest to hash the Signer object" #endif byte hashBuf[WC_MAX_DIGEST_SIZE]; wc_HashAlg hash; size_t i; AssertIntEQ(wc_HashInit(&hash, hashType), 0); for (i = 0; i < CA_TABLE_SIZE; i++) { Signer* cur; for (cur = caTable[i]; cur != NULL; cur = cur->next) AssertIntEQ(wc_HashUpdate(&hash, hashType, (byte*)cur, sizeof(*cur)), 0); } AssertIntEQ(wc_HashFinal(&hash, hashType, hashBuf), 0); AssertIntEQ(wc_HashFree(&hash, hashType), 0); return MakeWordFromHash(hashBuf); } static word32 test_tls_cert_store_unchanged_before_hashes[2]; static size_t test_tls_cert_store_unchanged_before_hashes_idx; static word32 test_tls_cert_store_unchanged_after_hashes[2]; static size_t test_tls_cert_store_unchanged_after_hashes_idx; static int test_tls_cert_store_unchanged_ctx_ready(WOLFSSL_CTX* ctx) { EXPECT_DECLS; ExpectIntNE(test_tls_cert_store_unchanged_before_hashes [test_tls_cert_store_unchanged_before_hashes_idx++] = test_tls_cert_store_unchanged_HashCaTable(ctx->cm->caTable), 0); wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER | WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0); return EXPECT_RESULT(); } static int test_tls_cert_store_unchanged_ctx_cleanup(WOLFSSL_CTX* ctx) { EXPECT_DECLS; ExpectIntEQ(wolfSSL_CTX_UnloadIntermediateCerts(ctx), WOLFSSL_SUCCESS); ExpectIntNE(test_tls_cert_store_unchanged_after_hashes [test_tls_cert_store_unchanged_after_hashes_idx++] = test_tls_cert_store_unchanged_HashCaTable(ctx->cm->caTable), 0); return EXPECT_RESULT(); } static int test_tls_cert_store_unchanged_on_hs(WOLFSSL_CTX **ctx, WOLFSSL **ssl) { EXPECT_DECLS; WOLFSSL_CERT_MANAGER* cm; (void)ssl; /* WARNING: this approach bypasses the reference counter check in * wolfSSL_CTX_UnloadIntermediateCerts. It is not recommended as it may * cause unexpected behaviour when other active connections try accessing * the caTable. */ ExpectNotNull(cm = wolfSSL_CTX_GetCertManager(*ctx)); ExpectIntEQ(wolfSSL_CertManagerUnloadIntermediateCerts(cm), WOLFSSL_SUCCESS); ExpectIntNE(test_tls_cert_store_unchanged_after_hashes [test_tls_cert_store_unchanged_after_hashes_idx++] = test_tls_cert_store_unchanged_HashCaTable((*ctx)->cm->caTable), 0); return EXPECT_RESULT(); } static int test_tls_cert_store_unchanged_ssl_ready(WOLFSSL* ssl) { EXPECT_DECLS; WOLFSSL_CTX* ctx; ExpectNotNull(ctx = wolfSSL_get_SSL_CTX(ssl)); return EXPECT_RESULT(); } #endif static int test_tls_cert_store_unchanged(void) { EXPECT_DECLS; #if !defined(NO_CERTS) && defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && \ !defined(NO_SHA256) test_ssl_cbf client_cbf; test_ssl_cbf server_cbf; int i; for (i = 0; i < 2; i++) { XMEMSET(&client_cbf, 0, sizeof(client_cbf)); XMEMSET(&server_cbf, 0, sizeof(server_cbf)); test_tls_cert_store_unchanged_before_hashes_idx = 0; XMEMSET(test_tls_cert_store_unchanged_before_hashes, 0, sizeof(test_tls_cert_store_unchanged_before_hashes)); test_tls_cert_store_unchanged_after_hashes_idx = 0; XMEMSET(test_tls_cert_store_unchanged_after_hashes, 0, sizeof(test_tls_cert_store_unchanged_after_hashes)); client_cbf.ctx_ready = test_tls_cert_store_unchanged_ctx_ready; server_cbf.ctx_ready = test_tls_cert_store_unchanged_ctx_ready; client_cbf.ssl_ready = test_tls_cert_store_unchanged_ssl_ready; server_cbf.ssl_ready = test_tls_cert_store_unchanged_ssl_ready; switch (i) { case 0: client_cbf.on_ctx_cleanup = test_tls_cert_store_unchanged_ctx_cleanup; server_cbf.on_ctx_cleanup = test_tls_cert_store_unchanged_ctx_cleanup; break; case 1: client_cbf.on_handshake = test_tls_cert_store_unchanged_on_hs; server_cbf.on_handshake = test_tls_cert_store_unchanged_on_hs; break; default: Fail(("Should not enter here"), ("Entered here")); } #ifdef WOLFSSL_PEM_TO_DER client_cbf.certPemFile = "certs/intermediate/client-chain.pem"; server_cbf.certPemFile = "certs/intermediate/server-chain.pem"; #else client_cbf.certPemFile = "certs/intermediate/client-chain.der"; server_cbf.certPemFile = "certs/intermediate/server-chain.der"; #endif server_cbf.caPemFile = caCertFile; ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&client_cbf, &server_cbf, NULL), TEST_SUCCESS); ExpectBufEQ(test_tls_cert_store_unchanged_before_hashes, test_tls_cert_store_unchanged_after_hashes, sizeof(test_tls_cert_store_unchanged_after_hashes)); } #endif return EXPECT_RESULT(); } #endif /* !WOLFSSL_TEST_APPLE_NATIVE_CERT_VALIDATION */ static int test_wolfSSL_SendUserCanceled(void) { EXPECT_DECLS; #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) size_t i; struct { method_provider client_meth; method_provider server_meth; const char* tls_version; } params[] = { #if defined(WOLFSSL_TLS13) /* With WOLFSSL_TLS13_MIDDLEBOX_COMPAT a short ID will result in an error */ { wolfTLSv1_3_client_method, wolfTLSv1_3_server_method, "TLSv1_3" }, #ifdef WOLFSSL_DTLS13 { wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method, "DTLSv1_3" }, #endif #endif #ifndef WOLFSSL_NO_TLS12 { wolfTLSv1_2_client_method, wolfTLSv1_2_server_method, "TLSv1_2" }, #ifdef WOLFSSL_DTLS { wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method, "DTLSv1_2" }, #endif #endif #if !defined(NO_OLD_TLS) { wolfTLSv1_1_client_method, wolfTLSv1_1_server_method, "TLSv1_1" }, #ifdef WOLFSSL_DTLS { wolfDTLSv1_client_method, wolfDTLSv1_server_method, "DTLSv1_0" }, #endif #endif }; for (i = 0; i < sizeof(params)/sizeof(*params) && !EXPECT_FAIL(); i++) { WOLFSSL_CTX *ctx_c = NULL; WOLFSSL_CTX *ctx_s = NULL; WOLFSSL *ssl_c = NULL; WOLFSSL *ssl_s = NULL; struct test_memio_ctx test_ctx; WOLFSSL_ALERT_HISTORY h; printf("Testing %s\n", params[i].tls_version); XMEMSET(&h, 0, sizeof(h)); XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, params[i].client_meth, params[i].server_meth), 0); /* CH1 */ ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); ExpectIntEQ(wolfSSL_SendUserCanceled(ssl_s), WOLFSSL_SHUTDOWN_NOT_DONE); /* Alert closed connection */ ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_ZERO_RETURN); /* Last alert will be close notify because user_canceled should be * followed by a close_notify */ ExpectIntEQ(wolfSSL_get_alert_history(ssl_c, &h), WOLFSSL_SUCCESS); ExpectIntEQ(h.last_rx.code, close_notify); ExpectIntEQ(h.last_rx.level, alert_warning); wolfSSL_free(ssl_c); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_c); wolfSSL_CTX_free(ctx_s); } #endif return EXPECT_RESULT(); } #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \ defined(HAVE_OCSP) && \ defined(HAVE_CERTIFICATE_STATUS_REQUEST) && \ !defined(WOLFSSL_NO_TLS12) static int test_ocsp_callback_fails_cb(void* ctx, const char* url, int urlSz, byte* ocspReqBuf, int ocspReqSz, byte** ocspRespBuf) { (void)ctx; (void)url; (void)urlSz; (void)ocspReqBuf; (void)ocspReqSz; (void)ocspRespBuf; return WOLFSSL_CBIO_ERR_GENERAL; } static int test_ocsp_callback_fails(void) { WOLFSSL_CTX *ctx_c = NULL; WOLFSSL_CTX *ctx_s = NULL; WOLFSSL *ssl_c = NULL; WOLFSSL *ssl_s = NULL; struct test_memio_ctx test_ctx; EXPECT_DECLS; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, wolfTLSv1_2_client_method, wolfTLSv1_2_server_method), 0); ExpectIntEQ(wolfSSL_CTX_EnableOCSPStapling(ctx_c), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_EnableOCSPStapling(ctx_s), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_UseOCSPStapling(ssl_c, WOLFSSL_CSR_OCSP,0), WOLFSSL_SUCCESS); /* override URL to avoid exing from SendCertificateStatus because of no AuthInfo on the certificate */ ExpectIntEQ(wolfSSL_CTX_SetOCSP_OverrideURL(ctx_s, "http://dummy.test"), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_EnableOCSP(ctx_s, WOLFSSL_OCSP_NO_NONCE | WOLFSSL_OCSP_URL_OVERRIDE), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx_s, caCertFile, 0), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_SetOCSP_Cb(ssl_s, test_ocsp_callback_fails_cb, NULL, NULL), WOLFSSL_SUCCESS); ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), -1); ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WC_NO_ERR_TRACE(OCSP_INVALID_STATUS)); wolfSSL_free(ssl_c); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_c); wolfSSL_CTX_free(ctx_s); return EXPECT_RESULT(); } #else static int test_ocsp_callback_fails(void) { return TEST_SKIPPED; } #endif /* defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \ defined(HAVE_OCSP) && \ defined(HAVE_CERTIFICATE_STATUS_REQUEST) */ #ifdef HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES static int test_wolfSSL_SSLDisableRead_recv(WOLFSSL *ssl, char *buf, int sz, void *ctx) { (void)ssl; (void)buf; (void)sz; (void)ctx; return WOLFSSL_CBIO_ERR_GENERAL; } static int test_wolfSSL_SSLDisableRead(void) { EXPECT_DECLS; WOLFSSL_CTX *ctx_c = NULL; WOLFSSL *ssl_c = NULL; struct test_memio_ctx test_ctx; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, NULL, &ssl_c, NULL, wolfTLS_client_method, NULL), 0); wolfSSL_SSLSetIORecv(ssl_c, test_wolfSSL_SSLDisableRead_recv); wolfSSL_SSLDisableRead(ssl_c); /* Disabling reading should not even go into the IO layer */ ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); wolfSSL_SSLEnableRead(ssl_c); /* By enabling reading we should reach the IO that will return an error */ ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), SOCKET_ERROR_E); wolfSSL_free(ssl_c); wolfSSL_CTX_free(ctx_c); return EXPECT_RESULT(); } #else static int test_wolfSSL_SSLDisableRead(void) { EXPECT_DECLS; return EXPECT_RESULT(); } #endif static int test_wolfSSL_inject(void) { EXPECT_DECLS; #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && !defined(NO_SHA256) size_t i; struct { method_provider client_meth; method_provider server_meth; const char* tls_version; } params[] = { #if defined(WOLFSSL_TLS13) /* With WOLFSSL_TLS13_MIDDLEBOX_COMPAT a short ID will result in an error */ { wolfTLSv1_3_client_method, wolfTLSv1_3_server_method, "TLSv1_3" }, #ifdef WOLFSSL_DTLS13 { wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method, "DTLSv1_3" }, #endif #endif #ifndef WOLFSSL_NO_TLS12 { wolfTLSv1_2_client_method, wolfTLSv1_2_server_method, "TLSv1_2" }, #ifdef WOLFSSL_DTLS { wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method, "DTLSv1_2" }, #endif #endif #if !defined(NO_OLD_TLS) { wolfTLSv1_1_client_method, wolfTLSv1_1_server_method, "TLSv1_1" }, #ifdef WOLFSSL_DTLS { wolfDTLSv1_client_method, wolfDTLSv1_server_method, "DTLSv1_0" }, #endif #endif }; for (i = 0; i < XELEM_CNT(params) && !EXPECT_FAIL(); i++) { WOLFSSL_CTX *ctx_c = NULL; WOLFSSL_CTX *ctx_s = NULL; WOLFSSL *ssl_c = NULL; WOLFSSL *ssl_s = NULL; struct test_memio_ctx test_ctx; WOLFSSL_ALERT_HISTORY h; int rounds; int hs_c = 0; int hs_s = 0; printf("Testing %s\n", params[i].tls_version); XMEMSET(&h, 0, sizeof(h)); XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, params[i].client_meth, params[i].server_meth), 0); for (rounds = 0; rounds < 10 && EXPECT_SUCCESS(); rounds++) { if (!hs_c) { wolfSSL_SetLoggingPrefix("client"); if (wolfSSL_negotiate(ssl_c) != 1) { ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); } else hs_c = 1; } if (!hs_s) { wolfSSL_SetLoggingPrefix("server"); if (test_ctx.s_len > 0) { ExpectIntEQ(wolfSSL_inject(ssl_s, test_ctx.s_buff, test_ctx.s_len), 1); test_memio_clear_buffer(&test_ctx, 0); } if (wolfSSL_negotiate(ssl_s) != 1) { ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ); } else hs_s = 1; } if (!hs_c) { wolfSSL_SetLoggingPrefix("client"); if (test_ctx.c_len > 0) { ExpectIntEQ(wolfSSL_inject(ssl_c, test_ctx.c_buff, test_ctx.c_len), 1); test_memio_clear_buffer(&test_ctx, 1); } } wolfSSL_SetLoggingPrefix(NULL); } ExpectIntEQ(hs_c, 1); ExpectIntEQ(hs_s, 1); wolfSSL_free(ssl_c); wolfSSL_free(ssl_s); wolfSSL_CTX_free(ctx_c); wolfSSL_CTX_free(ctx_s); } #endif return EXPECT_RESULT(); } /*----------------------------------------------------------------------------* | Main *----------------------------------------------------------------------------*/ int testAll = 1; int stopOnFail = 0; /*----------------------------------------------------------------------------*/ /* LMS tests */ /*----------------------------------------------------------------------------*/ int test_wc_LmsKey_sign_verify(void); int test_wc_LmsKey_reload_cache(void); int test_rfc9802_lms_x509_verify(void); int test_rfc9802_xmss_x509_verify(void); #if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY) #include #define LMS_TEST_PRIV_KEY_FILE "/tmp/wolfssl_test_lms.key" static int test_lms_write_key(const byte* priv, word32 privSz, void* context) { FILE* f = fopen((const char*)context, "wb"); int ret = WC_LMS_RC_SAVED_TO_NV_MEMORY; if (f == NULL) return -1; if (fwrite(priv, 1, privSz, f) != privSz) ret = -1; fclose(f); return ret; } static int test_lms_read_key(byte* priv, word32 privSz, void* context) { FILE* f = fopen((const char*)context, "rb"); if (f == NULL) return -1; if (fread(priv, 1, privSz, f) == 0) { fclose(f); return -1; } fclose(f); return WC_LMS_RC_READ_TO_MEMORY; } /* Helper: init an LMS key with callbacks and L1-H10-W8 params */ static int test_lms_init_key(LmsKey* key, WC_RNG* rng) { int ret; ret = wc_LmsKey_Init(key, NULL, INVALID_DEVID); if (ret != 0) return ret; #if !defined(WOLFSSL_LMS_MAX_HEIGHT) || (WOLFSSL_LMS_MAX_HEIGHT >= 10) ret = wc_LmsKey_SetParameters(key, 1, 10, 8); #else ret = wc_LmsKey_SetParameters(key, 1, 5, 8); #endif if (ret != 0) return ret; ret = wc_LmsKey_SetWriteCb(key, test_lms_write_key); if (ret != 0) return ret; ret = wc_LmsKey_SetReadCb(key, test_lms_read_key); if (ret != 0) return ret; ret = wc_LmsKey_SetContext(key, (void*)LMS_TEST_PRIV_KEY_FILE); if (ret != 0) return ret; (void)rng; return 0; } #endif /* WOLFSSL_HAVE_LMS && !WOLFSSL_LMS_VERIFY_ONLY */ /* * Test basic LMS sign/verify with multiple signings. * Uses L1-H10-W8 (1024 total signatures, 32-entry leaf cache). */ int test_wc_LmsKey_sign_verify(void) { EXPECT_DECLS; #if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY) LmsKey key; WC_RNG rng; byte msg[] = "test message for LMS signing"; byte sig[2048]; word32 sigSz; int i; int numSigs = 5; ExpectIntEQ(wc_InitRng(&rng), 0); remove(LMS_TEST_PRIV_KEY_FILE); ExpectIntEQ(test_lms_init_key(&key, &rng), 0); ExpectIntEQ(wc_LmsKey_MakeKey(&key, &rng), 0); for (i = 0; i < numSigs; i++) { sigSz = sizeof(sig); ExpectIntEQ(wc_LmsKey_Sign(&key, sig, &sigSz, msg, sizeof(msg)), 0); ExpectIntEQ(wc_LmsKey_Verify(&key, sig, sigSz, msg, sizeof(msg)), 0); } wc_LmsKey_Free(&key); wc_FreeRng(&rng); remove(LMS_TEST_PRIV_KEY_FILE); #endif return EXPECT_RESULT(); } /* * Test LMS key reload after advancing past the leaf cache window. * * Reproduces a heap-buffer-overflow bug in wc_lms_treehash_init() where the * leaf cache write uses (i * hash_len) instead of ((i - leaf->idx) * hash_len). * When q > max_cb (default 32), wc_LmsKey_Reload calls wc_hss_init_auth_path * which calls wc_lms_treehash_init with q > 0, causing writes past the end of * the leaf cache buffer. * * Reproduction steps: * 1. Generate L1-H10-W8 key (cacheBits=5, max_cb=32) * 2. Sign 33 times to advance q past the cache window * 3. Free the key and reload from persisted state * 4. Sign and verify after reload * * Without the fix: heap-buffer-overflow at wc_lms_impl.c:1965 * With the fix: all operations succeed, signatures verify */ int test_wc_LmsKey_reload_cache(void) { EXPECT_DECLS; #if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY) && \ (!defined(WOLFSSL_LMS_MAX_HEIGHT) || (WOLFSSL_LMS_MAX_HEIGHT >= 10)) LmsKey key; LmsKey vkey; WC_RNG rng; byte msg[] = "test message for LMS signing"; byte sig[2048]; word32 sigSz; byte pub[64]; word32 pubSz = sizeof(pub); int i; /* Sign 33 times to advance q past the 32-entry cache window. */ int preSigs = 33; ExpectIntEQ(wc_InitRng(&rng), 0); /* Phase 1: Generate key and sign past cache window */ remove(LMS_TEST_PRIV_KEY_FILE); ExpectIntEQ(test_lms_init_key(&key, &rng), 0); ExpectIntEQ(wc_LmsKey_MakeKey(&key, &rng), 0); for (i = 0; i < preSigs; i++) { sigSz = sizeof(sig); ExpectIntEQ(wc_LmsKey_Sign(&key, sig, &sigSz, msg, sizeof(msg)), 0); } /* Save public key for verification after reload */ ExpectIntEQ(wc_LmsKey_ExportPubRaw(&key, pub, &pubSz), 0); wc_LmsKey_Free(&key); /* Phase 2: Reload key. Triggers wc_lms_treehash_init with q=33 */ ExpectIntEQ(test_lms_init_key(&key, &rng), 0); ExpectIntEQ(wc_LmsKey_Reload(&key), 0); /* Phase 3: Sign after reload and verify with separate verify-only key */ sigSz = sizeof(sig); ExpectIntEQ(wc_LmsKey_Sign(&key, sig, &sigSz, msg, sizeof(msg)), 0); ExpectIntEQ(wc_LmsKey_Init(&vkey, NULL, INVALID_DEVID), 0); #if !defined(WOLFSSL_LMS_MAX_HEIGHT) || (WOLFSSL_LMS_MAX_HEIGHT >= 10) ExpectIntEQ(wc_LmsKey_SetParameters(&vkey, 1, 10, 8), 0); #else ExpectIntEQ(wc_LmsKey_SetParameters(&vkey, 1, 5, 8), 0); #endif ExpectIntEQ(wc_LmsKey_ImportPubRaw(&vkey, pub, pubSz), 0); ExpectIntEQ(wc_LmsKey_Verify(&vkey, sig, sigSz, msg, sizeof(msg)), 0); wc_LmsKey_Free(&vkey); wc_LmsKey_Free(&key); wc_FreeRng(&rng); remove(LMS_TEST_PRIV_KEY_FILE); #endif return EXPECT_RESULT(); } /*----------------------------------------------------------------------------*/ /* RFC 9802 (HSS/LMS and XMSS/XMSS^MT in X.509) tests */ /*----------------------------------------------------------------------------*/ /* For every committed self-signed test certificate confirm: * - wc_ParseCert succeeds on the RFC 9802 AlgorithmIdentifier encoding * (OID-only SEQUENCE, no NULL parameters) * - keyOID and signatureOID are set to the expected values * - loading as a trust anchor and verifying the same bytes through * wolfSSL_CertManagerVerifyBuffer exercises the ConfirmSignature * path and succeeds on a valid cert * - flipping a byte in the signature AND flipping a byte in the * TBSCertificate both cause verification to fail. * * Test vectors are in certs/lms/ and certs/xmss/, generated with Bouncy * Castle 1.81. BC's default XMSS / XMSS^MT X.509 encoding uses pre- * standard ISARA OIDs and wraps the raw RFC 8391 pub key in an OCTET * STRING, so the fixtures were produced with a small generator that * overrides the AlgorithmIdentifier and SPKI to match RFC 9802. */ #if (defined(WOLFSSL_HAVE_LMS) || defined(WOLFSSL_HAVE_XMSS)) && \ !defined(NO_FILESYSTEM) && !defined(NO_CERTS) /* Sanity bound on a test fixture cert. The largest BC-generated * fixture we ship (XMSS^MT 40/8) is ~19 KiB; 1 MiB is well above * any realistic RFC 9802 cert and catches a wild XFTELL. Typed as * long to match XFTELL's return so the size comparison below isn't * a mixed long-vs-int compare. */ #define RFC9802_TEST_MAX_CERT_SIZE ((long)(1L << 20)) /* Load a whole file into a freshly-allocated buffer. Caller frees. */ static int rfc9802_load_file(const char* path, byte** out, int* outLen) { EXPECT_DECLS; XFILE f = XBADFILE; long sz = 0; size_t got = 0; byte* buf = NULL; *out = NULL; *outLen = 0; ExpectTrue((f = XFOPEN(path, "rb")) != XBADFILE); if (f == XBADFILE) return TEST_FAIL; if (XFSEEK(f, 0, XSEEK_END) == 0) sz = XFTELL(f); (void)XFSEEK(f, 0, XSEEK_SET); ExpectIntGT(sz, 0); ExpectIntLT(sz, RFC9802_TEST_MAX_CERT_SIZE); /* Hard-fail before XMALLOC if XFSEEK / XFTELL produced an unusable * size: ExpectInt* records the failure but doesn't short-circuit, * so without this guard a -1 from XFTELL would cast to a multi-GiB * (size_t) allocation, and a 0 would request a zero-byte malloc. */ if (sz <= 0 || sz >= RFC9802_TEST_MAX_CERT_SIZE) { XFCLOSE(f); return TEST_FAIL; } ExpectNotNull(buf = (byte*)XMALLOC((size_t)sz, NULL, DYNAMIC_TYPE_TMP_BUFFER)); if (buf != NULL) { got = XFREAD(buf, 1, (size_t)sz, f); ExpectIntEQ(got, (size_t)sz); /* On a short read the caller would otherwise proceed with a * partially-initialized buffer and produce cascading parse * failures driven by the uninitialized tail. Free here so the * caller's `if (buf == NULL) return TEST_FAIL;` short-circuits * cleanly with a single recorded failure. */ if (got != (size_t)sz) { XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); buf = NULL; sz = 0; } } XFCLOSE(f); *out = buf; *outLen = (int)sz; return EXPECT_RESULT(); } static int rfc9802_verify_one_cert(const char* path, word32 expectedKeyOID, word32 expectedSigOID) { EXPECT_DECLS; byte* buf = NULL; byte* tampered = NULL; int bytes = 0; DecodedCert cert; WOLFSSL_CERT_MANAGER* cm = NULL; word32 certBegin = 0; word32 sigIndex = 0; ExpectIntEQ(rfc9802_load_file(path, &buf, &bytes), TEST_SUCCESS); if (buf == NULL) return TEST_FAIL; /* Parse + check OIDs, capture certBegin and sigIndex for later tamper. */ wc_InitDecodedCert(&cert, buf, (word32)bytes, NULL); ExpectIntEQ(wc_ParseCert(&cert, CERT_TYPE, NO_VERIFY, NULL), 0); ExpectIntEQ((int)cert.keyOID, (int)expectedKeyOID); ExpectIntEQ((int)cert.signatureOID, (int)expectedSigOID); certBegin = cert.certBegin; sigIndex = cert.sigIndex; wc_FreeDecodedCert(&cert); /* Full verify against a self-installed trust anchor. */ ExpectNotNull(cm = wolfSSL_CertManagerNew()); ExpectIntEQ(wolfSSL_CertManagerLoadCABuffer(cm, buf, (long)bytes, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CertManagerVerifyBuffer(cm, buf, (long)bytes, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); if (cm != NULL) { wolfSSL_CertManagerFree(cm); cm = NULL; } ExpectNotNull(tampered = (byte*)XMALLOC((size_t)bytes, NULL, DYNAMIC_TYPE_TMP_BUFFER)); /* Negative 1: flip a byte inside the signatureValue BIT STRING. * Everything after sigIndex is the signatureAlgorithm + the BIT * STRING payload, so flipping the last byte is always inside the * signature content. */ if (tampered != NULL) { XMEMCPY(tampered, buf, (size_t)bytes); tampered[bytes - 1] ^= 0x01; ExpectNotNull(cm = wolfSSL_CertManagerNew()); ExpectIntEQ(wolfSSL_CertManagerLoadCABuffer(cm, buf, (long)bytes, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); ExpectIntNE(wolfSSL_CertManagerVerifyBuffer(cm, tampered, (long)bytes, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); if (cm != NULL) { wolfSSL_CertManagerFree(cm); cm = NULL; } } /* Negative 2: flip a byte at the midpoint of the TBSCertificate. The * TBS is the first element of the outer Certificate SEQUENCE and * its bytes lie between (certBegin + outerSeqHeader) and sigIndex. * Picking the midpoint ensures we're inside TBS regardless of the * fixture's DN / extensions layout. */ if (tampered != NULL && sigIndex > certBegin + 8U) { word32 midTbs = certBegin + 8 + ((sigIndex - (certBegin + 8)) / 2); XMEMCPY(tampered, buf, (size_t)bytes); tampered[midTbs] ^= 0x01; ExpectNotNull(cm = wolfSSL_CertManagerNew()); ExpectIntEQ(wolfSSL_CertManagerLoadCABuffer(cm, buf, (long)bytes, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); ExpectIntNE(wolfSSL_CertManagerVerifyBuffer(cm, tampered, (long)bytes, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); if (cm != NULL) { wolfSSL_CertManagerFree(cm); cm = NULL; } } /* The fixtures MUST carry a KeyUsage extension with at least one of * digitalSignature / nonRepudiation / keyCertSign / cRLSign set per * RFC 9802 sec 3. Re-parse and assert that wolfSSL recorded a non- * empty set of KeyUsage bits from one of those values. */ wc_InitDecodedCert(&cert, buf, (word32)bytes, NULL); ExpectIntEQ(wc_ParseCert(&cert, CERT_TYPE, NO_VERIFY, NULL), 0); ExpectIntEQ(cert.extKeyUsageSet, 1); ExpectIntNE(cert.extKeyUsage & (KEYUSE_DIGITAL_SIG | KEYUSE_CONTENT_COMMIT | KEYUSE_KEY_CERT_SIGN | KEYUSE_CRL_SIGN), 0); wc_FreeDecodedCert(&cert); XFREE(tampered, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); return EXPECT_RESULT(); } #endif /* Direct wolfCrypt-level negative tests for the parameter-derivation * helpers used by the RFC 9802 parse path. These exercise failure modes * (unknown algorithm bytes, truncated inputs, mismatches) that a real * cert body wouldn't easily reach. */ #if defined(WOLFSSL_HAVE_LMS) static int rfc9802_lms_import_negative(void) { EXPECT_DECLS; LmsKey key; /* 60-byte buffer matches HSS_PUBLIC_KEY_LEN(32), just like a valid * SHA-256/M32/H5 key; the algorithm-type bytes are junk so param * derivation must fail cleanly. */ byte junk[60]; XMEMSET(junk, 0, sizeof(junk)); /* levels=1, lmsType=0xFFFFFFFF, lmOtsType=0xFFFFFFFF. */ junk[3] = 1; XMEMSET(junk + 4, 0xFF, 4); XMEMSET(junk + 8, 0xFF, 4); /* Unknown algorithm types must be rejected. */ ExpectIntEQ(wc_LmsKey_Init(&key, NULL, INVALID_DEVID), 0); ExpectIntEQ(wc_LmsKey_ImportPubRaw(&key, junk, sizeof(junk)), WC_NO_ERR_TRACE(NOT_COMPILED_IN)); wc_LmsKey_Free(&key); /* Too-short buffer: only L + lmsType, no lmOtsType. */ ExpectIntEQ(wc_LmsKey_Init(&key, NULL, INVALID_DEVID), 0); ExpectIntEQ(wc_LmsKey_ImportPubRaw(&key, junk, 8), WC_NO_ERR_TRACE(BUFFER_E)); wc_LmsKey_Free(&key); #if !defined(WOLFSSL_NO_LMS_SHA256_256) /* The two cases below pin specific SHA-256/M32 parameter codes * (L1_H5_W8, L1_H5_W4, L1_H10_W2). Skip them in builds where the * SHA-256/M32 family is disabled -- the family-agnostic checks * above (junk algorithm types, too-short buffer, GetSigLen on * unconfigured key) still cover the universal invariants. */ /* Pre-set params that disagree with the raw key's algorithm bytes: * configure H=5/W=8 but feed buffer that claims H=10 / W=2. */ XMEMSET(junk, 0, sizeof(junk)); junk[3] = 1; /* levels=1 */ junk[7] = 6; /* lmsType = LMS_SHA256_M32_H10 = 6 */ junk[11] = 2; /* lmOtsType = LMOTS_SHA256_N32_W2 = 2 */ ExpectIntEQ(wc_LmsKey_Init(&key, NULL, INVALID_DEVID), 0); ExpectIntEQ(wc_LmsKey_SetParameters(&key, 1, 5, 8), 0); ExpectIntEQ(wc_LmsKey_ImportPubRaw(&key, junk, sizeof(junk)), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); wc_LmsKey_Free(&key); #endif /* !WOLFSSL_NO_LMS_SHA256_256 */ /* GetSigLen on a key with no params set must not NULL-deref the * params pointer; it must return BAD_FUNC_ARG instead. */ { word32 sigLen = 0; ExpectIntEQ(wc_LmsKey_Init(&key, NULL, INVALID_DEVID), 0); ExpectIntEQ(wc_LmsKey_GetSigLen(&key, &sigLen), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); wc_LmsKey_Free(&key); } #if !defined(WOLFSSL_NO_LMS_SHA256_256) /* Partial-write invariant: a length mismatch after a successful * auto-derive must leave key->params NULL. Build a buffer whose * leading u32str(L) || lmsType || lmOtsType identifies a known * parameter set, but truncate to one byte less than the real pub * key length so the post-derive length check fails. */ { byte truncated[59]; /* HSS_PUBLIC_KEY_LEN(32) is 60 */ XMEMSET(truncated, 0, sizeof(truncated)); truncated[3] = 1; /* L = 1 */ truncated[7] = 5; /* lmsType = LMS_SHA256_M32_H5 */ truncated[11] = 4; /* lmOtsType = LMOTS_SHA256_N32_W4 */ ExpectIntEQ(wc_LmsKey_Init(&key, NULL, INVALID_DEVID), 0); ExpectNull(key.params); ExpectIntEQ(wc_LmsKey_ImportPubRaw(&key, truncated, sizeof(truncated)), WC_NO_ERR_TRACE(BUFFER_E)); ExpectNull(key.params); wc_LmsKey_Free(&key); } #endif /* !WOLFSSL_NO_LMS_SHA256_256 */ return EXPECT_RESULT(); } #endif #if defined(WOLFSSL_HAVE_XMSS) static int rfc9802_xmss_import_negative(void) { EXPECT_DECLS; XmssKey key; byte junk[8]; XMEMSET(junk, 0, sizeof(junk)); /* Too-short buffer. */ ExpectIntEQ(wc_XmssKey_Init(&key, NULL, INVALID_DEVID), 0); ExpectIntEQ(wc_XmssKey_ImportPubRaw_ex(&key, junk, 2, 0), WC_NO_ERR_TRACE(BUFFER_E)); wc_XmssKey_Free(&key); /* Unknown OID (all-zero) for both XMSS and XMSS^MT. */ ExpectIntEQ(wc_XmssKey_Init(&key, NULL, INVALID_DEVID), 0); ExpectIntEQ(wc_XmssKey_ImportPubRaw_ex(&key, junk, sizeof(junk), 0), WC_NO_ERR_TRACE(NOT_COMPILED_IN)); wc_XmssKey_Free(&key); ExpectIntEQ(wc_XmssKey_Init(&key, NULL, INVALID_DEVID), 0); ExpectIntEQ(wc_XmssKey_ImportPubRaw_ex(&key, junk, sizeof(junk), 1), WC_NO_ERR_TRACE(NOT_COMPILED_IN)); wc_XmssKey_Free(&key); /* NULL key / input. */ ExpectIntEQ(wc_XmssKey_ImportPubRaw_ex(NULL, junk, sizeof(junk), 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wc_XmssKey_Init(&key, NULL, INVALID_DEVID), 0); ExpectIntEQ(wc_XmssKey_ImportPubRaw_ex(&key, NULL, 8, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); wc_XmssKey_Free(&key); /* GetSigLen on a key with no params set must not NULL-deref the * params pointer; it must return BAD_FUNC_ARG instead. */ { word32 sigLen = 0; ExpectIntEQ(wc_XmssKey_Init(&key, NULL, INVALID_DEVID), 0); ExpectIntEQ(wc_XmssKey_GetSigLen(&key, &sigLen), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); wc_XmssKey_Free(&key); } /* Once params have been configured (state != INITED), the OID * prefix in the raw key MUST match key->oid and is_xmssmt MUST * match key->is_xmssmt. Set XMSS-SHA2_10_256 and feed a valid- * sized buffer whose 4-byte OID prefix is bogus -> BAD_FUNC_ARG. */ { byte mismatch[XMSS_SHA256_PUBLEN]; ExpectIntEQ(wc_XmssKey_Init(&key, NULL, INVALID_DEVID), 0); ExpectIntEQ(wc_XmssKey_SetParamStr(&key, "XMSS-SHA2_10_256"), 0); XMEMSET(mismatch, 0, sizeof(mismatch)); mismatch[3] = 0x77; /* nonsense OID */ ExpectIntEQ(wc_XmssKey_ImportPubRaw_ex(&key, mismatch, sizeof(mismatch), 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); /* Same buffer with the correct OID, but is_xmssmt hint * contradicts the configured family -> BAD_FUNC_ARG. */ mismatch[3] = 0x01; /* WC_XMSS_OID_SHA2_10_256 */ ExpectIntEQ(wc_XmssKey_ImportPubRaw_ex(&key, mismatch, sizeof(mismatch), 1), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); wc_XmssKey_Free(&key); } /* Partial-write invariant: a length mismatch after a successful * auto-derive must leave the key in its INITED state, with * key->params NULL. */ { byte truncated[XMSS_SHA256_PUBLEN - 1]; XMEMSET(truncated, 0, sizeof(truncated)); truncated[3] = 0x01; ExpectIntEQ(wc_XmssKey_Init(&key, NULL, INVALID_DEVID), 0); ExpectNull(key.params); ExpectIntEQ(wc_XmssKey_ImportPubRaw_ex(&key, truncated, sizeof(truncated), 0), WC_NO_ERR_TRACE(BUFFER_E)); ExpectNull(key.params); wc_XmssKey_Free(&key); } /* is_xmssmt disambiguation: XMSS oid=1 and XMSS^MT oid=1 share * the wire-numeric value but resolve to different parameter sets. * Importing the same 68-byte buffer with hint=0 vs hint=1 must * land in different tables and produce distinct is_xmssmt. */ { byte buf[XMSS_SHA256_PUBLEN]; XMEMSET(buf, 0, sizeof(buf)); buf[3] = 0x01; ExpectIntEQ(wc_XmssKey_Init(&key, NULL, INVALID_DEVID), 0); ExpectIntEQ(wc_XmssKey_ImportPubRaw_ex(&key, buf, sizeof(buf), 0), 0); ExpectIntEQ((int)key.is_xmssmt, 0); wc_XmssKey_Free(&key); ExpectIntEQ(wc_XmssKey_Init(&key, NULL, INVALID_DEVID), 0); ExpectIntEQ(wc_XmssKey_ImportPubRaw_ex(&key, buf, sizeof(buf), 1), 0); ExpectIntEQ((int)key.is_xmssmt, 1); wc_XmssKey_Free(&key); } /* Lenient state: re-importing the same pub key into a VERIFYONLY * key (params set, no private material) succeeds. The second * call exercises the lenient-state branch. */ { byte buf[XMSS_SHA256_PUBLEN]; XMEMSET(buf, 0, sizeof(buf)); buf[3] = 0x01; ExpectIntEQ(wc_XmssKey_Init(&key, NULL, INVALID_DEVID), 0); ExpectIntEQ(wc_XmssKey_ImportPubRaw_ex(&key, buf, sizeof(buf), 0), 0); ExpectIntEQ((int)key.state, (int)WC_XMSS_STATE_VERIFYONLY); ExpectIntEQ(wc_XmssKey_ImportPubRaw_ex(&key, buf, sizeof(buf), 0), 0); ExpectIntEQ((int)key.state, (int)WC_XMSS_STATE_VERIFYONLY); wc_XmssKey_Free(&key); } /* Strict signature-length check: wc_XmssKey_Verify rejects any * sigLen != key->params->sig_len. This guards every consumer * (RFC 9802 X.509, PKCS#7, CMS, ...) against a longer wrapper that * happens to start with a valid signature. Construct a key in * VERIFYONLY state, then verify with sig_len + 1 and sig_len - 1 * byte buffers; both must fail with BUFFER_E before any crypto * runs. The buffer contents are irrelevant since the length check * fires first. */ { byte pub[XMSS_SHA256_PUBLEN]; byte* sigBuf = NULL; word32 sigLen = 0; const byte msg[1] = { 0 }; XMEMSET(pub, 0, sizeof(pub)); pub[3] = 0x01; ExpectIntEQ(wc_XmssKey_Init(&key, NULL, INVALID_DEVID), 0); ExpectIntEQ(wc_XmssKey_ImportPubRaw_ex(&key, pub, sizeof(pub), 0), 0); ExpectIntEQ((int)key.state, (int)WC_XMSS_STATE_VERIFYONLY); ExpectIntEQ(wc_XmssKey_GetSigLen(&key, &sigLen), 0); ExpectIntGT(sigLen, 0); ExpectNotNull(sigBuf = (byte*)XMALLOC((size_t)sigLen + 1, NULL, DYNAMIC_TYPE_TMP_BUFFER)); if (sigBuf != NULL) { XMEMSET(sigBuf, 0, (size_t)sigLen + 1); ExpectIntEQ(wc_XmssKey_Verify(&key, sigBuf, sigLen + 1, msg, (int)sizeof(msg)), WC_NO_ERR_TRACE(BUFFER_E)); ExpectIntEQ(wc_XmssKey_Verify(&key, sigBuf, sigLen - 1, msg, (int)sizeof(msg)), WC_NO_ERR_TRACE(BUFFER_E)); XFREE(sigBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); } wc_XmssKey_Free(&key); } /* BAD_STATE_E branch: WC_XMSS_STATE_OK must be rejected. Reaching * OK normally requires a successful private-key Reload / sign, * which is unavailable in WOLFSSL_XMSS_VERIFY_ONLY builds. Force * the state directly to exercise the rejection without coupling * this helper to the signing test fixture; sk stays NULL so Free * is still safe. */ { byte pub[XMSS_SHA256_PUBLEN]; XMEMSET(pub, 0, sizeof(pub)); pub[3] = 0x01; ExpectIntEQ(wc_XmssKey_Init(&key, NULL, INVALID_DEVID), 0); ExpectIntEQ(wc_XmssKey_SetParamStr(&key, "XMSS-SHA2_10_256"), 0); key.state = WC_XMSS_STATE_OK; ExpectIntEQ(wc_XmssKey_ImportPubRaw_ex(&key, pub, sizeof(pub), 0), WC_NO_ERR_TRACE(BAD_STATE_E)); wc_XmssKey_Free(&key); } return EXPECT_RESULT(); } #endif /* Walk the AlgorithmIdentifier SEQUENCE that begins at sigIndex and * locate the byte offset of the last byte of its OID content. Handles * both short-form (length < 128) and long-form DER length encodings, * so a future fixture-regenerator that emits longer OIDs / SEQUENCEs * still drives this test rather than tripping the loud-fail branch. * * Returns 0 on success with *oidLastByte set; returns -1 on any DER * shape mismatch. */ #if defined(WOLFSSL_HAVE_XMSS) && !defined(NO_FILESYSTEM) && !defined(NO_CERTS) static int rfc9802_find_sig_alg_oid_last_byte(const byte* buf, word32 bufLen, word32 sigIndex, word32* oidLastByte) { word32 idx = sigIndex; word32 oidContentLen = 0; /* AlgorithmIdentifier ::= SEQUENCE { algorithm OID, ... } */ if (idx >= bufLen || buf[idx] != 0x30) return -1; idx++; /* Skip SEQUENCE length (short or long form). */ if (idx >= bufLen) return -1; if (buf[idx] < 0x80) { idx++; } else { word32 nbytes = (word32)(buf[idx] & 0x7F); if (nbytes == 0 || nbytes > 4 || idx + 1 + nbytes > bufLen) return -1; idx += 1 + nbytes; } /* algorithm OID tag. */ if (idx >= bufLen || buf[idx] != 0x06) return -1; idx++; /* OID length (short or long form). */ if (idx >= bufLen) return -1; if (buf[idx] < 0x80) { oidContentLen = buf[idx]; idx++; } else { word32 nbytes = (word32)(buf[idx] & 0x7F); word32 i; if (nbytes == 0 || nbytes > 4 || idx + 1 + nbytes > bufLen) return -1; for (i = 0; i < nbytes; i++) oidContentLen = (oidContentLen << 8) | buf[idx + 1 + i]; idx += 1 + nbytes; } if (oidContentLen == 0 || idx + oidContentLen > bufLen) return -1; *oidLastByte = idx + oidContentLen - 1; return 0; } /* Helper: load fixture, locate last byte of outer signatureAlgorithm * OID, patch it from `expected` to `swap`, and assert that verifying * the patched cert against itself as a trust anchor fails. */ static int rfc9802_assert_oid_patch_breaks_verify(const char* path, byte expectedLastByte, byte patchedLastByte) { EXPECT_DECLS; byte* buf = NULL; int bytes = 0; DecodedCert cert; WOLFSSL_CERT_MANAGER* cm = NULL; word32 sigIndex = 0; word32 lastOidByte = 0; ExpectIntEQ(rfc9802_load_file(path, &buf, &bytes), TEST_SUCCESS); if (buf == NULL) return TEST_FAIL; wc_InitDecodedCert(&cert, buf, (word32)bytes, NULL); ExpectIntEQ(wc_ParseCert(&cert, CERT_TYPE, NO_VERIFY, NULL), 0); sigIndex = cert.sigIndex; wc_FreeDecodedCert(&cert); ExpectIntEQ(rfc9802_find_sig_alg_oid_last_byte(buf, (word32)bytes, sigIndex, &lastOidByte), 0); /* Sanity-check the fixture matches the family the caller asserted, * so a future regenerator swapping fixtures fails loudly here * rather than silently testing the wrong direction. */ ExpectIntEQ((int)buf[lastOidByte], (int)expectedLastByte); if (lastOidByte < (word32)bytes && buf[lastOidByte] == expectedLastByte) { buf[lastOidByte] = patchedLastByte; ExpectNotNull(cm = wolfSSL_CertManagerNew()); /* After the patch the cert's outer signatureAlgorithm and SPKI * disagree. Verification must fail somewhere (at parse, at * load, or at ConfirmSignature). The load is best-effort - * some shape changes get caught there, others only at verify. */ (void)wolfSSL_CertManagerLoadCABuffer(cm, buf, (long)bytes, WOLFSSL_FILETYPE_ASN1); ExpectIntNE(wolfSSL_CertManagerVerifyBuffer(cm, buf, (long)bytes, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); if (cm != NULL) { wolfSSL_CertManagerFree(cm); cm = NULL; } } XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); return EXPECT_RESULT(); } /* X.509-level negative: swap the outer signatureAlgorithm OID byte so * the cert declares XMSS where the SPKI is XMSS^MT, and vice versa. * SigOidMatchesKeyOid must reject both directions before any crypto. */ static int rfc9802_xmss_sig_oid_mismatch(void) { EXPECT_DECLS; /* XMSS sigOID ends 0x22; XMSS^MT sigOID ends 0x23. Patch each * direction so the asymmetric-key path is exercised both ways - * a regression that only stripped the check from one branch of * SigOidMatchesKeyOid would otherwise be missed. */ ExpectIntEQ(rfc9802_assert_oid_patch_breaks_verify( "./certs/xmss/bc_xmss_sha2_10_256_root.der", /* expected XMSS */ 0x22, /* patched to XMSS^MT */ 0x23), TEST_SUCCESS); ExpectIntEQ(rfc9802_assert_oid_patch_breaks_verify( "./certs/xmss/bc_xmssmt_sha2_20_2_256_root.der", /* expected XMSS^MT */ 0x23, /* patched to XMSS */ 0x22), TEST_SUCCESS); return EXPECT_RESULT(); } #endif /* Exercise a real CA -> leaf certificate chain, not just self-signed. * Loads the CA as a trust anchor and verifies the leaf against it. */ #if defined(WOLFSSL_HAVE_LMS) && !defined(NO_FILESYSTEM) && !defined(NO_CERTS) static int rfc9802_lms_chain_verify(void) { EXPECT_DECLS; byte* caBuf = NULL; byte* leafBuf = NULL; int caLen = 0; int leafLen = 0; WOLFSSL_CERT_MANAGER* cm = NULL; ExpectIntEQ(rfc9802_load_file("./certs/lms/bc_lms_chain_ca.der", &caBuf, &caLen), TEST_SUCCESS); ExpectIntEQ(rfc9802_load_file("./certs/lms/bc_lms_chain_leaf.der", &leafBuf, &leafLen), TEST_SUCCESS); ExpectNotNull(cm = wolfSSL_CertManagerNew()); /* Only the CA is a trust anchor; the leaf is verified against it. */ ExpectIntEQ(wolfSSL_CertManagerLoadCABuffer(cm, caBuf, (long)caLen, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CertManagerVerifyBuffer(cm, leafBuf, (long)leafLen, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); /* Without loading the CA the leaf must NOT verify. */ if (cm != NULL) { wolfSSL_CertManagerFree(cm); cm = NULL; } ExpectNotNull(cm = wolfSSL_CertManagerNew()); ExpectIntNE(wolfSSL_CertManagerVerifyBuffer(cm, leafBuf, (long)leafLen, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); if (cm != NULL) { wolfSSL_CertManagerFree(cm); cm = NULL; } XFREE(leafBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(caBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); return EXPECT_RESULT(); } #endif /* Mirror of rfc9802_lms_chain_verify but for an XMSS CA -> leaf pair. */ #if defined(WOLFSSL_HAVE_XMSS) && !defined(NO_FILESYSTEM) && !defined(NO_CERTS) static int rfc9802_xmss_chain_verify(void) { EXPECT_DECLS; byte* caBuf = NULL; byte* leafBuf = NULL; int caLen = 0; int leafLen = 0; WOLFSSL_CERT_MANAGER* cm = NULL; ExpectIntEQ(rfc9802_load_file("./certs/xmss/bc_xmss_chain_ca.der", &caBuf, &caLen), TEST_SUCCESS); ExpectIntEQ(rfc9802_load_file("./certs/xmss/bc_xmss_chain_leaf.der", &leafBuf, &leafLen), TEST_SUCCESS); ExpectNotNull(cm = wolfSSL_CertManagerNew()); ExpectIntEQ(wolfSSL_CertManagerLoadCABuffer(cm, caBuf, (long)caLen, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CertManagerVerifyBuffer(cm, leafBuf, (long)leafLen, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); if (cm != NULL) { wolfSSL_CertManagerFree(cm); cm = NULL; } ExpectNotNull(cm = wolfSSL_CertManagerNew()); ExpectIntNE(wolfSSL_CertManagerVerifyBuffer(cm, leafBuf, (long)leafLen, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); if (cm != NULL) { wolfSSL_CertManagerFree(cm); cm = NULL; } XFREE(leafBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(caBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); return EXPECT_RESULT(); } #endif int test_rfc9802_lms_x509_verify(void) { EXPECT_DECLS; #if defined(WOLFSSL_HAVE_LMS) #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && \ !defined(WOLFSSL_NO_LMS_SHA256_256) /* Mixed single-level LMS and multi-level HSS fixtures. The HSS * public key carries only the top-level LMS/LM-OTS types, so * wc_LmsKey_ImportPubRaw's auto-derive path searches the map * by (levels, lmsType, lmOtsType). The bc_lms_native_bc_root * fixture is generated through Bouncy Castle's stock * JcaContentSignerBuilder("LMS") + JcaX509v3CertificateBuilder * with no overrides; including it here is the cross-impl interop * gate (BC's native LMS X.509 path is RFC 9802-compliant for HSS/ * LMS, so wolfSSL must accept it end-to-end). * * All fixtures use the SHA-256/M32 family, so the whole block * is gated on that family being compiled in. Truncated SHA-256/192 * or SHAKE-only builds skip this block. */ static const char* const lmsFiles[] = { "./certs/lms/bc_lms_sha256_h5_w4_root.der", #if !defined(WOLFSSL_LMS_MAX_HEIGHT) || (WOLFSSL_LMS_MAX_HEIGHT >= 10) "./certs/lms/bc_lms_sha256_h10_w8_root.der", #endif #if !defined(WOLFSSL_LMS_MAX_LEVELS) || (WOLFSSL_LMS_MAX_LEVELS >= 2) "./certs/lms/bc_hss_L2_H5_W8_root.der", #endif #if !defined(WOLFSSL_LMS_MAX_LEVELS) || (WOLFSSL_LMS_MAX_LEVELS >= 3) "./certs/lms/bc_hss_L3_H5_W4_root.der", #endif "./certs/lms/bc_lms_native_bc_root.der", }; size_t i; for (i = 0; i < sizeof(lmsFiles) / sizeof(lmsFiles[0]); i++) { ExpectIntEQ(rfc9802_verify_one_cert(lmsFiles[i], HSS_LMSk, CTC_HSS_LMS), TEST_SUCCESS); } ExpectIntEQ(rfc9802_lms_chain_verify(), TEST_SUCCESS); #endif /* !NO_FILESYSTEM && !NO_CERTS && !WOLFSSL_NO_LMS_SHA256_256 */ /* Pure wolfCrypt-level negative tests don't need filesystem or cert * support, so they run for any LMS-enabled build. */ ExpectIntEQ(rfc9802_lms_import_negative(), TEST_SUCCESS); #endif return EXPECT_RESULT(); } int test_rfc9802_xmss_x509_verify(void) { EXPECT_DECLS; #if defined(WOLFSSL_HAVE_XMSS) #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) static const char* const xmssFiles[] = { "./certs/xmss/bc_xmss_sha2_10_256_root.der", "./certs/xmss/bc_xmss_sha2_16_256_root.der", }; static const char* const xmssmtFiles[] = { "./certs/xmss/bc_xmssmt_sha2_20_2_256_root.der", "./certs/xmss/bc_xmssmt_sha2_20_4_256_root.der", "./certs/xmss/bc_xmssmt_sha2_40_8_256_root.der", }; size_t i; for (i = 0; i < sizeof(xmssFiles) / sizeof(xmssFiles[0]); i++) { ExpectIntEQ(rfc9802_verify_one_cert(xmssFiles[i], XMSSk, CTC_XMSS), TEST_SUCCESS); } for (i = 0; i < sizeof(xmssmtFiles) / sizeof(xmssmtFiles[0]); i++) { ExpectIntEQ(rfc9802_verify_one_cert(xmssmtFiles[i], XMSSMTk, CTC_XMSSMT), TEST_SUCCESS); } ExpectIntEQ(rfc9802_xmss_sig_oid_mismatch(), TEST_SUCCESS); ExpectIntEQ(rfc9802_xmss_chain_verify(), TEST_SUCCESS); #endif /* !NO_FILESYSTEM && !NO_CERTS */ /* Pure wolfCrypt-level negative tests don't need filesystem or cert * support, so they run for any XMSS-enabled build. */ ExpectIntEQ(rfc9802_xmss_import_negative(), TEST_SUCCESS); #endif return EXPECT_RESULT(); } #if defined(WOLFSSL_SNIFFER) && defined(WOLFSSL_SNIFFER_CHAIN_INPUT) static int test_sniffer_chain_input_overflow(void) { EXPECT_DECLS; struct iovec chain[3]; byte* data = NULL; char error[WOLFSSL_MAX_ERROR_SZ]; int ret; byte dummy[1] = {0}; /* Test 1: iov_len values that sum to more than INT_MAX. * Before the fix, these size_t values would be truncated when accumulated * into an int, causing an undersized allocation followed by an oversized * copy (heap buffer overflow). After the fix, the function should detect * the overflow and return an error without allocating or copying. */ chain[0].iov_base = dummy; chain[0].iov_len = (size_t)0x80000000UL; /* 2GB */ chain[1].iov_base = dummy; chain[1].iov_len = (size_t)0x80000000UL; /* 2GB */ chain[2].iov_base = dummy; chain[2].iov_len = (size_t)0x80000000UL; /* 2GB */ XMEMSET(error, 0, sizeof(error)); ret = ssl_DecodePacketWithChain(chain, 3, &data, error); ExpectIntEQ(ret, WOLFSSL_SNIFFER_ERROR); /* Test 2: total exactly at INT_MAX boundary should also be rejected since * it would require a ~2GB allocation that is unreasonable for a packet. */ chain[0].iov_len = (size_t)0x7FFFFFFFUL; /* INT_MAX */ chain[1].iov_len = (size_t)1; chain[2].iov_len = (size_t)0; XMEMSET(error, 0, sizeof(error)); ret = ssl_DecodePacketWithChain(chain, 2, &data, error); ExpectIntEQ(ret, WOLFSSL_SNIFFER_ERROR); return EXPECT_RESULT(); } #endif /* WOLFSSL_SNIFFER && WOLFSSL_SNIFFER_CHAIN_INPUT */ /* Test: wc_DhAgree must reject p-1 as peer public key. * ffdhe2048 p ends with ...FFFFFFFFFFFFFFFF so p-1 ends ...FFFFFFFFFFFFFFFE */ static int test_DhAgree_rejects_p_minus_1(void) { EXPECT_DECLS; #if !defined(HAVE_SELFTEST) && !defined(NO_DH) && \ defined(HAVE_FFDHE_2048) && !defined(WOLFSSL_NO_MALLOC) && \ (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)) DhKey key; WC_RNG rng; byte priv[256], pub[256], agree[256]; word32 privSz = sizeof(priv), pubSz = sizeof(pub), agreeSz; /* ffdhe2048 p - copied from wolfcrypt/src/dh.c dh_ffdhe2048_p. * p ends with 0xFF*8 so p-1 ends with ...0xFE */ static const byte ffdhe2048_p[256] = { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xAD,0xF8,0x54,0x58,0xA2,0xBB,0x4A,0x9A, 0xAF,0xDC,0x56,0x20,0x27,0x3D,0x3C,0xF1, 0xD8,0xB9,0xC5,0x83,0xCE,0x2D,0x36,0x95, 0xA9,0xE1,0x36,0x41,0x14,0x64,0x33,0xFB, 0xCC,0x93,0x9D,0xCE,0x24,0x9B,0x3E,0xF9, 0x7D,0x2F,0xE3,0x63,0x63,0x0C,0x75,0xD8, 0xF6,0x81,0xB2,0x02,0xAE,0xC4,0x61,0x7A, 0xD3,0xDF,0x1E,0xD5,0xD5,0xFD,0x65,0x61, 0x24,0x33,0xF5,0x1F,0x5F,0x06,0x6E,0xD0, 0x85,0x63,0x65,0x55,0x3D,0xED,0x1A,0xF3, 0xB5,0x57,0x13,0x5E,0x7F,0x57,0xC9,0x35, 0x98,0x4F,0x0C,0x70,0xE0,0xE6,0x8B,0x77, 0xE2,0xA6,0x89,0xDA,0xF3,0xEF,0xE8,0x72, 0x1D,0xF1,0x58,0xA1,0x36,0xAD,0xE7,0x35, 0x30,0xAC,0xCA,0x4F,0x48,0x3A,0x79,0x7A, 0xBC,0x0A,0xB1,0x82,0xB3,0x24,0xFB,0x61, 0xD1,0x08,0xA9,0x4B,0xB2,0xC8,0xE3,0xFB, 0xB9,0x6A,0xDA,0xB7,0x60,0xD7,0xF4,0x68, 0x1D,0x4F,0x42,0xA3,0xDE,0x39,0x4D,0xF4, 0xAE,0x56,0xED,0xE7,0x63,0x72,0xBB,0x19, 0x0B,0x07,0xA7,0xC8,0xEE,0x0A,0x6D,0x70, 0x9E,0x02,0xFC,0xE1,0xCD,0xF7,0xE2,0xEC, 0xC0,0x34,0x04,0xCD,0x28,0x34,0x2F,0x61, 0x91,0x72,0xFE,0x9C,0xE9,0x85,0x83,0xFF, 0x8E,0x4F,0x12,0x32,0xEE,0xF2,0x81,0x83, 0xC3,0xFE,0x3B,0x1B,0x4C,0x6F,0xAD,0x73, 0x3B,0xB5,0xFC,0xBC,0x2E,0xC2,0x20,0x05, 0xC5,0x8E,0xF1,0x83,0x7D,0x16,0x83,0xB2, 0xC6,0xF3,0x4A,0x26,0xC1,0xB2,0xEF,0xFA, 0x88,0x6B,0x42,0x38,0x61,0x28,0x5C,0x97, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF }; byte pMinus1[256]; XMEMSET(&key, 0, sizeof(DhKey)); XMEMSET(&rng, 0, sizeof(WC_RNG)); ExpectIntEQ(wc_InitRng(&rng), 0); ExpectIntEQ(wc_InitDhKey(&key), 0); ExpectIntEQ(wc_DhSetNamedKey(&key, WC_FFDHE_2048), 0); ExpectIntEQ(wc_DhGenerateKeyPair(&key, &rng, priv, &privSz, pub, &pubSz), 0); /* Construct p-1: last byte FF -> FE */ XMEMCPY(pMinus1, ffdhe2048_p, sizeof(ffdhe2048_p)); pMinus1[255] -= 1; /* wc_DhAgree must reject p-1 */ agreeSz = sizeof(agree); ExpectIntNE(wc_DhAgree(&key, agree, &agreeSz, priv, privSz, pMinus1, sizeof(pMinus1)), 0); wc_FreeDhKey(&key); wc_FreeRng(&rng); #endif return EXPECT_RESULT(); } /* ML-DSA HashML-DSA verify must reject hashLen > WC_MAX_DIGEST_SIZE */ static int test_mldsa_verify_hash(void) { EXPECT_DECLS; #if defined(HAVE_DILITHIUM) && \ !defined(WOLFSSL_DILITHIUM_NO_MAKE_KEY) && \ !defined(WOLFSSL_DILITHIUM_NO_VERIFY) dilithium_key key; WC_RNG rng; int res = 0; byte sig[4000]; byte hash[4096]; /* larger than WC_MAX_DIGEST_SIZE */ XMEMSET(&key, 0, sizeof(key)); XMEMSET(&rng, 0, sizeof(rng)); XMEMSET(sig, 0x41, sizeof(sig)); XMEMSET(hash, 'A', sizeof(hash)); ExpectIntEQ(wc_InitRng(&rng), 0); ExpectIntEQ(wc_dilithium_init(&key), 0); #ifndef WOLFSSL_NO_ML_DSA_65 ExpectIntEQ(wc_dilithium_set_level(&key, WC_ML_DSA_65), 0); #elif !defined(WOLFSSL_NO_ML_DSA_44) ExpectIntEQ(wc_dilithium_set_level(&key, WC_ML_DSA_44), 0); #else ExpectIntEQ(wc_dilithium_set_level(&key, WC_ML_DSA_87), 0); #endif ExpectIntEQ(wc_dilithium_make_key(&key, &rng), 0); /* hashLen=4096 must be rejected, not overflow the stack */ ExpectIntEQ(wc_dilithium_verify_ctx_hash(sig, sizeof(sig), NULL, 0, WC_HASH_TYPE_SHA256, hash, sizeof(hash), &res, &key), WC_NO_ERR_TRACE(BAD_LENGTH_E)); wc_dilithium_free(&key); DoExpectIntEQ(wc_FreeRng(&rng), 0); #endif return EXPECT_RESULT(); } /* Test: Ed448 must reject identity public key (0,1) */ static int test_ed448_rejects_identity_key(void) { EXPECT_DECLS; #if defined(HAVE_ED448) && !defined(HAVE_SELFTEST) && \ (!defined(HAVE_FIPS) || FIPS_VERSION_GE(7,0)) ed448_key key; byte identity[ED448_PUB_KEY_SIZE]; byte forged_sig[ED448_SIG_SIZE]; const byte msg[] = "test message"; int res = 0; XMEMSET(identity, 0, sizeof(identity)); identity[0] = 0x01; /* identity (0,1) encoding */ XMEMSET(forged_sig, 0, sizeof(forged_sig)); forged_sig[0] = 0x01; /* R = identity, S = 0 */ ExpectIntEQ(wc_ed448_init(&key), 0); /* The identity public key must be rejected at import time. */ ExpectIntNE(wc_ed448_import_public(identity, sizeof(identity), &key), 0); /* If import somehow succeeded, verify must also reject the forgery. */ if (EXPECT_SUCCESS() && key.pubKeySet) { int verifyRet = wc_ed448_verify_msg(forged_sig, sizeof(forged_sig), msg, sizeof(msg) - 1, &res, &key, NULL, 0); ExpectTrue(verifyRet != 0 || res == 0); } wc_ed448_free(&key); #endif return EXPECT_RESULT(); } /* Test: wc_PKCS7_DecodeEncryptedData must respect outputSz. * 588-byte EncryptedData blob: 496 bytes of 'A' encrypted with * AES-256-CBC under all-zero key/IV. Decrypted content is 496 bytes, * but we pass a 128-byte output buffer. Must return BUFFER_E. */ static int test_pkcs7_decode_encrypted_outputsz(void) { EXPECT_DECLS; #if defined(HAVE_PKCS7) && !defined(NO_AES) && defined(HAVE_AES_CBC) && \ !defined(WOLFSSL_NO_MALLOC) && defined(WOLFSSL_AES_256) wc_PKCS7* p7 = NULL; byte key[32]; byte out[128]; /* smaller than 496-byte decrypted content */ static const byte encBlob[] = { 0x30,0x82,0x02,0x48,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d, 0x01,0x07,0x06,0xa0,0x82,0x02,0x39,0x30,0x82,0x02,0x35,0x02, 0x01,0x00,0x30,0x82,0x02,0x2e,0x06,0x09,0x2a,0x86,0x48,0x86, 0xf7,0x0d,0x01,0x07,0x01,0x30,0x1d,0x06,0x09,0x60,0x86,0x48, 0x01,0x65,0x03,0x04,0x01,0x2a,0x04,0x10,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x80,0x82,0x02,0x00,0x7e,0x0e,0x75,0x77,0xef,0x9c,0x30,0xa6, 0xbf,0x0b,0x25,0xe0,0x62,0x1e,0x82,0x7e,0x76,0xf7,0x57,0xef, 0x12,0x71,0xc5,0x74,0x0e,0x60,0xc3,0x3c,0x8e,0xc3,0xce,0x70, 0xbd,0x3c,0xb4,0x60,0x76,0xb1,0xea,0xb5,0x4b,0xc1,0xfe,0x5b, 0x88,0xfa,0x43,0x46,0x03,0x28,0x9d,0xab,0x3d,0xb5,0x88,0x50, 0x07,0xfc,0x3c,0xc9,0x49,0x4d,0x68,0x97,0xb1,0x59,0xb6,0x35, 0xa1,0x68,0x80,0xb0,0x8f,0xb2,0x21,0x9b,0xfc,0xd8,0xf0,0x67, 0xbc,0x4b,0x9b,0x28,0x1c,0x3b,0xa0,0x40,0x76,0x8f,0x1f,0x9f, 0x87,0xe6,0xe4,0xa5,0xdc,0x9a,0x9a,0x84,0x86,0xff,0x43,0x8a, 0x57,0x8d,0x97,0xd2,0x8f,0x67,0x90,0xd8,0x4f,0x0f,0x0d,0xac, 0x56,0x6d,0x51,0x33,0xa3,0x37,0x9e,0xe9,0xbf,0x07,0xab,0x93, 0xbc,0xbe,0xc1,0x64,0x07,0x30,0xf0,0xff,0x89,0x0a,0x36,0x1c, 0xc8,0xe9,0xae,0x24,0x1f,0x95,0x5c,0xa1,0x8a,0x3e,0x15,0x86, 0x49,0x70,0x55,0xc2,0xa5,0x90,0xb9,0xda,0x2b,0x97,0x6f,0x5f, 0x60,0x61,0xc9,0xcf,0x4d,0x3a,0xb1,0xe4,0x9f,0x37,0x0f,0xf3, 0xba,0x85,0x04,0x52,0x68,0x00,0x47,0x3d,0x83,0xc1,0x3f,0xc6, 0x70,0x97,0xc1,0x0c,0xc0,0x0b,0xa2,0xcb,0x8c,0x88,0xb5,0x01, 0x29,0x7f,0x7e,0xd2,0x46,0x24,0x82,0x92,0x28,0xdd,0x49,0x53, 0x0f,0x76,0xad,0x4b,0x81,0x85,0x3a,0x9f,0xda,0x0d,0x69,0xe2, 0x57,0xb9,0xe9,0xfa,0x53,0xed,0x20,0x6f,0x62,0x43,0x1d,0x21, 0xa9,0x53,0x3d,0xd5,0xb9,0x1a,0x4b,0x3e,0xb7,0x05,0x87,0xb6, 0xe3,0xfe,0x03,0x09,0xe1,0x74,0x34,0x42,0x84,0xb1,0x06,0xf9, 0xfe,0x64,0xc1,0xd2,0xce,0x3d,0x29,0xf4,0x94,0xb8,0xfc,0xbe, 0xb1,0x90,0xd6,0x38,0x61,0x4e,0x43,0x36,0x4e,0x27,0x87,0xd3, 0x24,0xdc,0x34,0xf0,0x28,0x2d,0xc8,0xff,0x89,0x9f,0xeb,0xee, 0x0d,0x45,0xfb,0xc5,0x53,0xd3,0xdf,0xcb,0xf8,0xeb,0x7e,0xcb, 0x2a,0xd7,0xa2,0xd6,0x6a,0xf1,0xb8,0x24,0xa1,0x05,0x16,0x56, 0x2e,0x03,0xfe,0x21,0x19,0x36,0x8a,0xeb,0x50,0x8d,0x42,0x31, 0x1d,0xb3,0x0a,0x13,0x1d,0x16,0x09,0x0b,0x40,0x4e,0x90,0x78, 0xbf,0x41,0x5f,0x4d,0xd9,0xce,0x91,0xaa,0xd0,0x38,0x5c,0xfb, 0xc4,0x9f,0x55,0x4e,0x04,0x9d,0xd0,0xca,0x74,0x3c,0x6c,0x01, 0x1b,0x84,0x76,0xfa,0xba,0x5d,0x2d,0x35,0x7e,0xe3,0x37,0x8b, 0x72,0x0a,0xbb,0xa4,0x4d,0x56,0x2b,0x3b,0x9f,0x5a,0xa0,0xe3, 0x60,0x26,0x65,0x09,0xed,0xfc,0x10,0x0c,0xa1,0x4f,0x12,0x76, 0xe2,0x4c,0xbd,0x1b,0x67,0xb4,0xb4,0x54,0x5c,0x38,0x47,0x8b, 0x7e,0x35,0x8e,0x4d,0x4e,0xef,0x91,0x3f,0xff,0x16,0x0a,0x42, 0x0b,0xe5,0x28,0x26,0x24,0x9f,0x6f,0xb4,0x63,0x8a,0xa1,0x52, 0x22,0x3a,0xdb,0xd9,0x8e,0x76,0x6e,0x6a,0xa9,0xa1,0xec,0xf2, 0x9c,0x58,0xf8,0x6b,0xdd,0xf2,0xf8,0x2d,0xcb,0x8c,0x96,0xda, 0xb4,0x9c,0x44,0xdc,0xab,0x43,0x2c,0x22,0xf3,0xfe,0x1a,0xb9, 0x3b,0x82,0x30,0xa2,0xc7,0xef,0x52,0x08,0x7b,0x4f,0x3f,0x7a, 0x7e,0x28,0xd7,0x67,0xb9,0xb1,0x69,0x9b,0x96,0x3e,0xc5,0xe4, 0x45,0xb0,0x23,0x75,0x00,0xda,0xee,0xdb,0x6d,0xa9,0xe7,0x98 }; XMEMSET(key, 0, sizeof(key)); p7 = wc_PKCS7_New(NULL, INVALID_DEVID); ExpectNotNull(p7); if (p7 != NULL) { p7->encryptionKey = key; p7->encryptionKeySz = sizeof(key); /* 496-byte content into 128-byte buffer must return BUFFER_E */ ExpectIntLT(wc_PKCS7_DecodeEncryptedData(p7, (byte*)encBlob, (word32)sizeof(encBlob), out, sizeof(out)), 0); wc_PKCS7_Free(p7); } #endif return EXPECT_RESULT(); } /* Dummy ORI callback for PKCS#7 ORI overflow test */ #if defined(HAVE_PKCS7) && !defined(WOLFSSL_NO_MALLOC) static int test_dummy_ori_cb(wc_PKCS7* pkcs7, byte* oriType, word32 oriTypeSz, byte* oriValue, word32 oriValueSz, byte* decryptedKey, word32* decryptedKeySz, void* ctx) { (void)pkcs7; (void)oriType; (void)oriTypeSz; (void)oriValue; (void)oriValueSz; (void)decryptedKey; (void)decryptedKeySz; (void)ctx; return -1; } #endif /* Test: PKCS#7 ORI must reject OID larger than MAX_OID_SZ (32) */ static int test_pkcs7_ori_oversized_oid(void) { EXPECT_DECLS; #if defined(HAVE_PKCS7) && !defined(WOLFSSL_NO_MALLOC) wc_PKCS7* p7 = NULL; byte out[256]; /* EnvelopedData with [4] IMPLICIT ORI containing an 80-byte OID */ static const byte poc[] = { 0x30, 0x6b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x03, 0xa0, 0x5e, 0x30, 0x5c, 0x02, 0x01, 0x00, 0x31, 0x57, 0xa4, 0x55, 0x06, 0x50, 0x2a, 0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41, 0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41, 0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41, 0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41, 0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41, 0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41, 0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41, 0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41, 0x04, 0x01, 0x00 }; p7 = wc_PKCS7_New(NULL, INVALID_DEVID); ExpectNotNull(p7); if (p7 != NULL) { wc_PKCS7_SetOriDecryptCb(p7, test_dummy_ori_cb); /* Must return error (ASN_PARSE_E), not overflow the stack */ ExpectIntLT(wc_PKCS7_DecodeEnvelopedData(p7, (byte*)poc, sizeof(poc), out, sizeof(out)), 0); wc_PKCS7_Free(p7); } #endif return EXPECT_RESULT(); } /* ORI callback that flags if oriValueSz looks like an underflow (>= 0x80000000) */ #if defined(HAVE_PKCS7) && !defined(WOLFSSL_NO_MALLOC) static int test_ori_underflow_cb(wc_PKCS7* pkcs7, byte* oriType, word32 oriTypeSz, byte* oriValue, word32 oriValueSz, byte* decryptedKey, word32* decryptedKeySz, void* ctx) { int* called = (int*)ctx; (void)pkcs7; (void)oriType; (void)oriTypeSz; (void)oriValue; (void)decryptedKey; (void)decryptedKeySz; if (called != NULL) *called = (int)oriValueSz; /* record what we received */ return -1; } #endif /* Test: PKCS#7 ORI must reject when OID consumption exceeds the [4] implicit * SEQUENCE length (integer underflow in oriValueSz computation). * * With implicit tagging, [4] CONSTRUCTED replaces the SEQUENCE tag, so * wc_PKCS7_DecryptOri reads seqSz directly from the [4] length field. * We set [4] length = 5 while the OID inside consumes 22 bytes * (tag + length + 20 content), triggering oriValueSz = 5 - 22 = underflow. * * The buffer includes a dummy EncryptedContentInfo after the RecipientInfos * so the total message is large enough for the PKCS7 streaming code (which * requests the full remaining message before parsing the ORI). */ static int test_pkcs7_ori_seqsz_underflow(void) { EXPECT_DECLS; #if defined(HAVE_PKCS7) && !defined(WOLFSSL_NO_MALLOC) wc_PKCS7* p7 = NULL; byte out[256]; int cbCalled = 0; /* * Byte layout (all outer lengths match actual byte counts on wire): * * OID inside [4]: 06 14 <20 bytes> = 22 bytes * [4] (declared len 5, actual content 22): * a4 05 <22 bytes> = 24 bytes on wire * SET: 31 18 <24 bytes> = 26 bytes on wire * version: 02 01 00 = 3 bytes * EncryptedContentInfo (filler, never parsed): * 30 0b { 06 09 <9 bytes OID> } = 13 bytes on wire * EnvelopedData: 30 2a <3+26+13=42 bytes> = 44 bytes on wire * [0] EXPLICIT: a0 2c <44 bytes> = 46 bytes on wire * OID(envelopedData): 06 09 <9 bytes> = 11 bytes on wire * ContentInfo: 30 39 <11+46=57 bytes> = 59 bytes total */ static const byte poc[] = { /* ContentInfo SEQUENCE (length 57) */ 0x30, 0x39, /* contentType = envelopedData 1.2.840.113549.1.7.3 */ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x03, /* [0] EXPLICIT (length 44) */ 0xa0, 0x2c, /* EnvelopedData SEQUENCE (length 42) */ 0x30, 0x2a, /* version = 0 */ 0x02, 0x01, 0x00, /* RecipientInfos SET (length 24) */ 0x31, 0x18, /* [4] CONSTRUCTED = ORI implicit SEQUENCE, declared len 5 */ /* Actual OID is 22 bytes -> exceeds declared 5 */ 0xa4, 0x05, /* OID: tag=06, len=0x14(20), content=20 bytes = 22 total */ 0x06, 0x14, 0x2a, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, /* EncryptedContentInfo SEQUENCE (length 11) - filler so * streaming has enough data; never actually parsed because * DecryptOri fails before we get here */ 0x30, 0x0b, /* contentType = data 1.2.840.113549.1.7.1 */ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01 }; p7 = wc_PKCS7_New(NULL, INVALID_DEVID); ExpectNotNull(p7); if (p7 != NULL) { wc_PKCS7_SetOriDecryptCb(p7, test_ori_underflow_cb); wc_PKCS7_SetOriDecryptCtx(p7, &cbCalled); /* Must return an error before the callback sees an underflowed size */ ExpectIntLT(wc_PKCS7_DecodeEnvelopedData(p7, (byte*)poc, sizeof(poc), out, sizeof(out)), 0); /* The callback must NOT have been invoked with a wrapped oriValueSz. * cbCalled == 0 means the callback was never reached (ideal). * cbCalled < 0 would indicate the underflow was passed through. */ ExpectIntGE(cbCalled, 0); wc_PKCS7_Free(p7); } #endif return EXPECT_RESULT(); } /* Test: PKCS#7 ORI must reject when seqSz extends oriValue past input buffer. * * The first ORI bounds check (OID exceeds SEQUENCE boundary) is covered by * test_pkcs7_ori_seqsz_underflow. This test covers the *second* check: * oriValue region extends past the end of the input buffer. We craft a * message where the [4] SEQUENCE length is valid relative to the OID * (OID fits inside it), but the remaining oriValue portion extends past * the end of the actual input buffer. * * To bypass GetLength's own bounds validation, we set the outer lengths * (EnvelopedData SEQUENCE, RecipientInfos SET) to match the [4] claim, * but truncate the actual buffer we pass to DecodeEnvelopedData. */ static int test_pkcs7_ori_orivalue_overflow(void) { EXPECT_DECLS; #if defined(HAVE_PKCS7) && !defined(WOLFSSL_NO_MALLOC) wc_PKCS7* p7 = NULL; byte out[256]; /* EnvelopedData with [4] ORI whose seqSz (40) is valid for the OID * (6 bytes consumed) but oriValueSz (34) extends past the truncated * input buffer. * * Layout: * ContentInfo SEQUENCE * OID envelopedData * [0] EXPLICIT * EnvelopedData SEQUENCE * version = 0 * RecipientInfos SET * [4] CONSTRUCTED (seqSz = 40) * OID (tag 06, len 04, 4 content bytes = 6 total) * oriValue should be 34 bytes but input is truncated * EncryptedContentInfo (filler for streaming) * * We pass the full array to DecodeEnvelopedData, but the actual * input ends before [4]'s declared 40 bytes are consumed. */ static const byte poc[] = { /* ContentInfo SEQUENCE */ 0x30, 0x43, /* contentType = envelopedData 1.2.840.113549.1.7.3 */ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x03, /* [0] EXPLICIT */ 0xa0, 0x36, /* EnvelopedData SEQUENCE */ 0x30, 0x34, /* version = 0 */ 0x02, 0x01, 0x00, /* RecipientInfos SET (len = 44 covers [4] tag+len+40) */ 0x31, 0x2c, /* [4] CONSTRUCTED = ORI implicit SEQUENCE, seqSz = 40 */ 0xa4, 0x28, /* OID: tag=06, len=04, 4 content bytes = 6 total */ 0x06, 0x04, 0x2a, 0x03, 0x04, 0x05, /* Only 4 bytes of oriValue here, but seqSz claims 34 more */ 0x00, 0x00, 0x00, 0x00, /* EncryptedContentInfo SEQUENCE (filler) */ 0x30, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01 }; p7 = wc_PKCS7_New(NULL, INVALID_DEVID); ExpectNotNull(p7); if (p7 != NULL) { wc_PKCS7_SetOriDecryptCb(p7, test_dummy_ori_cb); /* Must return error - oriValue extends past input buffer */ ExpectIntLT(wc_PKCS7_DecodeEnvelopedData(p7, (byte*)poc, sizeof(poc), out, sizeof(out)), 0); wc_PKCS7_Free(p7); } #endif return EXPECT_RESULT(); } /* Test: PKCS#7 KTRI must not match recipient when SKID length differs * from expected keyIdSize. * * The fix adds a `length == keyIdSize` check before comparing the SKID * bytes. Without this check, XMEMCMP could compare against data beyond * the SKID content. This test crafts a KTRI RecipientInfo where the * [0] SubjectKeyIdentifier has length 5 instead of KEYID_SIZE (20). * The decode must return an error (no matching recipient). */ static int test_pkcs7_ktri_skid_length_mismatch(void) { EXPECT_DECLS; #if defined(HAVE_PKCS7) && !defined(NO_RSA) && !defined(WOLFSSL_NO_MALLOC) wc_PKCS7* p7 = NULL; byte out[256]; /* Minimal EnvelopedData with KTRI using version=2 (SKID path). * The SKID [0] has length 5 instead of 20. * * ContentInfo SEQUENCE * OID envelopedData * [0] EXPLICIT * EnvelopedData SEQUENCE * version = 2 * RecipientInfos SET * KTRI SEQUENCE * version = 2 * [0] SKID (5 bytes, should be 20) * AlgorithmIdentifier (RSA OID) * OCTET STRING (fake encrypted key) * EncryptedContentInfo (filler) */ static const byte poc[] = { /* ContentInfo SEQUENCE */ 0x30, 0x46, /* contentType = envelopedData 1.2.840.113549.1.7.3 */ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x03, /* [0] EXPLICIT */ 0xa0, 0x39, /* EnvelopedData SEQUENCE */ 0x30, 0x37, /* version = 2 (triggers SKID-based recipient identification) */ 0x02, 0x01, 0x02, /* RecipientInfos SET */ 0x31, 0x21, /* KTRI SEQUENCE */ 0x30, 0x1f, /* version = 2 (SKID) */ 0x02, 0x01, 0x02, /* [0] IMPLICIT SubjectKeyIdentifier, length = 5 (wrong!) */ 0x80, 0x05, 0x01, 0x02, 0x03, 0x04, 0x05, /* AlgorithmIdentifier: RSA 1.2.840.113549.1.1.1 */ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, /* NULL params */ /* encryptedKey OCTET STRING (2 bytes fake) */ 0x04, 0x02, 0xAA, 0xBB, /* EncryptedContentInfo SEQUENCE (filler) */ 0x30, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01 }; p7 = wc_PKCS7_New(NULL, INVALID_DEVID); ExpectNotNull(p7); if (p7 != NULL) { /* Decode without a cert - SKID will never match, and the * mismatched SKID length must not cause out-of-bounds reads */ ExpectIntLT(wc_PKCS7_DecodeEnvelopedData(p7, (byte*)poc, sizeof(poc), out, sizeof(out)), 0); wc_PKCS7_Free(p7); } #endif return EXPECT_RESULT(); } /* Test: PKCS#7 KARI must reject BIT STRING with length < 2 in * OriginatorPublicKey. * * The fix adds `if (length < 2) return ASN_PARSE_E` after parsing * the BIT STRING tag and length. A BIT STRING must have at least * the unused-bits byte plus one byte of content. This test crafts * a KARI [1] RecipientInfo where the OriginatorPublicKey's BIT STRING * has length 1 (degenerate). The PKCS7 object is initialized with a * real ECC cert so that KariParseRecipCert succeeds and parsing reaches * the BIT STRING validation. */ static int test_pkcs7_kari_degenerate_bitstring(void) { EXPECT_DECLS; #if defined(HAVE_PKCS7) && defined(HAVE_ECC) && defined(HAVE_X963_KDF) && \ !defined(WOLFSSL_NO_MALLOC) wc_PKCS7* p7 = NULL; byte out[256]; byte* eccCert = NULL; byte* eccPrivKey = NULL; word32 eccCertSz = 0; word32 eccPrivKeySz = 0; #if !defined(USE_CERT_BUFFERS_256) && !defined(NO_FILESYSTEM) XFILE f = XBADFILE; #endif /* Minimal EnvelopedData with KARI [1] containing a degenerate * BIT STRING (length 1) in OriginatorPublicKey. * * ContentInfo SEQUENCE * OID envelopedData * [0] EXPLICIT * EnvelopedData SEQUENCE * version = 2 * RecipientInfos SET * [1] CONSTRUCTED (KARI) * version = 3 * [0] CONSTRUCTED (OriginatorIdentifierOrKey) * [1] CONSTRUCTED (OriginatorPublicKey) * AlgorithmIdentifier (ECDSAk) * BIT STRING length=1 (degenerate!) * EncryptedContentInfo (filler) */ static const byte poc[] = { /* ContentInfo SEQUENCE */ 0x30, 0x44, /* contentType = envelopedData 1.2.840.113549.1.7.3 */ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x03, /* [0] EXPLICIT */ 0xa0, 0x37, /* EnvelopedData SEQUENCE */ 0x30, 0x35, /* version = 2 */ 0x02, 0x01, 0x02, /* RecipientInfos SET */ 0x31, 0x1f, /* [1] CONSTRUCTED (KARI implicit) */ 0xa1, 0x1d, /* version = 3 */ 0x02, 0x01, 0x03, /* [0] CONSTRUCTED (OriginatorIdentifierOrKey) */ 0xa0, 0x18, /* [1] CONSTRUCTED (OriginatorPublicKey) */ 0xa1, 0x16, /* AlgorithmIdentifier SEQUENCE */ 0x30, 0x13, /* OID: id-ecPublicKey 1.2.840.10045.2.1 */ 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, /* OID: prime256v1 1.2.840.10045.3.1.7 */ 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, /* BIT STRING with length 1 - degenerate! */ 0x03, 0x01, 0x00, /* EncryptedContentInfo SEQUENCE (filler) */ 0x30, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01 }; /* Load ECC cert and key so KariParseRecipCert succeeds and * parsing reaches the BIT STRING check */ #ifdef USE_CERT_BUFFERS_256 eccCertSz = (word32)sizeof_cliecc_cert_der_256; ExpectNotNull(eccCert = (byte*)XMALLOC(eccCertSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER)); if (eccCert != NULL) XMEMCPY(eccCert, cliecc_cert_der_256, eccCertSz); eccPrivKeySz = (word32)sizeof_ecc_clikey_der_256; ExpectNotNull(eccPrivKey = (byte*)XMALLOC(eccPrivKeySz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER)); if (eccPrivKey != NULL) XMEMCPY(eccPrivKey, ecc_clikey_der_256, eccPrivKeySz); #elif !defined(NO_FILESYSTEM) eccCertSz = FOURK_BUF; ExpectNotNull(eccCert = (byte*)XMALLOC(eccCertSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER)); ExpectTrue((f = XFOPEN("./certs/client-ecc-cert.der", "rb")) != XBADFILE); ExpectTrue((eccCertSz = (word32)XFREAD(eccCert, 1, eccCertSz, f)) > 0); if (f != XBADFILE) { XFCLOSE(f); f = XBADFILE; } eccPrivKeySz = FOURK_BUF; ExpectNotNull(eccPrivKey = (byte*)XMALLOC(eccPrivKeySz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER)); ExpectTrue((f = XFOPEN("./certs/ecc-client-key.der", "rb")) != XBADFILE); ExpectTrue((eccPrivKeySz = (word32)XFREAD(eccPrivKey, 1, eccPrivKeySz, f)) > 0); if (f != XBADFILE) XFCLOSE(f); #else eccCert = NULL; eccCertSz = 0; eccPrivKey = NULL; eccPrivKeySz = 0; #endif p7 = wc_PKCS7_New(HEAP_HINT, INVALID_DEVID); ExpectNotNull(p7); if (p7 != NULL && eccCert != NULL) { ExpectIntEQ(wc_PKCS7_InitWithCert(p7, eccCert, eccCertSz), 0); if (p7 != NULL) { p7->privateKey = eccPrivKey; p7->privateKeySz = eccPrivKeySz; } /* Must return error - BIT STRING length < 2 is invalid */ ExpectIntLT(wc_PKCS7_DecodeEnvelopedData(p7, (byte*)poc, sizeof(poc), out, sizeof(out)), 0); if (p7 != NULL) { p7->privateKey = NULL; p7->privateKeySz = 0; } wc_PKCS7_Free(p7); } else if (p7 != NULL) { wc_PKCS7_Free(p7); } XFREE(eccCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(eccPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); #endif return EXPECT_RESULT(); } /* Test: PKCS#7 EncryptedData must reject when encryptedContentSz exceeds * the remaining input buffer. * * The fix adds `encryptedContentSz > (int)(pkiMsgSz - idx)` to the * existing `encryptedContentSz <= 0` check in stage 6. This test crafts * a minimal EncryptedData where the [0] IMPLICIT content length claims * 0x200 (512) bytes but only 32 bytes of ciphertext are present. */ static int test_pkcs7_encrypted_content_size_overflow(void) { EXPECT_DECLS; #if defined(HAVE_PKCS7) && !defined(NO_AES) && defined(HAVE_AES_CBC) && \ defined(WOLFSSL_AES_256) && !defined(NO_PKCS7_ENCRYPTED_DATA) && \ !defined(WOLFSSL_NO_MALLOC) wc_PKCS7* p7 = NULL; byte key[32]; byte out[256]; /* EncryptedData with [0] content claiming 512 bytes but only 32 present. * * ContentInfo SEQUENCE * OID encryptedData (1.2.840.113549.1.7.6) * [0] EXPLICIT * EncryptedData SEQUENCE * version = 0 * EncryptedContentInfo SEQUENCE * OID data (1.2.840.113549.1.7.1) * AlgorithmIdentifier * OID AES-256-CBC (2.16.840.1.101.3.4.1.42) * OCTET STRING IV (16 zero bytes) * [0] IMPLICIT content (claimed len=0x200, actual=32 bytes) */ static const byte poc[] = { /* ContentInfo SEQUENCE (len covers entire message) */ 0x30, 0x50, /* OID encryptedData 1.2.840.113549.1.7.6 */ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x06, /* [0] EXPLICIT */ 0xa0, 0x43, /* EncryptedData SEQUENCE */ 0x30, 0x41, /* version = 0 */ 0x02, 0x01, 0x00, /* EncryptedContentInfo SEQUENCE */ 0x30, 0x3c, /* OID data 1.2.840.113549.1.7.1 */ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, /* AlgorithmIdentifier SEQUENCE */ 0x30, 0x1d, /* OID AES-256-CBC 2.16.840.1.101.3.4.1.42 */ 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x2a, /* IV: OCTET STRING (16 zero bytes) */ 0x04, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [0] IMPLICIT encryptedContent - claims 512 bytes! * Only 16 bytes of fake ciphertext follow. */ 0x80, 0x82, 0x02, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA }; XMEMSET(key, 0, sizeof(key)); p7 = wc_PKCS7_New(NULL, INVALID_DEVID); ExpectNotNull(p7); if (p7 != NULL) { p7->encryptionKey = key; p7->encryptionKeySz = sizeof(key); /* Must return error - content extends past input buffer */ ExpectIntLT(wc_PKCS7_DecodeEncryptedData(p7, (byte*)poc, sizeof(poc), out, sizeof(out)), 0); wc_PKCS7_Free(p7); } #endif return EXPECT_RESULT(); } /* Test: PKCS#7 SignedData must reject when the signature field is not * an OCTET STRING. * * The fix adds `else if (ret == 0) { ret = ASN_PARSE_E; }` so that * when the tag at the signature position is not ASN_OCTET_STRING, * parsing returns an error instead of silently continuing with no * signature. This test encodes a valid SignedData, then corrupts * the signature OCTET STRING tag and verifies that decode fails. */ static int test_pkcs7_signed_bad_sig_tag(void) { EXPECT_DECLS; #if defined(HAVE_PKCS7) && !defined(NO_RSA) && !defined(NO_SHA256) && \ !defined(WOLFSSL_NO_MALLOC) PKCS7* pkcs7 = NULL; WC_RNG rng; byte encoded[FOURK_BUF]; int encodedSz = 0; int i; byte* rsaCert = NULL; byte* rsaPrivKey = NULL; word32 rsaCertSz = 0; word32 rsaPrivKeySz = 0; #if !defined(USE_CERT_BUFFERS_2048) && !defined(USE_CERT_BUFFERS_1024) && \ !defined(NO_FILESYSTEM) XFILE f = XBADFILE; #endif const byte data[] = "Test signed data"; XMEMSET(&rng, 0, sizeof(WC_RNG)); /* Load RSA cert and key */ #if defined(USE_CERT_BUFFERS_2048) rsaCertSz = (word32)sizeof_client_cert_der_2048; ExpectNotNull(rsaCert = (byte*)XMALLOC(rsaCertSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER)); if (rsaCert != NULL) XMEMCPY(rsaCert, client_cert_der_2048, rsaCertSz); rsaPrivKeySz = (word32)sizeof_client_key_der_2048; ExpectNotNull(rsaPrivKey = (byte*)XMALLOC(rsaPrivKeySz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER)); if (rsaPrivKey != NULL) XMEMCPY(rsaPrivKey, client_key_der_2048, rsaPrivKeySz); #elif defined(USE_CERT_BUFFERS_1024) rsaCertSz = (word32)sizeof_client_cert_der_1024; ExpectNotNull(rsaCert = (byte*)XMALLOC(rsaCertSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER)); if (rsaCert != NULL) XMEMCPY(rsaCert, client_cert_der_1024, rsaCertSz); rsaPrivKeySz = (word32)sizeof_client_key_der_1024; ExpectNotNull(rsaPrivKey = (byte*)XMALLOC(rsaPrivKeySz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER)); if (rsaPrivKey != NULL) XMEMCPY(rsaPrivKey, client_key_der_1024, rsaPrivKeySz); #elif !defined(NO_FILESYSTEM) rsaCertSz = FOURK_BUF; ExpectNotNull(rsaCert = (byte*)XMALLOC(rsaCertSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER)); ExpectTrue((f = XFOPEN("./certs/client-cert.der", "rb")) != XBADFILE); ExpectTrue((rsaCertSz = (word32)XFREAD(rsaCert, 1, rsaCertSz, f)) > 0); if (f != XBADFILE) { XFCLOSE(f); f = XBADFILE; } rsaPrivKeySz = FOURK_BUF; ExpectNotNull(rsaPrivKey = (byte*)XMALLOC(rsaPrivKeySz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER)); ExpectTrue((f = XFOPEN("./certs/client-key.der", "rb")) != XBADFILE); ExpectTrue((rsaPrivKeySz = (word32)XFREAD(rsaPrivKey, 1, rsaPrivKeySz, f)) > 0); if (f != XBADFILE) XFCLOSE(f); #else rsaCert = NULL; rsaCertSz = 0; rsaPrivKey = NULL; rsaPrivKeySz = 0; #endif if (rsaCert == NULL || rsaPrivKey == NULL) { XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); return TEST_SKIPPED; } ExpectIntEQ(wc_InitRng(&rng), 0); /* Encode a valid SignedData */ ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId)); ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, rsaCert, rsaCertSz), 0); if (pkcs7 != NULL) { pkcs7->content = (byte*)data; pkcs7->contentSz = (word32)sizeof(data); pkcs7->contentOID = DATA; pkcs7->hashOID = SHA256h; pkcs7->encryptOID = RSAk; pkcs7->privateKey = rsaPrivKey; pkcs7->privateKeySz = rsaPrivKeySz; pkcs7->rng = &rng; } ExpectIntGT(encodedSz = wc_PKCS7_EncodeSignedData(pkcs7, encoded, sizeof(encoded)), 0); wc_PKCS7_Free(pkcs7); pkcs7 = NULL; /* Find the signature OCTET STRING tag (0x04) near the end of the * encoded message and corrupt it. The signature is the last large * OCTET STRING in the SignerInfo. Search backwards for 0x04 followed * by a length that looks like an RSA signature (>= 64 bytes). * This heuristic depends on the signature being the last large * OCTET STRING; the found==1 assertion below guards against * silent false passes if encoding changes. */ if (EXPECT_SUCCESS()) { int found = 0; for (i = encodedSz - 10; i > 10; i--) { if (encoded[i] == 0x04) { int len = 0, lbytes = 0; if (encoded[i+1] < 0x80) { len = encoded[i+1]; lbytes = 1; } else if (encoded[i+1] == 0x81) { len = encoded[i+2]; lbytes = 2; } else if (encoded[i+1] == 0x82) { len = (encoded[i+2] << 8) | encoded[i+3]; lbytes = 3; } /* RSA signature is typically >= 128 bytes */ if (len >= 64 && i + 1 + lbytes + len <= encodedSz) { /* Corrupt the OCTET STRING tag to INTEGER */ encoded[i] = 0x02; /* ASN_INTEGER instead of OCTET STRING */ found = 1; break; } } } ExpectIntEQ(found, 1); } /* Verify the corrupted SignedData - must fail */ if (EXPECT_SUCCESS()) { ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId)); ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, NULL, 0), 0); ExpectIntLT(wc_PKCS7_VerifySignedData(pkcs7, encoded, (word32)encodedSz), 0); wc_PKCS7_Free(pkcs7); pkcs7 = NULL; } DoExpectIntEQ(wc_FreeRng(&rng), 0); XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); #endif return EXPECT_RESULT(); } /* Test: PKCS#7 EnvelopedData must reject when encryptedContentTotalSz * exceeds the remaining input buffer. * * The fix adds a bounds check under NO_PKCS7_STREAM, but the same * crafted message should also be properly handled in streaming mode. * This test crafts an EnvelopedData where the [0] content length * claims 512 bytes but only minimal data follows. */ static int test_pkcs7_enveloped_content_size_overflow(void) { EXPECT_DECLS; #if defined(HAVE_PKCS7) && !defined(WOLFSSL_NO_MALLOC) && !defined(NO_RSA) wc_PKCS7* p7 = NULL; byte out[256]; /* EnvelopedData with KTRI where the EncryptedContentInfo [0] claims * 512 bytes but only 16 are present. * * The outer structure is valid enough to reach the content parsing: * ContentInfo -> EnvelopedData -> version=0 -> * RecipientInfos (empty SET) -> EncryptedContentInfo -> * contentType + AlgorithmIdentifier + [0] oversized content */ static const byte poc[] = { /* ContentInfo SEQUENCE */ 0x30, 0x50, /* OID envelopedData 1.2.840.113549.1.7.3 */ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x03, /* [0] EXPLICIT */ 0xa0, 0x43, /* EnvelopedData SEQUENCE */ 0x30, 0x41, /* version = 0 */ 0x02, 0x01, 0x00, /* RecipientInfos SET (empty - no recipients) */ 0x31, 0x00, /* EncryptedContentInfo SEQUENCE */ 0x30, 0x3c, /* OID data 1.2.840.113549.1.7.1 */ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, /* AlgorithmIdentifier SEQUENCE */ 0x30, 0x1d, /* OID AES-256-CBC 2.16.840.1.101.3.4.1.42 */ 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x2a, /* IV: OCTET STRING (16 zero bytes) */ 0x04, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* [0] IMPLICIT encryptedContent - claims 512 bytes! */ 0x80, 0x82, 0x02, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA }; p7 = wc_PKCS7_New(NULL, INVALID_DEVID); ExpectNotNull(p7); if (p7 != NULL) { /* With an empty RecipientInfos SET, the function may fail at * the recipient matching stage before reaching the content-size * bounds check. The ExpectIntLT assertion ensures the * oversized content does not cause a buffer over-read. */ ExpectIntLT(wc_PKCS7_DecodeEnvelopedData(p7, (byte*)poc, sizeof(poc), out, sizeof(out)), 0); wc_PKCS7_Free(p7); } #endif return EXPECT_RESULT(); } /* Dilithium verify_ctx_msg must reject absurdly large msgLen */ static int test_dilithium_hash(void) { EXPECT_DECLS; #if defined(HAVE_DILITHIUM) && \ !defined(WOLFSSL_DILITHIUM_NO_MAKE_KEY) && \ !defined(WOLFSSL_DILITHIUM_NO_VERIFY) dilithium_key key; WC_RNG rng; int res = 0; byte sig[4000]; byte msg[64]; XMEMSET(&key, 0, sizeof(key)); XMEMSET(&rng, 0, sizeof(rng)); XMEMSET(sig, 0, sizeof(sig)); XMEMSET(msg, 'A', sizeof(msg)); ExpectIntEQ(wc_InitRng(&rng), 0); ExpectIntEQ(wc_dilithium_init(&key), 0); #ifndef WOLFSSL_NO_ML_DSA_65 ExpectIntEQ(wc_dilithium_set_level(&key, WC_ML_DSA_65), 0); #elif !defined(WOLFSSL_NO_ML_DSA_44) ExpectIntEQ(wc_dilithium_set_level(&key, WC_ML_DSA_44), 0); #else ExpectIntEQ(wc_dilithium_set_level(&key, WC_ML_DSA_87), 0); #endif ExpectIntEQ(wc_dilithium_make_key(&key, &rng), 0); ExpectIntEQ(wc_dilithium_verify_ctx_msg(sig, sizeof(sig), NULL, 0, msg, 0xFFFFFFC0, &res, &key), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); wc_dilithium_free(&key); DoExpectIntEQ(wc_FreeRng(&rng), 0); #endif return EXPECT_RESULT(); } /* PKCS7 CBC must validate all padding bytes */ static int test_pkcs7_padding(void) { EXPECT_DECLS; #if defined(HAVE_PKCS7) && !defined(NO_AES) && defined(HAVE_AES_CBC) && \ defined(WOLFSSL_AES_256) && !defined(NO_PKCS7_ENCRYPTED_DATA) PKCS7 pkcs7; byte key[32]; byte plaintext[27]; /* 27 bytes -> padded to 32 -> padding = 05 05 05 05 05 */ byte encoded[4096]; byte output[256]; byte modified[4096]; int encodedSz = 0; int outSz; int ctOff = -1; int ctLen = 0; XMEMSET(key, 0xAA, sizeof(key)); XMEMSET(plaintext, 'X', sizeof(plaintext)); /* Encode EncryptedData */ XMEMSET(&pkcs7, 0, sizeof(pkcs7)); ExpectIntEQ(wc_PKCS7_Init(&pkcs7, NULL, INVALID_DEVID), 0); pkcs7.content = plaintext; pkcs7.contentSz = sizeof(plaintext); pkcs7.contentOID = DATA; pkcs7.encryptOID = AES256CBCb; pkcs7.encryptionKey = key; pkcs7.encryptionKeySz = sizeof(key); ExpectIntGT(encodedSz = wc_PKCS7_EncodeEncryptedData(&pkcs7, encoded, sizeof(encoded)), 0); /* Verify normal decrypt works */ ExpectIntEQ(outSz = wc_PKCS7_DecodeEncryptedData(&pkcs7, encoded, (word32)encodedSz, output, sizeof(output)), (int)sizeof(plaintext)); wc_PKCS7_Free(&pkcs7); /* encryptedContent is the last element in the DER, so it ends at encodedSz; * 27-byte plaintext -> 32-byte AES-256-CBC ciphertext. */ ctLen = 32; ctOff = encodedSz - ctLen; /* Corrupt an interior padding byte via CBC bit-flip */ if (EXPECT_SUCCESS()) { XMEMCPY(modified, encoded, (size_t)encodedSz); /* Flip byte in penultimate block to corrupt interior padding */ modified[ctOff + ctLen - 32 + 11] ^= 0x42; /* Decrypt modified ciphertext - must fail, not succeed */ XMEMSET(&pkcs7, 0, sizeof(pkcs7)); ExpectIntEQ(wc_PKCS7_Init(&pkcs7, NULL, INVALID_DEVID), 0); pkcs7.encryptionKey = key; pkcs7.encryptionKeySz = sizeof(key); outSz = wc_PKCS7_DecodeEncryptedData(&pkcs7, modified, (word32)encodedSz, output, sizeof(output)); /* Must return an error - if it returns plaintext size, padding * oracle vulnerability exists */ ExpectIntLT(outSz, 0); wc_PKCS7_Free(&pkcs7); } #endif return EXPECT_RESULT(); } TEST_CASE testCases[] = { TEST_DECL(test_fileAccess), /********************************* * wolfcrypt *********************************/ TEST_DECL(test_ForceZero), TEST_DECL(test_wolfCrypt_Init), TEST_DECL(test_wc_LoadStaticMemory_ex), TEST_DECL(test_wc_LoadStaticMemory_CTX), TEST_DECL(test_wc_FreeCertList), /* Locking with Compat Mutex */ TEST_DECL(test_wc_SetMutexCb), TEST_DECL(test_wc_LockMutex_ex), /* Digests */ /* test_md2.c */ TEST_MD2_DECLS, /* test_md4.c */ TEST_MD4_DECLS, /* test_md5.c */ TEST_MD5_DECLS, /* test_sha.c */ TEST_SHA_DECLS, /* test_sha256.c */ TEST_SHA256_DECLS, TEST_SHA224_DECLS, /* test_sha512.c */ TEST_SHA512_DECLS, TEST_SHA512_224_DECLS, TEST_SHA512_256_DECLS, TEST_SHA384_DECLS, /* test_sha3.c */ TEST_SHA3_DECLS, TEST_SHAKE128_DECLS, TEST_SHAKE256_DECLS, /* test_blake.c */ TEST_BLAKE2B_DECLS, TEST_BLAKE2S_DECLS, /* test_sm3.c: SM3 Digest */ TEST_SM3_DECLS, /* test_ripemd.c */ TEST_RIPEMD_DECLS, /* test_hash.c */ TEST_HASH_DECLS, /* HMAC */ TEST_HMAC_DECLS, /* CMAC */ TEST_CMAC_DECLS, /* SHE */ TEST_SHE_DECLS, #ifdef WOLFSSL_SHE_EXTENDED TEST_SHE_EXT_DECLS, #endif #if defined(WOLF_CRYPTO_CB) && defined(WOLFSSL_SHE) TEST_SHE_CB_DECLS, #endif /* Cipher */ /* Triple-DES */ TEST_DES3_DECLS, /* Chacha20 */ TEST_CHACHA_DECLS, /* Poly1305 */ TEST_POLY1305_DECLS, /* Chacha20-Poly1305 and Xchacha20-Poly1305 */ TEST_CHACHA20_POLY1305_DECLS, /* Camellia */ TEST_CAMELLIA_DECLS, /* ARC4 */ TEST_ARC4_DECLS, /* RC2 */ TEST_RC2_DECLS, /* AES cipher and GMAC. */ TEST_AES_DECLS, #if defined(WOLFSSL_AES_EAX) && defined(WOLFSSL_AES_256) && \ (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5, 3)) && !defined(HAVE_SELFTEST) TEST_AES_EAX_DECLS, #endif /* WOLFSSL_AES_EAX */ #if defined(WOLFSSL_AES_SIV) && defined(WOLFSSL_AES_128) TEST_AES_SIV_DECLS, #endif /* WOLFSSL_AES_SIV && WOLFSSL_AES_128 */ TEST_GMAC_DECLS, /* Ascon */ TEST_ASCON_DECLS, /* SM4 cipher */ TEST_SM4_DECLS, /* wc_encrypt API */ TEST_WC_ENCRYPT_DECLS, /* RNG tests */ TEST_RANDOM_DECLS, /* Public key */ /* wolfmath MP API tests */ TEST_WOLFMATH_DECLS, /* RSA */ TEST_RSA_DECLS, /* DSA */ TEST_DSA_DECLS, /* DH */ TEST_DH_DECLS, /* wolfCrypt ECC tests */ TEST_ECC_DECLS, /* SM2 elliptic curve */ TEST_SM2_DECLS, /* Curve25519 */ TEST_CURVE25519_DECLS, /* ED25519 */ TEST_ED25519_DECLS, /* Curve448 */ TEST_CURVE448_DECLS, /* Ed448 */ TEST_ED448_DECLS, /* Kyber */ TEST_MLKEM_DECLS, /* Dilithium */ TEST_MLDSA_DECLS, /* SLH-DSA */ TEST_SLHDSA_DECLS, /* Signature API */ TEST_SIGNATURE_DECLS, /* ASN */ TEST_ASN_DECLS, /* LMS */ TEST_DECL_GROUP("lms", test_wc_LmsKey_sign_verify), TEST_DECL_GROUP("lms", test_wc_LmsKey_reload_cache), /* RFC 9802 (HSS/LMS and XMSS/XMSS^MT in X.509) */ TEST_DECL_GROUP("lms", test_rfc9802_lms_x509_verify), TEST_DECL_GROUP("xmss", test_rfc9802_xmss_x509_verify), /* PEM and DER APIs. */ TEST_DECL(test_wc_PemToDer), TEST_DECL(test_wc_AllocDer), TEST_DECL(test_wc_CertPemToDer), TEST_DECL(test_wc_KeyPemToDer), TEST_DECL(test_wc_PubKeyPemToDer), TEST_DECL(test_wc_PemPubKeyToDer), TEST_DECL(test_wc_GetPubKeyDerFromCert), TEST_DECL(test_wc_GetSubjectPubKeyInfoDerFromCert), TEST_DECL(test_wc_CheckCertSigPubKey), /* wolfCrypt ASN tests */ TEST_DECL(test_ToTraditional), TEST_DECL(test_wc_CreateEncryptedPKCS8Key), TEST_DECL(test_wc_DecryptedPKCS8Key), TEST_DECL(test_wc_GetPkcs8TraditionalOffset), /* Certificate */ TEST_DECL(test_wc_SetSubjectRaw), TEST_DECL(test_wc_GetSubjectRaw), TEST_DECL(test_wc_SetIssuerRaw), TEST_DECL(test_wc_SetIssueBuffer), TEST_DECL(test_wc_SetSubjectKeyId), TEST_DECL(test_wc_SetSubject), TEST_DECL(test_CheckCertSignature), TEST_DECL(test_wc_ParseCert), TEST_DECL(test_wc_ParseCert_Error), TEST_DECL(test_MakeCertWithPathLen), TEST_DECL(test_PathLenSelfIssued), TEST_DECL(test_PathLenSelfIssuedAllowed), TEST_DECL(test_PathLenNoKeyUsage), TEST_DECL(test_NameConstraints_OtherName), TEST_DECL(test_ParseSerial0FixtureMatrix), TEST_DECL(test_MakeCertWithCaFalse), #ifdef WOLFSSL_CERT_SIGN_CB TEST_DECL(test_wc_SignCert_cb), #endif TEST_DECL(test_wc_SetAcmeIdentifierExt), TEST_DECL(test_wc_SetKeyUsage), TEST_DECL(test_wc_SetAuthKeyIdFromPublicKey_ex), TEST_DECL(test_wc_SetSubjectBuffer), TEST_DECL(test_wc_SetSubjectKeyIdFromPublicKey_ex), /* wolfcrypt PKCS#7 */ TEST_PKCS7_DECLS, TEST_PKCS7_SIGNED_DATA_DECLS, TEST_PKCS7_ENCRYPTED_DATA_DECLS, TEST_PKCS7_SIGNED_ENCRYPTED_DATA_DECLS, TEST_PKCS7_COMPRESSED_DATA_DECLS, /* wolfCrypt PKCS#12 */ TEST_PKCS12_DECLS, /* * test_wolfCrypt_Cleanup needs to come after the above wolfCrypt tests to * avoid memory leaks. */ TEST_DECL(test_wolfCrypt_Cleanup), TEST_DECL(test_wolfSSL_Init), /* x509 -- must appear after test_wolfSSL_Init(). */ TEST_X509_DECLS, TEST_DECL(test_dual_alg_support), TEST_DECL(test_dual_alg_crit_ext_support), TEST_DECL(test_dual_alg_ecdsa_mldsa), TEST_DECL(test_wolfSSL_use_AltPrivateKey_Id), TEST_DECL(test_wolfSSL_use_AltPrivateKey_Label), /********************************* * OpenSSL compatibility API tests *********************************/ /* If at some point a stub get implemented this test should fail indicating * a need to implement a new test case */ TEST_DECL(test_stubs_are_stubs), /* ASN.1 compatibility API tests */ TEST_OSSL_ASN1_BIT_STRING_DECLS, TEST_OSSL_ASN1_INTEGER_DECLS, TEST_OSSL_ASN1_OBJECT_DECLS, TEST_OSSL_ASN1_STRING_DECLS, TEST_OSSL_ASN1_TIME_DECLS, TEST_OSSL_ASN1_TYPE_DECLS, TEST_SSL_SK_DECLS, TEST_DECL(test_wolfSSL_lhash), TEST_DECL(test_wolfSSL_certs), TEST_DECL(test_wolfSSL_X509_ext_d2i), TEST_DECL(test_wolfSSL_private_keys), TEST_SSL_PEM_DECLS, /* EVP API testing */ TEST_EVP_ENC_DECLS, TEST_EVP_DIGEST_DECLS, TEST_EVP_CIPHER_DECLS, TEST_EVP_PKEY_DECLS, TEST_DECL(test_wolfSSL_d2i_and_i2d_PublicKey), TEST_DECL(test_wolfSSL_d2i_and_i2d_PublicKey_ecc), #ifndef NO_BIO TEST_DECL(test_wolfSSL_d2i_PUBKEY), #endif TEST_DECL(test_wolfSSL_d2i_and_i2d_DSAparams), TEST_DECL(test_wolfSSL_i2d_PrivateKey), #if (defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO)) && !defined(NO_RSA) && \ !defined(NO_TLS) #ifndef NO_BIO TEST_DECL(test_wolfSSL_d2i_PrivateKeys_bio), #endif /* !NO_BIO */ #endif #if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) TEST_DECL(test_wolfSSL_ERR_peek_last_error_line), #endif #ifndef NO_BIO TEST_DECL(test_wolfSSL_ERR_print_errors_cb), TEST_DECL(test_wolfSSL_GetLoggingCb), TEST_DECL(test_WOLFSSL_ERROR_MSG), TEST_DECL(test_wc_ERR_remove_state), TEST_DECL(test_wc_ERR_print_errors_fp), #endif TEST_DECL(test_wolfSSL_configure_args), TEST_DECL(test_wolfSSL_sk_SSL_CIPHER), TEST_DECL(test_wolfSSL_set1_curves_list), TEST_DECL(test_wolfSSL_curves_mismatch), TEST_DECL(test_wolfSSL_set1_sigalgs_list), TEST_DECL(test_wolfSSL_OtherName), TEST_DECL(test_wolfSSL_FPKI), TEST_DECL(test_wolfSSL_URI), /* X509 tests */ TEST_OSSL_X509_DECLS, TEST_OSSL_X509_NAME_DECLS, TEST_OSSL_X509_EXT_DECLS, TEST_OSSL_X509_PK_DECLS, TEST_OSSL_X509_VFY_PARAMS_DECLS, TEST_OSSL_X509_IO_DECLS, TEST_OSSL_X509_CRYPTO_DECLS, TEST_OSSL_X509_ACERT_DECLS, TEST_OSSL_X509_INFO_DECLS, TEST_DECL(test_wolfSSL_X509_ALGOR_get0), TEST_DECL(test_wolfSSL_X509_SEP), TEST_DECL(test_wolfSSL_X509_set_extensions), TEST_DECL(test_wolfSSL_X509_set_authority_key_id_roundtrip), TEST_DECL(test_wolfSSL_X509_set_authority_key_id_ex_roundtrip), TEST_DECL(test_wolfSSL_X509_set_authority_key_id_overwrite), TEST_DECL(test_wolfSSL_X509_CRL), #ifndef NO_BIO TEST_DECL(test_wolfSSL_X509_print), TEST_DECL(test_wolfSSL_X509_CRL_print), #endif /* X509 Store tests */ TEST_OSSL_X509_STORE_DECLS, TEST_OSSL_X509_LOOKUP_DECLS, TEST_DECL(test_GENERAL_NAME_set0_othername), TEST_DECL(test_RID_GENERAL_NAME_free), TEST_DECL(test_RID_X509_get_ext_d2i), TEST_DECL(test_othername_and_SID_ext), TEST_DECL(test_wolfSSL_dup_CA_list), /* OpenSSL sk_X509 API test */ TEST_DECL(test_sk_X509), /* OpenSSL sk_X509_CRL API test */ TEST_DECL(test_sk_X509_CRL_decode), #if (defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)) && !defined(NO_CERTS) && \ defined(HAVE_CRL) && defined(WOLFSSL_CERT_GEN) TEST_DECL(test_wolfSSL_X509_CRL_add_revoked_oversized_revocation_date), #endif #if (defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)) && !defined(NO_CERTS) && \ defined(HAVE_CRL) && !defined(NO_FILESYSTEM) && \ !defined(NO_STDIO_FILESYSTEM) TEST_DECL(test_wolfSSL_X509_CRL_reason_critical_boolean), #endif TEST_DECL(test_sk_X509_CRL_encode), TEST_DECL(test_wolfSSL_X509_CRL_sign_large), TEST_DECL(test_wc_MakeCRL_max_crlnum), /* OpenSSL X509 REQ API test */ TEST_DECL(test_wolfSSL_d2i_X509_REQ), TEST_DECL(test_X509_REQ), TEST_DECL(test_wolfSSL_X509_REQ_print), /* RAND compatibility API */ TEST_OSSL_RAND_DECLS, /* BN compatibility API */ TEST_OSSL_ASN1_BN_DECLS, /* OpenSSL PKCS5 API test */ TEST_DECL(test_wolfSSL_PKCS5), /* OpenSSL PKCS8 API test */ TEST_DECL(test_wolfSSL_PKCS8_Compat), TEST_DECL(test_wolfSSL_PKCS8_d2i), /* OpenSSL PKCS7 API test */ TEST_OSSL_PKCS7_DECLS, TEST_OSSL_SMIME_DECLS, /* OpenSSL PKCS12 API test */ TEST_OSSL_PKCS12_DECLS, /* Can't memory test as callbacks use Assert. */ TEST_DECL(test_error_queue_per_thread), TEST_DECL(test_wolfSSL_ERR_put_error), TEST_DECL(test_wolfSSL_ERR_get_error_order), #ifndef NO_BIO TEST_DECL(test_wolfSSL_ERR_print_errors), #endif TEST_OSSL_OBJ_DECLS, #ifndef NO_BIO TEST_OSSL_BIO_DECLS, #endif TEST_DECL(test_wolfSSL_check_domain), TEST_DECL(test_wolfSSL_check_domain_basic), TEST_DECL(test_wolfSSL_check_ip_param_basic), TEST_DECL(test_wolfSSL_check_ip_address_basic), TEST_DECL(test_wolfSSL_cert_cb), TEST_DECL(test_wolfSSL_cert_cb_dyn_ciphers), TEST_DECL(test_wolfSSL_ciphersuite_auth), TEST_DECL(test_wolfSSL_sigalg_info), /* Can't memory test as tcp_connect aborts. */ TEST_DECL(test_wolfSSL_d2i_SSL_SESSION_bounds_check), TEST_DECL(test_wolfSSL_SESSION), TEST_DECL(test_wolfSSL_SESSION_expire_downgrade), TEST_DECL(test_wolfSSL_CTX_sess_set_remove_cb), TEST_DECL(test_wolfSSL_ticket_keys), TEST_DECL(test_wolfSSL_sk_GENERAL_NAME), TEST_DECL(test_wolfSSL_GENERAL_NAME_print), TEST_DECL(test_wolfSSL_sk_DIST_POINT), TEST_DECL(test_wolfSSL_verify_mode), TEST_DECL(test_wolfSSL_verify_depth), TEST_DECL(test_wolfSSL_verify_result), TEST_DECL(test_wolfSSL_msg_callback), TEST_DECL(test_wolfSSL_OCSP_id_get0_info), TEST_DECL(test_wolfSSL_i2d_OCSP_CERTID), TEST_DECL(test_wolfSSL_d2i_OCSP_CERTID), TEST_DECL(test_wolfSSL_OCSP_id_cmp), TEST_DECL(test_wolfSSL_OCSP_SINGLERESP_get0_id), TEST_DECL(test_wolfSSL_OCSP_single_get0_status), TEST_DECL(test_wolfSSL_OCSP_resp_count), TEST_DECL(test_wolfSSL_OCSP_resp_get0), TEST_DECL(test_wolfSSL_OCSP_parse_url), TEST_DECL(test_wolfSSL_OCSP_REQ_CTX), TEST_DECL(test_wolfSSL_X509_get1_ca_issuers), TEST_DECL(test_wolfSSL_X509_get1_aia_multi), TEST_DECL(test_wolfSSL_X509_get1_aia_overflow), TEST_DECL(test_wolfSSL_SubjectInfoAccess_no_caRepository), TEST_DECL(test_wolfSSL_PEM_read), TEST_DECL(test_wolfSSL_OpenSSL_version), TEST_DECL(test_wolfSSL_OpenSSL_add_all_algorithms), TEST_DECL(test_wolfSSL_OPENSSL_hexstr2buf), TEST_DECL(test_CONF_modules_xxx), #ifdef OPENSSL_ALL TEST_DECL(test_wolfSSL_TXT_DB), TEST_DECL(test_wolfSSL_NCONF), #endif TEST_DECL(test_wolfSSL_CRYPTO_memcmp), TEST_DECL(test_wolfSSL_CRYPTO_get_ex_new_index), TEST_DECL(test_wolfSSL_SESSION_get_ex_new_index), TEST_DECL(test_CRYPTO_set_dynlock_xxx), TEST_DECL(test_CRYPTO_THREADID_xxx), TEST_DECL(test_ENGINE_cleanup), /* test the no op functions for compatibility */ TEST_DECL(test_no_op_functions), /* OpenSSL error API tests */ TEST_DECL(test_ERR_load_crypto_strings), #ifdef OPENSSL_ALL TEST_DECL(test_wolfSSL_sk_CIPHER_description), TEST_DECL(test_wolfSSL_get_ciphers_compat), TEST_DECL(test_wolfSSL_get_ciphers_compat_empty), TEST_DECL(test_wolfSSL_CTX_ctrl), #endif /* OPENSSL_ALL */ #if (defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO)) && !defined(NO_RSA) TEST_DECL(test_wolfSSL_CTX_use_certificate_ASN1), #endif /* (OPENSSL_ALL || WOLFSSL_ASIO) && !NO_RSA */ /********************************* * Crypto API tests *********************************/ TEST_OSSL_DIGEST_DECLS, TEST_OSSL_MAC_DECLS, TEST_OSSL_CIPHER_DECLS, TEST_OSSL_RSA_DECLS, TEST_OSSL_DH_DECLS, #if defined(HAVE_ECC) && !defined(OPENSSL_NO_PK) TEST_OSSL_EC_DECLS, #endif #ifdef OPENSSL_EXTRA TEST_OSSL_ECX_DECLS, #endif TEST_OSSL_DSA_DECLS, TEST_DECL(test_openssl_generate_key_and_cert), TEST_DECL(test_wolfSSL_FIPS_mode), TEST_DECL(test_openssl_FIPS_drbg), /********************************* * CertManager API tests *********************************/ TEST_CERTMAN_DECLS, TEST_DECL(test_wolfSSL_CheckOCSPResponse), /********************************* * SSL/TLS API tests *********************************/ TEST_DECL(test_wolfSSL_Method_Allocators), #if !defined(NO_WOLFSSL_SERVER) && !defined(NO_TLS) TEST_DECL(test_wolfSSL_CTX_new), #endif TEST_DECL(test_server_wolfSSL_new), TEST_DECL(test_client_wolfSSL_new), #if (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) && \ !defined(NO_TLS) && \ (!defined(NO_RSA) || defined(HAVE_ECC)) && !defined(NO_FILESYSTEM) TEST_DECL(test_for_double_Free), #endif TEST_DECL(test_wolfSSL_set_options), TEST_TLS13_DECLS, TEST_DECL(test_wolfSSL_tmp_dh), TEST_DECL(test_wolfSSL_tmp_dh_regression), TEST_DECL(test_wolfSSL_ctrl), TEST_DECL(test_wolfSSL_get0_param), TEST_DECL(test_wolfSSL_set1_host), #if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && \ (defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \ defined(HAVE_LIGHTY) || defined(WOLFSSL_HAPROXY) || \ defined(WOLFSSL_OPENSSH) || defined(HAVE_SBLIM_SFCB))) TEST_DECL(test_wolfSSL_set_SSL_CTX), #endif TEST_DECL(test_wolfSSL_CTX_get_min_proto_version), TEST_DECL(test_wolfSSL_security_level), TEST_DECL(test_wolfSSL_crypto_policy), TEST_DECL(test_wolfSSL_crypto_policy_certs_and_keys), TEST_DECL(test_wolfSSL_crypto_policy_tls_methods), TEST_DECL(test_wolfSSL_crypto_policy_ciphers), TEST_DECL(test_wolfSSL_SSL_in_init), TEST_DECL(test_wolfSSL_CTX_set_timeout), TEST_DECL(test_wolfSSL_set_psk_use_session_callback), TEST_DECL(test_CONF_CTX_FILE), TEST_DECL(test_CONF_CTX_CMDLINE), #if !defined(NO_CERTS) && (!defined(NO_WOLFSSL_CLIENT) || \ !defined(WOLFSSL_NO_CLIENT_AUTH)) && !defined(NO_FILESYSTEM) && \ !defined(WOLFSSL_TEST_APPLE_NATIVE_CERT_VALIDATION) && \ (!defined(NO_RSA) || defined(HAVE_ECC)) && !defined(NO_SHA256) /* Use the Cert Manager(CM) API to generate the error ASN_SIG_CONFIRM_E */ /* Bad certificate signature tests */ TEST_DECL(test_EccSigFailure_cm), TEST_DECL(test_RsaSigFailure_cm), #endif TEST_DECL(test_wc_CheckPrivateKey_RSA_pub_only), /* PKCS8 testing */ TEST_DECL(test_wolfSSL_no_password_cb), TEST_DECL(test_wolfSSL_PKCS8), TEST_DECL(test_wolfSSL_PKCS8_ED25519), TEST_DECL(test_wolfSSL_PKCS8_ED448), #ifdef HAVE_IO_TESTS_DEPENDENCIES TEST_DECL(test_wolfSSL_get_finished), /* Uses Assert in handshake callback. */ TEST_DECL(test_wolfSSL_CTX_add_session), /* Large number of memory allocations. */ TEST_DECL(test_wolfSSL_CTX_add_session_ext_tls13), /* Large number of memory allocations. */ TEST_DECL(test_wolfSSL_CTX_add_session_ext_dtls13), /* Large number of memory allocations. */ TEST_DECL(test_wolfSSL_CTX_add_session_ext_tls12), /* Large number of memory allocations. */ TEST_DECL(test_wolfSSL_CTX_add_session_ext_dtls12), /* Large number of memory allocations. */ TEST_DECL(test_wolfSSL_CTX_add_session_ext_tls11), /* Large number of memory allocations. */ TEST_DECL(test_wolfSSL_CTX_add_session_ext_dtls1), #endif TEST_DECL(test_SSL_CIPHER_get_xxx), TEST_DECL(test_wolfSSL_ERR_strings), TEST_DECL(test_wolfSSL_CTX_set_cipher_list_bytes), TEST_DECL(test_wolfSSL_set_cipher_list_tls12_keeps_tls13), TEST_DECL(test_wolfSSL_set_cipher_list_tls13_keeps_tls12), TEST_DECL(test_wolfSSL_set_cipher_list_tls12_with_version), TEST_DECL(test_wolfSSL_set_cipher_list_tls13_with_version), TEST_DECL(test_wolfSSL_set_alpn_protos_default_fails), TEST_DECL(test_wolfSSL_CTX_use_certificate), TEST_DECL(test_wolfSSL_CTX_use_certificate_file), TEST_DECL(test_wolfSSL_CTX_use_certificate_buffer), TEST_DECL(test_wolfSSL_use_certificate_buffer), TEST_DECL(test_wolfSSL_CTX_use_PrivateKey_file), TEST_DECL(test_wolfSSL_CTX_use_RSAPrivateKey_file), TEST_DECL(test_wolfSSL_use_RSAPrivateKey_file), TEST_DECL(test_wolfSSL_CTX_use_PrivateKey), TEST_DECL(test_wolfSSL_CTX_load_verify_locations), /* Large number of memory allocations. */ TEST_DECL(test_wolfSSL_CTX_load_system_CA_certs), TEST_DECL(test_wolfSSL_CTX_add_extra_chain_cert), #if defined(HAVE_CERT_CHAIN_VALIDATION) && \ !defined(WOLFSSL_TEST_APPLE_NATIVE_CERT_VALIDATION) TEST_DECL(test_wolfSSL_CertRsaPss), #endif TEST_DECL(test_wolfSSL_CTX_load_verify_locations_ex), TEST_DECL(test_wolfSSL_CTX_load_verify_buffer_ex), TEST_DECL(test_wolfSSL_CTX_load_verify_chain_buffer_format), TEST_DECL(test_wolfSSL_CTX_add1_chain_cert), TEST_DECL(test_wolfSSL_add_to_chain_overflow), TEST_DECL(test_wolfSSL_CTX_use_certificate_chain_buffer_format), TEST_DECL(test_wolfSSL_CTX_use_certificate_chain_file_format), TEST_DECL(test_wolfSSL_use_certificate_chain_file), TEST_DECL(test_wolfSSL_CTX_trust_peer_cert), TEST_DECL(test_wolfSSL_CTX_LoadCRL), TEST_DECL(test_wolfSSL_CTX_LoadCRL_largeCRLnum), TEST_DECL(test_wolfSSL_crl_update_cb), TEST_DECL(test_wolfSSL_CTX_SetTmpDH_file), TEST_DECL(test_wolfSSL_CTX_SetTmpDH_buffer), TEST_DECL(test_wolfSSL_CTX_SetMinMaxDhKey_Sz), TEST_DECL(test_wolfSSL_CTX_der_load_verify_locations), TEST_DECL(test_wolfSSL_CTX_enable_disable), TEST_DECL(test_wolfSSL_CTX_ticket_API), TEST_DECL(test_wolfSSL_SetTmpDH_file), TEST_DECL(test_wolfSSL_SetTmpDH_buffer), TEST_DECL(test_wolfSSL_SetMinMaxDhKey_Sz), TEST_DECL(test_SetTmpEC_DHE_Sz), TEST_DECL(test_wolfSSL_CTX_get0_privatekey), #ifdef WOLFSSL_DTLS TEST_DECL(test_wolfSSL_DtlsUpdateWindow), TEST_DECL(test_wolfSSL_DTLS_fragment_buckets), #endif TEST_DECL(test_wolfSSL_dtls_set_mtu), /* Uses Assert in handshake callback. */ TEST_DECL(test_wolfSSL_dtls_plaintext), #if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) && \ defined(HAVE_IO_TESTS_DEPENDENCIES) TEST_DECL(test_wolfSSL_read_write), TEST_DECL(test_wolfSSL_read_write_ex), /* Can't memory test as server hangs if client fails before second connect. */ TEST_DECL(test_wolfSSL_reuse_WOLFSSLobj), TEST_DECL(test_wolfSSL_CTX_verifyDepth_ServerClient_1), TEST_DECL(test_wolfSSL_CTX_verifyDepth_ServerClient_2), TEST_DECL(test_wolfSSL_CTX_verifyDepth_ServerClient_3), TEST_DECL(test_wolfSSL_CTX_set_cipher_list), /* Can't memory test as server hangs. */ TEST_DECL(test_wolfSSL_dtls_export), /* Uses Assert in handshake callback. */ TEST_DECL(test_wolfSSL_tls_export), #endif TEST_DECL(test_wolfSSL_dtls_export_peers), TEST_DECL(test_wolfSSL_dtls_import_state_extra_window_words), TEST_DECL(test_wolfSSL_SetMinVersion), TEST_DECL(test_wolfSSL_CTX_SetMinVersion), /* wolfSSL handshake APIs. */ TEST_DECL(test_wolfSSL_CTX_get0_set1_param), TEST_DECL(test_wolfSSL_a2i_IPADDRESS), TEST_DECL(test_wolfSSL_BUF), TEST_DECL(test_wolfSSL_set_tlsext_status_type), TEST_DECL(test_wolfSSL_get_client_ciphers), /* Can't memory test as server hangs. */ TEST_DECL(test_wolfSSL_CTX_set_client_CA_list), TEST_DECL(test_wolfSSL_CTX_add_client_CA), TEST_DECL(test_wolfSSL_CTX_set_srp_username), TEST_DECL(test_wolfSSL_CTX_set_srp_password), TEST_DECL(test_wolfSSL_CTX_set_keylog_callback), TEST_DECL(test_wolfSSL_CTX_get_keylog_callback), TEST_DECL(test_wolfSSL_Tls12_Key_Logging_test), /* Can't memory test as server hangs. */ TEST_DECL(test_wolfSSL_Tls13_Key_Logging_test), TEST_DECL(test_wolfSSL_Tls13_postauth), TEST_DECL(test_wolfSSL_set_ecdh_auto), TEST_DECL(test_wolfSSL_CTX_set_ecdh_auto), TEST_DECL(test_wolfSSL_set_minmax_proto_version), TEST_DECL(test_wolfSSL_CTX_set_max_proto_version), TEST_DECL(test_wolfSSL_THREADID_hash), /* TLS extensions tests */ #ifdef HAVE_IO_TESTS_DEPENDENCIES #ifdef HAVE_SNI TEST_DECL(test_wolfSSL_UseSNI_params), /* Uses Assert in handshake callback. */ TEST_DECL(test_wolfSSL_UseSNI_connection), TEST_DECL(test_wolfSSL_SNI_GetFromBuffer), #endif /* HAVE_SNI */ #endif TEST_DECL(test_wolfSSL_UseTrustedCA), TEST_DECL(test_wolfSSL_UseMaxFragment), TEST_DECL(test_wolfSSL_UseTruncatedHMAC), TEST_DECL(test_wolfSSL_UseSupportedCurve), #if defined(HAVE_ALPN) && defined(HAVE_IO_TESTS_DEPENDENCIES) /* Uses Assert in handshake callback. */ TEST_DECL(test_wolfSSL_UseALPN_connection), TEST_DECL(test_wolfSSL_UseALPN_params), #endif #ifdef HAVE_ALPN_PROTOS_SUPPORT /* Uses Assert in handshake callback. */ TEST_DECL(test_wolfSSL_set_alpn_protos), TEST_DECL(test_wolfSSL_select_next_proto), #endif TEST_DECL(test_tls_ems_downgrade), TEST_DECL(test_tls_ems_resumption_downgrade), TEST_DECL(test_tls12_chacha20_poly1305_bad_tag), TEST_DECL(test_tls13_null_cipher_bad_hmac), TEST_DECL(test_scr_verify_data_mismatch), TEST_DECL(test_tls13_hrr_cipher_suite_mismatch), TEST_DECL(test_tls13_ticket_age_out_of_window), TEST_DECL(test_wolfSSL_DisableExtendedMasterSecret), TEST_DECL(test_certificate_authorities_certificate_request), TEST_DECL(test_certificate_authorities_client_hello), TEST_DECL(test_TLSX_TCA_Find), TEST_DECL(test_TLSX_SNI_GetSize_overflow), TEST_DECL(test_TLSX_ECH_msg_type_validation), TEST_DECL(test_TLSX_SRTP_msg_type_validation), TEST_DECL(test_wolfSSL_wolfSSL_UseSecureRenegotiation), TEST_DECL(test_wolfSSL_clear_secure_renegotiation), TEST_DECL(test_wolfSSL_SCR_Reconnect), TEST_DECL(test_wolfSSL_SCR_check_enabled), TEST_DECL(test_wolfSSL_ticket_keycb_bad_hmac), TEST_DECL(test_tls_ext_duplicate), TEST_DECL(test_tls_ext_word16_overflow), TEST_DECL(test_tls_bad_legacy_version), #if defined(WOLFSSL_TLS13) && defined(HAVE_ECH) #if defined(HAVE_IO_TESTS_DEPENDENCIES) TEST_DECL(test_wolfSSL_Tls13_ECH_params), TEST_DECL(test_wolfSSL_Tls13_ECH_params_b64), /* Uses Assert in handshake callback. */ TEST_DECL(test_wolfSSL_Tls13_ECH), TEST_DECL(test_wolfSSL_Tls13_ECH_HRR), TEST_DECL(test_wolfSSL_SubTls13_ECH), #endif #if defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) TEST_DECL(test_wolfSSL_Tls13_ECH_all_algos), TEST_DECL(test_wolfSSL_Tls13_ECH_no_private_name), TEST_DECL(test_wolfSSL_Tls13_ECH_bad_configs), TEST_DECL(test_wolfSSL_Tls13_ECH_retry_configs), TEST_DECL(test_wolfSSL_Tls13_ECH_retry_configs_bad), TEST_DECL(test_wolfSSL_Tls13_ECH_retry_configs_auth_fail), TEST_DECL(test_wolfSSL_Tls13_ECH_new_config), TEST_DECL(test_wolfSSL_Tls13_ECH_GREASE), TEST_DECL(test_wolfSSL_Tls13_ECH_disable_conn), TEST_DECL(test_wolfSSL_Tls13_ECH_long_SNI), TEST_DECL(test_wolfSSL_Tls13_ECH_HRR_rejection), TEST_DECL(test_wolfSSL_Tls13_ECH_ch2_no_ech), TEST_DECL(test_wolfSSL_Tls13_ECH_ch2_decrypt_error), TEST_DECL(test_wolfSSL_Tls13_ECH_rejected_cert_valid), TEST_DECL(test_wolfSSL_Tls13_ECH_rejected_empty_client_cert), #endif #if defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_TEST_ECH) && \ !defined(WOLFSSL_NO_TLS12) TEST_DECL(test_wolfSSL_Tls13_ECH_tamper_client), #endif TEST_DECL(test_wolfSSL_Tls13_ECH_enable_disable), #endif /* WOLFSSL_TLS13 && HAVE_ECH */ TEST_DECL(test_wolfSSL_X509_TLS_version_test_1), TEST_DECL(test_wolfSSL_X509_TLS_version_test_2), /* OCSP Stapling */ TEST_DECL(test_wolfSSL_UseOCSPStapling), TEST_DECL(test_wolfSSL_UseOCSPStaplingV2), TEST_DECL(test_self_signed_stapling), TEST_DECL(test_ocsp_callback_fails), /* Multicast */ TEST_DECL(test_wolfSSL_mcast), TEST_DECL(test_wolfSSL_read_detect_TCP_disconnect), TEST_DECL(test_wolfSSL_msgCb), TEST_DECL(test_wolfSSL_either_side), TEST_DECL(test_wolfSSL_DTLS_either_side), /* Uses Assert in handshake callback. */ TEST_DECL(test_wolfSSL_dtls_fragments), /* Uses Assert in handshake callback. */ TEST_DECL(test_wolfSSL_dtls_AEAD_limit), /* Uses Assert in handshake callback. */ TEST_DECL(test_wolfSSL_ignore_alert_before_cookie), /* Uses Assert in handshake callback. */ TEST_DECL(test_wolfSSL_dtls_bad_record), /* Uses Assert in handshake callback. */ TEST_DECL(test_wolfSSL_dtls_stateless), TEST_DECL(test_wolfSSL_dtls_stateless_hrr_group), TEST_DECL(test_generate_cookie), #ifndef NO_BIO TEST_OSSL_BIO_TLS_DECLS, #endif #if defined(HAVE_PK_CALLBACKS) && !defined(WOLFSSL_NO_TLS12) TEST_DECL(test_DhCallbacks), #endif #if defined(HAVE_KEYING_MATERIAL) && defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) TEST_DECL(test_export_keying_material), #endif /* Can't memory test as client/server Asserts in thread. */ TEST_DECL(test_ticket_and_psk_mixing), /* Can't memory test as client/server Asserts in thread. */ TEST_DECL(test_prioritize_psk), /* Can't memory test as client/server hangs. */ TEST_DECL(test_wc_CryptoCb), /* Can't memory test as client/server hangs. */ TEST_DECL(test_wolfSSL_CTX_StaticMemory), #if !defined(NO_FILESYSTEM) && \ defined(WOLFSSL_DTLS) && !defined(WOLFSSL_NO_TLS12) && \ !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) #ifdef WOLFSSL_DTLS_NO_HVR_ON_RESUME TEST_DECL(test_wolfSSL_dtls_stateless_resume), #endif /* WOLFSSL_DTLS_NO_HVR_ON_RESUME */ #ifdef HAVE_MAX_FRAGMENT TEST_DECL(test_wolfSSL_dtls_stateless_maxfrag), #endif /* HAVE_MAX_FRAGMENT */ #ifndef NO_RSA TEST_DECL(test_wolfSSL_dtls_stateless2), #if !defined(NO_OLD_TLS) TEST_DECL(test_wolfSSL_dtls_stateless_downgrade), #endif /* !defined(NO_OLD_TLS) */ #endif /* ! NO_RSA */ #endif /* defined(WOLFSSL_DTLS) && !defined(WOLFSSL_NO_TLS12) && \ * !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) */ TEST_DECL(test_wolfSSL_CTX_set_ciphersuites), TEST_DECL(test_wolfSSL_CRL_CERT_REVOKED_alert), TEST_DECL(test_TLS_13_ticket_different_ciphers), TEST_DECL(test_WOLFSSL_dtls_version_alert), #if defined(WOLFSSL_TICKET_NONCE_MALLOC) && defined(HAVE_SESSION_TICKET) \ && defined(WOLFSSL_TLS13) && \ (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3)))\ && defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) TEST_DECL(test_ticket_nonce_malloc), #endif TEST_DECL(test_ticket_ret_create), TEST_DECL(test_ticket_enc_corrupted), TEST_DECL(test_wrong_cs_downgrade), TEST_DECL(test_extra_alerts_wrong_cs), TEST_DECL(test_extra_alerts_skip_hs), TEST_DECL(test_extra_alerts_bad_psk), TEST_DECL(test_multiple_shutdown_nonblocking), /* Can't memory test as client/server Asserts. */ TEST_DECL(test_harden_no_secure_renegotiation), TEST_DECL(test_override_alt_cert_chain), TEST_DECL(test_rpk_set_xxx_cert_type), TEST_DECL(test_dtls13_bad_epoch_ch), TEST_DECL(test_short_session_id), TEST_DECL(test_wolfSSL_dtls13_null_cipher), /* Can't memory test as client/server hangs. */ TEST_DECL(test_dtls_msg_from_other_peer), TEST_DECL(test_dtls_ipv6_check), TEST_DECL(test_wolfSSL_SCR_after_resumption), TEST_DECL(test_dtls_no_extensions), TEST_DECL(test_tls_alert_no_server_hello), TEST_DECL(test_TLSX_CA_NAMES_bad_extension), TEST_DECL(test_dtls_1_0_hvr_downgrade), TEST_DECL(test_session_ticket_no_id), TEST_DECL(test_session_ticket_hs_update), TEST_DECL(test_dtls_downgrade_scr_server), TEST_DECL(test_dtls_downgrade_scr), TEST_DECL(test_dtls_client_hello_timeout_downgrade), TEST_DECL(test_dtls_client_hello_timeout), TEST_DECL(test_dtls_dropped_ccs), TEST_DECL(test_dtls_seq_num_downgrade), TEST_DECL(test_certreq_sighash_algos), TEST_DECL(test_revoked_loaded_int_cert), TEST_DECL(test_dtls_frag_ch), TEST_DECL(test_dtls13_frag_ch_pq), TEST_DECL(test_dtls_empty_keyshare_with_cookie), TEST_DECL(test_dtls_old_seq_number), TEST_DECL(test_dtls12_missing_finished), TEST_DECL(test_dtls13_missing_finished_client), TEST_DECL(test_dtls13_missing_finished_server), TEST_DECL(test_dtls13_finished_send_error_propagation), TEST_DTLS_DECLS, TEST_DECL(test_tls_multi_handshakes_one_record), TEST_DECL(test_write_dup), TEST_DECL(test_write_dup_want_write), TEST_DECL(test_write_dup_want_write_simul), TEST_DECL(test_write_dup_oom), TEST_DECL(test_read_write_hs), TEST_DECL(test_get_signature_nid), #ifndef WOLFSSL_TEST_APPLE_NATIVE_CERT_VALIDATION TEST_DECL(test_tls_cert_store_unchanged), #endif TEST_DECL(test_wolfSSL_SendUserCanceled), TEST_DECL(test_wolfSSL_SSLDisableRead), TEST_DECL(test_wolfSSL_inject), TEST_DECL(test_ocsp_status_callback), TEST_DECL(test_ocsp_basic_verify), TEST_DECL(test_ocsp_responder_keyhash_binding), TEST_DECL(test_ocsp_response_parsing), TEST_DECL(test_ocsp_certid_enc_dec), TEST_DECL(test_ocsp_certid_dup), TEST_DECL(test_ocsp_tls_cert_cb), TEST_DECL(test_ocsp_cert_unknown_crl_fallback), TEST_DECL(test_ocsp_cert_unknown_crl_fallback_nonleaf), TEST_DECL(test_tls13_nonblock_ocsp_low_mfl), TEST_DECL(test_ocsp_responder), TEST_TLS_DECLS, TEST_DECL(test_wc_DhSetNamedKey), TEST_DECL(test_DhAgree_rejects_p_minus_1), TEST_DECL(test_ed448_rejects_identity_key), TEST_DECL(test_pkcs7_decode_encrypted_outputsz), TEST_DECL(test_pkcs7_ori_oversized_oid), TEST_DECL(test_pkcs7_ori_seqsz_underflow), TEST_DECL(test_pkcs7_ori_orivalue_overflow), TEST_DECL(test_pkcs7_ktri_skid_length_mismatch), TEST_DECL(test_pkcs7_kari_degenerate_bitstring), TEST_DECL(test_pkcs7_encrypted_content_size_overflow), TEST_DECL(test_pkcs7_signed_bad_sig_tag), TEST_DECL(test_pkcs7_enveloped_content_size_overflow), TEST_DECL(test_pkcs7_padding), #if defined(WOLFSSL_SNIFFER) && defined(WOLFSSL_SNIFFER_CHAIN_INPUT) TEST_DECL(test_sniffer_chain_input_overflow), #endif TEST_DECL(test_mldsa_verify_hash), TEST_DECL(test_dilithium_hash), /* This test needs to stay at the end to clean up any caches allocated. */ TEST_DECL(test_wolfSSL_Cleanup) }; #define TEST_CASE_CNT (int)(sizeof(testCases) / sizeof(*testCases)) static void TestSetup(void) { #ifdef WOLFSSL_SWDEV /* Re-arm the swdev cryptocb registration in case the previous test * tore down wolfCrypt and wiped gCryptoDev. */ (void)wc_SwDev_Init(); #endif } static void TestCleanup(void) { #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) /* Clear any errors added to the error queue during the test run. */ wolfSSL_ERR_clear_error(); #endif /* OPENSSL_EXTRA || DEBUG_WOLFSSL_VERBOSE */ #ifdef WOLFSSL_SWDEV wc_SwDev_Cleanup(); #endif } void ApiTest_StopOnFail(void) { stopOnFail = 1; } /* Print out all API test cases with numeric identifier. */ void ApiTest_PrintTestCases(void) { int i; const char* lastGroup = NULL; printf("All Test Cases:\n"); for (i = 0; i < TEST_CASE_CNT; i++) { if ((lastGroup != NULL) && ((testCases[i].group == NULL) || XSTRCMP(testCases[i].group, lastGroup) != 0)) { printf("End Group : %s\n", lastGroup); } if ((testCases[i].group != NULL) && ((lastGroup == NULL) || XSTRCMP(testCases[i].group, lastGroup) != 0)) { printf("Begin Group: %s\n", testCases[i].group); } lastGroup = testCases[i].group; printf("%3d: %s\n", i + 1, testCases[i].name); } } /* Print out all API group names. */ void ApiTest_PrintGroups(void) { int i; const char* lastGroup = NULL; printf("All Groups:\n"); for (i = 0; i < TEST_CASE_CNT; i++) { if ((testCases[i].group != NULL) && ((lastGroup == NULL) || XSTRCMP(testCases[i].group, lastGroup) != 0)) { printf(" %s\n", testCases[i].group); } lastGroup = testCases[i].group; } } /* Add test case with group name to the list to run. * * @param [in] name Group name of test case to run. * @return 0 on success. * @return BAD_FUNC_ARG when group name does not select any tests. */ int ApiTest_RunGroup(char* name) { int i; int cnt = 0; for (i = 0; i < TEST_CASE_CNT; i++) { if ((testCases[i].group != NULL) && (XSTRCMP(testCases[i].group, name) == 0)) { testAll = 0; testCases[i].run = 1; cnt++; } } if (cnt == 0) { printf("Group name not found: %s\n", name); printf("Use --groups to see all test group names.\n"); return BAD_FUNC_ARG; } return 0; } /* Add test case with index to the list to run. * * @param [in] idx Index of test case to run starting at 1. * @return 0 on success. * @return BAD_FUNC_ARG when index is out of range of test case identifiers. */ int ApiTest_RunIdx(int idx) { if (idx < 1 || idx > TEST_CASE_CNT) { printf("Index out of range (1 - %d): %d\n", TEST_CASE_CNT, idx); return BAD_FUNC_ARG; } testAll = 0; testCases[idx-1].run = 1; return 0; } /* Add test cases with part of the name to the list to run. * * @param [in] name Part of the name of test cases to run. * @return 0 on success. * @return BAD_FUNC_ARG when name is not a known test case name. */ int ApiTest_RunPartName(char* name) { int i; int cnt = 0; for (i = 0; i < TEST_CASE_CNT; i++) { if (XSTRSTR(testCases[i].name, name) != NULL) { cnt++; testAll = 0; testCases[i].run = 1; } } if (cnt > 0) return 0; printf("Not found a test case with: %s\n", name); printf("Use --list to see all test case names.\n"); return BAD_FUNC_ARG; } /* Add test case with name to the list to run. * * @param [in] name Name of test case to run. * @return 0 on success. * @return BAD_FUNC_ARG when name is not a known test case name. */ int ApiTest_RunName(char* name) { int i; for (i = 0; i < TEST_CASE_CNT; i++) { if (XSTRCMP(testCases[i].name, name) == 0) { testAll = 0; testCases[i].run = 1; return 0; } } printf("Test case name not found: %s\n", name); printf("Use --list to see all test case names.\n"); return BAD_FUNC_ARG; } /* Converts the result code to a string. * * @param [in] res Test result code. * @return String describing test result. */ static const char* apitest_res_string(int res) { const char* str = "invalid result"; switch (res) { case TEST_SUCCESS: str = "passed"; break; case TEST_FAIL: str = "failed"; break; case TEST_SKIPPED: str = "skipped"; break; } return str; } #ifndef WOLFSSL_UNIT_TEST_NO_TIMING static double gettime_secs(void) #if defined(_WIN32) && (defined(_MSC_VER) || defined(__WATCOMC__)) { /* there's no gettimeofday for Windows, so we'll use system time */ #define EPOCH_DIFF 11644473600LL FILETIME currentFileTime; ULARGE_INTEGER uli = { 0, 0 }; #if defined(__WATCOMC__) GetSystemTimeAsFileTime(¤tFileTime); #else GetSystemTimePreciseAsFileTime(¤tFileTime); #endif uli.LowPart = currentFileTime.dwLowDateTime; uli.HighPart = currentFileTime.dwHighDateTime; /* Convert to seconds since Unix epoch */ return (double)((uli.QuadPart - (EPOCH_DIFF * 10000000)) / 10000000.0); } #else { struct timeval tv; LIBCALL_CHECK_RET(gettimeofday(&tv, 0)); return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0; } #endif #endif int ApiTest(void) { int i; int ret; int res = 0; #ifndef WOLFSSL_UNIT_TEST_NO_TIMING double timeDiff; #endif int passed = 0; int skipped = 0; int failed = 0; printf(" Begin API Tests\n"); fflush(stdout); #ifdef WOLFCRYPT_ONLY if (wolfCrypt_Init() != 0) { printf("wolfCrypt Initialization failed\n"); res = 1; } #else if (wolfSSL_Init() != WOLFSSL_SUCCESS) { printf("wolfSSL Initialization failed\n"); res = 1; } #endif #ifdef WOLFSSL_SWDEV if (res == 0 && wc_SwDev_Init() != 0) { printf("wc_SwDev_Init failed\n"); res = 1; } #endif #ifdef WOLFSSL_DUMP_MEMIO_STREAM if (res == 0) { if (create_tmp_dir(tmpDirName, sizeof(tmpDirName) - 1) == NULL) { printf("failed to create tmp dir\n"); res = 1; } else { tmpDirNameSet = 1; } } #endif if (res == 0) { const char* lastGroup = NULL; for (i = 0; i < TEST_CASE_CNT; ++i) { EXPECT_DECLS; #ifdef WOLFSSL_DUMP_MEMIO_STREAM currentTestName = testCases[i].name; #endif /* When not testing all cases then skip if not marked for running. */ if (!testAll && !testCases[i].run) { continue; } TestSetup(); if ((lastGroup != NULL) && ((testCases[i].group == NULL) || XSTRCMP(testCases[i].group, lastGroup) != 0)) { printf(" End Group : %s\n", lastGroup); } if ((testCases[i].group != NULL) && ((lastGroup == NULL) || XSTRCMP(testCases[i].group, lastGroup) != 0)) { printf(" Begin Group: %s\n", testCases[i].group); } lastGroup = testCases[i].group; printf(" %4d: %-51s:", i + 1, testCases[i].name); fflush(stdout); #ifndef WOLFSSL_UNIT_TEST_NO_TIMING timeDiff = gettime_secs(); #endif ret = testCases[i].func(); #ifndef WOLFSSL_UNIT_TEST_NO_TIMING timeDiff = gettime_secs() - timeDiff; #endif #ifndef WOLFSSL_UNIT_TEST_NO_TIMING if (ret != TEST_SKIPPED) { printf(" %s (%9.5lf)\n", apitest_res_string(ret), timeDiff); } else #endif { printf(" %s\n", apitest_res_string(ret)); } fflush(stdout); /* if return code is < 0 and not skipped then assert error */ Expect((ret > 0 || ret == TEST_SKIPPED), ("Test failed\n"), ("ret %d", ret)); testCases[i].fail = ((ret <= 0) && (ret != TEST_SKIPPED)); res |= ((ret <= 0) && (ret != TEST_SKIPPED)); if (testCases[i].fail) failed++; else if (ret == TEST_SKIPPED) skipped++; else passed++; TestCleanup(); if (testCases[i].fail && stopOnFail) { testAll = 0; break; } } if (lastGroup != NULL) { printf(" End Group : %s\n", lastGroup); } } #if defined(HAVE_ECC) && defined(FP_ECC) && defined(HAVE_THREAD_LS) \ && (defined(NO_MAIN_DRIVER) || defined(HAVE_STACK_SIZE)) wc_ecc_fp_free(); /* free per thread cache */ #endif #ifdef WOLFSSL_SWDEV wc_SwDev_Cleanup(); #endif #ifdef WOLFCRYPT_ONLY wolfCrypt_Cleanup(); #else wolfSSL_Cleanup(); #endif (void)testDevId; if (res != 0) { printf("\nFAILURES:\n"); for (i = 0; i < TEST_CASE_CNT; ++i) { if (testCases[i].fail) { printf(" %3d: %s\n", i + 1, testCases[i].name); } } printf("\n"); fflush(stdout); } #ifdef WOLFSSL_DUMP_MEMIO_STREAM if (tmpDirNameSet) { printf("\nBinary dumps of the memio streams can be found in the\n" "%s directory. This can be imported into\n" "Wireshark by transforming the file with\n" "\tod -Ax -tx1 -v stream.dump > stream.dump.hex\n" "And then loading test_output.dump.hex into Wireshark using\n" "the \"Import from Hex Dump...\" option and selecting the\n" "TCP encapsulation option.\n", tmpDirName); } #endif printf(" End API Tests\n"); printf(" Failed/Skipped/Passed/All: %d/%d/%d/%d\n", failed, skipped, passed, failed + skipped + passed); fflush(stdout); return res; }