diff --git a/examples/client/client.c b/examples/client/client.c index e47cf054f..11f2c92b6 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -949,7 +949,7 @@ static int ClientRead(WOLFSSL* ssl, char* reply, int replyLen, int mustRead, /* 4. add the same message into Japanese section */ /* (will be translated later) */ /* 5. add printf() into suitable position of Usage() */ -static const char* client_usage_msg[][66] = { +static const char* client_usage_msg[][67] = { /* English */ { " NOTE: All files relative to wolfSSL home dir\n", /* 0 */ @@ -1120,8 +1120,15 @@ static const char* client_usage_msg[][66] = { #ifdef HAVE_CURVE448 "-8 Use X448 for key exchange\n", /* 66 */ #endif -#ifdef HAVE_CRL - "-C Disable CRL\n", +#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(OLFSSL_CERT_EXT)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + "-9 Use hash dir look up for certificate loading\n" + " loading from /certs folder\n" + " files in the folder would have the form \"hash.N\" file name\n" + " e.g symbolic link to the file at certs folder\n" + " ln -s ca-cert.pem `openssl x509 -in ca-cert.pem -hash -noout`.0\n", + /* 67 */ #endif NULL, }, @@ -1294,8 +1301,19 @@ static const char* client_usage_msg[][66] = { #ifdef HAVE_TRUSTED_CA "-5 信頼できる認証局の鍵表示を使用する\n", /* 63 */ #endif + "-6 WANT_WRITE エラーを全てのIO 送信でシュミレートします\n", #ifdef HAVE_CURVE448 "-8 Use X448 for key exchange\n", /* 66 */ +#endif +#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(OLFSSL_CERT_EXT)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + "-9 証明書の読み込みに hash dir 機能を使用する\n" + " /certs フォルダーからロードします\n" + " フォルダー中のファイルは、\"hash.N\"[N:0-9]名である必要があります\n" + " 以下の例ではca-cert.pemにシンボリックリンクを設定します\n" + " ln -s ca-cert.pem `openssl x509 -in ca-cert.pem -hash -noout`.0\n", + /* 67 */ #endif NULL, }, @@ -1465,9 +1483,15 @@ static void Usage(void) #ifdef HAVE_TRUSTED_CA printf("%s", msg[++msgid]); /* -5 */ #endif + printf("%s", msg[++msgid]); /* -6 */ #ifdef HAVE_CURVE448 printf("%s", msg[++msgid]); /* -8 */ #endif +#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(OLFSSL_CERT_EXT)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + printf("%s", msg[++msgid]); /* -9 */ +#endif } THREAD_RETURN WOLFSSL_THREAD client_test(void* args) @@ -1601,6 +1625,11 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifdef HAVE_WNR const char* wnrConfigFile = wnrConfig; +#endif +#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(OLFSSL_CERT_EXT)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + int useCertFolder = 0; #endif char buffer[WOLFSSL_MAX_ERROR_SZ]; @@ -1686,7 +1715,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) while ((ch = mygetopt(argc, argv, "?:" "ab:c:defgh:i;jk:l:mnop:q:rstuv:wxyz" "A:B:CDE:F:GH:IJKL:M:NO:PQRS:TUVW:XYZ:" - "01:23:4568" + "01:23:45689" "@#")) != -1) { switch (ch) { case '?' : @@ -2162,7 +2191,13 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #endif #endif break; - + case '9' : +#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(OLFSSL_CERT_EXT)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + useCertFolder = 1; + break; +#endif case '@' : { #ifdef HAVE_WC_INTROSPECTION @@ -2622,6 +2657,29 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) } if (!usePsk && !useAnon && !useVerifyCb && myVerifyAction != VERIFY_FORCE_FAIL) { + #if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(OLFSSL_CERT_EXT)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + if (useCertFolder) { + WOLFSSL_X509_STORE *store; + WOLFSSL_X509_LOOKUP *lookup; + + store = wolfSSL_CTX_get_cert_store(ctx); + if (store == NULL) { + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("can't get WOLFSSL_X509_STORE"); + } + lookup = wolfSSL_X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); + if (lookup == NULL) { + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("can't add lookup"); + } + if (wolfSSL_X509_LOOKUP_ctrl(lookup, WOLFSSL_X509_L_ADD_DIR, caCertFolder, + X509_FILETYPE_PEM, NULL) != WOLFSSL_SUCCESS) { + err_sys("X509_LOOKUP_ctrl w/ L_ADD_DIR failed"); + } + } else { + #endif #ifdef NO_FILESYSTEM if (wolfSSL_CTX_load_verify_buffer(ctx, ca_cert_der_2048, sizeof_ca_cert_der_2048, SSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) { @@ -2669,6 +2727,11 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) } } #endif /* WOLFSSL_TRUST_PEER_CERT && !NO_FILESYSTEM */ + #if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(OLFSSL_CERT_EXT)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + } + #endif } if (useVerifyCb || myVerifyAction == VERIFY_FORCE_FAIL || myVerifyAction == VERIFY_USE_PREVERFIY) { diff --git a/examples/server/server.c b/examples/server/server.c index d69b276c7..092f86345 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -582,7 +582,7 @@ static void ServerWrite(WOLFSSL* ssl, const char* output, int outputLen) /* 4. add the same message into Japanese section */ /* (will be translated later) */ /* 5. add printf() into suitable position of Usage() */ -static const char* server_usage_msg[][56] = { +static const char* server_usage_msg[][57] = { /* English */ { " NOTE: All files relative to wolfSSL home dir\n", /* 0 */ @@ -705,6 +705,16 @@ static const char* server_usage_msg[][56] = { /* 55 */ #ifdef HAVE_CURVE448 "-8 Pre-generate Key share using Curve448 only\n", /* 56 */ +#endif +#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(OLFSSL_CERT_EXT)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + "-9 Use hash dir look up for certificate loading\n" + " loading from /certs folder\n" + " files in the folder would have the form \"hash.N\" file name\n" + " e.g symbolic link to the file at certs folder\n" + " ln -s client-ca.pem `openssl x509 -in client-ca.pem -hash -noout`.0\n", + /* 57 */ #endif NULL, }, @@ -838,6 +848,16 @@ static const char* server_usage_msg[][56] = { /* 55 */ #ifdef HAVE_CURVE448 "-8 Pre-generate Key share using Curve448 only\n", /* 56 */ +#endif +#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(OLFSSL_CERT_EXT)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + "-9 証明書の読み込みに hash dir 機能を使用する\n" + " /certs フォルダーからロードします\n" + " フォルダー中のファイルは、\"hash.N\"[N:0-9]名である必要があります\n" + " 以下の例ではca-cert.pemにシンボリックリンクを設定します\n" + " ln -s client-ca.pem `openssl x509 -in client-ca.pem -hash -noout`.0\n", + /* 57 */ #endif NULL, }, @@ -966,9 +986,15 @@ static void Usage(void) #ifdef HAVE_TRUSTED_CA printf("%s", msg[++msgId]); /* -5 */ #endif /* HAVE_TRUSTED_CA */ + printf("%s", msg[++msgId]); /* -6 */ #ifdef HAVE_CURVE448 printf("%s", msg[++msgId]); /* -8 */ #endif +#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(OLFSSL_CERT_EXT)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + printf("%s", msg[++msgId]); /* -9 */ +#endif } THREAD_RETURN WOLFSSL_THREAD server_test(void* args) @@ -1126,6 +1152,11 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) #ifdef HAVE_ENCRYPT_THEN_MAC int disallowETM = 0; #endif +#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(OLFSSL_CERT_EXT)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + int useCertFolder = 0; +#endif ((func_args*)args)->return_code = -1; /* error state */ @@ -1191,8 +1222,8 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) while ((ch = mygetopt(argc, argv, "?:" "abc:defgijk:l:mnop:q:rstuv:wxy" "A:B:C:D:E:FGH:IJKL:MNO:PQR:S:T;UVYZ:" - "01:23:4:568" - "@#")) != -1) { + "01:23:4:5689" + "@#")) != -1) { switch (ch) { case '?' : if(myoptarg!=NULL) { @@ -1620,7 +1651,13 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) #endif #endif break; - + case '9' : +#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(OLFSSL_CERT_EXT)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + useCertFolder = 1; + break; +#endif case '@' : { #ifdef HAVE_WC_INTROSPECTION @@ -2011,7 +2048,29 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) #ifdef TEST_BEFORE_DATE verify_flags |= WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY; #endif - + #if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(OLFSSL_CERT_EXT)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + if (useCertFolder) { + WOLFSSL_X509_STORE *store; + WOLFSSL_X509_LOOKUP *lookup; + + store = wolfSSL_CTX_get_cert_store(ctx); + if (store == NULL) { + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("can't get WOLFSSL_X509_STORE"); + } + lookup = wolfSSL_X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); + if (lookup == NULL) { + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("can't add lookup"); + } + if (wolfSSL_X509_LOOKUP_ctrl(lookup, WOLFSSL_X509_L_ADD_DIR, caCertFolder, + X509_FILETYPE_PEM, NULL) != WOLFSSL_SUCCESS) { + err_sys("X509_LOOKUP_ctrl w/ L_ADD_DIR failed"); + } + } else { + #endif if (wolfSSL_CTX_load_verify_locations_ex(ctx, verifyCert, 0, verify_flags) != WOLFSSL_SUCCESS) { err_sys_ex(catastrophic, @@ -2026,6 +2085,11 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) } } #endif /* WOLFSSL_TRUST_PEER_CERT */ + #if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(OLFSSL_CERT_EXT)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + } + #endif } #endif diff --git a/scripts/crl-revoked.test b/scripts/crl-revoked.test index 9d7f7eba0..46d511a1c 100755 --- a/scripts/crl-revoked.test +++ b/scripts/crl-revoked.test @@ -107,9 +107,13 @@ run_test() { echo "" echo "Successful Revocation!!!!" echo "" - exit_code=0 - echo "exiting with $exit_code" - exit $exit_code + if [ $exit_hash_dir_code -ne 0 ]; then + exit_code=1 + else + exit_code=0 + echo "exiting with $exit_code" + exit $exit_code + fi ;; *) echo "" @@ -120,9 +124,88 @@ run_test() { esac } +run_hashdir_test() { + echo -e "\n\nHash dir with CRL and Certificate loading" + remove_ready_file + # create hashed cert and crl + pushd ${CERT_DIR} + # ca file + ca_hash_name=`openssl x509 -in ca-cert.pem -hash -noout` + if [ -f "$ca_hash_name".0 ]; then + rm "$ca_hash_name".0 + fi + ln -s ca-cert.pem "$ca_hash_name".0 + # crl file + crl_hash_name=`openssl crl -in ./crl/crl.pem -hash -noout` + if [ -f "$crl_hash_name".r0 ]; then + rm "$crl_hash_name".r0 + fi + ln -s ./crl/crl.pem "$crl_hash_name".r0 + popd + + # starts the server on crl_port, -R generates ready file to be used as a + # mutex lock, -c loads the revoked certificate. We capture the processid + # into the variable server_pid + ./examples/server/server -R $ready_file -p $crl_port \ + -c ${CERT_DIR}/server-revoked-cert.pem \ + -k ${CERT_DIR}/server-revoked-key.pem & + server_pid=$! + while [ ! -s $ready_file -a "$counter" -lt 20 ]; do + echo -e "waiting for ready file..." + sleep 0.1 + counter=$((counter+ 1)) + done + + # get created port 0 ephemeral port + crl_port="$(cat $ready_file)" + + # starts client on crl_port and captures the output from client + capture_out=$(./examples/client/client -p $crl_port -9 2>&1) + client_result=$? + + wait $server_pid + server_result=$? + + case "$capture_out" in + *$revocation_code*) + # only exit with zero on detection of the expected error code + echo "" + echo "Successful Revocation!!!! with hash dir" + echo "" + exit_hash_dir_code=0 + ;; + *) + echo "" + echo "Certificate was not revoked saw this instead: $capture_out" + echo "" + echo "configure with --enable-crl and run this script again" + echo "" + exit_hash_dir_code=1 + esac + + # clean up hashed cert and crl + pushd ${CERT_DIR} + rm "$ca_hash_name".0 + rm "$crl_hash_name".r0 + popd + +} ######### begin program ######### +# Check for enabling hash dir feature +./examples/client/client -? 2>&1 | grep -- 'hash dir' +if [ $? -eq 0 ]; then + hash_dir=yes + exit_hash_dir_code=1 +fi + +if [ "$hash_dir" = "yes" ]; then + run_hashdir_test +else + exit_hash_dir_code=0 +fi + # run the test run_test diff --git a/src/crl.c b/src/crl.c index 34f6281a8..5d6c7da61 100644 --- a/src/crl.c +++ b/src/crl.c @@ -364,6 +364,20 @@ int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert) } #endif +#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(OLFSSL_CERT_EXT)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + if (foundEntry == 0) { + if (crl->cm->x509_store_p != NULL) { + ret = LoadCrlCertByIssuer(crl->cm->x509_store_p, + (WOLFSSL_X509_NAME*)cert->issuerName, X509_LU_CRL); + if (ret == WOLFSSL_SUCCESS) { + /* try again */ + ret = CheckCertCRLList(crl, cert, &foundEntry); + } + } + } +#endif if (foundEntry == 0) { WOLFSSL_MSG("Couldn't find CRL for status check"); ret = CRL_MISSING; diff --git a/src/internal.c b/src/internal.c index b020213b9..d8c45cbf7 100644 --- a/src/internal.c +++ b/src/internal.c @@ -1809,7 +1809,9 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap) #ifdef OPENSSL_EXTRA /* setup WOLFSSL_X509_STORE */ ctx->x509_store.cm = ctx->cm; - + /* set pointer back to x509 store */ + ctx->cm->x509_store_p = &ctx->x509_store; + /* WOLFSSL_X509_VERIFY_PARAM */ if ((ctx->param = (WOLFSSL_X509_VERIFY_PARAM*)XMALLOC( sizeof(WOLFSSL_X509_VERIFY_PARAM), @@ -1818,6 +1820,13 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap) return MEMORY_E; } XMEMSET(ctx->param, 0, sizeof(WOLFSSL_X509_VERIFY_PARAM)); + /* WOLFSS_X509_LOOKUP */ + if ((ctx->x509_store.lookup.dirs = (WOLFSSL_BY_DIR*)XMALLOC(sizeof(WOLFSSL_BY_DIR), + ctx->heap, DYNAMIC_TYPE_OPENSSL)) == NULL) { + WOLFSSL_MSG("ctx-x509_store.lookup.dir memory allocation error"); + return MEMORY_E; + } + XMEMSET(ctx->x509_store.lookup.dirs, 0, sizeof(WOLFSSL_BY_DIR)); #endif #endif @@ -1969,6 +1978,15 @@ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx) if (ctx->param) { XFREE(ctx->param, ctx->heap, DYNAMIC_TYPE_OPENSSL); } + + if (ctx->x509_store.lookup.dirs) { +#if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + if (!ctx->x509_store.lookup.dirs->dir_entry) { + wolfSSL_sk_BY_DIR_entry_free(ctx->x509_store.lookup.dirs->dir_entry); + } +#endif + XFREE(ctx->x509_store.lookup.dirs, ctx->heap, DYNAMIC_TYPE_OPENSSL); + } #endif #ifdef WOLFSSL_STATIC_EPHEMERAL #ifndef NO_DH @@ -10555,6 +10573,176 @@ static void FreeProcPeerCertArgs(WOLFSSL* ssl, void* pArgs) args->dCert = NULL; } } +#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(OLFSSL_CERT_EXT)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) +/* load certificate file which has .(r)N[0..N] in the folder */ +/* (r), in the case of CRL file */ +int LoadCrlCertByIssuer(WOLFSSL_X509_STORE* store, X509_NAME* issuer, int type) +{ + const int MAX_SUFFIX = 10; + int ret = WOLFSSL_SUCCESS; + WOLFSSL_X509_LOOKUP* lookup = &store->lookup; + WOLFSSL_BY_DIR_entry* entry; + WOLFSSL_BY_DIR_HASH hash_tmp; + WOLFSSL_BY_DIR_HASH* ph = NULL; + WOLFSSL_X509* x509; + unsigned long hash = 0; + char* filename = NULL; + const char* post = ""; + byte* pbuf = NULL; + int len, num, i, index; + byte suffix = 0; + int retHash = NOT_COMPILED_IN; + byte dgt[WC_MAX_DIGEST_SIZE]; + + WOLFSSL_ENTER("LoadCrlCertByIssuer"); + + /* sanity check */ + if (store == NULL || lookup->dirs == NULL || lookup->type != 1 + || (type != X509_LU_X509 && type != X509_LU_CRL)) { + return WOLFSSL_FAILURE; + } + + len = wolfSSL_i2d_X509_NAME_canon(issuer, &pbuf); + if (len > 0) { + #ifndef NO_SHA + retHash = wc_ShaHash((const byte*)pbuf, len, dgt); + #endif + if (retHash == 0) { + /* 4 bytes in small endian as unsigned long */ + hash = (((unsigned long)dgt[3] << 24) | + ((unsigned long)dgt[2] << 16) | + ((unsigned long)dgt[1] << 8) | + ((unsigned long)dgt[0])); + } else { + WOLFSSL_MSG("failed hash operation"); + return WOLFSSL_FAILURE; + } + } + + /* try to load each hashed name file in path */ +#if !defined(NO_FILESYSTE) && !defined(NO_WOLFSSL_DIR) + + if (type == X509_LU_CRL) { + post = "r"; + } + + num = wolfSSL_sk_BY_DIR_entry_num(lookup->dirs->dir_entry); + + for (i=0; idirs->dir_entry, i); + + len = XSTRLEN(entry->dir_name) + 13; + + if (filename != NULL) { + XFREE(filename, NULL, DYNAMIC_TYPE_OPENSSL); + } + + filename = (char*)XMALLOC(len, NULL, DYNAMIC_TYPE_OPENSSL); + if (filename == NULL) { + WOLFSSL_MSG("memory allcation error"); + return MEMORY_E; + } + + if (type == X509_LU_CRL && entry->hashes != NULL) { + /* lock the list */ + if (wc_LockMutex(&lookup->dirs->lock) != 0) { + WOLFSSL_MSG("wc_LockMutex cdir Lock error"); + return BAD_MUTEX_E; + } + + hash_tmp.hash_value = hash; + index = wolfSSL_sk_BY_DIR_HASH_find(entry->hashes, &hash_tmp); + if (index >= 0) { + WOLFSSL_MSG("find hashed CRL in list"); + ph = wolfSSL_sk_BY_DIR_HASH_value(entry->hashes, index); + suffix = ph->last_suffix; + } else { + ph = NULL; + suffix = 0; + } + + wc_UnLockMutex(&lookup->dirs->lock); + } + + for (; suffix < MAX_SUFFIX;suffix++) { + /* /folder-path/.(r)N[0..9] */ + XSNPRINTF(filename, len, "%s/%08lx.%s%d", entry->dir_name, + hash, post, suffix); + if(wc_FileExists(filename) == 0/*0 file exists */) { + + if (type == X509_LU_X509) { + x509 = wolfSSL_X509_load_certificate_file(filename, + WOLFSSL_FILETYPE_PEM); + if (x509 != NULL) { + ret = wolfSSL_X509_STORE_add_cert(store, x509); + } else { + WOLFSSL_MSG("failed to load certificate\n"); + ret = WOLFSSL_FAILURE; + break; + } + } +#ifdef HAVE_CRL + else if (type == X509_LU_CRL) { + ret = wolfSSL_X509_load_crl_file(&store->lookup, filename, + WOLFSSL_FILETYPE_PEM); + printf("return load crl file %d\n", ret); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("failed to load CRL\n"); + break; + } + } +#else + else if (type == X509_LU_CRL) { + WOLFSSL_MSG("CRL is not supported"); + ret = WOLFSSL_FAILURE; + break; + } +#endif + } else + break; + } + + if (type == X509_LU_CRL) { + if (wc_LockMutex(&lookup->dirs->lock) != 0) { + WOLFSSL_MSG("wc_LockMutex cdir Lock error"); + return BAD_MUTEX_E; + } + if (ph == NULL) { + ph = wolfSSL_BY_DIR_HASH_new(); + if (ph == NULL) { + WOLFSSL_MSG("failed to allocate hash stack"); + ret = WOLFSSL_FAILURE; + } else { + ph->hash_value = hash; + ph->last_suffix = suffix; + + ret = wolfSSL_sk_BY_DIR_HASH_push(entry->hashes, ph); + } + } + wc_UnLockMutex(&lookup->dirs->lock); + } + + XFREE(filename, NULL, DYNAMIC_TYPE_OPENSSL); + } +#else + (void) type; + (void) ret; + (void) x509; + (void) filename; + (void) suffix; + (void) num; + (void) i; + ret = WOLFSSL_NOT_IMPLEMENTED; +#endif + WOLFSSL_LEAVE("LoadCrlCertByIssuer", ret); + + return ret; +} +#endif + static int ProcessPeerCertParse(WOLFSSL* ssl, ProcPeerCertArgs* args, int certType, int verify, byte** pSubjectHash, int* pAlreadySigner) @@ -10651,6 +10839,45 @@ static int ProcessPeerCertParse(WOLFSSL* ssl, ProcPeerCertArgs* args, /* Parse Certificate */ ret = ParseCertRelative(args->dCert, certType, verify, ssl->ctx->cm); +#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(OLFSSL_CERT_EXT)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + if (ret == ASN_NO_SIGNER_E) { + WOLFSSL_MSG("try to load certificate if hash dir is set"); + if (ssl->ctx->x509_store_pt != NULL) { + ret = LoadCrlCertByIssuer(ssl->ctx->x509_store_pt, + (WOLFSSL_X509_NAME*)args->dCert->issuerName, + X509_LU_X509); + } else { + ret = LoadCrlCertByIssuer(&ssl->ctx->x509_store, + (WOLFSSL_X509_NAME*)args->dCert->issuerName, + X509_LU_X509); + } + + if (ret == WOLFSSL_SUCCESS) { + /* re try Parse Certificate */ + InitDecodedCert(args->dCert, cert->buffer, cert->length, ssl->heap); + args->dCertInit = 1; + args->dCert->sigCtx.devId = ssl->devId; + #ifdef WOLFSSL_ASYNC_CRYPT + args->dCert->sigCtx.asyncCtx = ssl; + #endif + #ifdef HAVE_PK_CALLBACKS + /* setup the PK callback context */ + ret = InitSigPkCb(ssl, &args->dCert->sigCtx); + if (ret != 0) + return ret; + #endif + ret = ParseCertRelative(args->dCert, certType, verify, + ssl->ctx->cm); + } else { + WOLFSSL_MSG("failed to load certificate from hash folder"); + /* restore return code */ + ret = ASN_NO_SIGNER_E; + } + } +#endif + /* perform below checks for date failure cases */ if (ret == 0 || ret == ASN_BEFORE_DATE_E || ret == ASN_AFTER_DATE_E) { /* get subject and determine if already loaded */ diff --git a/src/ssl.c b/src/ssl.c index 64dc9b623..11f47938e 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -15821,6 +15821,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) ctx->x509_store.cache = str->cache; ctx->x509_store_pt = str; /* take ownership of store and free it with CTX free */ + ctx->cm->x509_store_p = ctx->x509_store_pt; } @@ -23132,6 +23133,21 @@ int wolfSSL_X509_cmp(const WOLFSSL_X509 *a, const WOLFSSL_X509 *b) #if !defined(NO_CERTS) && (defined(OPENSSL_EXTRA) || \ defined(OPENSSL_EXTRA_X509_SMALL)) + int wolfSSL_ASN1_STRING_copy(WOLFSSL_ASN1_STRING* dest, + const WOLFSSL_ASN1_STRING* src) + { + if (src == NULL || dest == NULL) { + return WOLFSSL_FAILURE; + } + dest->type = src->type; + if(wolfSSL_ASN1_STRING_set(dest, src->data, src->length) + != WOLFSSL_SUCCESS) { + return WOLFSSL_FAILURE; + } + dest->flags = src->flags; + + return WOLFSSL_SUCCESS; + } /* Creates a new WOLFSSL_ASN1_STRING structure given the input type. * * type is the type of set when WOLFSSL_ASN1_STRING is created @@ -24813,6 +24829,111 @@ WOLFSSL_X509_LOOKUP_METHOD* wolfSSL_X509_LOOKUP_file(void) return &meth; } +static int x509AddCertDir(void *p, const char *argc, long argl) +{ + WOLFSSL_ENTER("x509AddCertDir"); + + (void)argl; +#if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + WOLFSSL_BY_DIR *ctx = (WOLFSSL_BY_DIR*)p; + WOLFSSL_BY_DIR_entry *entry; + size_t pathLen; + int i, num; + const char* c; +#ifdef WOLFSSL_SMALL_STACK + char *buf; +#else + char buf[MAX_FILENAME_SZ]; +#endif + + pathLen = 0; + c = argc; + /* zero length */ + if (c == NULL || *c == '\0') return WOLFSSL_FAILURE; + +#ifdef WOLFSSL_SMALL_STACK + buf = (char*)XMALLOC(MAX_FILENAME_SZ, NULL, DYNAMIC_TYPE_OPENSSL); + if (buf == NULL) { + WOLFSSL_LEAVE("x509AddCertDir", MEMORY_E); + return MEMORY_E; + } +#endif + + XMEMSET(buf, 0, MAX_FILENAME_SZ); + + do { + if (*c == SEPARATOR_CHAR || *c == '\0') { + + num = wolfSSL_sk_BY_DIR_entry_num(ctx->dir_entry); + + for (i=0; idir_entry, i); + + if (XSTRLEN(entry->dir_name) == pathLen && + XSTRNCMP(entry->dir_name, buf, pathLen) == 0) { + WOLFSSL_MSG("dir entry found"); + break; + } + } + + if (num == -1 || i == num) { + WOLFSSL_MSG("no entry found"); + + if (ctx->dir_entry == NULL) { + ctx->dir_entry = wolfSSL_sk_BY_DIR_entry_new_null(); + + if (ctx->dir_entry == NULL) { + WOLFSSL_MSG("failed to allocate dir_entry"); + return 0; + } + } + + entry = wolfSSL_BY_DIR_entry_new(); + if (entry == NULL) { + WOLFSSL_MSG("failed to allocate dir entry"); + return 0; + } + entry->dir_type = argl; + entry->dir_name = (char*)XMALLOC(pathLen + 1/* \0 termination*/ + , NULL, DYNAMIC_TYPE_OPENSSL); + entry->hashes = wolfSSL_sk_BY_DIR_HASH_new_null(); + if (entry->dir_name == NULL || entry->hashes == NULL) { + WOLFSSL_MSG("failed to allocate dir name"); + wolfSSL_BY_DIR_entry_free(entry); + return 0; + } + + XSTRNCPY(entry->dir_name, buf, pathLen); + entry->dir_name[pathLen] = '\0'; + + if (wolfSSL_sk_BY_DIR_entry_push(ctx->dir_entry, entry) + != WOLFSSL_SUCCESS) { + wolfSSL_BY_DIR_entry_free(entry); + return 0; + } + } + /* skip separator */ + if (*c == SEPARATOR_CHAR) c++; + + pathLen = 0; + XMEMSET(buf, 0, MAX_FILENAME_SZ); + } + buf[pathLen++] = *c; + + } while(*c++ != '\0'); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(buf, 0, DYNAMIC_TYPE_OPENSSL); +#endif + + return WOLFSSL_SUCCESS; +#else + (void)p; + (void)argc; + return WOLFSSL_NOT_IMPLEMENTED; +#endif +} int wolfSSL_X509_LOOKUP_ctrl(WOLFSSL_X509_LOOKUP *ctx, int cmd, const char *argc, long argl, char **ret) @@ -24823,41 +24944,43 @@ int wolfSSL_X509_LOOKUP_ctrl(WOLFSSL_X509_LOOKUP *ctx, int cmd, */ int lret = WOLFSSL_FAILURE; + WOLFSSL_ENTER("wolfSSL_X509_LOOKUP_ctrl"); +#if !defined(NO_FILESYSTEM) /* returns FAILURE *if the X509_LOOKUP doesn't have an associated X509_LOOKUP_METHOD */ if (ctx != NULL) { switch (cmd) { case WOLFSSL_X509_L_FILE_LOAD: - if (argl == WOLFSSL_FILETYPE_PEM) { -#ifdef HAVE_CRL - lret = wolfSSL_X509_load_cert_crl_file(ctx, argc, - X509_FILETYPE_PEM); -#else - lret = 0; -#endif - } else { - lret = wolfSSL_X509_LOOKUP_load_file(ctx, argc, (int)argl); - } /* expects to return a number of processed cert or crl file */ - if (lret != 0) - lret = WOLFSSL_SUCCESS; - else - lret = WOLFSSL_FAILURE; + lret = wolfSSL_X509_load_cert_crl_file(ctx, argc, argl) > 0 ? + WOLFSSL_SUCCESS : WOLFSSL_FAILURE; break; case WOLFSSL_X509_L_ADD_DIR: + /* store directory loaction to use it later */ +#if !defined(NO_WOLFSSL_DIR) + lret = x509AddCertDir(ctx->dirs, argc, argl); +#else + lret = WOLFSSL_NOT_IMPLEMENTED +#endif + break; case WOLFSSL_X509_L_ADD_STORE: case WOLFSSL_X509_L_LOAD_STORE: - return WOLFSSL_SUCCESS; + return WOLFSSL_NOT_IMPLEMENTED; default: break; } - } - - (void)argc; (void)argl; (void)ret; - + (void)ret; +#else + (void)ctx; + (void)argc; + (void)argl; + (void)ret; + (void)cmd; + lret = WOLFSSL_NOT_IMPLEMENTED; +#endif return lret; } @@ -24869,10 +24992,10 @@ WOLFSSL_X509_LOOKUP* wolfSSL_X509_STORE_add_lookup(WOLFSSL_X509_STORE* store, if (store == NULL) return NULL; - /* Method is a dummy value and is not needed. */ - (void)m; /* Make sure the lookup has a back reference to the store. */ store->lookup.store = store; + /* store a type to know which method wants to be used for */ + store->lookup.type = m->type; return &store->lookup; } @@ -25727,7 +25850,13 @@ WOLFSSL_X509_STORE* wolfSSL_X509_STORE_new(void) NULL, DYNAMIC_TYPE_OPENSSL)) == NULL) { goto err_exit; } - + XMEMSET(store->param, 0, sizeof(WOLFSSL_X509_VERIFY_PARAM)); + if ((store->lookup.dirs = (WOLFSSL_BY_DIR*)XMALLOC(sizeof(WOLFSSL_BY_DIR), + NULL, DYNAMIC_TYPE_OPENSSL)) == NULL) { + WOLFSSL_MSG("store->lookup.dir memory allocation error"); + goto err_exit; + } + XMEMSET(store->lookup.dirs, 0, sizeof(WOLFSSL_BY_DIR)); #endif return store; @@ -25753,6 +25882,16 @@ void wolfSSL_X509_STORE_free(WOLFSSL_X509_STORE* store) XFREE(store->param, NULL, DYNAMIC_TYPE_OPENSSL); store->param = NULL; } + + if (store->lookup.dirs != NULL) { +#if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + if (!store->lookup.dirs->dir_entry) { + wolfSSL_sk_BY_DIR_entry_free(store->lookup.dirs->dir_entry); + } +#endif + XFREE(store->lookup.dirs, NULL, DYNAMIC_TYPE_OPENSSL); + store->lookup.dirs = NULL; + } #endif XFREE(store, NULL, DYNAMIC_TYPE_X509_STORE); } @@ -26166,6 +26305,87 @@ WOLFSSL_X509 *wolfSSL_d2i_X509_fp(XFILE fp, WOLFSSL_X509 **x509) WOLFSSL_ENTER("wolfSSL_d2i_X509_fp"); return (WOLFSSL_X509 *)wolfSSL_d2i_X509_fp_ex(fp, (void **)x509, CERT_TYPE); } + +WOLFSSL_API int wolfSSL_X509_load_cert_crl_file(WOLFSSL_X509_LOOKUP *ctx, + const char *file, int type) +{ + STACK_OF(WOLFSSL_X509_INFO) *info; + WOLFSSL_X509_INFO *info_tmp; + WOLFSSL_BIO *bio; + WOLFSSL_X509 *x509 = NULL; + + int i; + int cnt = 0; + int num = 0; + + WOLFSSL_ENTER("wolfSSL_X509_load_ceretificate_crl_file"); + + if (type != WOLFSSL_FILETYPE_PEM) { + x509 = wolfSSL_X509_load_certificate_file(file, type); + if (x509 != NULL) { + if (wolfSSL_X509_STORE_add_cert(ctx->store, x509) + == WOLFSSL_SUCCESS) { + cnt++; + } else { + WOLFSSL_MSG("wolfSSL_X509_STORE_add_cert error"); + } + } else { + WOLFSSL_MSG("wolfSSL_X509_load_certificate_file error"); + } + + } else { +#ifdef OPENSSL_ALL + bio = wolfSSL_BIO_new_file(file, "rb"); + if(!bio) { + WOLFSSL_MSG("wolfSSL_BIO_new error"); + return cnt; + } + + info = wolfSSL_PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL); + + wolfSSL_BIO_free(bio); + + if (!info) { + WOLFSSL_MSG("wolfSSL_PEM_X509_INFO_read_bio error"); + return cnt; + } + num = wolfSSL_sk_X509_INFO_num(info); + for (i=0; i < num; i++) { + info_tmp = wolfSSL_sk_X509_INFO_value(info, i); + + if (info_tmp->x509) { + if(wolfSSL_X509_STORE_add_cert(ctx->store, info_tmp->x509) == + WOLFSSL_SUCCESS) { + cnt ++; + } else { + WOLFSSL_MSG("wolfSSL_X509_STORE_add_cert failed"); + } + } +#ifdef HAVE_CRL + if (info_tmp->crl) { + if(wolfSSL_X509_STORE_add_crl(ctx->store, info_tmp->crl) == + WOLFSSL_SUCCESS) { + cnt ++; + } else { + WOLFSSL_MSG("wolfSSL_X509_STORE_add_crl failed"); + } + } +#endif + } + wolfSSL_sk_X509_INFO_pop_free(info, X509_INFO_free); +#else + (void)i; + (void)cnt; + (void)num; + (void)info_tmp; + (void)info; + (void)bio; +#endif + } + + WOLFSSL_LEAVE("wolfSSL_X509_load_ceretificate_crl_file", cnt); + return cnt; +} #endif /* !NO_FILESYSTEM */ @@ -26271,65 +26491,7 @@ WOLFSSL_API int wolfSSL_X509_load_crl_file(WOLFSSL_X509_LOOKUP *ctx, return ret; } -WOLFSSL_API int wolfSSL_X509_load_cert_crl_file(WOLFSSL_X509_LOOKUP *ctx, - const char *file, int type) -{ - STACK_OF(WOLFSSL_X509_INFO) *info; - WOLFSSL_X509_INFO *info_tmp; - WOLFSSL_BIO *bio; - int i; - int cnt = 0; - int num = 0; - - WOLFSSL_ENTER("wolfSSL_X509_load_ceretificate_crl_file"); - - if (type != WOLFSSL_FILETYPE_PEM) { - cnt = wolfSSL_X509_LOOKUP_load_file(ctx, file, type); - } else { -#ifdef OPENSSL_ALL - bio = wolfSSL_BIO_new_file(file, "rb"); - if(!bio) { - WOLFSSL_MSG("wolfSSL_BIO_new error"); - return cnt; - } - - info = wolfSSL_PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL); - - wolfSSL_BIO_free(bio); - - if (!info) { - WOLFSSL_MSG("wolfSSL_PEM_X509_INFO_read_bio error"); - return cnt; - } - - for (i=0; i < num; i++) { - info_tmp = wolfSSL_sk_X509_INFO_value(info, i); - - if (info_tmp->x509) { - wolfSSL_X509_STORE_add_cert(ctx->store, info_tmp->x509); - cnt ++; - } - - if (info_tmp->crl) { - wolfSSL_X509_STORE_add_cert(ctx->store, info_tmp->x509); - cnt ++; - } - } - wolfSSL_sk_X509_INFO_pop_free(info, X509_INFO_free); -#else - (void)i; - (void)cnt; - (void)num; - (void)info_tmp; - (void)info; - (void)bio; -#endif - } - - WOLFSSL_LEAVE("wolfSSL_X509_load_ceretificate_crl_file", count); - return cnt; -} #endif /* !NO_FILESYSTEM */ @@ -41390,6 +41552,168 @@ static int ConvertNIDToWolfSSL(int nid) } } +#if defined(OPENSSL_ALL) +static int wolfSSL_ASN1_STRING_canon(WOLFSSL_ASN1_STRING* asn_out, + const WOLFSSL_ASN1_STRING* asn_in) +{ + char* dst; + char* src; + int i, len; + + switch (asn_in->type) { + case MBSTRING_UTF8: + case V_ASN1_PRINTABLESTRING: + break; + default: + WOLFSSL_MSG("just copy string"); + return wolfSSL_ASN1_STRING_copy(asn_out, asn_in); + } + /* type is set as UTF8 */ + asn_out->type = MBSTRING_UTF8; + asn_out->length = wolfSSL_ASN1_STRING_to_UTF8( + (unsigned char**)&asn_out->data + , (WOLFSSL_ASN1_STRING*)asn_in); + + if (asn_out->length < 0) { + return WOLFSSL_FAILURE; + } + /* point to the last */ + dst = asn_out->data + asn_out->length; + /* point to the start */ + src = asn_out->data; + + len = asn_out->length; + + /* trimming spaces at the head and tail */ + dst--; + for (; (len > 0 && XISSPACE(*dst));len--) { + dst--; + } + for (; (len > 0 && XISSPACE(*src));len--){ + src++; + } + + /* point to the start */ + dst = asn_out->data; + + for (i = 0; i < len;dst++, i++) { + if (!XISASCII(*src)) { + /* keep non-ascii code */ + *dst = *src++; + } else if (XISSPACE(*src)) { + *dst = 0x20; /* space */ + /* remove the rest of spaces */ + while (XISSPACE(*++src) && i++ < len); + } else { + *dst = XTOLOWER(*src++); + } + } + /* put actual length */ + asn_out->length = dst - asn_out->data; + return WOLFSSL_SUCCESS; +} +/* this is to converts the x509 name structure into canonical DER format +* , which has the following rules: +* convert to UTF8 +* convert to lower case +* multi-spaces collapsed +* leading SEQUENCE hader is skipped +*/ +int wolfSSL_i2d_X509_NAME_canon(WOLFSSL_X509_NAME* name, unsigned char** out) +{ + int totalBytes = 0, i, idx; + byte *output, *local = NULL; +#ifdef WOLFSSL_SMALL_STACK + EncodedName* names = NULL; +#else + EncodedName names[MAX_NAME_ENTRIES]; +#endif + + if (out == NULL || name == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + names = (EncodedName*)XMALLOC(sizeof(EncodedName) * MAX_NAME_ENTRIES, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (names == NULL) + return MEMORY_E; +#endif + + XMEMSET(names, 0, sizeof(EncodedName) * MAX_NAME_ENTRIES); + + for (i = 0; i < MAX_NAME_ENTRIES; i++) { + WOLFSSL_X509_NAME_ENTRY* entry; + int ret; + + entry = wolfSSL_X509_NAME_get_entry(name, i); + if (entry != NULL && entry->set == 1) { + const char* nameStr; + WOLFSSL_ASN1_STRING* data; + WOLFSSL_ASN1_STRING* cano_data; + + cano_data = wolfSSL_ASN1_STRING_new(); + if (cano_data == NULL) + return MEMORY_E; + + data = wolfSSL_X509_NAME_ENTRY_get_data(entry); + if (data == NULL) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + wolfSSL_ASN1_STRING_free(cano_data); + WOLFSSL_MSG("Error getting entry data"); + return WOLFSSL_FATAL_ERROR; + } + if (wolfSSL_ASN1_STRING_canon(cano_data, data) != WOLFSSL_SUCCESS) { + return WOLFSSL_FAILURE; + } + nameStr = (const char*)wolfSSL_ASN1_STRING_data(cano_data); + + ret = wc_EncodeName_cano(&names[i], nameStr, CTC_UTF8, + ConvertNIDToWolfSSL(entry->nid)); + if (ret < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + wolfSSL_ASN1_STRING_free(cano_data); + WOLFSSL_MSG("EncodeName failed"); + return WOLFSSL_FATAL_ERROR; + } + totalBytes += ret; + } + } + + /* skip header */ + /* check if using buffer passed in */ + if (*out == NULL) { + *out = local = (unsigned char*)XMALLOC(totalBytes, NULL, + DYNAMIC_TYPE_OPENSSL); + if (*out == NULL) { + return MEMORY_E; + } + } + output = *out; + idx = 0; + + for (i = 0; i < MAX_NAME_ENTRIES; i++) { + if (names[i].used) { + XMEMCPY(output + idx, names[i].encoded, names[i].totalLen); + idx += names[i].totalLen; + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + /* used existing buffer passed in, so increment pointer */ + if (local == NULL) { + *out += totalBytes; + } + return totalBytes; +} +#endif + /* Converts the x509 name structure into DER format. * * out pointer to either a pre setup buffer or a pointer to null for @@ -45970,6 +46294,391 @@ void wolfSSL_sk_SSL_CIPHER_free(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk) } } +#if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) +/* WOLFSSL_BY_DIR_HASH stuff */ +WOLFSSL_BY_DIR_HASH* wolfSSL_BY_DIR_HASH_new(void) +{ + WOLFSSL_BY_DIR_HASH* dir_hash; + + WOLFSSL_ENTER("wolfSSL_BY_DIR_HASH_new"); + + dir_hash = (WOLFSSL_BY_DIR_HASH*)XMALLOC(sizeof(WOLFSSL_BY_DIR_HASH), NULL, + DYNAMIC_TYPE_OPENSSL); + if (dir_hash) { + XMEMSET(dir_hash, 0, sizeof(WOLFSSL_BY_DIR_HASH)); + } + return dir_hash; +} + +void wolfSSL_BY_DIR_HASH_free(WOLFSSL_BY_DIR_HASH* dir_hash) +{ + if (dir_hash == NULL) + return; + + XFREE(dir_hash, NULL, DYNAMIC_TYPE_OPENSSL); +} + +WOLFSSL_STACK* wolfSSL_sk_BY_DIR_HASH_new_null(void) +{ + WOLFSSL_STACK* sk = wolfSSL_sk_new_node(NULL); + + WOLFSSL_ENTER("wolfSSL_sk_BY_DIR_HASH_new_null"); + + if (sk) { + sk->type = STACK_TYPE_BY_DIR_hash; + } + return sk; +} + +/* returns value less than 0 on fail to match + * On a successful match the priority level found is returned + */ +int wolfSSL_sk_BY_DIR_HASH_find( + WOLF_STACK_OF(WOLFSSL_BY_DIR_HASH)* sk, const WOLFSSL_BY_DIR_HASH* toFind) +{ + WOLFSSL_STACK* next; + int i, sz; + + WOLFSSL_ENTER("wolfSSL_sk_BY_DIR_HASH_find"); + + if (sk == NULL || toFind == NULL) { + return WOLFSSL_FAILURE; + } + + sz = wolfSSL_sk_BY_DIR_HASH_num(sk); + next = sk; + for (i = 0; i < sz && next != NULL; i++) { + if (next->data.dir_hash->hash_value == toFind->hash_value) { + return sz - i; /* reverse because stack pushed highest on first */ + } + next = next->next; + } + return -1; +} + +int wolfSSL_sk_BY_DIR_HASH_num(const WOLF_STACK_OF(WOLFSSL_BY_DIR_HASH) *sk) +{ + WOLFSSL_ENTER("wolfSSL_sk_WOLFSSL_BY_DIR_HASH_num"); + + if (sk == NULL) + return -1; + return (int)sk->num; +} + +WOLFSSL_BY_DIR_HASH* wolfSSL_sk_BY_DIR_HASH_value( + const WOLF_STACK_OF(WOLFSSL_BY_DIR_HASH) *sk, int i) +{ + WOLFSSL_ENTER("wolfSSL_sk_BY_DIR_HASH_value"); + + for (; sk != NULL && i > 0; i--) + sk = sk->next; + + if (i != 0 || sk == NULL) + return NULL; + return sk->data.dir_hash; +} + +WOLFSSL_BY_DIR_HASH* wolfSSL_sk_BY_DIR_HASH_pop( + WOLF_STACK_OF(WOLFSSL_BY_DIR_HASH)* sk) +{ + WOLFSSL_STACK* node; + WOLFSSL_BY_DIR_HASH* hash; + + WOLFSSL_ENTER("wolfSSL_sk_BY_DIR_HASH_pop"); + + if (sk == NULL) { + return NULL; + } + + node = sk->next; + hash = sk->data.dir_hash; + + if (node != NULL) { /* update sk and remove node from stack */ + sk->data.dir_hash = node->data.dir_hash; + sk->next = node->next; + wolfSSL_sk_free_node(node); + } + else { /* last x509 in stack */ + sk->data.dir_hash = NULL; + } + + if (sk->num > 0) { + sk->num -= 1; + } + + return hash; +} + +void wolfSSL_sk_BY_DIR_HASH_pop_free(WOLF_STACK_OF(BY_DIR_HASH)* sk, + void (*f) (WOLFSSL_BY_DIR_HASH*)) +{ + WOLFSSL_STACK* node; + + WOLFSSL_ENTER("wolfSSL_sk_BY_DIR_HASH_pop_free"); + + if (sk == NULL) { + return; + } + + /* parse through stack freeing each node */ + node = sk->next; + while (node && sk->num > 1) { + WOLFSSL_STACK* tmp = node; + node = node->next; + + if (f) + f(tmp->data.dir_hash); + else + wolfSSL_BY_DIR_HASH_free(tmp->data.dir_hash); + tmp->data.dir_hash = NULL; + XFREE(tmp, NULL, DYNAMIC_TYPE_OPENSSL); + sk->num -= 1; + } + + /* free head of stack */ + if (sk->num == 1) { + if (f) + f(sk->data.dir_hash); + else + wolfSSL_BY_DIR_HASH_free(sk->data.dir_hash); + sk->data.dir_hash = NULL; + } + XFREE(sk, NULL, DYNAMIC_TYPE_OPENSSL); +} + +void wolfSSL_sk_BY_DIR_HASH_free(WOLF_STACK_OF(WOLFSSL_BY_DIR_HASH) *sk) +{ + wolfSSL_sk_BY_DIR_HASH_pop_free(sk, NULL); +} + + +/* Adds the WOLFSSL_BY_DIR_HASH to the stack "sk". "sk" takes control of "in" and + * tries to free it when the stack is free'd. + * + * return 1 on success 0 on fail + */ +int wolfSSL_sk_BY_DIR_HASH_push(WOLF_STACK_OF(WOLFSSL_BY_DIR_HASH)* sk, + WOLFSSL_BY_DIR_HASH* in) +{ + WOLFSSL_STACK* node; + + WOLFSSL_ENTER("wolfSSL_sk_BY_DIR_HASH_push"); + + if (sk == NULL || in == NULL) { + return WOLFSSL_FAILURE; + } + + /* no previous values in stack */ + if (sk->data.dir_hash == NULL) { + sk->data.dir_hash = in; + sk->num += 1; + return WOLFSSL_SUCCESS; + } + + /* stack already has value(s) create a new node and add more */ + node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_OPENSSL); + if (node == NULL) { + WOLFSSL_MSG("Memory error"); + return WOLFSSL_FAILURE; + } + XMEMSET(node, 0, sizeof(WOLFSSL_STACK)); + + /* push new obj onto head of stack */ + node->data.dir_hash = sk->data.dir_hash; + node->next = sk->next; + node->type = sk->type; + sk->next = node; + sk->data.dir_hash = in; + sk->num += 1; + + return WOLFSSL_SUCCESS; +} + + +/* WOLFSSL_BY_DIR_entry stuff */ +WOLFSSL_BY_DIR_entry* wolfSSL_BY_DIR_entry_new(void) +{ + WOLFSSL_BY_DIR_entry* entry; + + WOLFSSL_ENTER("wolfSSL_BY_DIR_entry_new"); + + entry = (WOLFSSL_BY_DIR_entry*)XMALLOC(sizeof(WOLFSSL_BY_DIR_entry), NULL, + DYNAMIC_TYPE_OPENSSL); + + if (entry) { + XMEMSET(entry, 0, sizeof(WOLFSSL_BY_DIR_entry)); + } + return entry; +} + +void wolfSSL_BY_DIR_entry_free(WOLFSSL_BY_DIR_entry* entry) +{ + WOLFSSL_ENTER("wolfSSL_BY_DIR_entry_free"); + + if (entry == NULL) + return; + + if (entry->hashes) { + wolfSSL_sk_BY_DIR_HASH_free(entry->hashes); + } + + if (entry->dir_name != NULL) { + XFREE(entry->dir_name, NULL, DYNAMIC_TYPE_OPENSSL); + } + + XFREE(entry, NULL, DYNAMIC_TYPE_OPENSSL); +} + +WOLFSSL_STACK* wolfSSL_sk_BY_DIR_entry_new_null(void) +{ + WOLFSSL_STACK* sk = wolfSSL_sk_new_node(NULL); + + WOLFSSL_ENTER("wolfSSL_sk_BY_DIR_entry_new_null"); + + if (sk) { + sk->type = STACK_TYPE_BY_DIR_entry; + } + return sk; +} + +int wolfSSL_sk_BY_DIR_entry_num(const WOLF_STACK_OF(WOLFSSL_BY_DIR_entry) *sk) +{ + WOLFSSL_ENTER("wolfSSL_sk_BY_DIR_entry_num"); + + if (sk == NULL) + return -1; + return (int)sk->num; +} + +WOLFSSL_BY_DIR_entry* wolfSSL_sk_BY_DIR_entry_value( + const WOLF_STACK_OF(WOLFSSL_BY_DIR_entry) *sk, int i) +{ + WOLFSSL_ENTER("wolfSSL_sk_BY_DIR_entry_value"); + + for (; sk != NULL && i > 0; i--) + sk = sk->next; + + if (i != 0 || sk == NULL) + return NULL; + return sk->data.dir_entry; +} + +WOLFSSL_BY_DIR_entry* wolfSSL_sk_BY_DIR_entry_pop( + WOLF_STACK_OF(WOLFSSL_BY_DIR_entry)* sk) +{ + WOLFSSL_STACK* node; + WOLFSSL_BY_DIR_entry* entry; + + WOLFSSL_ENTER("wolfSSL_sk_BY_DIR_entry_pop"); + + if (sk == NULL) { + return NULL; + } + + node = sk->next; + entry = sk->data.dir_entry; + + if (node != NULL) { /* update sk and remove node from stack */ + sk->data.dir_entry = node->data.dir_entry; + sk->next = node->next; + wolfSSL_sk_free_node(node); + } + else { /* last x509 in stack */ + sk->data.dir_entry = NULL; + } + + if (sk->num > 0) { + sk->num -= 1; + } + + return entry; +} + +void wolfSSL_sk_BY_DIR_entry_pop_free(WOLF_STACK_OF(WOLFSSL_BY_DIR_entry)* sk, + void (*f) (WOLFSSL_BY_DIR_entry*)) +{ + WOLFSSL_STACK* node; + + WOLFSSL_ENTER("wolfSSL_sk_BY_DIR_entry_pop_free"); + + if (sk == NULL) { + return; + } + + /* parse through stack freeing each node */ + node = sk->next; + while (node && sk->num > 1) { + WOLFSSL_STACK* tmp = node; + node = node->next; + + if (f) + f(tmp->data.dir_entry); + else + wolfSSL_BY_DIR_entry_free(tmp->data.dir_entry); + tmp->data.dir_entry = NULL; + XFREE(tmp, NULL, DYNAMIC_TYPE_OPENSSL); + sk->num -= 1; + } + + /* free head of stack */ + if (sk->num == 1) { + if (f) + f(sk->data.dir_entry); + else + wolfSSL_BY_DIR_entry_free(sk->data.dir_entry); + sk->data.dir_entry = NULL; + } + XFREE(sk, NULL, DYNAMIC_TYPE_OPENSSL); +} + +void wolfSSL_sk_BY_DIR_entry_free(WOLF_STACK_OF(wolfSSL_BY_DIR_entry) *sk) +{ + wolfSSL_sk_BY_DIR_entry_pop_free(sk, NULL); +} + +/* Adds the wolfSSL_BY_DIR_entry to the stack "sk". "sk" takes control of "in" and + * tries to free it when the stack is free'd. + * + * return 1 on success 0 on fail + */ +int wolfSSL_sk_BY_DIR_entry_push(WOLF_STACK_OF(WOLFSSL_BY_DIR_entry)* sk, + WOLFSSL_BY_DIR_entry* in) +{ + WOLFSSL_STACK* node; + + if (sk == NULL || in == NULL) { + return WOLFSSL_FAILURE; + } + + /* no previous values in stack */ + if (sk->data.dir_entry == NULL) { + sk->data.dir_entry = in; + sk->num += 1; + return WOLFSSL_SUCCESS; + } + + /* stack already has value(s) create a new node and add more */ + node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_OPENSSL); + if (node == NULL) { + WOLFSSL_MSG("Memory error"); + return WOLFSSL_FAILURE; + } + XMEMSET(node, 0, sizeof(WOLFSSL_STACK)); + + /* push new obj onto head of stack */ + node->data.dir_entry = sk->data.dir_entry; + node->next = sk->next; + node->type = sk->type; + sk->next = node; + sk->data.dir_entry = in; + sk->num += 1; + + return WOLFSSL_SUCCESS; +} + +#endif /* OPENSSL_ALL */ int wolfSSL_sk_X509_INFO_num(const WOLF_STACK_OF(WOLFSSL_X509_INFO) *sk) { diff --git a/tests/api.c b/tests/api.c index dde3d5406..c0ee92ddb 100644 --- a/tests/api.c +++ b/tests/api.c @@ -25732,6 +25732,137 @@ static void test_wolfSSL_X509_NAME(void) #endif /* defined(OPENSSL_EXTRA) && !defined(NO_DES3) */ } +static void test_wolfSSL_sk_X509_BY_DIR_HASH(void) +{ +#if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + STACK_OF(WOLFSSL_BY_DIR_HASH) *hash_stack; + WOLFSSL_BY_DIR_HASH *hash1; + WOLFSSL_BY_DIR_HASH *hash2; + WOLFSSL_BY_DIR_HASH *h; + const unsigned long dummy_hash[2] = { + 0x12345678, + 0x9abcdef0 + }; + int i, num; + + printf(testingFmt, "test_wolfSSL_sk_X509_BY_DIR_HASH"); + + /* new */ + AssertNotNull(hash1 = wolfSSL_BY_DIR_HASH_new()); + hash1->hash_value = dummy_hash[0]; + + AssertNotNull(hash2 = wolfSSL_BY_DIR_HASH_new()); + hash2->hash_value = dummy_hash[1]; + + AssertNotNull(hash_stack = wolfSSL_sk_BY_DIR_HASH_new_null()); + + /* push */ + AssertIntEQ(wolfSSL_sk_BY_DIR_HASH_push(NULL, NULL), + WOLFSSL_FAILURE); + AssertIntEQ(wolfSSL_sk_BY_DIR_HASH_push(NULL, hash1), + WOLFSSL_FAILURE); + AssertIntEQ(wolfSSL_sk_BY_DIR_HASH_push(hash_stack, NULL), + WOLFSSL_FAILURE); + + AssertIntEQ(wolfSSL_sk_BY_DIR_HASH_push(hash_stack, hash1), + WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_sk_BY_DIR_HASH_push(hash_stack, + hash2), WOLFSSL_SUCCESS); + /* num and value */ + AssertIntEQ((num = wolfSSL_sk_BY_DIR_HASH_num(hash_stack)), 2); + for (i = 0; i < num; i++) { + AssertNotNull(h = wolfSSL_sk_BY_DIR_HASH_value(hash_stack, i)); + AssertTrue(h->hash_value == dummy_hash[num - i - 1]); + } + + /* pop */ + AssertNotNull(h = wolfSSL_sk_BY_DIR_HASH_pop(hash_stack)); + AssertIntEQ((num = wolfSSL_sk_BY_DIR_HASH_num(hash_stack)), 1); + + /* find */ + AssertIntEQ(wolfSSL_sk_BY_DIR_HASH_find(NULL, NULL), + WOLFSSL_FAILURE); + AssertIntEQ(wolfSSL_sk_BY_DIR_HASH_find(NULL, hash1), + WOLFSSL_FAILURE); + AssertIntEQ(wolfSSL_sk_BY_DIR_HASH_find(hash_stack, NULL), + WOLFSSL_FAILURE); + + AssertIntEQ(wolfSSL_sk_BY_DIR_HASH_push(hash_stack, hash2), + 1); + + /* free */ + wolfSSL_sk_BY_DIR_HASH_free(hash_stack); + + printf(resultFmt, passed); +#endif +} + + +static void test_wolfSSL_sk_X509_BY_DIR(void) +{ +#if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + STACK_OF(WOLFSSL_BY_DIR_entry) *entry_stack; + WOLFSSL_BY_DIR_entry *entry1; + WOLFSSL_BY_DIR_entry *entry2; + WOLFSSL_BY_DIR_entry *ent; + const char* dummy_dir[2] = { + "/hoge/hoge/foo/foo", + "/foo1/hoge2/abc/defg" + }; + int i, num; + size_t len; + + printf(testingFmt, "test_wolfSSL_X509_sk_BY_DIR"); + + /* new */ + AssertNotNull(entry1 = wolfSSL_BY_DIR_entry_new()); + len = XSTRLEN(dummy_dir[0]); + entry1->dir_name = (char*)XMALLOC(len + 1, NULL, DYNAMIC_TYPE_OPENSSL); + AssertNotNull(entry1->dir_name); + XMEMSET(entry1->dir_name, 0, len + 1); + XSTRNCPY(entry1->dir_name, dummy_dir[0], len + 1); + + AssertNotNull(entry2 = wolfSSL_BY_DIR_entry_new()); + len = XSTRLEN(dummy_dir[1]); + entry2->dir_name = (char*)XMALLOC(len + 1, NULL, DYNAMIC_TYPE_OPENSSL); + AssertNotNull(entry2->dir_name); + XMEMSET(entry2->dir_name, 0, len + 1); + XSTRNCPY(entry2->dir_name, dummy_dir[1], len + 1); + + AssertNotNull(entry_stack = wolfSSL_sk_BY_DIR_entry_new_null()); + + /* push */ + AssertIntEQ(wolfSSL_sk_BY_DIR_entry_push(NULL, NULL), + WOLFSSL_FAILURE); + AssertIntEQ(wolfSSL_sk_BY_DIR_entry_push(NULL, entry1), + WOLFSSL_FAILURE); + AssertIntEQ(wolfSSL_sk_BY_DIR_entry_push(entry_stack, NULL), + WOLFSSL_FAILURE); + + AssertIntEQ(wolfSSL_sk_BY_DIR_entry_push(entry_stack, entry1), + WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_sk_BY_DIR_entry_push(entry_stack, + entry2), WOLFSSL_SUCCESS); + /* num and value */ + AssertIntEQ((num = wolfSSL_sk_BY_DIR_entry_num(entry_stack)), 2); + for (i = 0; i < num; i++) { + AssertNotNull(ent = wolfSSL_sk_BY_DIR_entry_value(entry_stack, i)); + len = XSTRLEN(dummy_dir[num - i - 1]); + AssertTrue(XSTRLEN(ent->dir_name) == len); + AssertIntEQ(XSTRNCMP(ent->dir_name, dummy_dir[num - i - 1], len), 0); + } + + /* pop */ + AssertNotNull(ent = wolfSSL_sk_BY_DIR_entry_pop(entry_stack)); + AssertIntEQ((len = wolfSSL_sk_BY_DIR_entry_num(entry_stack)), 1); + + /* free */ + wolfSSL_sk_BY_DIR_entry_free(entry_stack); + + printf(resultFmt, passed); +#endif +} + #ifndef NO_BIO static void test_wolfSSL_X509_INFO(void) { @@ -27967,7 +28098,286 @@ static int verify_cb(int ok, X509_STORE_CTX *ctx) } #endif +static void test_wolfSSL_X509_Name_canon(void) +{ +#if defined(OPENSSL_ALL) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_SHA) && \ + defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(OLFSSL_CERT_EXT)) + + const long ex_hash1 = 0x0fdb2da4; + const long ex_hash2 = 0x9f3e8c9e; + X509_NAME *name = NULL; + X509 *x509 = NULL; + FILE* file = NULL; + unsigned long hash = 0; + byte digest[WC_MAX_DIGEST_SIZE] = {0}; + byte *pbuf = NULL; + word32 len = 0; + (void) ex_hash2; + printf(testingFmt, "test_wolfSSL_X509_Name_canon()"); + file = XFOPEN(caCertFile, "rb"); + AssertNotNull(file); + AssertNotNull(x509 = PEM_read_X509(file, NULL, NULL, NULL)); + AssertNotNull(name = X509_get_issuer_name(x509)); + + AssertIntGT((len = wolfSSL_i2d_X509_NAME_canon(name, &pbuf)), 0); + AssertIntEQ(wc_ShaHash((const byte*)pbuf, (word32)len, digest), 0); + + hash = (((unsigned long)digest[3] << 24) | + ((unsigned long)digest[2] << 16) | + ((unsigned long)digest[1] << 8) | + ((unsigned long)digest[0])); + AssertIntEQ(hash, ex_hash1); + + XFCLOSE(file); + X509_free(x509); + XFREE(pbuf, NULL, DYNAMIC_TYPE_OPENSSL); + pbuf = NULL; + + file = XFOPEN(cliCertFile, "rb"); + AssertNotNull(file); + AssertNotNull(x509 = PEM_read_X509(file, NULL, NULL, NULL)); + AssertNotNull(name = X509_get_issuer_name(x509)); + + AssertIntGT((len = wolfSSL_i2d_X509_NAME_canon(name, &pbuf)), 0); + AssertIntEQ(wc_ShaHash((const byte*)pbuf, (word32)len, digest), 0); + + hash = (((unsigned long)digest[3] << 24) | + ((unsigned long)digest[2] << 16) | + ((unsigned long)digest[1] << 8) | + ((unsigned long)digest[0])); + + AssertIntEQ(hash, ex_hash2); + + XFCLOSE(file); + X509_free(x509); + XFREE(pbuf, NULL, DYNAMIC_TYPE_OPENSSL); + + printf(resultFmt, passed); + +#endif + +} + +static void test_wolfSSL_X509_LOOKUP_ctrl_hash_dir(void) +{ +#if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + const int MAX_DIR = 4; + const char paths[][32] = { + "./certs/ed25519", + "./certs/ecc", + "./certs/crl", + "./certs/", + }; + + char CertCrl_path[MAX_FILENAME_SZ]; + char *p; + X509_STORE* str; + X509_LOOKUP* lookup; + WOLFSSL_BY_DIR_entry *dir; + WOLFSSL_STACK* sk = NULL; + int num = 0, len, total_len, i; + + (void) sk; + (void) num; + + printf(testingFmt, "test_wolfSSL_X509_LOOKUP_ctrl_hash_dir()"); + + XMEMSET(CertCrl_path, 0, MAX_FILENAME_SZ); + + /* illegal string */ + AssertNotNull((str = wolfSSL_X509_STORE_new())); + AssertNotNull(lookup = X509_STORE_add_lookup(str, X509_LOOKUP_file())); + AssertIntEQ(X509_LOOKUP_ctrl(lookup, X509_L_ADD_DIR, "", + SSL_FILETYPE_PEM,NULL), 0); + + /* free store */ + X509_STORE_free(str); + + /* short folder string */ + AssertNotNull((str = wolfSSL_X509_STORE_new())); + AssertNotNull(lookup = X509_STORE_add_lookup(str, X509_LOOKUP_file())); + AssertIntEQ(X509_LOOKUP_ctrl(lookup, X509_L_ADD_DIR, "./", + SSL_FILETYPE_PEM,NULL), 1); + AssertNotNull(sk = lookup->dirs->dir_entry); + AssertIntEQ((num = wolfSSL_sk_BY_DIR_entry_num(sk)), 1); + + dir = wolfSSL_sk_BY_DIR_entry_value(sk, 0); + printf("dir->dir_name %s\n", dir->dir_name); + AssertIntEQ(XSTRLEN((const char*)dir->dir_name), XSTRLEN("./")); + AssertIntEQ(XMEMCMP(dir->dir_name, "./", + XSTRLEN((const char*)dir->dir_name)), 0); + + /* free store */ + X509_STORE_free(str); + + /* typical function check */ + p = &CertCrl_path[0]; + total_len = 0; + + for(i = MAX_DIR - 1; i>=0 && total_len < MAX_FILENAME_SZ; i--) { + len = XSTRLEN((const char*)&paths[i]); + total_len += len; + XSTRNCPY(p, paths[i], MAX_FILENAME_SZ - total_len); + p += len; + if (i != 0) *(p++) = SEPARATOR_CHAR; + } + + AssertNotNull((str = wolfSSL_X509_STORE_new())); + AssertNotNull(lookup = X509_STORE_add_lookup(str, X509_LOOKUP_file())); + AssertIntEQ(X509_LOOKUP_ctrl(lookup, X509_L_ADD_DIR, CertCrl_path, + SSL_FILETYPE_PEM,NULL), 1); + AssertNotNull(sk = lookup->dirs->dir_entry); + AssertIntEQ((num = wolfSSL_sk_BY_DIR_entry_num(sk)), MAX_DIR); + + for(i = 0; idir_name), XSTRLEN(paths[i])); + AssertIntEQ(XMEMCMP(dir->dir_name, paths[i], + XSTRLEN((const char*)dir->dir_name)), 0); + } + + X509_STORE_free(str); + + printf(resultFmt, passed); +#endif + +} + +static void test_wolfSSL_X509_LOOKUP_ctrl_file(void) +{ +#if defined(OPENSSL_ALL) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) && \ + defined(WOLFSSL_SIGNER_DER_CERT) + + X509_STORE_CTX* ctx; + X509_STORE* str; + X509_LOOKUP* lookup; + + X509* cert1; + X509* x509Ca; + X509* x509Svr; + X509* issuer; + + WOLFSSL_STACK* sk = NULL; + X509_NAME* caName; + X509_NAME* issuerName; + + FILE* file1 = NULL; + int i, cert_count, cmp; + + char der[] = "certs/ca-cert.der"; + +#ifdef HAVE_CRL + char pem[][100] = { + "./certs/crl/crl.pem", + "./certs/crl/crl2.pem", + "./certs/crl/caEccCrl.pem", + "./certs/crl/eccCliCRL.pem", + "./certs/crl/eccSrvCRL.pem", + "" + }; +#endif + printf(testingFmt, "test_wolfSSL_X509_LOOKUP_ctrl_file()"); + AssertNotNull(file1=fopen("./certs/ca-cert.pem", "rb")); + + AssertNotNull(cert1 = wolfSSL_PEM_read_X509(file1, NULL, NULL, NULL)); + fclose(file1); + + AssertNotNull(ctx = X509_STORE_CTX_new()); + AssertNotNull((str = wolfSSL_X509_STORE_new())); + AssertNotNull(lookup = X509_STORE_add_lookup(str, X509_LOOKUP_file())); + AssertIntEQ(X509_LOOKUP_ctrl(lookup, X509_L_FILE_LOAD, caCertFile, + SSL_FILETYPE_PEM,NULL), 1); + AssertNotNull(sk = wolfSSL_CertManagerGetCerts(str->cm)); + AssertIntEQ((cert_count = sk_X509_num(sk)), 1); + + /* check if CA cert is loaded into the store */ + for (i = 0; i < cert_count; i++) { + x509Ca = sk_X509_value(sk, i); + AssertIntEQ(0, wolfSSL_X509_cmp(x509Ca, cert1)); + } + + AssertNotNull((x509Svr = + wolfSSL_X509_load_certificate_file(svrCertFile, SSL_FILETYPE_PEM))); + + AssertIntEQ(X509_STORE_CTX_init(ctx, str, x509Svr, NULL), SSL_SUCCESS); + + AssertNull(X509_STORE_CTX_get0_current_issuer(NULL)); + issuer = X509_STORE_CTX_get0_current_issuer(ctx); + AssertNotNull(issuer); + + caName = X509_get_subject_name(x509Ca); + AssertNotNull(caName); + issuerName = X509_get_subject_name(issuer); + AssertNotNull(issuerName); + cmp = X509_NAME_cmp(caName, issuerName); + AssertIntEQ(cmp, 0); + + /* load der format */ + X509_STORE_free(str); + sk_X509_free(sk); + + AssertNotNull((str = wolfSSL_X509_STORE_new())); + AssertNotNull(lookup = X509_STORE_add_lookup(str, X509_LOOKUP_file())); + AssertIntEQ(X509_LOOKUP_ctrl(lookup, X509_L_FILE_LOAD, der, + SSL_FILETYPE_ASN1,NULL), 1); + AssertNotNull(sk = wolfSSL_CertManagerGetCerts(str->cm)); + AssertIntEQ((cert_count = sk_X509_num(sk)), 1); + + /* check if CA cert is loaded into the store */ + for (i = 0; i < cert_count; i++) { + x509Ca = sk_X509_value(sk, i); + AssertIntEQ(0, wolfSSL_X509_cmp(x509Ca, cert1)); + } + +#ifdef HAVE_CRL + /* once feeing store */ + wolfSSL_X509_STORE_free(str); + str = NULL; + + AssertNotNull(str = wolfSSL_X509_STORE_new()); + AssertNotNull(lookup = X509_STORE_add_lookup(str, X509_LOOKUP_file())); + AssertIntEQ(X509_LOOKUP_ctrl(lookup, X509_L_FILE_LOAD, caCertFile, + SSL_FILETYPE_PEM,NULL), 1); + AssertIntEQ(X509_LOOKUP_ctrl(lookup, X509_L_FILE_LOAD, + "certs/server-revoked-cert.pem", + SSL_FILETYPE_PEM,NULL), 1); + if (str) { + AssertIntEQ(wolfSSL_CertManagerVerify(str->cm, svrCertFile, + WOLFSSL_FILETYPE_PEM), 1); + /* since store hasn't yet known the revoked cert*/ + AssertIntEQ(wolfSSL_CertManagerVerify(str->cm, + "certs/server-revoked-cert.pem", + WOLFSSL_FILETYPE_PEM), 1); + } + for (i = 0; pem[i][0] != '\0'; i++) + { + AssertIntEQ(X509_LOOKUP_ctrl(lookup, X509_L_FILE_LOAD, pem[i], + SSL_FILETYPE_PEM, NULL), 1); + } + + if (str) { + /* since store knows crl list */ + AssertIntEQ(wolfSSL_CertManagerVerify(str->cm, + "certs/server-revoked-cert.pem", + WOLFSSL_FILETYPE_PEM ), CRL_CERT_REVOKED); + } + +#endif + X509_free(issuer); + X509_STORE_CTX_free(ctx); + X509_free(x509Svr); + X509_STORE_free(str); + sk_X509_free(sk); + X509_free(x509Ca); + X509_free(cert1); + + printf(resultFmt, passed); +#endif +} static void test_wolfSSL_X509_STORE_CTX_get0_current_issuer(void) { #if defined(OPENSSL_EXTRA) && !defined(NO_RSA) @@ -39608,7 +40018,7 @@ static void test_wolfSSL_X509_load_crl_file(void) WOLFSSL_X509_STORE* store; WOLFSSL_X509_LOOKUP* lookup; - printf(testingFmt, "wolfSSL_X509_laod_crl_file"); + printf(testingFmt, "wolfSSL_X509_load_crl_file"); AssertNotNull(store = wolfSSL_X509_STORE_new()); AssertNotNull(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file())); @@ -41649,6 +42059,8 @@ void ApiTest(void) #ifndef NO_BIO test_wolfSSL_X509_INFO(); #endif + test_wolfSSL_sk_X509_BY_DIR_HASH(); + test_wolfSSL_sk_X509_BY_DIR(); test_wolfSSL_X509_subject_name_hash(); test_wolfSSL_X509_issuer_name_hash(); test_wolfSSL_X509_check_host(); @@ -41698,6 +42110,9 @@ void ApiTest(void) test_generate_cookie(); test_wolfSSL_X509_STORE_set_flags(); test_wolfSSL_X509_LOOKUP_load_file(); + test_wolfSSL_X509_Name_canon(); + test_wolfSSL_X509_LOOKUP_ctrl_file(); + test_wolfSSL_X509_LOOKUP_ctrl_hash_dir(); test_wolfSSL_X509_NID(); test_wolfSSL_X509_STORE_CTX_set_time(); test_wolfSSL_get0_param(); diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index f70c69a86..dea8abaf8 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -13172,6 +13172,86 @@ int wc_EncodeName(EncodedName* name, const char* nameStr, char nameType, return idx; } +/* +* this wrappes wc_EncodeName for EMAIL OID + */ +int wc_EncodeName_cano(EncodedName* name, const char* nameStr, char nameType, + byte type) +{ + word32 idx = 0; + + if (nameStr) { + /* bottom up */ + byte firstLen[1 + MAX_LENGTH_SZ]; + byte secondLen[MAX_LENGTH_SZ]; + byte sequence[MAX_SEQ_SZ]; + byte set[MAX_SET_SZ]; + + int strLen = (int)XSTRLEN(nameStr); + int thisLen = strLen; + int firstSz, secondSz, seqSz, setSz; + + const byte EMAIL_OID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x09, 0x01, 0x0c }; + + if (type != ASN_EMAIL_NAME) { + return wc_EncodeName(name, nameStr, nameType, type); + } + + if (strLen == 0) { /* no user data for this item */ + name->used = 0; + return 0; + } + secondSz = SetLength(strLen, secondLen); + thisLen += secondSz; + thisLen += EMAIL_JOINT_LEN; + firstSz = EMAIL_JOINT_LEN; + thisLen++; /* id type */ + firstSz = SetObjectId(firstSz, firstLen); + thisLen += firstSz; + + seqSz = SetSequence(thisLen, sequence); + thisLen += seqSz; + setSz = SetSet(thisLen, set); + thisLen += setSz; + + if (thisLen > (int)sizeof(name->encoded)) { + return BUFFER_E; + } + + /* store it */ + idx = 0; + /* set */ + XMEMCPY(name->encoded, set, setSz); + idx += setSz; + /* seq */ + XMEMCPY(name->encoded + idx, sequence, seqSz); + idx += seqSz; + /* asn object id */ + XMEMCPY(name->encoded + idx, firstLen, firstSz); + idx += firstSz; + /* email joint id */ + XMEMCPY(name->encoded + idx, EMAIL_OID, sizeof(EMAIL_OID)); + idx += (int)sizeof(EMAIL_OID); + /* second length */ + XMEMCPY(name->encoded + idx, secondLen, secondSz); + idx += secondSz; + /* str value */ + XMEMCPY(name->encoded + idx, nameStr, strLen); + idx += strLen; + + name->type = type; + name->totalLen = idx; + name->used = 1; + } + else + name->used = 0; + + return idx; +} + + + /* encode CertName into output, return total bytes written */ int SetName(byte* output, word32 outputSz, CertName* name) { diff --git a/wolfcrypt/src/wc_port.c b/wolfcrypt/src/wc_port.c index 2e6dc17ac..aada029ae 100644 --- a/wolfcrypt/src/wc_port.c +++ b/wolfcrypt/src/wc_port.c @@ -415,6 +415,39 @@ int wc_FileLoad(const char* fname, unsigned char** buf, size_t* bufLen, #if !defined(NO_WOLFSSL_DIR) && \ !defined(WOLFSSL_NUCLEUS) && !defined(WOLFSSL_NUCLEUS_1_2) +/* File Handling Helper */ +/* returns 0 if file exists, WC_ISFILEEXIST_NOFILE if file doesn't exist */ +int wc_FileExists(const char* fname) +{ + struct ReadDirCtx ctx; + + if (fname == NULL) + return 0; + + if (XSTAT(fname, &ctx.s) != 0) { + WOLFSSL_MSG("stat on name failed"); + return BAD_PATH_ERROR; + }else +#if defined(USE_WINDOWS_API) + if (ctx.s.st_mode & _S_IFREG) { + return 0; + } +#elif defined(WOLFSSL_ZEPHYR) + if (ctx.s.type == FS_DIR_ENTRY_FILE) { + return 0; + } + +#elif defined(WOLFSSL_TELIT_M2MB) + if (ctx.s.st_mode & M2MB_S_IFREG) { + return 0; + } +#else + if (S_ISREG(ctx.s.st_mode)) { + return 0; + } +#endif + return WC_ISFILEEXIST_NOFILE; +} /* File Handling Helpers */ /* returns 0 if file found, WC_READDIR_NOFILE if no files or negative error */ @@ -485,11 +518,7 @@ int wc_ReadDirFirst(ReadDirCtx* ctx, const char* path, char** name) * of earlier check it is known that dnameLen is less than * MAX_FILENAME_SZ - (pathLen + 2) so dnameLen +1 will fit */ XSTRNCPY(ctx->name + pathLen + 1, ctx->entry.name, dnameLen + 1); - if (fs_stat(ctx->name, &ctx->s) != 0) { - WOLFSSL_MSG("stat on name failed"); - ret = BAD_PATH_ERROR; - break; - } else if (ctx->s.type == FS_DIR_ENTRY_FILE) { + if ((ret = wc_FileExists(ctx->name)) == 0) { if (name) *name = ctx->name; return 0; @@ -517,12 +546,7 @@ int wc_ReadDirFirst(ReadDirCtx* ctx, const char* path, char** name) * MAX_FILENAME_SZ - (pathLen + 2) so dnameLen +1 will fit */ XSTRNCPY(ctx->name + pathLen + 1, ctx->entry->d_name, dnameLen + 1); - if (m2mb_fs_stat(ctx->name, &ctx->s) != 0) { - WOLFSSL_MSG("stat on name failed"); - ret = BAD_PATH_ERROR; - break; - } - else if (ctx->s.st_mode & M2MB_S_IFREG) { + if ((ret = wc_FileExists(ctx->name)) == 0) { if (name) *name = ctx->name; return 0; @@ -549,11 +573,7 @@ int wc_ReadDirFirst(ReadDirCtx* ctx, const char* path, char** name) * of earlier check it is known that dnameLen is less than * MAX_FILENAME_SZ - (pathLen + 2) so dnameLen +1 will fit */ XSTRNCPY(ctx->name + pathLen + 1, ctx->entry->d_name, dnameLen + 1); - if (stat(ctx->name, &ctx->s) != 0) { - WOLFSSL_MSG("stat on name failed"); - ret = BAD_PATH_ERROR; - break; - } else if (S_ISREG(ctx->s.st_mode)) { + if ((ret = wc_FileExists(ctx->name)) == 0) { if (name) *name = ctx->name; return 0; @@ -615,11 +635,7 @@ int wc_ReadDirNext(ReadDirCtx* ctx, const char* path, char** name) * MAX_FILENAME_SZ - (pathLen + 2) so that dnameLen +1 will fit */ XSTRNCPY(ctx->name + pathLen + 1, ctx->entry.name, dnameLen + 1); - if (fs_stat(ctx->name, &ctx->s) != 0) { - WOLFSSL_MSG("stat on name failed"); - ret = BAD_PATH_ERROR; - break; - } else if (ctx->s.type == FS_DIR_ENTRY_FILE) { + if ((ret = wc_FileExists(ctx->name)) == 0) { if (name) *name = ctx->name; return 0; @@ -641,12 +657,7 @@ int wc_ReadDirNext(ReadDirCtx* ctx, const char* path, char** name) * MAX_FILENAME_SZ - (pathLen + 2) so dnameLen +1 will fit */ XSTRNCPY(ctx->name + pathLen + 1, ctx->entry->d_name, dnameLen + 1); - if (m2mb_fs_stat(ctx->name, &ctx->s) != 0) { - WOLFSSL_MSG("stat on name failed"); - ret = BAD_PATH_ERROR; - break; - } - else if (ctx->s.st_mode & M2MB_S_IFREG) { + if ((ret = wc_FileExists(ctx->name)) == 0) { if (name) *name = ctx->name; return 0; @@ -667,11 +678,7 @@ int wc_ReadDirNext(ReadDirCtx* ctx, const char* path, char** name) * MAX_FILENAME_SZ - (pathLen + 2) so that dnameLen +1 will fit */ XSTRNCPY(ctx->name + pathLen + 1, ctx->entry->d_name, dnameLen + 1); - if (stat(ctx->name, &ctx->s) != 0) { - WOLFSSL_MSG("stat on name failed"); - ret = BAD_PATH_ERROR; - break; - } else if (S_ISREG(ctx->s.st_mode)) { + if ((ret = wc_FileExists(ctx->name)) == 0) { if (name) *name = ctx->name; return 0; diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 9246f66e9..2b5a492b3 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -2066,6 +2066,9 @@ struct WOLFSSL_CERT_MANAGER { #endif #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) short minEccKeySz; /* minimum allowed ECC key size */ +#endif +#if defined(OPENSSL_EXTRA) + WOLFSSL_X509_STORE *x509_store_p; /* pointer back to x509 store */ #endif wolfSSL_Mutex refMutex; /* reference count mutex */ int refCount; /* reference count */ @@ -3691,6 +3694,8 @@ typedef struct Arrays { #define STACK_TYPE_X509_NAME 9 #define STACK_TYPE_CONF_VALUE 10 #define STACK_TYPE_X509_INFO 11 +#define STACK_TYPE_BY_DIR_entry 12 +#define STACK_TYPE_BY_DIR_hash 13 struct WOLFSSL_STACK { unsigned long num; /* number of nodes in stack @@ -3716,6 +3721,8 @@ struct WOLFSSL_STACK { void* generic; char* string; WOLFSSL_GENERAL_NAME* gn; + WOLFSSL_BY_DIR_entry* dir_entry; + WOLFSSL_BY_DIR_HASH* dir_hash; } data; void* heap; /* memory heap hint */ WOLFSSL_STACK* next; @@ -4811,6 +4818,12 @@ WOLFSSL_LOCAL void FreeKey(WOLFSSL* ssl, int type, void** pKey); WOLFSSL_LOCAL int wolfSSL_AsyncPush(WOLFSSL* ssl, WC_ASYNC_DEV* asyncDev); #endif +#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ + (defined(WOLFSSL_CERT_REQ) || defined(OLFSSL_CERT_EXT)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) +WOLFSSL_LOCAL int LoadCrlCertByIssuer(WOLFSSL_X509_STORE* store, + X509_NAME* issuer, int Type); +#endif #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 1e593213e..22ea2f5a4 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -192,6 +192,9 @@ typedef struct WOLFSSL_ASN1_OBJECT WOLFSSL_ASN1_OBJECT; typedef struct WOLFSSL_ASN1_OTHERNAME WOLFSSL_ASN1_OTHERNAME; typedef struct WOLFSSL_X509V3_CTX WOLFSSL_X509V3_CTX; typedef struct WOLFSSL_v3_ext_method WOLFSSL_v3_ext_method; +typedef struct WOLFSSL_BY_DIR WOLFSSL_BY_DIR; +typedef struct WOLFSSL_BY_DIR_entry WOLFSSL_BY_DIR_entry; +typedef struct WOLFSSL_BY_DIR_HASH WOLFSSL_BY_DIR_HASH; typedef struct WOLFSSL_ASN1_STRING WOLFSSL_ASN1_STRING; typedef struct WOLFSSL_dynlock_value WOLFSSL_dynlock_value; @@ -276,7 +279,21 @@ struct WOLFSSL_X509V3_CTX { WOLFSSL_X509* x509; }; +struct WOLFSSL_BY_DIR_HASH { + unsigned long hash_value; + int last_suffix; +}; +struct WOLFSSL_BY_DIR_entry { + char* dir_name; + int dir_type; + WOLF_STACK_OF(WOLFSSL_BY_DIR_HASH) *hashes; +}; + +struct WOLFSSL_BY_DIR { + WOLF_STACK_OF(WOLFSSL_BY_DIR_entry) *dir_entry; + wolfSSL_Mutex lock; /* dir list lock */ +}; struct WOLFSSL_ASN1_OBJECT { void* heap; @@ -531,6 +548,8 @@ struct WOLFSSL_X509_LOOKUP_METHOD { struct WOLFSSL_X509_LOOKUP { WOLFSSL_X509_STORE *store; + int type; + WOLFSSL_BY_DIR* dirs; }; struct WOLFSSL_X509_STORE { @@ -1421,6 +1440,8 @@ WOLFSSL_API void wolfSSL_X509_STORE_set_verify_cb(WOLFSSL_X509_STORE *st, WOLFSSL_X509_STORE_CTX_verify_cb verify_cb); WOLFSSL_API int wolfSSL_i2d_X509_NAME(WOLFSSL_X509_NAME* n, unsigned char** out); +WOLFSSL_API int wolfSSL_i2d_X509_NAME_canon(WOLFSSL_X509_NAME* name, + unsigned char** out); WOLFSSL_API WOLFSSL_X509_NAME *wolfSSL_d2i_X509_NAME(WOLFSSL_X509_NAME **name, unsigned char **in, long length); #ifndef NO_RSA @@ -1499,6 +1520,8 @@ WOLFSSL_API int wolfSSL_ASN1_STRING_set(WOLFSSL_ASN1_STRING* asn1, const void* data, int dataSz); WOLFSSL_API unsigned char* wolfSSL_ASN1_STRING_data(WOLFSSL_ASN1_STRING*); WOLFSSL_API int wolfSSL_ASN1_STRING_length(WOLFSSL_ASN1_STRING*); +WOLFSSL_API int wolfSSL_ASN1_STRING_copy(WOLFSSL_ASN1_STRING* dst, + const WOLFSSL_ASN1_STRING* src); WOLFSSL_API int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX*); WOLFSSL_API const char* wolfSSL_X509_verify_cert_error_string(long); WOLFSSL_API int wolfSSL_X509_get_signature_type(WOLFSSL_X509*); @@ -3828,6 +3851,38 @@ WOLFSSL_API int wolfSSL_sk_CONF_VALUE_push(WOLF_STACK_OF(WOLFSSL_CONF_VALUE)* sk WOLFSSL_CONF_VALUE* val); #endif /* OPENSSL_ALL || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY || OPENSSL_EXTRA || HAVE_LIGHTY */ +#if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) +WOLFSSL_API WOLFSSL_BY_DIR_HASH* wolfSSL_BY_DIR_HASH_new(void); +WOLFSSL_API void wolfSSL_BY_DIR_HASH_free(WOLFSSL_BY_DIR_HASH* dir_hash); +WOLFSSL_API WOLFSSL_STACK* wolfSSL_sk_BY_DIR_HASH_new_null(void); +WOLFSSL_API int wolfSSL_sk_BY_DIR_HASH_find( + WOLF_STACK_OF(WOLFSSL_BY_DIR_HASH)* sk, const WOLFSSL_BY_DIR_HASH* toFind); +WOLFSSL_API int wolfSSL_sk_BY_DIR_HASH_num(const WOLF_STACK_OF(WOLFSSL_BY_DIR_HASH) *sk); +WOLFSSL_API WOLFSSL_BY_DIR_HASH* wolfSSL_sk_BY_DIR_HASH_value( + const WOLF_STACK_OF(WOLFSSL_BY_DIR_HASH) *sk, int i); +WOLFSSL_API WOLFSSL_BY_DIR_HASH* wolfSSL_sk_BY_DIR_HASH_pop( + WOLF_STACK_OF(WOLFSSL_BY_DIR_HASH)* sk); +WOLFSSL_API void wolfSSL_sk_BY_DIR_HASH_pop_free(WOLF_STACK_OF(WOLFSSL_BY_DIR_HASH)* sk, + void (*f) (WOLFSSL_BY_DIR_HASH*)); +WOLFSSL_API void wolfSSL_sk_BY_DIR_HASH_free(WOLF_STACK_OF(WOLFSSL_BY_DIR_HASH) *sk); +WOLFSSL_API int wolfSSL_sk_BY_DIR_HASH_push(WOLF_STACK_OF(WOLFSSL_BY_DIR_HASH)* sk, + WOLFSSL_BY_DIR_HASH* in); +/* WOLFSSL_BY_DIR_entry stuff */ +WOLFSSL_API WOLFSSL_BY_DIR_entry* wolfSSL_BY_DIR_entry_new(void); +WOLFSSL_API void wolfSSL_BY_DIR_entry_free(WOLFSSL_BY_DIR_entry* entry); +WOLFSSL_API WOLFSSL_STACK* wolfSSL_sk_BY_DIR_entry_new_null(void); +WOLFSSL_API int wolfSSL_sk_BY_DIR_entry_num(const WOLF_STACK_OF(WOLFSSL_BY_DIR_entry) *sk); +WOLFSSL_API WOLFSSL_BY_DIR_entry* wolfSSL_sk_BY_DIR_entry_value( + const WOLF_STACK_OF(WOLFSSL_BY_DIR_entry) *sk, int i); +WOLFSSL_API WOLFSSL_BY_DIR_entry* wolfSSL_sk_BY_DIR_entry_pop( + WOLF_STACK_OF(WOLFSSL_BY_DIR_entry)* sk); +WOLFSSL_API void wolfSSL_sk_BY_DIR_entry_pop_free(WOLF_STACK_OF(wolfSSL_BY_DIR_entry)* sk, + void (*f) (WOLFSSL_BY_DIR_entry*)); +WOLFSSL_API void wolfSSL_sk_BY_DIR_entry_free(WOLF_STACK_OF(wolfSSL_BY_DIR_entry) *sk); +WOLFSSL_API int wolfSSL_sk_BY_DIR_entry_push(WOLF_STACK_OF(wolfSSL_BY_DIR_entry)* sk, + WOLFSSL_BY_DIR_entry* in); +#endif /* OPENSSL_ALL && !NO_FILESYSTEM && !NO_WOLFSSL_DIR */ + #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) WOLFSSL_API WOLFSSL_ASN1_BIT_STRING* wolfSSL_ASN1_BIT_STRING_new(void); WOLFSSL_API void wolfSSL_ASN1_BIT_STRING_free(WOLFSSL_ASN1_BIT_STRING*); diff --git a/wolfssl/test.h b/wolfssl/test.h index 50a5c96a2..16fe232ce 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -349,6 +349,7 @@ #define cliEd448CertFile "certs/ed448/client-ed448.pem" #define cliEd448KeyFile "certs/ed448/client-ed448-priv.pem" #define caEd448CertFile "certs/ed448/ca-ed448.pem" +#define caCertFolder "certs/" #ifdef HAVE_WNR /* Whitewood netRandom default config file */ #define wnrConfig "wnr-example.conf" @@ -382,6 +383,7 @@ #define cliEd448CertFile "./certs/ed448/client-ed448.pem" #define cliEd448KeyFile "./certs/ed448/client-ed448-priv.pem" #define caEd448CertFile "./certs/ed448/ca-ed448.pem" +#define caCertFolder "./certs/" #ifdef HAVE_WNR /* Whitewood netRandom default config file */ #define wnrConfig "./wnr-example.conf" diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index ddac56b34..1ad8176b2 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -1173,6 +1173,8 @@ WOLFSSL_LOCAL int wc_OBJ_sn2nid(const char *sn); WOLFSSL_LOCAL int wc_EncodeName(EncodedName* name, const char* nameStr, char nameType, byte type); +WOLFSSL_LOCAL int wc_EncodeName_cano(EncodedName* name, const char* nameStr, + char nameType, byte type); /* ASN.1 helper functions */ #ifdef WOLFSSL_CERT_GEN WOLFSSL_ASN_API int SetName(byte* output, word32 outputSz, CertName* name); diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index e1d4aa2da..494d20df2 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -659,6 +659,8 @@ decouple library dependencies with standard string, memory and so on. #endif #ifdef OPENSSL_ALL #define XISALNUM(c) isalnum((c)) + #define XISASCII(c) isascii((c)) + #define XISSPACE(c) isspace((c)) #endif /* needed by wolfSSL_check_domain_name() */ #define XTOLOWER(c) tolower((c)) diff --git a/wolfssl/wolfcrypt/wc_port.h b/wolfssl/wolfcrypt/wc_port.h index 8a41f4b99..36c858f53 100644 --- a/wolfssl/wolfcrypt/wc_port.h +++ b/wolfssl/wolfcrypt/wc_port.h @@ -676,14 +676,25 @@ WOLFSSL_API int wolfCrypt_Cleanup(void); #define XFGETS fgets #define XFPRINTF fprintf - #if !defined(USE_WINDOWS_API) && !defined(NO_WOLFSSL_DIR)\ + #if !defined(NO_WOLFSSL_DIR)\ && !defined(WOLFSSL_NUCLEUS) && !defined(WOLFSSL_NUCLEUS_1_2) + #if defined(USE_WINDOWS_API) + #define XSTAT _stat + #define SEPARATOR_CHAR ';' + #elif defined(WOLFSSL_ZEPHYR) + #define XSTAT fs_stat + #elif defined(WOLFSSL_TELIT_M2MB) + #define XSTAT m2mb_fs_stat + #else #include #include #include #define XWRITE write #define XREAD read #define XCLOSE close + #define XSTAT stat + #define SEPARATOR_CHAR ':' + #endif #endif #endif @@ -732,7 +743,7 @@ WOLFSSL_API int wolfCrypt_Cleanup(void); #else struct dirent* entry; DIR* dir; - struct stat s; + struct XSTAT s; #endif char name[MAX_FILENAME_SZ]; } ReadDirCtx; @@ -743,6 +754,9 @@ WOLFSSL_API int wolfCrypt_Cleanup(void); WOLFSSL_API int wc_ReadDirNext(ReadDirCtx* ctx, const char* path, char** name); WOLFSSL_API void wc_ReadDirClose(ReadDirCtx* ctx); #endif /* !NO_WOLFSSL_DIR */ + #define WC_ISFILEEXIST_NOFILE -1 + + WOLFSSL_API int wc_FileExists(const char* fname); #endif /* !NO_FILESYSTEM */