cjson
.github
workflows CI.yml ci-fuzz.yml
CONTRIBUTING.md
fuzzing
inputs test1 test10 test11 test2 test3 test3.bu test3.uf test3.uu test4 test5 test6 test7 test8 test9
.gitignore CMakeLists.txt afl-prepare-linux.sh afl.c afl.sh cjson_read_fuzzer.c fuzz_main.c json.dict ossfuzz.sh
library_config cJSONConfig.cmake.in cJSONConfigVersion.cmake.in libcjson.pc.in libcjson_utils.pc.in uninstall.cmake
tests
inputs test1 test1.expected test10 test10.expected test11 test11.expected test2 test2.expected test3 test3.expected test4 test4.expected test5 test5.expected test6 test7 test7.expected test8 test8.expected test9 test9.expected
json-patch-tests .editorconfig .gitignore .npmignore README.md cjson-utils-tests.json package.json spec_tests.json tests.json
unity
auto colour_prompt.rb colour_reporter.rb generate_config.yml generate_module.rb generate_test_runner.rb parse_output.rb stylize_as_junit.rb test_file_filter.rb type_sanitizer.rb unity_test_summary.py unity_test_summary.rb unity_to_junit.py
docs ThrowTheSwitchCodingStandard.md UnityAssertionsCheatSheetSuitableforPrintingandPossiblyFraming.pdf UnityAssertionsReference.md UnityConfigurationGuide.md UnityGettingStartedGuide.md UnityHelperScriptsGuide.md license.txt
examples
example_1
src ProductionCode.c ProductionCode.h ProductionCode2.c ProductionCode2.h
makefile readme.txt
example_2
src ProductionCode.c ProductionCode.h ProductionCode2.c ProductionCode2.h
makefile readme.txt
example_3
helper UnityHelper.c UnityHelper.h
src ProductionCode.c ProductionCode.h ProductionCode2.c ProductionCode2.h
rakefile.rb rakefile_helper.rb readme.txt target_gcc_32.yml
unity_config.h
extras
eclipse error_parsers.txt
fixture
src unity_fixture.c unity_fixture.h unity_fixture_internals.h unity_fixture_malloc_overrides.h
rakefile.rb rakefile_helper.rb readme.txt
release build.info version.info
src unity.c unity.h unity_internals.h
.gitattributes .gitignore .travis.yml README.md
CMakeLists.txt cjson_add.c common.h compare_tests.c json_patch_tests.c minify_tests.c misc_tests.c misc_utils_tests.c old_utils_tests.c parse_array.c parse_examples.c parse_hex4.c parse_number.c parse_object.c parse_string.c parse_value.c parse_with_opts.c print_array.c print_number.c print_object.c print_string.c print_value.c readme_examples.c unity_setup.c
.editorconfig .gitattributes .gitignore .travis.yml CHANGELOG.md CMakeLists.txt CONTRIBUTORS.md LICENSE Makefile README.md SECURITY.md appveyor.yml cJSON.c cJSON.h cJSON_Utils.c cJSON_Utils.h test.c valgrind.supp
curl
.circleci config.yml
.github
ISSUE_TEMPLATE bug_report.yml config.yml docs.yml
scripts cleancmd.pl cmp-config.pl cmp-pkg-config.sh codespell-ignore.words codespell.sh distfiles.sh pyspelling.words pyspelling.yaml randcurl.pl requirements-docs.txt requirements-proselint.txt requirements.txt shellcheck-ci.sh shellcheck.sh spellcheck.curl trimmarkdownheader.pl typos.sh typos.toml verify-examples.pl verify-synopsis.pl yamlcheck.sh yamlcheck.yaml
workflows appveyor-status.yml checkdocs.yml checksrc.yml checkurls.yml codeql.yml configure-vs-cmake.yml curl-for-win.yml distcheck.yml fuzz.yml http3-linux.yml label.yml linux-old.yml linux.yml macos.yml non-native.yml windows.yml
CODEOWNERS CONTRIBUTING.md FUNDING.yml dependabot.yml labeler.yml lock.yml stale.yml
CMake CurlSymbolHiding.cmake CurlTests.c FindBrotli.cmake FindCares.cmake FindGSS.cmake FindGnuTLS.cmake FindLDAP.cmake FindLibbacktrace.cmake FindLibgsasl.cmake FindLibidn2.cmake FindLibpsl.cmake FindLibssh.cmake FindLibssh2.cmake FindLibuv.cmake FindMbedTLS.cmake FindNGHTTP2.cmake FindNGHTTP3.cmake FindNGTCP2.cmake FindNettle.cmake FindQuiche.cmake FindRustls.cmake FindWolfSSL.cmake FindZstd.cmake Macros.cmake OtherTests.cmake PickyWarnings.cmake Utilities.cmake cmake_uninstall.in.cmake curl-config.in.cmake unix-cache.cmake win32-cache.cmake
LICENSES BSD-4-Clause-UC.txt ISC.txt curl.txt
docs
cmdline-opts .gitignore CMakeLists.txt MANPAGE.md Makefile.am Makefile.inc _AUTHORS.md _BUGS.md _DESCRIPTION.md _ENVIRONMENT.md _EXITCODES.md _FILES.md _GLOBBING.md _NAME.md _OPTIONS.md _OUTPUT.md _PROGRESS.md _PROTOCOLS.md _PROXYPREFIX.md _SEEALSO.md _SYNOPSIS.md _URL.md _VARIABLES.md _VERSION.md _WWW.md abstract-unix-socket.md alt-svc.md anyauth.md append.md aws-sigv4.md basic.md ca-native.md cacert.md capath.md cert-status.md cert-type.md cert.md ciphers.md compressed-ssh.md compressed.md config.md connect-timeout.md connect-to.md continue-at.md cookie-jar.md cookie.md create-dirs.md create-file-mode.md crlf.md crlfile.md curves.md data-ascii.md data-binary.md data-raw.md data-urlencode.md data.md delegation.md digest.md disable-eprt.md disable-epsv.md disable.md disallow-username-in-url.md dns-interface.md dns-ipv4-addr.md dns-ipv6-addr.md dns-servers.md doh-cert-status.md doh-insecure.md doh-url.md dump-ca-embed.md dump-header.md ech.md egd-file.md engine.md etag-compare.md etag-save.md expect100-timeout.md fail-early.md fail-with-body.md fail.md false-start.md follow.md form-escape.md form-string.md form.md ftp-account.md ftp-alternative-to-user.md ftp-create-dirs.md ftp-method.md ftp-pasv.md ftp-port.md ftp-pret.md ftp-skip-pasv-ip.md ftp-ssl-ccc-mode.md ftp-ssl-ccc.md ftp-ssl-control.md get.md globoff.md happy-eyeballs-timeout-ms.md haproxy-clientip.md haproxy-protocol.md head.md header.md help.md hostpubmd5.md hostpubsha256.md hsts.md http0.9.md http1.0.md http1.1.md http2-prior-knowledge.md http2.md http3-only.md http3.md ignore-content-length.md insecure.md interface.md ip-tos.md ipfs-gateway.md ipv4.md ipv6.md json.md junk-session-cookies.md keepalive-cnt.md keepalive-time.md key-type.md key.md knownhosts.md krb.md libcurl.md limit-rate.md list-only.md local-port.md location-trusted.md location.md login-options.md mail-auth.md mail-from.md mail-rcpt-allowfails.md mail-rcpt.md mainpage.idx manual.md max-filesize.md max-redirs.md max-time.md metalink.md mptcp.md negotiate.md netrc-file.md netrc-optional.md netrc.md next.md no-alpn.md no-buffer.md no-clobber.md no-keepalive.md no-npn.md no-progress-meter.md no-sessionid.md noproxy.md ntlm-wb.md ntlm.md oauth2-bearer.md out-null.md output-dir.md output.md parallel-immediate.md parallel-max-host.md parallel-max.md parallel.md pass.md path-as-is.md pinnedpubkey.md post301.md post302.md post303.md preproxy.md progress-bar.md proto-default.md proto-redir.md proto.md proxy-anyauth.md proxy-basic.md proxy-ca-native.md proxy-cacert.md proxy-capath.md proxy-cert-type.md proxy-cert.md proxy-ciphers.md proxy-crlfile.md proxy-digest.md proxy-header.md proxy-http2.md proxy-insecure.md proxy-key-type.md proxy-key.md proxy-negotiate.md proxy-ntlm.md proxy-pass.md proxy-pinnedpubkey.md proxy-service-name.md proxy-ssl-allow-beast.md proxy-ssl-auto-client-cert.md proxy-tls13-ciphers.md proxy-tlsauthtype.md proxy-tlspassword.md proxy-tlsuser.md proxy-tlsv1.md proxy-user.md proxy.md proxy1.0.md proxytunnel.md pubkey.md quote.md random-file.md range.md rate.md raw.md referer.md remote-header-name.md remote-name-all.md remote-name.md remote-time.md remove-on-error.md request-target.md request.md resolve.md retry-all-errors.md retry-connrefused.md retry-delay.md retry-max-time.md retry.md sasl-authzid.md sasl-ir.md service-name.md show-error.md show-headers.md sigalgs.md silent.md skip-existing.md socks4.md socks4a.md socks5-basic.md socks5-gssapi-nec.md socks5-gssapi-service.md socks5-gssapi.md socks5-hostname.md socks5.md speed-limit.md speed-time.md ssl-allow-beast.md ssl-auto-client-cert.md ssl-no-revoke.md ssl-reqd.md ssl-revoke-best-effort.md ssl-sessions.md ssl.md sslv2.md sslv3.md stderr.md styled-output.md suppress-connect-headers.md tcp-fastopen.md tcp-nodelay.md telnet-option.md tftp-blksize.md tftp-no-options.md time-cond.md tls-earlydata.md tls-max.md tls13-ciphers.md tlsauthtype.md tlspassword.md tlsuser.md tlsv1.0.md tlsv1.1.md tlsv1.2.md tlsv1.3.md tlsv1.md tr-encoding.md trace-ascii.md trace-config.md trace-ids.md trace-time.md trace.md unix-socket.md upload-file.md upload-flags.md url-query.md url.md use-ascii.md user-agent.md user.md variable.md verbose.md version.md vlan-priority.md write-out.md xattr.md
examples .checksrc .gitignore 10-at-a-time.c CMakeLists.txt Makefile.am Makefile.example Makefile.inc README.md adddocsref.pl address-scope.c altsvc.c anyauthput.c block_ip.c cacertinmem.c certinfo.c chkspeed.c connect-to.c cookie_interface.c crawler.c debug.c default-scheme.c ephiperfifo.c evhiperfifo.c externalsocket.c fileupload.c ftp-delete.c ftp-wildcard.c ftpget.c ftpgetinfo.c ftpgetresp.c ftpsget.c ftpupload.c ftpuploadfrommem.c ftpuploadresume.c getinfo.c getinmemory.c getredirect.c getreferrer.c ghiper.c headerapi.c hiperfifo.c hsts-preload.c htmltidy.c htmltitle.cpp http-options.c http-post.c http2-download.c http2-pushinmemory.c http2-serverpush.c http2-upload.c http3-present.c http3.c httpcustomheader.c httpput-postfields.c httpput.c https.c imap-append.c imap-authzid.c imap-copy.c imap-create.c imap-delete.c imap-examine.c imap-fetch.c imap-list.c imap-lsub.c imap-multi.c imap-noop.c imap-search.c imap-ssl.c imap-store.c imap-tls.c interface.c ipv6.c keepalive.c localport.c log_failed_transfers.c maxconnects.c multi-app.c multi-debugcallback.c multi-double.c multi-event.c multi-formadd.c multi-legacy.c multi-post.c multi-single.c multi-uv.c netrc.c parseurl.c persistent.c pop3-authzid.c pop3-dele.c pop3-list.c pop3-multi.c pop3-noop.c pop3-retr.c pop3-ssl.c pop3-stat.c pop3-tls.c pop3-top.c pop3-uidl.c post-callback.c postinmemory.c postit2-formadd.c postit2.c progressfunc.c protofeats.c range.c resolve.c rtsp-options.c sendrecv.c sepheaders.c sessioninfo.c sftpget.c sftpuploadresume.c shared-connection-cache.c simple.c simplepost.c simplessl.c smooth-gtk-thread.c smtp-authzid.c smtp-expn.c smtp-mail.c smtp-mime.c smtp-multi.c smtp-ssl.c smtp-tls.c smtp-vrfy.c sslbackend.c synctime.c threaded.c unixsocket.c url2file.c urlapi.c usercertinmem.c version-check.pl websocket-cb.c websocket-updown.c websocket.c xmlstream.c
internals BUFQ.md BUFREF.md CHECKSRC.md CLIENT-READERS.md CLIENT-WRITERS.md CODE_STYLE.md CONNECTION-FILTERS.md CREDENTIALS.md CURLX.md DYNBUF.md HASH.md LLIST.md MID.md MQTT.md MULTI-EV.md NEW-PROTOCOL.md PEERS.md PORTING.md RATELIMITS.md README.md SCORECARD.md SPLAY.md STRPARSE.md THRDPOOL-AND-QUEUE.md TIME-KEEPING.md TLS-SESSIONS.md UINT_SETS.md WEBSOCKET.md
libcurl
opts CMakeLists.txt CURLINFO_ACTIVESOCKET.md CURLINFO_APPCONNECT_TIME.md CURLINFO_APPCONNECT_TIME_T.md CURLINFO_CAINFO.md CURLINFO_CAPATH.md CURLINFO_CERTINFO.md CURLINFO_CONDITION_UNMET.md CURLINFO_CONNECT_TIME.md CURLINFO_CONNECT_TIME_T.md CURLINFO_CONN_ID.md CURLINFO_CONTENT_LENGTH_DOWNLOAD.md CURLINFO_CONTENT_LENGTH_DOWNLOAD_T.md CURLINFO_CONTENT_LENGTH_UPLOAD.md CURLINFO_CONTENT_LENGTH_UPLOAD_T.md CURLINFO_CONTENT_TYPE.md CURLINFO_COOKIELIST.md CURLINFO_EARLYDATA_SENT_T.md CURLINFO_EFFECTIVE_METHOD.md CURLINFO_EFFECTIVE_URL.md CURLINFO_FILETIME.md CURLINFO_FILETIME_T.md CURLINFO_FTP_ENTRY_PATH.md CURLINFO_HEADER_SIZE.md CURLINFO_HTTPAUTH_AVAIL.md CURLINFO_HTTPAUTH_USED.md CURLINFO_HTTP_CONNECTCODE.md CURLINFO_HTTP_VERSION.md CURLINFO_LASTSOCKET.md CURLINFO_LOCAL_IP.md CURLINFO_LOCAL_PORT.md CURLINFO_NAMELOOKUP_TIME.md CURLINFO_NAMELOOKUP_TIME_T.md CURLINFO_NUM_CONNECTS.md CURLINFO_OS_ERRNO.md CURLINFO_POSTTRANSFER_TIME_T.md CURLINFO_PRETRANSFER_TIME.md CURLINFO_PRETRANSFER_TIME_T.md CURLINFO_PRIMARY_IP.md CURLINFO_PRIMARY_PORT.md CURLINFO_PRIVATE.md CURLINFO_PROTOCOL.md CURLINFO_PROXYAUTH_AVAIL.md CURLINFO_PROXYAUTH_USED.md CURLINFO_PROXY_ERROR.md CURLINFO_PROXY_SSL_VERIFYRESULT.md CURLINFO_QUEUE_TIME_T.md CURLINFO_REDIRECT_COUNT.md CURLINFO_REDIRECT_TIME.md CURLINFO_REDIRECT_TIME_T.md CURLINFO_REDIRECT_URL.md CURLINFO_REFERER.md CURLINFO_REQUEST_SIZE.md CURLINFO_RESPONSE_CODE.md CURLINFO_RETRY_AFTER.md CURLINFO_RTSP_CLIENT_CSEQ.md CURLINFO_RTSP_CSEQ_RECV.md CURLINFO_RTSP_SERVER_CSEQ.md CURLINFO_RTSP_SESSION_ID.md CURLINFO_SCHEME.md CURLINFO_SIZE_DELIVERED.md CURLINFO_SIZE_DOWNLOAD.md CURLINFO_SIZE_DOWNLOAD_T.md CURLINFO_SIZE_UPLOAD.md CURLINFO_SIZE_UPLOAD_T.md CURLINFO_SPEED_DOWNLOAD.md CURLINFO_SPEED_DOWNLOAD_T.md CURLINFO_SPEED_UPLOAD.md CURLINFO_SPEED_UPLOAD_T.md CURLINFO_SSL_ENGINES.md CURLINFO_SSL_VERIFYRESULT.md CURLINFO_STARTTRANSFER_TIME.md CURLINFO_STARTTRANSFER_TIME_T.md CURLINFO_TLS_SESSION.md CURLINFO_TLS_SSL_PTR.md CURLINFO_TOTAL_TIME.md CURLINFO_TOTAL_TIME_T.md CURLINFO_USED_PROXY.md CURLINFO_XFER_ID.md CURLMINFO_XFERS_ADDED.md CURLMINFO_XFERS_CURRENT.md CURLMINFO_XFERS_DONE.md CURLMINFO_XFERS_PENDING.md CURLMINFO_XFERS_RUNNING.md CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE.md CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE.md CURLMOPT_MAXCONNECTS.md CURLMOPT_MAX_CONCURRENT_STREAMS.md CURLMOPT_MAX_HOST_CONNECTIONS.md CURLMOPT_MAX_PIPELINE_LENGTH.md CURLMOPT_MAX_TOTAL_CONNECTIONS.md CURLMOPT_NETWORK_CHANGED.md CURLMOPT_NOTIFYDATA.md CURLMOPT_NOTIFYFUNCTION.md CURLMOPT_PIPELINING.md CURLMOPT_PIPELINING_SERVER_BL.md CURLMOPT_PIPELINING_SITE_BL.md CURLMOPT_PUSHDATA.md CURLMOPT_PUSHFUNCTION.md CURLMOPT_QUICK_EXIT.md CURLMOPT_RESOLVE_THREADS_MAX.md CURLMOPT_SOCKETDATA.md CURLMOPT_SOCKETFUNCTION.md CURLMOPT_TIMERDATA.md CURLMOPT_TIMERFUNCTION.md CURLOPT_ABSTRACT_UNIX_SOCKET.md CURLOPT_ACCEPTTIMEOUT_MS.md CURLOPT_ACCEPT_ENCODING.md CURLOPT_ADDRESS_SCOPE.md CURLOPT_ALTSVC.md CURLOPT_ALTSVC_CTRL.md CURLOPT_APPEND.md CURLOPT_AUTOREFERER.md CURLOPT_AWS_SIGV4.md CURLOPT_BUFFERSIZE.md CURLOPT_CAINFO.md CURLOPT_CAINFO_BLOB.md CURLOPT_CAPATH.md CURLOPT_CA_CACHE_TIMEOUT.md CURLOPT_CERTINFO.md CURLOPT_CHUNK_BGN_FUNCTION.md CURLOPT_CHUNK_DATA.md CURLOPT_CHUNK_END_FUNCTION.md CURLOPT_CLOSESOCKETDATA.md CURLOPT_CLOSESOCKETFUNCTION.md CURLOPT_CONNECTTIMEOUT.md CURLOPT_CONNECTTIMEOUT_MS.md CURLOPT_CONNECT_ONLY.md CURLOPT_CONNECT_TO.md CURLOPT_CONV_FROM_NETWORK_FUNCTION.md CURLOPT_CONV_FROM_UTF8_FUNCTION.md CURLOPT_CONV_TO_NETWORK_FUNCTION.md CURLOPT_COOKIE.md CURLOPT_COOKIEFILE.md CURLOPT_COOKIEJAR.md CURLOPT_COOKIELIST.md CURLOPT_COOKIESESSION.md CURLOPT_COPYPOSTFIELDS.md CURLOPT_CRLF.md CURLOPT_CRLFILE.md CURLOPT_CURLU.md CURLOPT_CUSTOMREQUEST.md CURLOPT_DEBUGDATA.md CURLOPT_DEBUGFUNCTION.md CURLOPT_DEFAULT_PROTOCOL.md CURLOPT_DIRLISTONLY.md CURLOPT_DISALLOW_USERNAME_IN_URL.md CURLOPT_DNS_CACHE_TIMEOUT.md CURLOPT_DNS_INTERFACE.md CURLOPT_DNS_LOCAL_IP4.md CURLOPT_DNS_LOCAL_IP6.md CURLOPT_DNS_SERVERS.md CURLOPT_DNS_SHUFFLE_ADDRESSES.md CURLOPT_DNS_USE_GLOBAL_CACHE.md CURLOPT_DOH_SSL_VERIFYHOST.md CURLOPT_DOH_SSL_VERIFYPEER.md CURLOPT_DOH_SSL_VERIFYSTATUS.md CURLOPT_DOH_URL.md CURLOPT_ECH.md CURLOPT_EGDSOCKET.md CURLOPT_ERRORBUFFER.md CURLOPT_EXPECT_100_TIMEOUT_MS.md CURLOPT_FAILONERROR.md CURLOPT_FILETIME.md CURLOPT_FNMATCH_DATA.md CURLOPT_FNMATCH_FUNCTION.md CURLOPT_FOLLOWLOCATION.md CURLOPT_FORBID_REUSE.md CURLOPT_FRESH_CONNECT.md CURLOPT_FTPPORT.md CURLOPT_FTPSSLAUTH.md CURLOPT_FTP_ACCOUNT.md CURLOPT_FTP_ALTERNATIVE_TO_USER.md CURLOPT_FTP_CREATE_MISSING_DIRS.md CURLOPT_FTP_FILEMETHOD.md CURLOPT_FTP_SKIP_PASV_IP.md CURLOPT_FTP_SSL_CCC.md CURLOPT_FTP_USE_EPRT.md CURLOPT_FTP_USE_EPSV.md CURLOPT_FTP_USE_PRET.md CURLOPT_GSSAPI_DELEGATION.md CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.md CURLOPT_HAPROXYPROTOCOL.md CURLOPT_HAPROXY_CLIENT_IP.md CURLOPT_HEADER.md CURLOPT_HEADERDATA.md CURLOPT_HEADERFUNCTION.md CURLOPT_HEADEROPT.md CURLOPT_HSTS.md CURLOPT_HSTSREADDATA.md CURLOPT_HSTSREADFUNCTION.md CURLOPT_HSTSWRITEDATA.md CURLOPT_HSTSWRITEFUNCTION.md CURLOPT_HSTS_CTRL.md CURLOPT_HTTP09_ALLOWED.md CURLOPT_HTTP200ALIASES.md CURLOPT_HTTPAUTH.md CURLOPT_HTTPGET.md CURLOPT_HTTPHEADER.md CURLOPT_HTTPPOST.md CURLOPT_HTTPPROXYTUNNEL.md CURLOPT_HTTP_CONTENT_DECODING.md CURLOPT_HTTP_TRANSFER_DECODING.md CURLOPT_HTTP_VERSION.md CURLOPT_IGNORE_CONTENT_LENGTH.md CURLOPT_INFILESIZE.md CURLOPT_INFILESIZE_LARGE.md CURLOPT_INTERFACE.md CURLOPT_INTERLEAVEDATA.md CURLOPT_INTERLEAVEFUNCTION.md CURLOPT_IOCTLDATA.md CURLOPT_IOCTLFUNCTION.md CURLOPT_IPRESOLVE.md CURLOPT_ISSUERCERT.md CURLOPT_ISSUERCERT_BLOB.md CURLOPT_KEEP_SENDING_ON_ERROR.md CURLOPT_KEYPASSWD.md CURLOPT_KRBLEVEL.md CURLOPT_LOCALPORT.md CURLOPT_LOCALPORTRANGE.md CURLOPT_LOGIN_OPTIONS.md CURLOPT_LOW_SPEED_LIMIT.md CURLOPT_LOW_SPEED_TIME.md CURLOPT_MAIL_AUTH.md CURLOPT_MAIL_FROM.md CURLOPT_MAIL_RCPT.md CURLOPT_MAIL_RCPT_ALLOWFAILS.md CURLOPT_MAXAGE_CONN.md CURLOPT_MAXCONNECTS.md CURLOPT_MAXFILESIZE.md CURLOPT_MAXFILESIZE_LARGE.md CURLOPT_MAXLIFETIME_CONN.md CURLOPT_MAXREDIRS.md CURLOPT_MAX_RECV_SPEED_LARGE.md CURLOPT_MAX_SEND_SPEED_LARGE.md CURLOPT_MIMEPOST.md CURLOPT_MIME_OPTIONS.md CURLOPT_NETRC.md CURLOPT_NETRC_FILE.md CURLOPT_NEW_DIRECTORY_PERMS.md CURLOPT_NEW_FILE_PERMS.md CURLOPT_NOBODY.md CURLOPT_NOPROGRESS.md CURLOPT_NOPROXY.md CURLOPT_NOSIGNAL.md CURLOPT_OPENSOCKETDATA.md CURLOPT_OPENSOCKETFUNCTION.md CURLOPT_PASSWORD.md CURLOPT_PATH_AS_IS.md CURLOPT_PINNEDPUBLICKEY.md CURLOPT_PIPEWAIT.md CURLOPT_PORT.md CURLOPT_POST.md CURLOPT_POSTFIELDS.md CURLOPT_POSTFIELDSIZE.md CURLOPT_POSTFIELDSIZE_LARGE.md CURLOPT_POSTQUOTE.md CURLOPT_POSTREDIR.md CURLOPT_PREQUOTE.md CURLOPT_PREREQDATA.md CURLOPT_PREREQFUNCTION.md CURLOPT_PRE_PROXY.md CURLOPT_PRIVATE.md CURLOPT_PROGRESSDATA.md CURLOPT_PROGRESSFUNCTION.md CURLOPT_PROTOCOLS.md CURLOPT_PROTOCOLS_STR.md CURLOPT_PROXY.md CURLOPT_PROXYAUTH.md CURLOPT_PROXYHEADER.md CURLOPT_PROXYPASSWORD.md CURLOPT_PROXYPORT.md CURLOPT_PROXYTYPE.md CURLOPT_PROXYUSERNAME.md CURLOPT_PROXYUSERPWD.md CURLOPT_PROXY_CAINFO.md CURLOPT_PROXY_CAINFO_BLOB.md CURLOPT_PROXY_CAPATH.md CURLOPT_PROXY_CRLFILE.md CURLOPT_PROXY_ISSUERCERT.md CURLOPT_PROXY_ISSUERCERT_BLOB.md CURLOPT_PROXY_KEYPASSWD.md CURLOPT_PROXY_PINNEDPUBLICKEY.md CURLOPT_PROXY_SERVICE_NAME.md CURLOPT_PROXY_SSLCERT.md CURLOPT_PROXY_SSLCERTTYPE.md CURLOPT_PROXY_SSLCERT_BLOB.md CURLOPT_PROXY_SSLKEY.md CURLOPT_PROXY_SSLKEYTYPE.md CURLOPT_PROXY_SSLKEY_BLOB.md CURLOPT_PROXY_SSLVERSION.md CURLOPT_PROXY_SSL_CIPHER_LIST.md CURLOPT_PROXY_SSL_OPTIONS.md CURLOPT_PROXY_SSL_VERIFYHOST.md CURLOPT_PROXY_SSL_VERIFYPEER.md CURLOPT_PROXY_TLS13_CIPHERS.md CURLOPT_PROXY_TLSAUTH_PASSWORD.md CURLOPT_PROXY_TLSAUTH_TYPE.md CURLOPT_PROXY_TLSAUTH_USERNAME.md CURLOPT_PROXY_TRANSFER_MODE.md CURLOPT_PUT.md CURLOPT_QUICK_EXIT.md CURLOPT_QUOTE.md CURLOPT_RANDOM_FILE.md CURLOPT_RANGE.md CURLOPT_READDATA.md CURLOPT_READFUNCTION.md CURLOPT_REDIR_PROTOCOLS.md CURLOPT_REDIR_PROTOCOLS_STR.md CURLOPT_REFERER.md CURLOPT_REQUEST_TARGET.md CURLOPT_RESOLVE.md CURLOPT_RESOLVER_START_DATA.md CURLOPT_RESOLVER_START_FUNCTION.md CURLOPT_RESUME_FROM.md CURLOPT_RESUME_FROM_LARGE.md CURLOPT_RTSP_CLIENT_CSEQ.md CURLOPT_RTSP_REQUEST.md CURLOPT_RTSP_SERVER_CSEQ.md CURLOPT_RTSP_SESSION_ID.md CURLOPT_RTSP_STREAM_URI.md CURLOPT_RTSP_TRANSPORT.md CURLOPT_SASL_AUTHZID.md CURLOPT_SASL_IR.md CURLOPT_SEEKDATA.md CURLOPT_SEEKFUNCTION.md CURLOPT_SERVER_RESPONSE_TIMEOUT.md CURLOPT_SERVER_RESPONSE_TIMEOUT_MS.md CURLOPT_SERVICE_NAME.md CURLOPT_SHARE.md CURLOPT_SOCKOPTDATA.md CURLOPT_SOCKOPTFUNCTION.md CURLOPT_SOCKS5_AUTH.md CURLOPT_SOCKS5_GSSAPI_NEC.md CURLOPT_SOCKS5_GSSAPI_SERVICE.md CURLOPT_SSH_AUTH_TYPES.md CURLOPT_SSH_COMPRESSION.md CURLOPT_SSH_HOSTKEYDATA.md CURLOPT_SSH_HOSTKEYFUNCTION.md CURLOPT_SSH_HOST_PUBLIC_KEY_MD5.md CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256.md CURLOPT_SSH_KEYDATA.md CURLOPT_SSH_KEYFUNCTION.md CURLOPT_SSH_KNOWNHOSTS.md CURLOPT_SSH_PRIVATE_KEYFILE.md CURLOPT_SSH_PUBLIC_KEYFILE.md CURLOPT_SSLCERT.md CURLOPT_SSLCERTTYPE.md CURLOPT_SSLCERT_BLOB.md CURLOPT_SSLENGINE.md CURLOPT_SSLENGINE_DEFAULT.md CURLOPT_SSLKEY.md CURLOPT_SSLKEYTYPE.md CURLOPT_SSLKEY_BLOB.md CURLOPT_SSLVERSION.md CURLOPT_SSL_CIPHER_LIST.md CURLOPT_SSL_CTX_DATA.md CURLOPT_SSL_CTX_FUNCTION.md CURLOPT_SSL_EC_CURVES.md CURLOPT_SSL_ENABLE_ALPN.md CURLOPT_SSL_ENABLE_NPN.md CURLOPT_SSL_FALSESTART.md CURLOPT_SSL_OPTIONS.md CURLOPT_SSL_SESSIONID_CACHE.md CURLOPT_SSL_SIGNATURE_ALGORITHMS.md CURLOPT_SSL_VERIFYHOST.md CURLOPT_SSL_VERIFYPEER.md CURLOPT_SSL_VERIFYSTATUS.md CURLOPT_STDERR.md CURLOPT_STREAM_DEPENDS.md CURLOPT_STREAM_DEPENDS_E.md CURLOPT_STREAM_WEIGHT.md CURLOPT_SUPPRESS_CONNECT_HEADERS.md CURLOPT_TCP_FASTOPEN.md CURLOPT_TCP_KEEPALIVE.md CURLOPT_TCP_KEEPCNT.md CURLOPT_TCP_KEEPIDLE.md CURLOPT_TCP_KEEPINTVL.md CURLOPT_TCP_NODELAY.md CURLOPT_TELNETOPTIONS.md CURLOPT_TFTP_BLKSIZE.md CURLOPT_TFTP_NO_OPTIONS.md CURLOPT_TIMECONDITION.md CURLOPT_TIMEOUT.md CURLOPT_TIMEOUT_MS.md CURLOPT_TIMEVALUE.md CURLOPT_TIMEVALUE_LARGE.md CURLOPT_TLS13_CIPHERS.md CURLOPT_TLSAUTH_PASSWORD.md CURLOPT_TLSAUTH_TYPE.md CURLOPT_TLSAUTH_USERNAME.md CURLOPT_TRAILERDATA.md CURLOPT_TRAILERFUNCTION.md CURLOPT_TRANSFERTEXT.md CURLOPT_TRANSFER_ENCODING.md CURLOPT_UNIX_SOCKET_PATH.md CURLOPT_UNRESTRICTED_AUTH.md CURLOPT_UPKEEP_INTERVAL_MS.md CURLOPT_UPLOAD.md CURLOPT_UPLOAD_BUFFERSIZE.md CURLOPT_UPLOAD_FLAGS.md CURLOPT_URL.md CURLOPT_USERAGENT.md CURLOPT_USERNAME.md CURLOPT_USERPWD.md CURLOPT_USE_SSL.md CURLOPT_VERBOSE.md CURLOPT_WILDCARDMATCH.md CURLOPT_WRITEDATA.md CURLOPT_WRITEFUNCTION.md CURLOPT_WS_OPTIONS.md CURLOPT_XFERINFODATA.md CURLOPT_XFERINFOFUNCTION.md CURLOPT_XOAUTH2_BEARER.md CURLSHOPT_LOCKFUNC.md CURLSHOPT_SHARE.md CURLSHOPT_UNLOCKFUNC.md CURLSHOPT_UNSHARE.md CURLSHOPT_USERDATA.md Makefile.am Makefile.inc
.gitignore ABI.md CMakeLists.txt Makefile.am Makefile.inc curl_easy_cleanup.md curl_easy_duphandle.md curl_easy_escape.md curl_easy_getinfo.md curl_easy_header.md curl_easy_init.md curl_easy_nextheader.md curl_easy_option_by_id.md curl_easy_option_by_name.md curl_easy_option_next.md curl_easy_pause.md curl_easy_perform.md curl_easy_recv.md curl_easy_reset.md curl_easy_send.md curl_easy_setopt.md curl_easy_ssls_export.md curl_easy_ssls_import.md curl_easy_strerror.md curl_easy_unescape.md curl_easy_upkeep.md curl_escape.md curl_formadd.md curl_formfree.md curl_formget.md curl_free.md curl_getdate.md curl_getenv.md curl_global_cleanup.md curl_global_init.md curl_global_init_mem.md curl_global_sslset.md curl_global_trace.md curl_mime_addpart.md curl_mime_data.md curl_mime_data_cb.md curl_mime_encoder.md curl_mime_filedata.md curl_mime_filename.md curl_mime_free.md curl_mime_headers.md curl_mime_init.md curl_mime_name.md curl_mime_subparts.md curl_mime_type.md curl_mprintf.md curl_multi_add_handle.md curl_multi_assign.md curl_multi_cleanup.md curl_multi_fdset.md curl_multi_get_handles.md curl_multi_get_offt.md curl_multi_info_read.md curl_multi_init.md curl_multi_notify_disable.md curl_multi_notify_enable.md curl_multi_perform.md curl_multi_poll.md curl_multi_remove_handle.md curl_multi_setopt.md curl_multi_socket.md curl_multi_socket_action.md curl_multi_socket_all.md curl_multi_strerror.md curl_multi_timeout.md curl_multi_wait.md curl_multi_waitfds.md curl_multi_wakeup.md curl_pushheader_byname.md curl_pushheader_bynum.md curl_share_cleanup.md curl_share_init.md curl_share_setopt.md curl_share_strerror.md curl_slist_append.md curl_slist_free_all.md curl_strequal.md curl_strnequal.md curl_unescape.md curl_url.md curl_url_cleanup.md curl_url_dup.md curl_url_get.md curl_url_set.md curl_url_strerror.md curl_version.md curl_version_info.md curl_ws_meta.md curl_ws_recv.md curl_ws_send.md curl_ws_start_frame.md libcurl-easy.md libcurl-env-dbg.md libcurl-env.md libcurl-errors.md libcurl-multi.md libcurl-security.md libcurl-share.md libcurl-thread.md libcurl-tutorial.md libcurl-url.md libcurl-ws.md libcurl.m4 libcurl.md mksymbolsmanpage.pl symbols-in-versions symbols.pl
tests CI.md FILEFORMAT.md HTTP.md TEST-SUITE.md
.gitignore ALTSVC.md BINDINGS.md BUG-BOUNTY.md BUGS.md CIPHERS-TLS12.md CIPHERS.md CMakeLists.txt CODE_OF_CONDUCT.md CODE_REVIEW.md CONTRIBUTE.md CURL-DISABLE.md CURLDOWN.md DEPRECATE.md DISTROS.md EARLY-RELEASE.md ECH.md EXPERIMENTAL.md FAQ.md FEATURES.md GOVERNANCE.md HELP-US.md HISTORY.md HSTS.md HTTP-COOKIES.md HTTP3.md HTTPSRR.md INFRASTRUCTURE.md INSTALL-CMAKE.md INSTALL.md INTERNALS.md IPFS.md KNOWN_BUGS.md KNOWN_RISKS.md MAIL-ETIQUETTE.md MANUAL.md Makefile.am README.md RELEASE-PROCEDURE.md ROADMAP.md RUSTLS.md SECURITY-ADVISORY.md SPONSORS.md SSL-PROBLEMS.md SSLCERTS.md THANKS THANKS-filter TODO.md TheArtOfHttpScripting.md URL-SYNTAX.md VERIFY.md VERSIONS.md VULN-DISCLOSURE-POLICY.md curl-config.md mk-ca-bundle.md options-in-versions runtests.md testcurl.md wcurl.md
include
curl Makefile.am curl.h curlver.h easy.h header.h mprintf.h multi.h options.h stdcheaders.h system.h typecheck-gcc.h urlapi.h websockets.h
Makefile.am README.md
lib
curlx base64.c base64.h basename.c basename.h dynbuf.c dynbuf.h fopen.c fopen.h inet_ntop.c inet_ntop.h inet_pton.c inet_pton.h multibyte.c multibyte.h nonblock.c nonblock.h snprintf.c snprintf.h strcopy.c strcopy.h strdup.c strdup.h strerr.c strerr.h strparse.c strparse.h timediff.c timediff.h timeval.c timeval.h version_win32.c version_win32.h wait.c wait.h warnless.c warnless.h winapi.c winapi.h
vauth cleartext.c cram.c digest.c digest.h digest_sspi.c gsasl.c krb5_gssapi.c krb5_sspi.c ntlm.c ntlm_sspi.c oauth2.c spnego_gssapi.c spnego_sspi.c vauth.c vauth.h
vquic curl_ngtcp2.c curl_ngtcp2.h curl_quiche.c curl_quiche.h vquic-tls.c vquic-tls.h vquic.c vquic.h vquic_int.h
vssh libssh.c libssh2.c ssh.h vssh.c vssh.h
vtls apple.c apple.h cipher_suite.c cipher_suite.h gtls.c gtls.h hostcheck.c hostcheck.h keylog.c keylog.h mbedtls.c mbedtls.h openssl.c openssl.h rustls.c rustls.h schannel.c schannel.h schannel_int.h schannel_verify.c vtls.c vtls.h vtls_int.h vtls_scache.c vtls_scache.h vtls_spack.c vtls_spack.h wolfssl.c wolfssl.h x509asn1.c x509asn1.h
.gitignore CMakeLists.txt Makefile.am Makefile.inc Makefile.soname altsvc.c altsvc.h amigaos.c amigaos.h arpa_telnet.h asyn-ares.c asyn-base.c asyn-thrdd.c asyn.h bufq.c bufq.h bufref.c bufref.h cf-dns.c cf-dns.h cf-h1-proxy.c cf-h1-proxy.h cf-h2-proxy.c cf-h2-proxy.h cf-haproxy.c cf-haproxy.h cf-https-connect.c cf-https-connect.h cf-ip-happy.c cf-ip-happy.h cf-socket.c cf-socket.h cfilters.c cfilters.h config-mac.h config-os400.h config-riscos.h config-win32.h conncache.c conncache.h connect.c connect.h content_encoding.c content_encoding.h cookie.c cookie.h creds.c creds.h cshutdn.c cshutdn.h curl_addrinfo.c curl_addrinfo.h curl_config-cmake.h.in curl_ctype.h curl_endian.c curl_endian.h curl_fnmatch.c curl_fnmatch.h curl_fopen.c curl_fopen.h curl_get_line.c curl_get_line.h curl_gethostname.c curl_gethostname.h curl_gssapi.c curl_gssapi.h curl_hmac.h curl_ldap.h curl_md4.h curl_md5.h curl_memrchr.c curl_memrchr.h curl_ntlm_core.c curl_ntlm_core.h curl_printf.h curl_range.c curl_range.h curl_sasl.c curl_sasl.h curl_setup.h curl_sha256.h curl_sha512_256.c curl_sha512_256.h curl_share.c curl_share.h curl_sspi.c curl_sspi.h curl_threads.c curl_threads.h curl_trc.c curl_trc.h cw-out.c cw-out.h cw-pause.c cw-pause.h dict.c dict.h dllmain.c dnscache.c dnscache.h doh.c doh.h dynhds.c dynhds.h easy.c easy_lock.h easygetopt.c easyif.h easyoptions.c easyoptions.h escape.c escape.h fake_addrinfo.c fake_addrinfo.h file.c file.h fileinfo.c fileinfo.h formdata.c formdata.h ftp-int.h ftp.c ftp.h ftplistparser.c ftplistparser.h functypes.h getenv.c getinfo.c getinfo.h gopher.c gopher.h hash.c hash.h headers.c headers.h hmac.c hostip.c hostip.h hostip4.c hostip6.c hsts.c hsts.h http.c http.h http1.c http1.h http2.c http2.h http_aws_sigv4.c http_aws_sigv4.h http_chunks.c http_chunks.h http_digest.c http_digest.h http_negotiate.c http_negotiate.h http_ntlm.c http_ntlm.h http_proxy.c http_proxy.h httpsrr.c httpsrr.h idn.c idn.h if2ip.c if2ip.h imap.c imap.h ldap.c libcurl.def libcurl.rc libcurl.vers.in llist.c llist.h macos.c macos.h md4.c md5.c memdebug.c mime.c mime.h mprintf.c mqtt.c mqtt.h multi.c multi_ev.c multi_ev.h multi_ntfy.c multi_ntfy.h multihandle.h multiif.h netrc.c netrc.h noproxy.c noproxy.h openldap.c optiontable.pl parsedate.c parsedate.h peer.c peer.h pingpong.c pingpong.h pop3.c pop3.h progress.c progress.h protocol.c protocol.h psl.c psl.h rand.c rand.h ratelimit.c ratelimit.h request.c request.h rtsp.c rtsp.h select.c select.h sendf.c sendf.h setopt.c setopt.h setup-os400.h setup-vms.h setup-win32.h sha256.c sigpipe.h slist.c slist.h smb.c smb.h smtp.c smtp.h sockaddr.h socketpair.c socketpair.h socks.c socks.h socks_gssapi.c socks_sspi.c splay.c splay.h strcase.c strcase.h strequal.c strerror.c strerror.h system_win32.c system_win32.h telnet.c telnet.h tftp.c tftp.h thrdpool.c thrdpool.h thrdqueue.c thrdqueue.h transfer.c transfer.h uint-bset.c uint-bset.h uint-hash.c uint-hash.h uint-spbset.c uint-spbset.h uint-table.c uint-table.h url.c url.h urlapi-int.h urlapi.c urldata.h version.c ws.c ws.h
m4 .gitignore curl-amissl.m4 curl-apple-sectrust.m4 curl-compilers.m4 curl-confopts.m4 curl-functions.m4 curl-gnutls.m4 curl-mbedtls.m4 curl-openssl.m4 curl-override.m4 curl-reentrant.m4 curl-rustls.m4 curl-schannel.m4 curl-sysconfig.m4 curl-wolfssl.m4 xc-am-iface.m4 xc-cc-check.m4 xc-lt-iface.m4 xc-val-flgs.m4 zz40-xc-ovr.m4 zz50-xc-ovr.m4
projects
OS400
rpg-examples HEADERAPI HTTPPOST INMEMORY SIMPLE1 SIMPLE2 SMTPSRCMBR
.checksrc README.OS400 ccsidcurl.c ccsidcurl.h config400.default curl.cmd curl.inc.in curlcl.c curlmain.c initscript.sh make-docs.sh make-include.sh make-lib.sh make-src.sh make-tests.sh makefile.sh os400sys.c os400sys.h
Windows
tmpl .gitattributes README.txt curl-all.sln curl.sln curl.vcxproj curl.vcxproj.filters libcurl.sln libcurl.vcxproj libcurl.vcxproj.filters
.gitignore README.md generate.bat
vms Makefile.am backup_gnv_curl_src.com build_curl-config_script.com build_gnv_curl.com build_gnv_curl_pcsi_desc.com build_gnv_curl_pcsi_text.com build_gnv_curl_release_notes.com build_libcurl_pc.com build_vms.com clean_gnv_curl.com compare_curl_source.com config_h.com curl_crtl_init.c curl_gnv_build_steps.txt curl_release_note_start.txt curl_startup.com curlmsg.h curlmsg.msg curlmsg.sdl curlmsg_vms.h generate_config_vms_h_curl.com generate_vax_transfer.com gnv_conftest.c_first gnv_curl_configure.sh gnv_libcurl_symbols.opt gnv_link_curl.com macro32_exactcase.patch make_gnv_curl_install.sh make_pcsi_curl_kit_name.com pcsi_gnv_curl_file_list.txt pcsi_product_gnv_curl.com readme report_openssl_version.c setup_gnv_curl_build.com stage_curl_install.com vms_eco_level.h
Makefile.am README.md
scripts .checksrc CMakeLists.txt Makefile.am badwords badwords-all badwords.txt cd2cd cd2nroff cdall checksrc-all.pl checksrc.pl cmakelint.sh completion.pl contributors.sh contrithanks.sh coverage.sh delta dmaketgz extract-unit-protos firefox-db2pem.sh installcheck.sh maketgz managen mdlinkcheck mk-ca-bundle.pl mk-unity.pl nroff2cd perlcheck.sh pythonlint.sh randdisable release-notes.pl release-tools.sh schemetable.c singleuse.pl spacecheck.pl top-complexity top-length verify-release wcurl
src
toolx tool_time.c tool_time.h
.checksrc .gitignore CMakeLists.txt Makefile.am Makefile.inc config2setopts.c config2setopts.h curl.rc curlinfo.c mk-file-embed.pl mkhelp.pl slist_wc.c slist_wc.h terminal.c terminal.h tool_cb_dbg.c tool_cb_dbg.h tool_cb_hdr.c tool_cb_hdr.h tool_cb_prg.c tool_cb_prg.h tool_cb_rea.c tool_cb_rea.h tool_cb_see.c tool_cb_see.h tool_cb_soc.c tool_cb_soc.h tool_cb_wrt.c tool_cb_wrt.h tool_cfgable.c tool_cfgable.h tool_dirhie.c tool_dirhie.h tool_doswin.c tool_doswin.h tool_easysrc.c tool_easysrc.h tool_filetime.c tool_filetime.h tool_findfile.c tool_findfile.h tool_formparse.c tool_formparse.h tool_getparam.c tool_getparam.h tool_getpass.c tool_getpass.h tool_help.c tool_help.h tool_helpers.c tool_helpers.h tool_hugehelp.h tool_ipfs.c tool_ipfs.h tool_libinfo.c tool_libinfo.h tool_listhelp.c tool_main.c tool_main.h tool_msgs.c tool_msgs.h tool_operate.c tool_operate.h tool_operhlp.c tool_operhlp.h tool_paramhlp.c tool_paramhlp.h tool_parsecfg.c tool_parsecfg.h tool_progress.c tool_progress.h tool_sdecls.h tool_setopt.c tool_setopt.h tool_setup.h tool_ssls.c tool_ssls.h tool_stderr.c tool_stderr.h tool_urlglob.c tool_urlglob.h tool_util.c tool_util.h tool_version.h tool_vms.c tool_vms.h tool_writeout.c tool_writeout.h tool_writeout_json.c tool_writeout_json.h tool_xattr.c tool_xattr.h var.c var.h
tests
certs .gitignore CMakeLists.txt Makefile.am Makefile.inc genserv.pl srp-verifier-conf srp-verifier-db test-ca.cnf test-ca.prm test-client-cert.prm test-client-eku-only.prm test-localhost-san-first.prm test-localhost-san-last.prm test-localhost.nn.prm test-localhost.prm test-localhost0h.prm
cmake CMakeLists.txt test.c test.cpp test.sh
data .gitignore DISABLED Makefile.am data-xml1 data1400.c data1401.c data1402.c data1403.c data1404.c data1405.c data1406.c data1407.c data1420.c data1461.txt data1463.txt data1465.c data1481.c data1705-1.md data1705-2.md data1705-3.md data1705-4.md data1705-stdout.1 data1706-1.md data1706-2.md data1706-3.md data1706-4.md data1706-stdout.txt data320.html test1 test10 test100 test1000 test1001 test1002 test1003 test1004 test1005 test1006 test1007 test1008 test1009 test101 test1010 test1011 test1012 test1013 test1014 test1015 test1016 test1017 test1018 test1019 test102 test1020 test1021 test1022 test1023 test1024 test1025 test1026 test1027 test1028 test1029 test103 test1030 test1031 test1032 test1033 test1034 test1035 test1036 test1037 test1038 test1039 test104 test1040 test1041 test1042 test1043 test1044 test1045 test1046 test1047 test1048 test1049 test105 test1050 test1051 test1052 test1053 test1054 test1055 test1056 test1057 test1058 test1059 test106 test1060 test1061 test1062 test1063 test1064 test1065 test1066 test1067 test1068 test1069 test107 test1070 test1071 test1072 test1073 test1074 test1075 test1076 test1077 test1078 test1079 test108 test1080 test1081 test1082 test1083 test1084 test1085 test1086 test1087 test1088 test1089 test109 test1090 test1091 test1092 test1093 test1094 test1095 test1096 test1097 test1098 test1099 test11 test110 test1100 test1101 test1102 test1103 test1104 test1105 test1106 test1107 test1108 test1109 test111 test1110 test1111 test1112 test1113 test1114 test1115 test1116 test1117 test1118 test1119 test112 test1120 test1121 test1122 test1123 test1124 test1125 test1126 test1127 test1128 test1129 test113 test1130 test1131 test1132 test1133 test1134 test1135 test1136 test1137 test1138 test1139 test114 test1140 test1141 test1142 test1143 test1144 test1145 test1146 test1147 test1148 test1149 test115 test1150 test1151 test1152 test1153 test1154 test1155 test1156 test1157 test1158 test1159 test116 test1160 test1161 test1162 test1163 test1164 test1165 test1166 test1167 test1168 test1169 test117 test1170 test1171 test1172 test1173 test1174 test1175 test1176 test1177 test1178 test1179 test118 test1180 test1181 test1182 test1183 test1184 test1185 test1186 test1187 test1188 test1189 test119 test1190 test1191 test1192 test1193 test1194 test1195 test1196 test1197 test1198 test1199 test12 test120 test1200 test1201 test1202 test1203 test1204 test1205 test1206 test1207 test1208 test1209 test121 test1210 test1211 test1212 test1213 test1214 test1215 test1216 test1217 test1218 test1219 test122 test1220 test1221 test1222 test1223 test1224 test1225 test1226 test1227 test1228 test1229 test123 test1230 test1231 test1232 test1233 test1234 test1235 test1236 test1237 test1238 test1239 test124 test1240 test1241 test1242 test1243 test1244 test1245 test1246 test1247 test1248 test1249 test125 test1250 test1251 test1252 test1253 test1254 test1255 test1256 test1257 test1258 test1259 test126 test1260 test1261 test1262 test1263 test1264 test1265 test1266 test1267 test1268 test1269 test127 test1270 test1271 test1272 test1273 test1274 test1275 test1276 test1277 test1278 test1279 test128 test1280 test1281 test1282 test1283 test1284 test1285 test1286 test1287 test1288 test1289 test129 test1290 test1291 test1292 test1293 test1294 test1295 test1296 test1297 test1298 test1299 test13 test130 test1300 test1301 test1302 test1303 test1304 test1305 test1306 test1307 test1308 test1309 test131 test1310 test1311 test1312 test1313 test1314 test1315 test1316 test1317 test1318 test1319 test132 test1320 test1321 test1322 test1323 test1324 test1325 test1326 test1327 test1328 test1329 test133 test1330 test1331 test1332 test1333 test1334 test1335 test1336 test1337 test1338 test1339 test134 test1340 test1341 test1342 test1343 test1344 test1345 test1346 test1347 test1348 test1349 test135 test1350 test1351 test1352 test1353 test1354 test1355 test1356 test1357 test1358 test1359 test136 test1360 test1361 test1362 test1363 test1364 test1365 test1366 test1367 test1368 test1369 test137 test1370 test1371 test1372 test1373 test1374 test1375 test1376 test1377 test1378 test1379 test138 test1380 test1381 test1382 test1383 test1384 test1385 test1386 test1387 test1388 test1389 test139 test1390 test1391 test1392 test1393 test1394 test1395 test1396 test1397 test1398 test1399 test14 test140 test1400 test1401 test1402 test1403 test1404 test1405 test1406 test1407 test1408 test1409 test141 test1410 test1411 test1412 test1413 test1414 test1415 test1416 test1417 test1418 test1419 test142 test1420 test1421 test1422 test1423 test1424 test1425 test1426 test1427 test1428 test1429 test143 test1430 test1431 test1432 test1433 test1434 test1435 test1436 test1437 test1438 test1439 test144 test1440 test1441 test1442 test1443 test1444 test1445 test1446 test1447 test1448 test1449 test145 test1450 test1451 test1452 test1453 test1454 test1455 test1456 test1457 test1458 test1459 test146 test1460 test1461 test1462 test1463 test1464 test1465 test1466 test1467 test1468 test1469 test147 test1470 test1471 test1472 test1473 test1474 test1475 test1476 test1477 test1478 test1479 test148 test1480 test1481 test1482 test1483 test1484 test1485 test1486 test1487 test1488 test1489 test149 test1490 test1491 test1492 test1493 test1494 test1495 test1496 test1497 test1498 test1499 test15 test150 test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 test1508 test1509 test151 test1510 test1511 test1512 test1513 test1514 test1515 test1516 test1517 test1518 test1519 test152 test1520 test1521 test1522 test1523 test1524 test1525 test1526 test1527 test1528 test1529 test153 test1530 test1531 test1532 test1533 test1534 test1535 test1536 test1537 test1538 test1539 test154 test1540 test1541 test1542 test1543 test1544 test1545 test1546 test1547 test1548 test1549 test155 test1550 test1551 test1552 test1553 test1554 test1555 test1556 test1557 test1558 test1559 test156 test1560 test1561 test1562 test1563 test1564 test1565 test1566 test1567 test1568 test1569 test157 test1570 test1571 test1572 test1573 test1574 test1575 test1576 test1577 test1578 test1579 test158 test1580 test1581 test1582 test1583 test1584 test1585 test1586 test1587 test1588 test1589 test159 test1590 test1591 test1592 test1593 test1594 test1595 test1596 test1597 test1598 test1599 test16 test160 test1600 test1601 test1602 test1603 test1604 test1605 test1606 test1607 test1608 test1609 test161 test1610 test1611 test1612 test1613 test1614 test1615 test1616 test1617 test1618 test1619 test162 test1620 test1621 test1622 test1623 test1624 test1625 test1626 test1627 test1628 test1629 test163 test1630 test1631 test1632 test1633 test1634 test1635 test1636 test1637 test1638 test1639 test164 test1640 test1641 test1642 test1643 test1644 test1645 test165 test1650 test1651 test1652 test1653 test1654 test1655 test1656 test1657 test1658 test1659 test166 test1660 test1661 test1662 test1663 test1664 test1665 test1666 test1667 test1668 test1669 test167 test1670 test1671 test1672 test1673 test1674 test1675 test1676 test168 test1680 test1681 test1682 test1683 test1684 test1685 test169 test17 test170 test1700 test1701 test1702 test1703 test1704 test1705 test1706 test1707 test1708 test1709 test171 test1710 test1711 test1712 test1713 test1714 test1715 test172 test1720 test1721 test173 test174 test175 test176 test177 test178 test179 test18 test180 test1800 test1801 test1802 test181 test182 test183 test184 test1847 test1848 test1849 test185 test1850 test1851 test186 test187 test188 test189 test19 test190 test1900 test1901 test1902 test1903 test1904 test1905 test1906 test1907 test1908 test1909 test191 test1910 test1911 test1912 test1913 test1914 test1915 test1916 test1917 test1918 test1919 test192 test1920 test1921 test193 test1933 test1934 test1935 test1936 test1937 test1938 test1939 test194 test1940 test1941 test1942 test1943 test1944 test1945 test1946 test1947 test1948 test195 test1955 test1956 test1957 test1958 test1959 test196 test1960 test1964 test1965 test1966 test197 test1970 test1971 test1972 test1973 test1974 test1975 test1976 test1977 test1978 test1979 test198 test1980 test1981 test1982 test1983 test1984 test199 test2 test20 test200 test2000 test2001 test2002 test2003 test2004 test2005 test2006 test2007 test2008 test2009 test201 test2010 test2011 test2012 test2013 test2014 test202 test2023 test2024 test2025 test2026 test2027 test2028 test2029 test203 test2030 test2031 test2032 test2033 test2034 test2035 test2037 test2038 test2039 test204 test2040 test2041 test2042 test2043 test2044 test2045 test2046 test2047 test2048 test2049 test205 test2050 test2051 test2052 test2053 test2054 test2055 test2056 test2057 test2058 test2059 test206 test2060 test2061 test2062 test2063 test2064 test2065 test2066 test2067 test2068 test2069 test207 test2070 test2071 test2072 test2073 test2074 test2075 test2076 test2077 test2078 test2079 test208 test2080 test2081 test2082 test2083 test2084 test2085 test2086 test2087 test2088 test2089 test209 test2090 test2091 test2092 test21 test210 test2100 test2101 test2102 test2103 test2104 test211 test212 test213 test214 test215 test216 test217 test218 test219 test22 test220 test2200 test2201 test2202 test2203 test2204 test2205 test2206 test2207 test221 test222 test223 test224 test225 test226 test227 test228 test229 test23 test230 test2300 test2301 test2302 test2303 test2304 test2306 test2307 test2308 test2309 test231 test232 test233 test234 test235 test236 test237 test238 test239 test24 test240 test2400 test2401 test2402 test2403 test2404 test2405 test2406 test2407 test2408 test2409 test241 test2410 test2411 test242 test243 test244 test245 test246 test247 test248 test249 test25 test250 test2500 test2501 test2502 test2503 test2504 test2505 test2506 test251 test252 test253 test254 test255 test256 test257 test258 test259 test26 test260 test2600 test2601 test2602 test2603 test2604 test2605 test261 test262 test263 test264 test265 test266 test267 test268 test269 test27 test270 test2700 test2701 test2702 test2703 test2704 test2705 test2706 test2707 test2708 test2709 test271 test2710 test2711 test2712 test2713 test2714 test2715 test2716 test2717 test2718 test2719 test272 test2720 test2721 test2722 test2723 test273 test274 test275 test276 test277 test278 test279 test28 test280 test281 test282 test283 test284 test285 test286 test287 test288 test289 test29 test290 test291 test292 test293 test294 test295 test296 test297 test298 test299 test3 test30 test300 test3000 test3001 test3002 test3003 test3004 test3005 test3006 test3007 test3008 test3009 test301 test3010 test3011 test3012 test3013 test3014 test3015 test3016 test3017 test3018 test3019 test302 test3020 test3021 test3022 test3023 test3024 test3025 test3026 test3027 test3028 test3029 test303 test3030 test3031 test3032 test3033 test3034 test3035 test3036 test304 test305 test306 test307 test308 test309 test31 test310 test3100 test3101 test3102 test3103 test3104 test3105 test3106 test311 test312 test313 test314 test315 test316 test317 test318 test319 test32 test320 test3200 test3201 test3202 test3203 test3204 test3205 test3206 test3207 test3208 test3209 test321 test3210 test3211 test3212 test3213 test3214 test3215 test3216 test3217 test3218 test3219 test322 test3220 test323 test324 test325 test326 test327 test328 test329 test33 test330 test3300 test3301 test3302 test331 test332 test333 test334 test335 test336 test337 test338 test339 test34 test340 test341 test342 test343 test344 test345 test346 test347 test348 test349 test35 test350 test351 test352 test353 test354 test355 test356 test357 test358 test359 test36 test360 test361 test362 test363 test364 test365 test366 test367 test368 test369 test37 test370 test371 test372 test373 test374 test375 test376 test378 test379 test38 test380 test381 test383 test384 test385 test386 test387 test388 test389 test39 test390 test391 test392 test393 test394 test395 test396 test397 test398 test399 test4 test40 test400 test4000 test4001 test401 test402 test403 test404 test405 test406 test407 test408 test409 test41 test410 test411 test412 test413 test414 test415 test416 test417 test418 test419 test42 test420 test421 test422 test423 test424 test425 test426 test427 test428 test429 test43 test430 test431 test432 test433 test434 test435 test436 test437 test438 test439 test44 test440 test441 test442 test443 test444 test445 test446 test447 test448 test449 test45 test450 test451 test452 test453 test454 test455 test456 test457 test458 test459 test46 test460 test461 test462 test463 test467 test468 test469 test47 test470 test471 test472 test473 test474 test475 test476 test477 test478 test479 test48 test480 test481 test482 test483 test484 test485 test486 test487 test488 test489 test49 test490 test491 test492 test493 test494 test495 test496 test497 test498 test499 test5 test50 test500 test501 test502 test503 test504 test505 test506 test507 test508 test509 test51 test510 test511 test512 test513 test514 test515 test516 test517 test518 test519 test52 test520 test521 test522 test523 test524 test525 test526 test527 test528 test529 test53 test530 test531 test532 test533 test534 test535 test536 test537 test538 test539 test54 test540 test541 test542 test543 test544 test545 test546 test547 test548 test549 test55 test550 test551 test552 test553 test554 test555 test556 test557 test558 test559 test56 test560 test561 test562 test563 test564 test565 test566 test567 test568 test569 test57 test570 test571 test572 test573 test574 test575 test576 test577 test578 test579 test58 test580 test581 test582 test583 test584 test585 test586 test587 test588 test589 test59 test590 test591 test592 test593 test594 test595 test596 test597 test598 test599 test6 test60 test600 test601 test602 test603 test604 test605 test606 test607 test608 test609 test61 test610 test611 test612 test613 test614 test615 test616 test617 test618 test619 test62 test620 test621 test622 test623 test624 test625 test626 test627 test628 test629 test63 test630 test631 test632 test633 test634 test635 test636 test637 test638 test639 test64 test640 test641 test642 test643 test644 test645 test646 test647 test648 test649 test65 test650 test651 test652 test653 test654 test655 test656 test658 test659 test66 test660 test661 test662 test663 test664 test665 test666 test667 test668 test669 test67 test670 test671 test672 test673 test674 test675 test676 test677 test678 test679 test68 test680 test681 test682 test683 test684 test685 test686 test687 test688 test689 test69 test690 test691 test692 test693 test694 test695 test696 test697 test698 test699 test7 test70 test700 test701 test702 test703 test704 test705 test706 test707 test708 test709 test71 test710 test711 test712 test713 test714 test715 test716 test717 test718 test719 test72 test720 test721 test722 test723 test724 test725 test726 test727 test728 test729 test73 test730 test731 test732 test733 test734 test735 test736 test737 test738 test739 test74 test740 test741 test742 test743 test744 test745 test746 test747 test748 test749 test75 test750 test751 test752 test753 test754 test755 test756 test757 test758 test759 test76 test760 test761 test762 test763 test764 test765 test766 test767 test768 test769 test77 test770 test771 test772 test773 test774 test775 test776 test777 test778 test779 test78 test780 test781 test782 test783 test784 test785 test786 test787 test788 test789 test79 test790 test791 test792 test793 test794 test795 test796 test797 test798 test799 test8 test80 test800 test801 test802 test803 test804 test805 test806 test807 test808 test809 test81 test810 test811 test812 test813 test814 test815 test816 test817 test818 test819 test82 test820 test821 test822 test823 test824 test825 test826 test827 test828 test829 test83 test830 test831 test832 test833 test834 test835 test836 test837 test838 test839 test84 test840 test841 test842 test843 test844 test845 test846 test847 test848 test849 test85 test850 test851 test852 test853 test854 test855 test856 test857 test858 test859 test86 test860 test861 test862 test863 test864 test865 test866 test867 test868 test869 test87 test870 test871 test872 test873 test874 test875 test876 test877 test878 test879 test88 test880 test881 test882 test883 test884 test885 test886 test887 test888 test889 test89 test890 test891 test892 test893 test894 test895 test896 test897 test898 test899 test9 test90 test900 test901 test902 test903 test904 test905 test906 test907 test908 test909 test91 test910 test911 test912 test913 test914 test915 test916 test917 test918 test919 test92 test920 test921 test922 test923 test924 test925 test926 test927 test928 test929 test93 test930 test931 test932 test933 test934 test935 test936 test937 test938 test939 test94 test940 test941 test942 test943 test944 test945 test946 test947 test948 test949 test95 test950 test951 test952 test953 test954 test955 test956 test957 test958 test959 test96 test960 test961 test962 test963 test964 test965 test966 test967 test968 test969 test97 test970 test971 test972 test973 test974 test975 test976 test977 test978 test979 test98 test980 test981 test982 test983 test984 test985 test986 test987 test988 test989 test99 test990 test991 test992 test993 test994 test995 test996 test997 test998 test999
http
testenv
mod_curltest .gitignore mod_curltest.c
__init__.py caddy.py certs.py client.py curl.py dante.py dnsd.py env.py httpd.py nghttpx.py ports.py sshd.py vsftpd.py ws_echo_server.py
.gitignore CMakeLists.txt Makefile.am config.ini.in conftest.py requirements.txt scorecard.py test_01_basic.py test_02_download.py test_03_goaway.py test_04_stuttered.py test_05_errors.py test_06_eyeballs.py test_07_upload.py test_08_caddy.py test_09_push.py test_10_proxy.py test_11_unix.py test_12_reuse.py test_13_proxy_auth.py test_14_auth.py test_15_tracing.py test_16_info.py test_17_ssl_use.py test_18_methods.py test_19_shutdown.py test_20_websockets.py test_21_resolve.py test_22_httpsrr.py test_30_vsftpd.py test_31_vsftpds.py test_32_ftps_vsftpd.py test_40_socks.py test_50_scp.py test_51_sftp.py
libtest .gitignore CMakeLists.txt Makefile.am Makefile.inc cli_ftp_upload.c cli_h2_pausing.c cli_h2_serverpush.c cli_h2_upgrade_extreme.c cli_hx_download.c cli_hx_upload.c cli_tls_session_reuse.c cli_upload_pausing.c cli_ws_data.c cli_ws_pingpong.c first.c first.h lib1156.c lib1301.c lib1308.c lib1485.c lib1500.c lib1501.c lib1502.c lib1506.c lib1507.c lib1508.c lib1509.c lib1510.c lib1511.c lib1512.c lib1513.c lib1514.c lib1515.c lib1517.c lib1518.c lib1520.c lib1522.c lib1523.c lib1525.c lib1526.c lib1527.c lib1528.c lib1529.c lib1530.c lib1531.c lib1532.c lib1533.c lib1534.c lib1535.c lib1536.c lib1537.c lib1538.c lib1540.c lib1541.c lib1542.c lib1545.c lib1549.c lib1550.c lib1551.c lib1552.c lib1553.c lib1554.c lib1555.c lib1556.c lib1557.c lib1558.c lib1559.c lib1560.c lib1564.c lib1565.c lib1567.c lib1568.c lib1569.c lib1571.c lib1576.c lib1582.c lib1587.c lib1588.c lib1589.c lib1591.c lib1592.c lib1593.c lib1594.c lib1597.c lib1598.c lib1599.c lib1662.c lib1900.c lib1901.c lib1902.c lib1903.c lib1905.c lib1906.c lib1907.c lib1908.c lib1910.c lib1911.c lib1912.c lib1913.c lib1915.c lib1916.c lib1918.c lib1919.c lib1920.c lib1921.c lib1933.c lib1934.c lib1935.c lib1936.c lib1937.c lib1938.c lib1939.c lib1940.c lib1945.c lib1947.c lib1948.c lib1955.c lib1956.c lib1957.c lib1958.c lib1959.c lib1960.c lib1964.c lib1965.c lib1970.c lib1971.c lib1972.c lib1973.c lib1974.c lib1975.c lib1977.c lib1978.c lib2023.c lib2032.c lib2082.c lib2301.c lib2302.c lib2304.c lib2306.c lib2308.c lib2309.c lib2402.c lib2404.c lib2405.c lib2502.c lib2504.c lib2505.c lib2506.c lib2700.c lib3010.c lib3025.c lib3026.c lib3027.c lib3033.c lib3034.c lib3100.c lib3101.c lib3102.c lib3103.c lib3104.c lib3105.c lib3207.c lib3208.c lib500.c lib501.c lib502.c lib503.c lib504.c lib505.c lib506.c lib507.c lib508.c lib509.c lib510.c lib511.c lib512.c lib513.c lib514.c lib515.c lib516.c lib517.c lib518.c lib519.c lib520.c lib521.c lib523.c lib524.c lib525.c lib526.c lib530.c lib533.c lib536.c lib537.c lib539.c lib540.c lib541.c lib542.c lib543.c lib544.c lib547.c lib549.c lib552.c lib553.c lib554.c lib555.c lib556.c lib557.c lib558.c lib559.c lib560.c lib562.c lib564.c lib566.c lib567.c lib568.c lib569.c lib570.c lib571.c lib572.c lib573.c lib574.c lib575.c lib576.c lib578.c lib579.c lib582.c lib583.c lib586.c lib589.c lib590.c lib591.c lib597.c lib598.c lib599.c lib643.c lib650.c lib651.c lib652.c lib653.c lib654.c lib655.c lib658.c lib659.c lib661.c lib666.c lib667.c lib668.c lib670.c lib674.c lib676.c lib677.c lib678.c lib694.c lib695.c lib751.c lib753.c lib757.c lib758.c lib766.c memptr.c mk-lib1521.pl test1013.pl test1022.pl test307.pl test610.pl test613.pl testtrace.c testtrace.h testutil.c testutil.h unitcheck.h
server .checksrc .gitignore CMakeLists.txt Makefile.am Makefile.inc dnsd.c first.c first.h getpart.c mqttd.c resolve.c rtspd.c sockfilt.c socksd.c sws.c tftpd.c util.c
tunit .gitignore CMakeLists.txt Makefile.am Makefile.inc README.md tool1394.c tool1604.c tool1621.c tool1622.c tool1623.c tool1720.c
unit .gitignore CMakeLists.txt Makefile.am Makefile.inc README.md unit1300.c unit1302.c unit1303.c unit1304.c unit1305.c unit1307.c unit1309.c unit1323.c unit1330.c unit1395.c unit1396.c unit1397.c unit1398.c unit1399.c unit1600.c unit1601.c unit1602.c unit1603.c unit1605.c unit1606.c unit1607.c unit1608.c unit1609.c unit1610.c unit1611.c unit1612.c unit1614.c unit1615.c unit1616.c unit1620.c unit1625.c unit1626.c unit1627.c unit1636.c unit1650.c unit1651.c unit1652.c unit1653.c unit1654.c unit1655.c unit1656.c unit1657.c unit1658.c unit1660.c unit1661.c unit1663.c unit1664.c unit1666.c unit1667.c unit1668.c unit1669.c unit1674.c unit1675.c unit1676.c unit1979.c unit1980.c unit2600.c unit2601.c unit2602.c unit2603.c unit2604.c unit2605.c unit3200.c unit3205.c unit3211.c unit3212.c unit3213.c unit3214.c unit3216.c unit3219.c unit3300.c unit3301.c unit3302.c
.gitignore CMakeLists.txt Makefile.am allversions.pm appveyor.pm azure.pm config.in configurehelp.pm.in devtest.pl dictserver.py directories.pm ech_combos.py ech_tests.sh ftpserver.pl getpart.pm globalconfig.pm http-server.pl http2-server.pl http3-server.pl memanalyze.pl memanalyzer.pm negtelnetserver.py nghttpx.conf pathhelp.pm processhelp.pm requirements.txt rtspserver.pl runner.pm runtests.pl secureserver.pl serverhelp.pm servers.pm smbserver.py sshhelp.pm sshserver.pl test1119.pl test1135.pl test1139.pl test1140.pl test1165.pl test1167.pl test1173.pl test1175.pl test1177.pl test1222.pl test1275.pl test1276.pl test1477.pl test1486.pl test1488.pl test1544.pl test1707.pl test745.pl test971.pl testcurl.pl testutil.pm tftpserver.pl util.py valgrind.pm valgrind.supp
.clang-tidy.yml .dir-locals.el .editorconfig .git-blame-ignore-revs .gitattributes .gitignore .mailmap CHANGES.md CMakeLists.txt COPYING Dockerfile GIT-INFO.md Makefile.am README README.md RELEASE-NOTES REUSE.toml SECURITY.md acinclude.m4 appveyor.sh appveyor.yml configure.ac curl-config.in libcurl.pc.in renovate.json
examples .env config.ini crypto_test.lua env_test.lua fs_example.lua http_server.lua https_test.lua ini_example.lua json.lua log.lua path_fs_example.lua process_example.lua request_download.lua request_test.lua run_all.lua sqlite_example.lua sqlite_http_template.lua stash_test.lua template_test.lua timer.lua websocket.lua
iniparser
.github
ISSUE_TEMPLATE config.yml
workflows disable-pull-requests.yml trigger-gitlab-ci.yml
cmake JoinPaths.cmake config.cmake.in pc.in
example iniexample.c iniwrite.c parse.c twisted-errors.ini twisted-genhuge.py twisted-ofkey.ini twisted-ofval.ini twisted.ini
src dictionary.c dictionary.h iniparser.c iniparser.h
test
ressources
bad_ini ends_well.ini twisted-errors.ini twisted-ofkey.ini twisted-ofval.ini
good_ini empty.ini spaced.ini spaced2.ini twisted.ini
gruezi.ini old.ini quotes.ini utf8.ini
CMakeLists.txt test_dictionary.c test_iniparser.c unity-config.yml unity_config.h
.cmake-format.py .gitignore .gitlab-ci.yml .gitmessage .travis.yml AUTHORS CMakeLists.txt FAQ-en.md FAQ-zhcn.md INSTALL LICENSE README.md compile_commands.json
jinjac
example CMakeLists.txt example.c
jinjac_test_app CMakeLists.txt jinjac_test_app.c
libjinjac
include jinjac.h
src CMakeLists.txt ast.c ast.h block_statement.c block_statement.h buffer.c buffer.h buildin.c buildin.h common.h convert.c convert.h flex_decl.h jfunction.c jfunction.h jinja_expression.l jinja_expression.y jinjac_parse.c jinjac_parse.h jinjac_stream.c jinjac_stream.h jlist.c jlist.h jobject.c jobject.h parameter.c parameter.h str_obj.c str_obj.h trace.c trace.h
CMakeLists.txt
test .gitignore CMakeLists.txt autotest.rb test_01.expected test_01.jinja test_01b.expected test_01b.jinja test_01c.expected test_01c.jinja test_01d.expected test_01d.jinja test_02.expected test_02.jinja test_03.expected test_03.jinja test_04.expected test_04.jinja test_05.expected test_05.jinja test_06.expected test_06.jinja test_07.expected test_07.jinja test_08.expected test_08.jinja test_08b.expected test_08b.jinja test_09.expected test_09.jinja test_10.expected test_10.jinja test_11.expected test_11.jinja test_12.expected test_12.jinja test_13.expected test_13.jinja test_14.expected test_14.jinja test_15.expected test_15.jinja test_16.expected test_16.jinja test_17.expected test_17.jinja test_18.expected test_18.jinja test_18b.expected test_18b.jinja test_18c.expected test_18c.jinja test_19.expected test_19.jinja test_19b.expected test_19b.jinja test_19c.expected test_19c.jinja test_19d.expected test_19d.jinja test_19e.expected test_19e.jinja test_19f.expected test_19f.jinja test_20.expected test_20.jinja test_21.expected test_21.jinja test_22.expected test_22.jinja test_22a.expected test_22a.jinja test_22b.expected test_22b.jinja test_23.expected test_23.jinja test_24.expected test_24.jinja
.gitignore CMakeLists.txt LICENSE.txt README.md build_coverage.sh build_debug.sh build_release.sh cppcheck_analysis.sh
libev Changes LICENSE Makefile Makefile.am Makefile.in README Symbols.ev Symbols.event aclocal.m4 autogen.sh compile config.guess config.h config.h.in config.status config.sub configure configure.ac depcomp ev++.h ev.3 ev.c ev.h ev.pod ev_epoll.c ev_kqueue.c ev_poll.c ev_port.c ev_select.c ev_vars.h ev_win32.c ev_wrap.h event.c event.h install-sh libev.m4 libtool ltmain.sh missing mkinstalldirs stamp-h1
luajit
doc
img contact.png
bluequad-print.css bluequad.css contact.html ext_buffer.html ext_c_api.html ext_ffi.html ext_ffi_api.html ext_ffi_semantics.html ext_ffi_tutorial.html ext_jit.html ext_profiler.html extensions.html install.html luajit.html running.html
dynasm dasm_arm.h dasm_arm.lua dasm_arm64.h dasm_arm64.lua dasm_mips.h dasm_mips.lua dasm_mips64.lua dasm_ppc.h dasm_ppc.lua dasm_proto.h dasm_x64.lua dasm_x86.h dasm_x86.lua dynasm.lua
etc luajit.1 luajit.pc
src
host .gitignore README buildvm.c buildvm.h buildvm_asm.c buildvm_fold.c buildvm_lib.c buildvm_libbc.h buildvm_peobj.c genlibbc.lua genminilua.lua genversion.lua minilua.c
jit .gitignore bc.lua bcsave.lua dis_arm.lua dis_arm64.lua dis_arm64be.lua dis_mips.lua dis_mips64.lua dis_mips64el.lua dis_mips64r6.lua dis_mips64r6el.lua dis_mipsel.lua dis_ppc.lua dis_x64.lua dis_x86.lua dump.lua p.lua v.lua zone.lua
.gitignore Makefile Makefile.dep lauxlib.h lib_aux.c lib_base.c lib_bit.c lib_buffer.c lib_debug.c lib_ffi.c lib_init.c lib_io.c lib_jit.c lib_math.c lib_os.c lib_package.c lib_string.c lib_table.c lj_alloc.c lj_alloc.h lj_api.c lj_arch.h lj_asm.c lj_asm.h lj_asm_arm.h lj_asm_arm64.h lj_asm_mips.h lj_asm_ppc.h lj_asm_x86.h lj_assert.c lj_bc.c lj_bc.h lj_bcdump.h lj_bcread.c lj_bcwrite.c lj_buf.c lj_buf.h lj_carith.c lj_carith.h lj_ccall.c lj_ccall.h lj_ccallback.c lj_ccallback.h lj_cconv.c lj_cconv.h lj_cdata.c lj_cdata.h lj_char.c lj_char.h lj_clib.c lj_clib.h lj_cparse.c lj_cparse.h lj_crecord.c lj_crecord.h lj_ctype.c lj_ctype.h lj_debug.c lj_debug.h lj_def.h lj_dispatch.c lj_dispatch.h lj_emit_arm.h lj_emit_arm64.h lj_emit_mips.h lj_emit_ppc.h lj_emit_x86.h lj_err.c lj_err.h lj_errmsg.h lj_ff.h lj_ffrecord.c lj_ffrecord.h lj_frame.h lj_func.c lj_func.h lj_gc.c lj_gc.h lj_gdbjit.c lj_gdbjit.h lj_ir.c lj_ir.h lj_ircall.h lj_iropt.h lj_jit.h lj_lex.c lj_lex.h lj_lib.c lj_lib.h lj_load.c lj_mcode.c lj_mcode.h lj_meta.c lj_meta.h lj_obj.c lj_obj.h lj_opt_dce.c lj_opt_fold.c lj_opt_loop.c lj_opt_mem.c lj_opt_narrow.c lj_opt_sink.c lj_opt_split.c lj_parse.c lj_parse.h lj_prng.c lj_prng.h lj_profile.c lj_profile.h lj_record.c lj_record.h lj_serialize.c lj_serialize.h lj_snap.c lj_snap.h lj_state.c lj_state.h lj_str.c lj_str.h lj_strfmt.c lj_strfmt.h lj_strfmt_num.c lj_strscan.c lj_strscan.h lj_tab.c lj_tab.h lj_target.h lj_target_arm.h lj_target_arm64.h lj_target_mips.h lj_target_ppc.h lj_target_x86.h lj_trace.c lj_trace.h lj_traceerr.h lj_udata.c lj_udata.h lj_vm.h lj_vmevent.c lj_vmevent.h lj_vmmath.c ljamalg.c lua.h lua.hpp luaconf.h luajit.c luajit_rolling.h lualib.h msvcbuild.bat nxbuild.bat ps4build.bat ps5build.bat psvitabuild.bat vm_arm.dasc vm_arm64.dasc vm_mips.dasc vm_mips64.dasc vm_ppc.dasc vm_x64.dasc vm_x86.dasc xb1build.bat xedkbuild.bat
.gitattributes .gitignore .relver COPYRIGHT Makefile README
sqlite shell.c sqlite3.c sqlite3.h sqlite3ext.h
wolfssl
.github
ISSUE_TEMPLATE bug_report.yaml other.yaml
actions
install-apt-deps action.yml
scripts
zephyr-4.x external_libc.conf zephyr-test.sh
openssl-ech.sh tls-anvil-test.sh
workflows
disabled haproxy.yml hitch.yml hostap.yml
hostap-files
configs
07c9f183ea744ac04585fb6dd10220c75a5e2e74 hostapd.config tests wpa_supplicant.config
b607d2723e927a3446d89aed813f1aa6068186bb hostapd.config tests wpa_supplicant.config
hostap_2_10 extra.patch hostapd.config tests wpa_supplicant.config
Makefile README dbus-wpa_supplicant.conf
ada.yml arduino.yml async-examples.yml async.yml atecc608-sim.yml bind.yml cmake-autoconf.yml cmake.yml codespell.yml coverity-scan-fixes.yml cryptocb-only.yml curl.yml cyrus-sasl.yml disable-pk-algs.yml docker-Espressif.yml docker-OpenWrt.yml emnet-nonblock.yml fil-c.yml freertos-mem-track.yml gencertbuf.yml grpc.yml haproxy.yml hostap-vm.yml intelasm-c-fallback.yml ipmitool.yml jwt-cpp.yml krb5.yml libspdm.yml libssh2.yml libvncserver.yml linuxkm.yml macos-apple-native-cert-validation.yml mbedtls.sh mbedtls.yml membrowse-comment.yml membrowse-onboard.yml membrowse-report.yml memcached.sh memcached.yml mono.yml mosquitto.yml msmtp.yml msys2.yml multi-arch.yml multi-compiler.yml net-snmp.yml nginx.yml no-malloc.yml no-tls.yml nss.sh nss.yml ntp.yml ocsp.yml openldap.yml openssh.yml openssl-ech.yml opensslcoexist.yml openvpn.yml os-check.yml packaging.yml pam-ipmi.yml pq-all.yml pr-commit-check.yml psk.yml puf.yml python.yml rng-tools.yml rust-wrapper.yml se050-sim.yml smallStackSize.yml socat.yml softhsm.yml sssd.yml stm32-sim.yml stsafe-a120-sim.yml stunnel.yml symbol-prefixes.yml threadx.yml tls-anvil.yml trackmemory.yml watcomc.yml win-csharp-test.yml wolfCrypt-Wconversion.yml wolfboot-integration.yml wolfsm.yml xcode.yml zephyr-4.x.yml zephyr.yml
PULL_REQUEST_TEMPLATE.md SECURITY.md membrowse-targets.json
Docker
OpenWrt Dockerfile README.md runTests.sh
packaging
debian Dockerfile
fedora Dockerfile
wolfCLU Dockerfile README.md
yocto Dockerfile buildAndPush.sh
Dockerfile Dockerfile.cross-compiler README.md buildAndPush.sh include.am run.sh
IDE
ARDUINO
sketches
wolfssl_client README.md
wolfssl_server README.md
wolfssl_version README.md
README.md
Arduino_README_prepend.md README.md include.am keywords.txt library.properties.template wolfssl-arduino.cpp wolfssl-arduino.sh wolfssl.h
AURIX Cpu0_Main.c README.md include.am user_settings.h wolf_main.c
Android Android.bp README.md include.am user_settings.h
CRYPTOCELL README.md include.am main.c user_settings.h
CSBENCH include.am user_settings.h
ECLIPSE
DEOS
deos_wolfssl .options
README.md deos_malloc.c include.am tls_wolfssl.c tls_wolfssl.h user_settings.h
MICRIUM README.md client_wolfssl.c client_wolfssl.h include.am server_wolfssl.c server_wolfssl.h user_settings.h wolfsslRunTests.c
RTTHREAD README.md include.am user_settings.h wolfssl_test.c
SIFIVE README.md include.am
Espressif
ESP-IDF
examples
template
VisualGDB wolfssl_template_IDF_v5.1_ESP32.vgdbproj
components
wolfssl
include user_settings.h
CMakeLists.txt Kconfig README.md component.mk
main
include main.h
CMakeLists.txt Kconfig.projbuild component.mk main.c
CMakeLists.txt Makefile README.md partitions_singleapp_large.csv sdkconfig.defaults sdkconfig.defaults.esp8266
wolfssl_benchmark
VisualGDB wolfssl_benchmark_IDF_v4.4_ESP32.sln wolfssl_benchmark_IDF_v4.4_ESP32.vgdbproj wolfssl_benchmark_IDF_v5_ESP32.sln wolfssl_benchmark_IDF_v5_ESP32.vgdbproj wolfssl_benchmark_IDF_v5_ESP32C3.sln wolfssl_benchmark_IDF_v5_ESP32C3.vgdbproj wolfssl_benchmark_IDF_v5_ESP32S3.sln wolfssl_benchmark_IDF_v5_ESP32S3.vgdbproj
components
wolfssl
include user_settings.h
CMakeLists.txt Kconfig README.md component.mk
main
include main.h
CMakeLists.txt Kconfig.projbuild component.mk main.c
CMakeLists.txt Makefile README.md partitions_singleapp_large.csv sdkconfig.defaults sdkconfig.defaults.esp8266
wolfssl_client
VisualGDB README.md wolfssl_client_IDF_v5_ESP32.sln wolfssl_client_IDF_v5_ESP32.vgdbproj
components
wolfssl
include user_settings.h
CMakeLists.txt Kconfig README.md component.mk
main
include client-tls.h main.h time_helper.h wifi_connect.h
CMakeLists.txt Kconfig.projbuild client-tls.c component.mk main.c time_helper.c wifi_connect.c
CMakeLists.txt Makefile README.md README_server_sm.md partitions_singleapp_large.csv sdkconfig.defaults sdkconfig.defaults.esp32c2 sdkconfig.defaults.esp8266 wolfssl_client_ESP8266.vgdbproj
wolfssl_server
VisualGDB README.md wolfssl_server_IDF_v5_ESP32.sln wolfssl_server_IDF_v5_ESP32.vgdbproj
components
wolfssl
include user_settings.h
CMakeLists.txt Kconfig README.md component.mk
main
include main.h server-tls.h time_helper.h wifi_connect.h
CMakeLists.txt Kconfig.projbuild component.mk main.c server-tls.c time_helper.c wifi_connect.c
CMakeLists.txt Makefile README.md README_server_sm.md partitions_singleapp_large.csv sdkconfig.defaults sdkconfig.defaults.esp32c2 sdkconfig.defaults.esp8266 wolfssl_server_ESP8266.vgdbproj
wolfssl_test
VisualGDB wolfssl_test-IDF_v5_ESP32.sln wolfssl_test-IDF_v5_ESP32.vgdbproj wolfssl_test-IDF_v5_ESP32C3.sln wolfssl_test-IDF_v5_ESP32C3.vgdbproj wolfssl_test-IDF_v5_ESP32C6.sln wolfssl_test-IDF_v5_ESP32C6.vgdbproj wolfssl_test_IDF_v5_ESP32S3.sln wolfssl_test_IDF_v5_ESP32S3.vgdbproj
components
wolfssl
include user_settings.h
CMakeLists.txt Kconfig README.md component.mk
main
include main.h
CMakeLists.txt Kconfig.projbuild component.mk main.c
CMakeLists.txt Makefile README.md partitions_singleapp_large.csv sdkconfig.defaults sdkconfig.defaults.esp32 sdkconfig.defaults.esp32c3 sdkconfig.defaults.esp32c6 sdkconfig.defaults.esp32h2 sdkconfig.defaults.esp32s2 sdkconfig.defaults.esp32s3 sdkconfig.defaults.esp8266 testAll.sh testMonitor.sh wolfssl_test_ESP8266.sln wolfssl_test_ESP8266.vgdbproj
wolfssl_test_idf
VisualGDB VisualGDB_wolfssl_test_idf.sln VisualGDB_wolfssl_test_idf.vgdbproj
main CMakeLists.txt Kconfig.projbuild component.mk main.c main_wip.c.ex time_helper.c time_helper.h
CMakeLists.txt Kconfig.projbuild README.md component.mk sdkconfig.defaults
README.md
libs CMakeLists.txt README.md component.mk tigard.cfg
test CMakeLists.txt README.md component.mk test_wolfssl.c
README.md README_32se.md UPDATE.md compileAllExamples.sh dummy_config_h dummy_test_paths.h setup.sh setup_win.bat user_settings.h
README.md include.am
GCC-ARM
Header user_settings.h
Source armtarget.c benchmark_main.c test_main.c tls_client.c tls_server.c wolf_main.c
Makefile Makefile.bench Makefile.client Makefile.common Makefile.server Makefile.static Makefile.test README.md include.am linker.ld linker_fips.ld
Gaisler-BCC README.md include.am
HEXAGON
DSP Makefile wolfssl_dsp.idl
Makefile README.md build.sh ecc-verify-benchmark.c ecc-verify.c include.am user_settings.h
HEXIWEAR
wolfSSL_HW .cwGeneratedFileSetLog user_settings.h
IAR-EWARM
Projects
benchmark benchmark-main.c current_time.c wolfCrypt-benchmark.ewd wolfCrypt-benchmark.ewp
common minimum-startup.c wolfssl.icf
lib wolfSSL-Lib.ewd wolfSSL-Lib.ewp
test test-main.c wolfCrypt-test.ewd wolfCrypt-test.ewp
user_settings.h wolfssl.eww
embOS
SAMV71_XULT
embOS_SAMV71_XULT_Linker_Script samv71q21_wolfssl.icf
embOS_SAMV71_XULT_user_settings user_settings.h user_settings_simple_example.h user_settings_verbose_example.h
embOS_wolfcrypt_benchmark_SAMV71_XULT
Application runBenchmarks.c
README_wolfcrypt_benchmark wolfcrypt_benchmark.ewd wolfcrypt_benchmark.ewp
embOS_wolfcrypt_lib_SAMV71_XULT README_wolfcrypt_lib wolfcrypt_lib.ewd wolfcrypt_lib.ewp
embOS_wolfcrypt_test_SAMV71_XULT
Application runWolfcryptTests.c
README_wolfcrypt_test wolfcrypt_test.ewd wolfcrypt_test.ewp
README_SAMV71
custom_port
custom_port_Linker_Script samv71q21_wolfssl.icf
custom_port_user_settings user_settings.h
wolfcrypt_benchmark_custom_port
Application runBenchmarks.c
wolfcrypt_test_custom_port
Application runWolfcryptTests.c
README_custom_port
extract_trial_here README_extract_trial_here
README
.gitignore README
IAR-MSP430 Makefile README.md include.am main.c user_settings.h
INTIME-RTOS Makefile README.md include.am libwolfssl.c libwolfssl.vcxproj user_settings.h wolfExamples.c wolfExamples.h wolfExamples.sln wolfExamples.vcxproj wolfssl-lib.sln wolfssl-lib.vcxproj
Infineon README.md include.am user_settings.h
KDS
config user_settings.h
include.am
LINUX-SGX README.md build.sh clean.sh include.am sgx_t_static.mk
LPCXPRESSO
lib_wolfssl lpc_18xx_port.c user_settings.h
wolf_example
src lpc_18xx_startup.c wolfssl_example.c
readme.txt
README.md
M68K
benchmark Makefile main.cpp
testwolfcrypt Makefile main.cpp
Makefile README.md include.am user_settings.h
MCUEXPRESSO
RT1170 fsl_caam_c.patch fsl_caam_h.patch user_settings.h
benchmark
source run_benchmark.c
wolfssl liblinks.xml
README.md include.am user_settings.h wolfcrypt_test.c
MDK-ARM
LPC43xx time-LCP43xx.c
MDK-ARM
wolfSSL Retarget.c cert_data.c cert_data.h config-BARE-METAL.h config-FS.h config-RTX-TCP-FS.h config-WOLFLIB.h main.c shell.c time-CortexM3-4.c time-dummy.c wolfssl_MDK_ARM.c wolfssl_MDK_ARM.h
STM32F2xx_StdPeriph_Lib time-STM32F2xx.c
MDK5-ARM
Conf user_settings.h
Inc wolfssl_MDK_ARM.h
Projects
CryptBenchmark Abstract.txt CryptBenchmark.sct CryptBenchmark.uvoptx CryptBenchmark.uvprojx main.c
CryptTest Abstract.txt CryptTest.sct CryptTest.uvoptx CryptTest.uvprojx main.c
EchoClient Abstract.txt EchoClient.uvoptx EchoClient.uvprojx main.c wolfssl-link.sct
EchoServer Abstract.txt EchoServer.uvoptx EchoServer.uvprojx main.c wolfssl-link.sct
SimpleClient Abstract.txt SimpleClient.uvoptx SimpleClient.uvprojx main.c wolfssl-link.sct
SimpleServer Abstract.txt SimpleServer.uvoptx SimpleServer.uvprojx main.c wolfssl-link.sct
wolfSSL-Full Abstract.txt main.c shell.c time-CortexM3-4.c wolfsslFull.uvoptx wolfsslFull.uvprojx
wolfSSL-Lib Abstract.txt wolfSSL-Lib.uvoptx wolfSSL-Lib.uvprojx
Src ssl-dummy.c
README.md include.am
MPLABX16
wolfcrypt_test.X
nbproject
private configurations.xml private.xml
configurations.xml include.am project.xml
Makefile
wolfssl.X
nbproject configurations.xml include.am project.xml
Makefile
README.md include.am main.c user_settings.h
MQX Makefile README-jp.md README.md client-tls.c include.am server-tls.c user_config.h user_settings.h
MSVS-2019-AZSPHERE
client client.c client.h
server server.c server.h
shared util.h
wolfssl_new_azsphere
HardwareDefinitions
avnet_mt3620_sk
inc
hw template_appliance.h
template_appliance.json
mt3620_rdb
inc
hw template_appliance.h
template_appliance.json
seeed_mt3620_mdb
inc
hw template_appliance.h
template_appliance.json
.gitignore CMakeLists.txt CMakeSettings.json app_manifest.json applibs_versions.h launch.vs.json main.c
README.md include.am user_settings.h
MYSQL CMakeLists_wolfCrypt.txt CMakeLists_wolfSSL.txt do.sh
NDS README.md
NETOS Makefile.wolfcrypt.inc README.md include.am user_settings.h user_settings.h-cert2425 user_settings.h-cert3389 wolfssl_netos_custom.c
OPENSTM32 README.md
PlatformIO
examples
wolfssl_benchmark
include README main.h
lib README
src CMakeLists.txt main.c
test README
CMakeLists.txt README.md platformio.ini sdkconfig.defaults wolfssl_benchmark.code-workspace
wolfssl_test
include README main.h
lib README
src CMakeLists.txt main.c
test README
CMakeLists.txt README.md platformio.ini sdkconfig.defaults wolfssl_test.code-workspace
README.md wolfssl_platformio.code-workspace
README.md include.am
QNX
CAAM-DRIVER Makefile
example-client Makefile client-tls.c
example-cmac Makefile cmac-test.c
example-server Makefile server-tls.c
testwolfcrypt Makefile
wolfssl Makefile user_settings.h
README.md include.am
RISCV
SIFIVE-HIFIVE1 Makefile README.md include.am main.c user_settings.h
SIFIVE-UNLEASHED README.md include.am
include.am
ROWLEY-CROSSWORKS-ARM Kinetis_FlashPlacement.xml README.md arm_startup.c benchmark_main.c hw.h include.am kinetis_hw.c retarget.c test_main.c user_settings.h wolfssl.hzp wolfssl_ltc.hzp
Renesas
cs+
Projects
common strings.h unistd.h user_settings.h wolfssl_dummy.c
t4_demo README_en.txt README_jp.txt t4_demo.mtpj wolf_client.c wolf_demo.h wolf_main.c wolf_server.c
test test.mtpj test_main.c
wolfssl_lib wolfssl_lib.mtpj
README include.am
e2studio
DK-S7G2
benchmark-template
src app_entry.c
example_server-template
src app_entry.c
wolfcrypttest-template
src app_entry.c
wolfssl-template-project configuration.xml
README.md include.am user_settings.h
Projects
common strings.h unistd.h user_settings.h wolfssl_dummy.c
test
src key_data.c key_data.h test_main.c wolf_client.c wolf_server.c wolfssl_demo.h
tools generate_rsa_keypair.sh genhexbuf.pl rsa_pss_sign.sh
wolfssl
src .gitkeep
wolfcrypt
src .gitkeep
README include.am
RA6M3
benchmark-wolfcrypt
common .gitkeep
script .gitkeep
src wolfssl_thread_entry.c
client-wolfssl
common
src .gitkeep
script .gitkeep
src wolfssl_thread_entry.c
wolfssl_thread_entry.h
common
ra6m3g README.md
src freertos_tcp_port.c
user_settings.h util.h
server-wolfssl
common
src .gitkeep
script .gitkeep
src wolfssl_thread_entry.c
wolfssl_thread_entry.h
test-wolfcrypt
common .gitkeep
script .gitkeep
src wolfssl_thread_entry.c
wolfssl
src .gitkeep
wolfcrypt .gitkeep
README.md README_APRA6M_en.md README_APRA6M_jp.md include.am
RA6M3G README.md
RA6M4
common user_settings.h wolfssl_demo.h
test
key_data key_data.h key_data_sce.c
src
SEGGER_RTT myprint.c
common .gitignore
test_main.c wolf_client.c wolfssl_sce_unit_test.c
test_RA6M4Debug.launch
tools
example_keys generate_SignedCA.sh rsa_private.pem rsa_public.pem
README.md
README.md include.am
RX65N
GR-ROSE
common strings.h unistd.h user_settings.h wolfssl_dummy.c
smc smc.scfg
test
src key_data.c key_data.h test_main.c wolf_client.c wolf_server.c wolfssl_demo.h
test.rcpc test_HardwareDebug.launch
tools
example_keys generate_SignedCA.sh rsa_private.pem rsa_public.pem
README.md
wolfssl wolfssl.rcpc
README_EN.md README_JP.md include.am
RSK
resource section.esi
wolfssl wolfssl.rcpc
wolfssl_demo key_data.c key_data.h user_settings.h wolfssl_demo.c wolfssl_demo.h
InstructionManualForExample_RSK+RX65N-2MB_EN.pdf InstructionManualForExample_RSK+RX65N-2MB_JP.pdf README_EN.md README_JP.md include.am
RX72N
EnvisionKit
Simple
common sectioninfo.esi wolfssl_dummy.c
test
src
client simple_tcp_client.c simple_tls_tsip_client.c
server simple_tcp_server.c simple_tls_server.c
test_main.c wolfssl_simple_demo.h
test.rcpc test.scfg test_HardwareDebug.launch
wolfssl wolfssl.rcpc
README_EN.md README_JP.md
resource section.esi
tools
example_keys generate_SignedCA.sh rsa_private.pem rsa_public.pem
README.md
wolfssl wolfssl.rcpc
wolfssl_demo key_data.c key_data.h user_settings.h wolfssl_demo.c wolfssl_demo.h wolfssl_tsip_unit_test.c
InstructionManualForExample_RX72N_EnvisonKit_EN.pdf InstructionManualForExample_RX72N_EnvisonKit_JP.pdf README_EN.md README_JP.md include.am
RZN2L
common user_settings.h wolfssl_demo.h
test
src
serial_io app_print.c
test wolf_client.c wolf_server.c wolfssl_rsip_unit_test.c
wolfCrypt .gitignore
wolfSSL .gitignore
local_system_init.c rzn2l_tst_thread_entry.c wolfssl_dummy.c
README.md include.am
SK-S7G2
common user_settings.h
wolfssl_lib configuration.xml
.gitignore README.md include.am
STARCORE README.txt include.am starcore_test.c user_settings.h
STM32Cube README.md STM32_Benchmarks.md default_conf.ftl include.am main.c wolfssl_example.c wolfssl_example.h
SimplicityStudio README.md include.am test_wolf.c user_settings.h
TRUESTUDIO
wolfssl user_settings.h
README include.am
VS-ARM README.md include.am user_settings.h wolfssl.sln wolfssl.vcxproj
VS-AZURE-SPHERE
client app_manifest.json client.c client.h client.vcxproj
server app_manifest.json server.c server.h server.vcxproj
shared util.h
wolfcrypt_test app_manifest.json wolfcrypt_test.vcxproj
README.md include.am user_settings.h wolfssl.sln wolfssl.vcxproj
VisualDSP include.am user_settings.h wolf_tasks.c
WICED-STUDIO README include.am user_settings.h
WIN README.txt include.am test.vcxproj user_settings.h user_settings_dtls.h wolfssl-fips.sln wolfssl-fips.vcxproj
WIN-SGX ReadMe.txt include.am wolfSSL_SGX.edl wolfSSL_SGX.sln wolfSSL_SGX.vcxproj
WIN-SRTP-KDF-140-3 README.txt include.am resource.h test.vcxproj user_settings.h wolfssl-fips.rc wolfssl-fips.sln wolfssl-fips.vcxproj
WIN10 README.txt include.am resource.h test.vcxproj user_settings.h wolfssl-fips.rc wolfssl-fips.sln wolfssl-fips.vcxproj
WINCE README.md include.am user_settings.h user_settings.h.140-2-deprecated
WORKBENCH README.md include.am
XCODE
Benchmark
wolfBench
Assets.xcassets
AppIcon.appiconset Contents.json
Base.lproj LaunchScreen.storyboard Main.storyboard
AppDelegate.h AppDelegate.m Info.plist ViewController.h ViewController.m main.m
wolfBench.xcodeproj project.pbxproj
include.am
wolfssl-FIPS.xcodeproj project.pbxproj
wolfssl.xcodeproj project.pbxproj
wolfssl_testsuite.xcodeproj project.pbxproj
README.md build-for-i386.sh include.am user_settings.h
XCODE-FIPSv2
macOS-C++
Intel user_settings.h
M1 user_settings.h
include.am user_settings.h
XCODE-FIPSv5 README include.am user_settings.h
XCODE-FIPSv6 README include.am user_settings.h
XilinxSDK
2018_2 lscript.ld
2019_2
wolfCrypt_example
src lscript.ld
wolfCrypt_example_system wolfCrypt_example_system.sprj
2022_1
wolfCrypt_FreeRTOS_example wolfCrypt_FreeRTOS_example.prj
wolfCrypt_FreeRTOS_example_system wolfCrypt_FreeRTOS_example_system.sprj
wolfCrypt_example wolfCrypt_example.prj
wolfCrypt_example_system wolfCrypt_example_system.sprj
.gitignore
README.md bench.sh combine.sh eclipse_formatter_profile.xml graph.sh include.am user_settings.h wolfssl_example.c
apple-universal
wolfssl-multiplatform
wolfssl-multiplatform
Assets.xcassets
AccentColor.colorset Contents.json
AppIcon.appiconset Contents.json
Contents.json
ContentView.swift simple_client_example.c simple_client_example.h wolfssl-multiplatform-Bridging-Header.h wolfssl_multiplatform.entitlements wolfssl_multiplatformApp.swift wolfssl_test_driver.c wolfssl_test_driver.h
wolfssl-multiplatform.xcodeproj project.pbxproj
.gitignore README.md build-wolfssl-framework.sh include.am
iotsafe Makefile README.md ca-cert.c devices.c devices.h include.am main.c memory-tls.c startup.c target.ld user_settings.h
iotsafe-raspberrypi Makefile README.md client-tls13.c include.am main.c
mynewt README.md apps.wolfcrypttest.pkg.yml crypto.wolfssl.pkg.yml crypto.wolfssl.syscfg.yml include.am setup.sh
zephyr README.md include.am
include.am
RTOS
nuttx
wolfssl .gitignore Kconfig Make.defs Makefile README.md setup-wolfssl.sh user_settings.h
include.am
bsdkm Makefile README.md bsdkm_wc_port.h include.am wolfkmod.c wolfkmod_aes.c x86_vecreg.c
certs
1024 ca-cert.der ca-cert.pem ca-key.der ca-key.pem client-cert.der client-cert.pem client-key.der client-key.pem client-keyPub.der dh1024.der dh1024.pem dsa-pub-1024.pem dsa1024.der dsa1024.pem include.am rsa1024.der server-cert.der server-cert.pem server-key.der server-key.pem
3072 client-cert.der client-cert.pem client-key.der client-key.pem client-keyPub.der include.am
4096 client-cert.der client-cert.pem client-key.der client-key.pem client-keyPub.der include.am
acert
rsa_pss acert.pem acert_ietf.pem acert_ietf_pubkey.pem acert_pubkey.pem
acert.pem acert_ietf.pem acert_ietf_pubkey.pem acert_pubkey.pem include.am
aia ca-issuers-cert.pem multi-aia-cert.pem overflow-aia-cert.pem
crl
extra-crls ca-int-cert-revoked.pem claim-root.pem crl_critical_entry.pem crlnum_57oct.pem crlnum_64oct.pem general-server-crl.pem large_crlnum.pem large_crlnum2.pem
hash_der 0fdb2da4.r0
hash_pem 0fdb2da4.r0
bad_time_fmt.pem ca-int-ecc.pem ca-int.pem ca-int2-ecc.pem ca-int2.pem caEcc384Crl.pem caEccCrl.der caEccCrl.pem cliCrl.pem client-int-ecc.pem client-int.pem crl.der crl.pem crl.revoked crl2.der crl2.pem crl_reason.pem crl_rsapss.pem eccCliCRL.pem eccSrvCRL.pem gencrls.sh include.am server-goodaltCrl.pem server-goodaltwildCrl.pem server-goodcnCrl.pem server-goodcnwildCrl.pem server-int-ecc.pem server-int.pem wolfssl.cnf
dilithium bench_dilithium_level2_key.der bench_dilithium_level3_key.der bench_dilithium_level5_key.der include.am
ecc bp256r1-key.der bp256r1-key.pem ca-secp256k1-cert.pem ca-secp256k1-key.pem client-bp256r1-cert.der client-bp256r1-cert.pem client-secp256k1-cert.der client-secp256k1-cert.pem genecc.sh include.am secp256k1-key.der secp256k1-key.pem secp256k1-param.pem secp256k1-privkey.der secp256k1-privkey.pem server-bp256r1-cert.der server-bp256r1-cert.pem server-secp256k1-cert.der server-secp256k1-cert.pem server2-secp256k1-cert.der server2-secp256k1-cert.pem wolfssl.cnf wolfssl_384.cnf
ed25519 ca-ed25519-key.der ca-ed25519-key.pem ca-ed25519-priv.der ca-ed25519-priv.pem ca-ed25519.der ca-ed25519.pem client-ed25519-key.der client-ed25519-key.pem client-ed25519-priv.der client-ed25519-priv.pem client-ed25519.der client-ed25519.pem eddsa-ed25519.der eddsa-ed25519.pem gen-ed25519-certs.sh gen-ed25519-keys.sh gen-ed25519.sh include.am root-ed25519-key.der root-ed25519-key.pem root-ed25519-priv.der root-ed25519-priv.pem root-ed25519.der root-ed25519.pem server-ed25519-cert.pem server-ed25519-key.der server-ed25519-key.pem server-ed25519-priv.der server-ed25519-priv.pem server-ed25519.der server-ed25519.pem
ed448 ca-ed448-key.der ca-ed448-key.pem ca-ed448-priv.der ca-ed448-priv.pem ca-ed448.der ca-ed448.pem client-ed448-key.der client-ed448-key.pem client-ed448-priv.der client-ed448-priv.pem client-ed448.der client-ed448.pem gen-ed448-certs.sh gen-ed448-keys.sh include.am root-ed448-key.der root-ed448-key.pem root-ed448-priv.der root-ed448-priv.pem root-ed448.der root-ed448.pem server-ed448-cert.pem server-ed448-key.der server-ed448-key.pem server-ed448-priv.der server-ed448-priv.pem server-ed448.der server-ed448.pem
external DigiCertGlobalRootCA.pem README.txt ca-digicert-ev.pem ca-globalsign-root.pem ca-google-root.pem ca_collection.pem include.am
falcon bench_falcon_level1_key.der bench_falcon_level5_key.der include.am
intermediate
ca_false_intermediate gentestcert.sh int_ca.key server.key test_ca.key test_ca.pem test_int_not_cacert.pem test_sign_bynoca_srv.pem wolfssl_base.conf wolfssl_srv.conf
ca-ecc-bad-aki.der ca-ecc-bad-aki.pem ca-int-cert.der ca-int-cert.pem ca-int-ecc-cert.der ca-int-ecc-cert.pem ca-int-ecc-key.der ca-int-ecc-key.pem ca-int-key.der ca-int-key.pem ca-int2-cert.der ca-int2-cert.pem ca-int2-ecc-cert.der ca-int2-ecc-cert.pem ca-int2-ecc-key.der ca-int2-ecc-key.pem ca-int2-key.der ca-int2-key.pem client-chain-alt-ecc.pem client-chain-alt.pem client-chain-ecc.der client-chain-ecc.pem client-chain.der client-chain.pem client-int-cert.der client-int-cert.pem client-int-ecc-cert.der client-int-ecc-cert.pem genintcerts.sh include.am server-chain-alt-ecc.pem server-chain-alt.pem server-chain-ecc.der server-chain-ecc.pem server-chain-short.pem server-chain.der server-chain.pem server-int-cert.der server-int-cert.pem server-int-ecc-cert.der server-int-ecc-cert.pem
lms bc_hss_L2_H5_W8_root.der bc_hss_L3_H5_W4_root.der bc_lms_chain_ca.der bc_lms_chain_leaf.der bc_lms_native_bc_root.der bc_lms_sha256_h10_w8_root.der bc_lms_sha256_h5_w4_root.der include.am
mldsa README.txt include.am mldsa44-cert.der mldsa44-cert.pem mldsa44-key.pem mldsa44_bare-priv.der mldsa44_bare-seed.der mldsa44_oqskeypair.der mldsa44_priv-only.der mldsa44_pub-spki.der mldsa44_seed-only.der mldsa44_seed-priv.der mldsa65-cert.der mldsa65-cert.pem mldsa65-key.pem mldsa65_bare-priv.der mldsa65_bare-seed.der mldsa65_oqskeypair.der mldsa65_priv-only.der mldsa65_pub-spki.der mldsa65_seed-only.der mldsa65_seed-priv.der mldsa87-cert.der mldsa87-cert.pem mldsa87-key.pem mldsa87_bare-priv.der mldsa87_bare-seed.der mldsa87_oqskeypair.der mldsa87_priv-only.der mldsa87_pub-spki.der mldsa87_seed-only.der mldsa87_seed-priv.der
ocsp imposter-root-ca-cert.der imposter-root-ca-cert.pem imposter-root-ca-key.der imposter-root-ca-key.pem include.am index-ca-and-intermediate-cas.txt index-ca-and-intermediate-cas.txt.attr index-intermediate1-ca-issued-certs.txt index-intermediate1-ca-issued-certs.txt.attr index-intermediate2-ca-issued-certs.txt index-intermediate2-ca-issued-certs.txt.attr index-intermediate3-ca-issued-certs.txt index-intermediate3-ca-issued-certs.txt.attr intermediate1-ca-cert.der intermediate1-ca-cert.pem intermediate1-ca-key.der intermediate1-ca-key.pem intermediate2-ca-cert.der intermediate2-ca-cert.pem intermediate2-ca-key.der intermediate2-ca-key.pem intermediate3-ca-cert.der intermediate3-ca-cert.pem intermediate3-ca-key.der intermediate3-ca-key.pem ocsp-responder-cert.der ocsp-responder-cert.pem ocsp-responder-key.der ocsp-responder-key.pem openssl.cnf renewcerts-for-test.sh renewcerts.sh root-ca-cert.der root-ca-cert.pem root-ca-crl.pem root-ca-key.der root-ca-key.pem server1-cert.der server1-cert.pem server1-chain-noroot.pem server1-key.der server1-key.pem server2-cert.der server2-cert.pem server2-key.der server2-key.pem server3-cert.der server3-cert.pem server3-key.der server3-key.pem server4-cert.der server4-cert.pem server4-key.der server4-key.pem server5-cert.der server5-cert.pem server5-key.der server5-key.pem test-leaf-response.der test-multi-response.der test-response-nointern.der test-response-rsapss.der test-response.der
p521 ca-p521-key.der ca-p521-key.pem ca-p521-priv.der ca-p521-priv.pem ca-p521.der ca-p521.pem client-p521-key.der client-p521-key.pem client-p521-priv.der client-p521-priv.pem client-p521.der client-p521.pem gen-p521-certs.sh gen-p521-keys.sh include.am root-p521-key.der root-p521-key.pem root-p521-priv.der root-p521-priv.pem root-p521.der root-p521.pem server-p521-cert.pem server-p521-key.der server-p521-key.pem server-p521-priv.der server-p521-priv.pem server-p521.der server-p521.pem
renewcerts wolfssl.cnf
rpk client-cert-rpk.der client-ecc-cert-rpk.der include.am server-cert-rpk.der server-ecc-cert-rpk.der
rsapss ca-3072-rsapss-key.der ca-3072-rsapss-key.pem ca-3072-rsapss-priv.der ca-3072-rsapss-priv.pem ca-3072-rsapss.der ca-3072-rsapss.pem ca-rsapss-key.der ca-rsapss-key.pem ca-rsapss-priv.der ca-rsapss-priv.pem ca-rsapss.der ca-rsapss.pem client-3072-rsapss-key.der client-3072-rsapss-key.pem client-3072-rsapss-priv.der client-3072-rsapss-priv.pem client-3072-rsapss.der client-3072-rsapss.pem client-rsapss-key.der client-rsapss-key.pem client-rsapss-priv.der client-rsapss-priv.pem client-rsapss.der client-rsapss.pem gen-rsapss-keys.sh include.am renew-rsapss-certs.sh root-3072-rsapss-key.der root-3072-rsapss-key.pem root-3072-rsapss-priv.der root-3072-rsapss-priv.pem root-3072-rsapss.der root-3072-rsapss.pem root-rsapss-key.der root-rsapss-key.pem root-rsapss-priv.der root-rsapss-priv.pem root-rsapss.der root-rsapss.pem server-3072-rsapss-cert.pem server-3072-rsapss-key.der server-3072-rsapss-key.pem server-3072-rsapss-priv.der server-3072-rsapss-priv.pem server-3072-rsapss.der server-3072-rsapss.pem server-mix-rsapss-cert.pem server-rsapss-cert.pem server-rsapss-key.der server-rsapss-key.pem server-rsapss-priv.der server-rsapss-priv.pem server-rsapss.der server-rsapss.pem
sia timestamping-sia-cert.pem
slhdsa bench_slhdsa_sha2_128f_key.der bench_slhdsa_sha2_128s_key.der bench_slhdsa_sha2_192f_key.der bench_slhdsa_sha2_192s_key.der bench_slhdsa_sha2_256f_key.der bench_slhdsa_sha2_256s_key.der bench_slhdsa_shake128f_key.der bench_slhdsa_shake128s_key.der bench_slhdsa_shake192f_key.der bench_slhdsa_shake192s_key.der bench_slhdsa_shake256f_key.der bench_slhdsa_shake256s_key.der client-mldsa44-priv.pem client-mldsa44-sha2.der client-mldsa44-sha2.pem client-mldsa44-shake.der client-mldsa44-shake.pem gen-slhdsa-mldsa-certs.sh include.am root-slhdsa-sha2-128s-priv.der root-slhdsa-sha2-128s-priv.pem root-slhdsa-sha2-128s.der root-slhdsa-sha2-128s.pem root-slhdsa-shake-128s-priv.der root-slhdsa-shake-128s-priv.pem root-slhdsa-shake-128s.der root-slhdsa-shake-128s.pem server-mldsa44-priv.pem server-mldsa44-sha2.der server-mldsa44-sha2.pem server-mldsa44-shake.der server-mldsa44-shake.pem
sm2 ca-sm2-key.der ca-sm2-key.pem ca-sm2-priv.der ca-sm2-priv.pem ca-sm2.der ca-sm2.pem client-sm2-key.der client-sm2-key.pem client-sm2-priv.der client-sm2-priv.pem client-sm2.der client-sm2.pem fix_sm2_spki.py gen-sm2-certs.sh gen-sm2-keys.sh include.am root-sm2-key.der root-sm2-key.pem root-sm2-priv.der root-sm2-priv.pem root-sm2.der root-sm2.pem self-sm2-cert.pem self-sm2-key.pem self-sm2-priv.pem server-sm2-cert.der server-sm2-cert.pem server-sm2-key.der server-sm2-key.pem server-sm2-priv.der server-sm2-priv.pem server-sm2.der server-sm2.pem
statickeys dh-ffdhe2048-params.pem dh-ffdhe2048-pub.der dh-ffdhe2048-pub.pem dh-ffdhe2048.der dh-ffdhe2048.pem ecc-secp256r1.der ecc-secp256r1.pem gen-static.sh include.am x25519-pub.der x25519-pub.pem x25519.der x25519.pem
test
expired expired-ca.der expired-ca.pem expired-cert.der expired-cert.pem
catalog.txt cert-bad-neg-int.der cert-bad-oid.der cert-bad-utf8.der cert-ext-ia.cfg cert-ext-ia.der cert-ext-ia.pem cert-ext-joi.cfg cert-ext-joi.der cert-ext-joi.pem cert-ext-mnc.der cert-ext-multiple.cfg cert-ext-multiple.der cert-ext-multiple.pem cert-ext-nc-combined.der cert-ext-nc-combined.pem cert-ext-nc.cfg cert-ext-nc.der cert-ext-nc.pem cert-ext-ncdns.der cert-ext-ncdns.pem cert-ext-ncip.der cert-ext-ncip.pem cert-ext-ncmixed.der cert-ext-ncmulti.der cert-ext-ncmulti.pem cert-ext-ncrid.der cert-ext-ncrid.pem cert-ext-nct.cfg cert-ext-nct.der cert-ext-nct.pem cert-ext-ndir-exc.cfg cert-ext-ndir-exc.der cert-ext-ndir-exc.pem cert-ext-ndir.cfg cert-ext-ndir.der cert-ext-ndir.pem cert-ext-ns.der cert-over-max-altnames.cfg cert-over-max-altnames.der cert-over-max-altnames.pem cert-over-max-nc.cfg cert-over-max-nc.der cert-over-max-nc.pem client-ecc-cert-ski.hex cn-ip-literal.der cn-ip-wildcard.der crit-cert.pem crit-key.pem dh1024.der dh1024.pem dh512.der dh512.pem digsigku.pem encrypteddata.msg gen-badsig.sh gen-ext-certs.sh gen-testcerts.sh include.am kari-keyid-cms.msg ktri-keyid-cms.msg ossl-trusted-cert.pem server-badaltname.der server-badaltname.pem server-badaltnull.der server-badaltnull.pem server-badcn.der server-badcn.pem server-badcnnull.der server-badcnnull.pem server-cert-ecc-badsig.der server-cert-ecc-badsig.pem server-cert-rsa-badsig.der server-cert-rsa-badsig.pem server-duplicate-policy.pem server-garbage.der server-garbage.pem server-goodalt.der server-goodalt.pem server-goodaltwild.der server-goodaltwild.pem server-goodcn.der server-goodcn.pem server-goodcnwild.der server-goodcnwild.pem server-localhost.der server-localhost.pem smime-test-canon.p7s smime-test-multipart-badsig.p7s smime-test-multipart.p7s smime-test.p7s
test-pathlen assemble-chains.sh chainA-ICA1-key.pem chainA-ICA1-pathlen0.pem chainA-assembled.pem chainA-entity-key.pem chainA-entity.pem chainB-ICA1-key.pem chainB-ICA1-pathlen0.pem chainB-ICA2-key.pem chainB-ICA2-pathlen1.pem chainB-assembled.pem chainB-entity-key.pem chainB-entity.pem chainC-ICA1-key.pem chainC-ICA1-pathlen1.pem chainC-assembled.pem chainC-entity-key.pem chainC-entity.pem chainD-ICA1-key.pem chainD-ICA1-pathlen127.pem chainD-assembled.pem chainD-entity-key.pem chainD-entity.pem chainE-ICA1-key.pem chainE-ICA1-pathlen128.pem chainE-assembled.pem chainE-entity-key.pem chainE-entity.pem chainF-ICA1-key.pem chainF-ICA1-pathlen1.pem chainF-ICA2-key.pem chainF-ICA2-pathlen0.pem chainF-assembled.pem chainF-entity-key.pem chainF-entity.pem chainG-ICA1-key.pem chainG-ICA1-pathlen0.pem chainG-ICA2-key.pem chainG-ICA2-pathlen1.pem chainG-ICA3-key.pem chainG-ICA3-pathlen99.pem chainG-ICA4-key.pem chainG-ICA4-pathlen5.pem chainG-ICA5-key.pem chainG-ICA5-pathlen20.pem chainG-ICA6-key.pem chainG-ICA6-pathlen10.pem chainG-ICA7-key.pem chainG-ICA7-pathlen100.pem chainG-assembled.pem chainG-entity-key.pem chainG-entity.pem chainH-ICA1-key.pem chainH-ICA1-pathlen0.pem chainH-ICA2-key.pem chainH-ICA2-pathlen2.pem chainH-ICA3-key.pem chainH-ICA3-pathlen2.pem chainH-ICA4-key.pem chainH-ICA4-pathlen2.pem chainH-assembled.pem chainH-entity-key.pem chainH-entity.pem chainI-ICA1-key.pem chainI-ICA1-no_pathlen.pem chainI-ICA2-key.pem chainI-ICA2-no_pathlen.pem chainI-ICA3-key.pem chainI-ICA3-pathlen2.pem chainI-assembled.pem chainI-entity-key.pem chainI-entity.pem chainJ-ICA1-key.pem chainJ-ICA1-no_pathlen.pem chainJ-ICA2-key.pem chainJ-ICA2-no_pathlen.pem chainJ-ICA3-key.pem chainJ-ICA3-no_pathlen.pem chainJ-ICA4-key.pem chainJ-ICA4-pathlen2.pem chainJ-assembled.pem chainJ-entity-key.pem chainJ-entity.pem include.am refreshkeys.sh
test-serial0 ee_normal.pem ee_serial0.pem generate_certs.sh include.am intermediate_serial0.pem root_serial0.pem root_serial0_key.pem selfsigned_nonca_serial0.pem
xmss bc_xmss_chain_ca.der bc_xmss_chain_leaf.der bc_xmss_sha2_10_256_root.der bc_xmss_sha2_16_256_root.der bc_xmssmt_sha2_20_2_256_root.der bc_xmssmt_sha2_20_4_256_root.der bc_xmssmt_sha2_40_8_256_root.der include.am
ca-cert-chain.der ca-cert.der ca-cert.pem ca-ecc-cert.der ca-ecc-cert.pem ca-ecc-key.der ca-ecc-key.pem ca-ecc384-cert.der ca-ecc384-cert.pem ca-ecc384-key.der ca-ecc384-key.pem ca-key-pkcs8-attribute.der ca-key.der ca-key.pem check_dates.sh client-absolute-urn.pem client-ca-cert.der client-ca-cert.pem client-ca.pem client-cert-ext.der client-cert-ext.pem client-cert.der client-cert.pem client-crl-dist.der client-crl-dist.pem client-ecc-ca-cert.der client-ecc-ca-cert.pem client-ecc-cert.der client-ecc-cert.pem client-ecc384-cert.der client-ecc384-cert.pem client-ecc384-key.der client-ecc384-key.pem client-key.der client-key.pem client-keyEnc.pem client-keyPub.der client-keyPub.pem client-relative-uri.pem client-uri-cert.pem csr.attr.der csr.dsa.der csr.dsa.pem csr.ext.der csr.signed.der dh-priv-2048.der dh-priv-2048.pem dh-pub-2048.der dh-pub-2048.pem dh-pubkey-2048.der dh2048.der dh2048.pem dh3072.der dh3072.pem dh4096.der dh4096.pem dsa-pubkey-2048.der dsa2048.der dsa2048.pem dsa3072.der dsaparams.der dsaparams.pem ecc-client-key.der ecc-client-key.pem ecc-client-keyPub.der ecc-client-keyPub.pem ecc-key-comp.pem ecc-keyPkcs8.der ecc-keyPkcs8.pem ecc-keyPkcs8Enc.der ecc-keyPkcs8Enc.pem ecc-keyPub.der ecc-keyPub.pem ecc-params.der ecc-params.pem ecc-privOnlyCert.pem ecc-privOnlyKey.pem ecc-privkey.der ecc-privkey.pem ecc-privkeyPkcs8.der ecc-privkeyPkcs8.pem ecc-rsa-server.p12 empty-issuer-cert.pem entity-no-ca-bool-cert.pem entity-no-ca-bool-key.pem fpki-cert.der fpki-certpol-cert.der gen_revoked.sh include.am renewcerts.sh rid-cert.der rsa-pub-2048.pem rsa2048.der rsa3072.der server-cert-chain.der server-cert.der server-cert.pem server-ecc-comp.der server-ecc-comp.pem server-ecc-rsa.der server-ecc-rsa.pem server-ecc-self.der server-ecc-self.pem server-ecc.der server-ecc.pem server-ecc384-cert.der server-ecc384-cert.pem server-ecc384-key.der server-ecc384-key.pem server-key.der server-key.pem server-keyEnc.pem server-keyPkcs8.der server-keyPkcs8.pem server-keyPkcs8Enc.der server-keyPkcs8Enc.pem server-keyPkcs8Enc12.pem server-keyPkcs8Enc2.pem server-keyPub.der server-keyPub.pem server-revoked-cert.pem server-revoked-key.pem taoCert.txt test-ber-exp02-05-2022.p7b test-degenerate.p7b test-multiple-recipients.p7b test-servercert-rc2.p12 test-servercert.p12 test-stream-dec.p7b test-stream-sign.p7b wolfssl-website-ca.pem x942dh2048.der x942dh2048.pem
cmake
consumer CMakeLists.txt README.md main.c
modules FindARIA.cmake FindOQS.cmake
Config.cmake.in README.md config.in functions.cmake include.am options.h.in wolfssl-config-version.cmake.in wolfssl-targets.cmake.in
debian
source format
changelog.in control.in copyright include.am libwolfssl-dev.install libwolfssl.install rules.in
doc
dox_comments
header_files aes.h arc4.h ascon.h asn.h asn_public.h blake2.h bn.h camellia.h chacha.h chacha20_poly1305.h cmac.h coding.h compress.h cryptocb.h curve25519.h curve448.h des3.h dh.h doxygen_groups.h doxygen_pages.h dsa.h ecc.h eccsi.h ed25519.h ed448.h error-crypt.h evp.h hash.h hmac.h iotsafe.h kdf.h logging.h md2.h md4.h md5.h memory.h ocsp.h pem.h pkcs11.h pkcs7.h poly1305.h psa.h puf.h pwdbased.h quic.h random.h ripemd.h rsa.h sakke.h sha.h sha256.h sha3.h sha512.h signature.h siphash.h srp.h ssl.h tfm.h types.h wc_encrypt.h wc_port.h wc_she.h wc_slhdsa.h wolfio.h
header_files-ja aes.h arc4.h ascon.h asn.h asn_public.h blake2.h bn.h camellia.h chacha.h chacha20_poly1305.h cmac.h coding.h compress.h cryptocb.h curve25519.h curve448.h des3.h dh.h doxygen_groups.h doxygen_pages.h dsa.h ecc.h eccsi.h ed25519.h ed448.h error-crypt.h evp.h hash.h hmac.h iotsafe.h kdf.h logging.h md2.h md4.h md5.h memory.h ocsp.h pem.h pkcs11.h pkcs7.h poly1305.h psa.h pwdbased.h quic.h random.h ripemd.h rsa.h sakke.h sha.h sha256.h sha3.h sha512.h signature.h siphash.h srp.h ssl.h tfm.h types.h wc_encrypt.h wc_port.h wolfio.h
formats
html
html_changes
search search.css search.js
customdoxygen.css doxygen.css menu.js menudata.js tabs.css
Doxyfile footer.html header.html mainpage.dox
pdf Doxyfile header.tex
images wolfssl_logo.png
QUIC.md README.txt README_DOXYGEN check_api.sh generate_documentation.sh include.am
examples
asn1 asn1.c dumpasn1.cfg gen_oid_names.rb include.am oid_names.h
async Makefile README.md async_client.c async_server.c async_tls.c async_tls.h include.am user_settings.h
benchmark include.am tls_bench.c tls_bench.h
client client.c client.h client.sln client.vcproj client.vcxproj include.am
configs README.md include.am user_settings_EBSnet.h user_settings_all.h user_settings_arduino.h user_settings_baremetal.h user_settings_ca.h user_settings_curve25519nonblock.h user_settings_dtls13.h user_settings_eccnonblock.h user_settings_espressif.h user_settings_fipsv2.h user_settings_fipsv5.h user_settings_min_ecc.h user_settings_openssl_compat.h user_settings_pkcs7.h user_settings_platformio.h user_settings_pq.h user_settings_rsa_only.h user_settings_stm32.h user_settings_template.h user_settings_tls12.h user_settings_tls13.h user_settings_wolfboot_keytools.h user_settings_wolfssh.h user_settings_wolftpm.h
crypto_policies
default wolfssl.txt
future wolfssl.txt
legacy wolfssl.txt
echoclient echoclient.c echoclient.h echoclient.sln echoclient.vcproj echoclient.vcxproj include.am quit
echoserver echoserver.c echoserver.h echoserver.sln echoserver.vcproj echoserver.vcxproj include.am
ocsp_responder include.am ocsp_responder.c ocsp_responder.h
pem include.am pem.c
sctp include.am sctp-client-dtls.c sctp-client.c sctp-server-dtls.c sctp-server.c
server include.am server.c server.h server.sln server.vcproj server.vcxproj
README.md include.am
linuxkm
patches
5.10.17 WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-5v10v17.patch
5.10.236 WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-5v10v236.patch
5.14.0-570.58.1.el9_6 WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-5v14-570v58v1-el9_6.patch
5.15 WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-5v15.patch
5.17 WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-5v17.patch
5.17-ubuntu-jammy-tegra WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-5v17-ubuntu-jammy-tegra.patch
6.1.73 WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-6v1v73.patch
6.12 WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-6v12.patch
6.15 WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-6v15.patch
7.0 WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-7v0.patch
regen-patches.sh
Kbuild Makefile README.md get_thread_size.c include.am linuxkm-fips-hash-wrapper.sh linuxkm-fips-hash.c linuxkm_memory.c linuxkm_memory.h linuxkm_wc_port.h lkcapi_aes_glue.c lkcapi_dh_glue.c lkcapi_ecdh_glue.c lkcapi_ecdsa_glue.c lkcapi_glue.c lkcapi_rsa_glue.c lkcapi_sha_glue.c module_exports.c.template module_hooks.c pie_redirect_table.c wolfcrypt.lds x86_vector_register_glue.c
m4 ax_add_am_macro.m4 ax_am_jobserver.m4 ax_am_macros.m4 ax_append_compile_flags.m4 ax_append_flag.m4 ax_append_link_flags.m4 ax_append_to_file.m4 ax_atomic.m4 ax_bsdkm.m4 ax_check_compile_flag.m4 ax_check_link_flag.m4 ax_compiler_version.m4 ax_count_cpus.m4 ax_create_generic_config.m4 ax_debug.m4 ax_file_escapes.m4 ax_harden_compiler_flags.m4 ax_linuxkm.m4 ax_print_to_file.m4 ax_pthread.m4 ax_require_defined.m4 ax_tls.m4 ax_vcs_checkout.m4 hexversion.m4 lib_socket_nsl.m4 visibility.m4
mcapi
wolfcrypt_mcapi.X
nbproject configurations.xml include.am project.xml
Makefile
wolfcrypt_test.X
nbproject configurations.xml include.am project.xml
Makefile
wolfssl.X
nbproject configurations.xml include.am project.xml
Makefile
zlib.X
nbproject configurations.xml include.am project.xml
Makefile
PIC32MZ-serial.h README crypto.c crypto.h include.am mcapi_test.c user_settings.h
mplabx
wolfcrypt_benchmark.X
nbproject configurations.xml include.am project.xml
Makefile
wolfcrypt_test.X
nbproject configurations.xml include.am project.xml
Makefile
wolfssl.X
nbproject configurations.xml include.am project.xml
Makefile
PIC32MZ-serial.h README benchmark_main.c include.am test_main.c user_settings.h
mqx
util_lib
Sources include.am util.c util.h
wolfcrypt_benchmark
Debugger K70FN1M0.mem init_kinetis.tcl mass_erase_kinetis.tcl
Sources include.am main.c main.h
ReferencedRSESystems.xml wolfcrypt_benchmark_twrk70f120m_Int_Flash_DDRData_Debug_PnE_U-MultiLink.launch wolfcrypt_benchmark_twrk70f120m_Int_Flash_DDRData_Release_PnE_U-MultiLink.launch wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Debug_JTrace.jlink wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Debug_JTrace.launch wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Debug_PnE_U-MultiLink.launch wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Release_PnE_U-MultiLink.launch
wolfcrypt_test
Debugger K70FN1M0.mem init_kinetis.tcl mass_erase_kinetis.tcl
Sources include.am main.c main.h
ReferencedRSESystems.xml wolfcrypt_test_twrk70f120m_Int_Flash_DDRData_Debug_PnE_U-MultiLink.launch wolfcrypt_test_twrk70f120m_Int_Flash_DDRData_Release_PnE_U-MultiLink.launch wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Debug_JTrace.jlink wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Debug_JTrace.launch wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Debug_PnE_U-MultiLink.launch wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Release_PnE_U-MultiLink.launch
wolfssl include.am
wolfssl_client
Debugger K70FN1M0.mem init_kinetis.tcl mass_erase_kinetis.tcl
Sources include.am main.c main.h
ReferencedRSESystems.xml wolfssl_client_twrk70f120m_Int_Flash_DDRData_Debug_PnE_U-MultiLink.launch wolfssl_client_twrk70f120m_Int_Flash_DDRData_Release_PnE_U-MultiLink.launch wolfssl_client_twrk70f120m_Int_Flash_SramData_Debug_JTrace.jlink wolfssl_client_twrk70f120m_Int_Flash_SramData_Debug_JTrace.launch wolfssl_client_twrk70f120m_Int_Flash_SramData_Debug_PnE_U-MultiLink.launch wolfssl_client_twrk70f120m_Int_Flash_SramData_Release_PnE_U-MultiLink.launch
README
rpm include.am spec.in
scripts
bench bench_functions.sh
aria-cmake-build-test.sh asn1_oid_sum.pl benchmark.test benchmark_compare.sh cleanup_testfiles.sh crl-gen-openssl.test crl-revoked.test dertoc.pl dtls.test dtlscid.test external.test google.test include.am makedistsmall.sh memtest.sh ocsp-responder-openssl-interop.test ocsp-stapling-with-ca-as-responder.test ocsp-stapling-with-wolfssl-responder.test ocsp-stapling.test ocsp-stapling2.test ocsp-stapling_tls13multi.test ocsp.test openssl.test openssl_srtp.test pem.test ping.test pkcallbacks.test psk.test resume.test rsapss.test sniffer-gen.sh sniffer-ipv6.pcap sniffer-static-rsa.pcap sniffer-testsuite.test sniffer-tls12-keylog.out sniffer-tls12-keylog.pcap sniffer-tls12-keylog.sslkeylog sniffer-tls13-dh-resume.pcap sniffer-tls13-dh.pcap sniffer-tls13-ecc-resume.pcap sniffer-tls13-ecc.pcap sniffer-tls13-hrr.pcap sniffer-tls13-keylog.out sniffer-tls13-keylog.pcap sniffer-tls13-keylog.sslkeylog sniffer-tls13-x25519-resume.pcap sniffer-tls13-x25519.pcap stm32l4-v4_0_1_build.sh tls13.test trusted_peer.test unit.test.in user_settings_asm.sh
src bio.c conf.c crl.c dtls.c dtls13.c include.am internal.c keys.c ocsp.c pk.c pk_ec.c pk_rsa.c quic.c sniffer.c ssl.c ssl_api_cert.c ssl_api_crl_ocsp.c ssl_api_pk.c ssl_asn1.c ssl_bn.c ssl_certman.c ssl_crypto.c ssl_ech.c ssl_load.c ssl_misc.c ssl_p7p12.c ssl_sess.c ssl_sk.c tls.c tls13.c wolfio.c x509.c x509_str.c
sslSniffer
sslSnifferTest README_WIN.md include.am snifftest.c sslSniffTest.vcproj sslSniffTest.vcxproj
README.md sslSniffer.vcproj sslSniffer.vcxproj
support gen-debug-trace-error-codes.sh include.am wolfssl.pc.in
tests
api api.h api_decl.h create_ocsp_test_blobs.py include.am test_aes.c test_aes.h test_arc4.c test_arc4.h test_ascon.c test_ascon.h test_ascon_kats.h test_asn.c test_asn.h test_blake2.c test_blake2.h test_camellia.c test_camellia.h test_certman.c test_certman.h test_chacha.c test_chacha.h test_chacha20_poly1305.c test_chacha20_poly1305.h test_cmac.c test_cmac.h test_curve25519.c test_curve25519.h test_curve448.c test_curve448.h test_des3.c test_des3.h test_dh.c test_dh.h test_digest.h test_dsa.c test_dsa.h test_dtls.c test_dtls.h test_ecc.c test_ecc.h test_ed25519.c test_ed25519.h test_ed448.c test_ed448.h test_evp.c test_evp.h test_evp_cipher.c test_evp_cipher.h test_evp_digest.c test_evp_digest.h test_evp_pkey.c test_evp_pkey.h test_hash.c test_hash.h test_hmac.c test_hmac.h test_md2.c test_md2.h test_md4.c test_md4.h test_md5.c test_md5.h test_mldsa.c test_mldsa.h test_mlkem.c test_mlkem.h test_ocsp.c test_ocsp.h test_ocsp_test_blobs.h test_ossl_asn1.c test_ossl_asn1.h test_ossl_bio.c test_ossl_bio.h test_ossl_bn.c test_ossl_bn.h test_ossl_cipher.c test_ossl_cipher.h test_ossl_dgst.c test_ossl_dgst.h test_ossl_dh.c test_ossl_dh.h test_ossl_dsa.c test_ossl_dsa.h test_ossl_ec.c test_ossl_ec.h test_ossl_ecx.c test_ossl_ecx.h test_ossl_mac.c test_ossl_mac.h test_ossl_obj.c test_ossl_obj.h test_ossl_p7p12.c test_ossl_p7p12.h test_ossl_pem.c test_ossl_pem.h test_ossl_rand.c test_ossl_rand.h test_ossl_rsa.c test_ossl_rsa.h test_ossl_sk.c test_ossl_sk.h test_ossl_x509.c test_ossl_x509.h test_ossl_x509_acert.c test_ossl_x509_acert.h test_ossl_x509_crypto.c test_ossl_x509_crypto.h test_ossl_x509_ext.c test_ossl_x509_ext.h test_ossl_x509_info.c test_ossl_x509_info.h test_ossl_x509_io.c test_ossl_x509_io.h test_ossl_x509_lu.c test_ossl_x509_lu.h test_ossl_x509_name.c test_ossl_x509_name.h test_ossl_x509_pk.c test_ossl_x509_pk.h test_ossl_x509_str.c test_ossl_x509_str.h test_ossl_x509_vp.c test_ossl_x509_vp.h test_pkcs12.c test_pkcs12.h test_pkcs7.c test_pkcs7.h test_poly1305.c test_poly1305.h test_random.c test_random.h test_rc2.c test_rc2.h test_ripemd.c test_ripemd.h test_rsa.c test_rsa.h test_sha.c test_sha.h test_sha256.c test_sha256.h test_sha3.c test_sha3.h test_sha512.c test_sha512.h test_she.c test_she.h test_signature.c test_signature.h test_slhdsa.c test_slhdsa.h test_sm2.c test_sm2.h test_sm3.c test_sm3.h test_sm4.c test_sm4.h test_tls.c test_tls.h test_tls13.c test_tls13.h test_tls_ext.c test_tls_ext.h test_wc_encrypt.c test_wc_encrypt.h test_wolfmath.c test_wolfmath.h test_x509.c test_x509.h
emnet
IP IP.h
Makefile emnet_nonblock_test.c emnet_shim.c
freertos-mem-track-repro FreeRTOS.h repro.c run.sh semphr.h task.h user_settings.h
swdev .gitignore Makefile README.md swdev.c swdev.h swdev_loader.c swdev_loader.h user_settings.h
CONF_FILES_README.md NCONF_test.cnf README TXT_DB.txt api.c include.am quic.c srp.c suites.c test-altchains.conf test-chains.conf test-dhprime.conf test-dtls-downgrade.conf test-dtls-fails-cipher.conf test-dtls-fails.conf test-dtls-group.conf test-dtls-mtu.conf test-dtls-reneg-client.conf test-dtls-reneg-server.conf test-dtls-resume.conf test-dtls-sha2.conf test-dtls-srtp-fails.conf test-dtls-srtp.conf test-dtls.conf test-dtls13-cid.conf test-dtls13-downgrade-fails.conf test-dtls13-downgrade.conf test-dtls13-pq-hybrid-extra-frag.conf test-dtls13-pq-hybrid-extra.conf test-dtls13-pq-hybrid-frag.conf test-dtls13-pq-standalone-frag.conf test-dtls13-pq-standalone.conf test-dtls13-psk.conf test-dtls13.conf test-ecc-cust-curves.conf test-ed25519.conf test-ed448.conf test-enckeys.conf test-fails.conf test-maxfrag-dtls.conf test-maxfrag.conf test-p521.conf test-psk-no-id-sha2.conf test-psk-no-id.conf test-psk.conf test-rsapss.conf test-sctp-sha2.conf test-sctp.conf test-sha2.conf test-sig.conf test-sm2.conf test-tls-downgrade.conf test-tls13-down.conf test-tls13-ecc.conf test-tls13-pq-hybrid-extra.conf test-tls13-pq-hybrid.conf test-tls13-pq-standalone.conf test-tls13-psk-certs.conf test-tls13-psk.conf test-tls13-slhdsa-fail.conf test-tls13-slhdsa-sha2.conf test-tls13-slhdsa-shake.conf test-tls13.conf test-trustpeer.conf test.conf unit.c unit.h utils.c utils.h w64wrapper.c
testsuite include.am testsuite.c testsuite.sln testsuite.vcproj testsuite.vcxproj utils.c utils.h
tirtos
packages
ti
net
wolfssl
tests
EK_TM4C1294XL
wolfcrypt
benchmark TM4C1294NC.icf benchmark.cfg main.c package.bld.hide package.xdc
test TM4C1294NC.icf main.c package.bld.hide package.xdc test.cfg
package.bld package.xdc package.xs
.gitignore README include.am products.mak wolfssl.bld wolfssl.mak
wolfcrypt
benchmark README.md benchmark-VS2022.sln benchmark-VS2022.vcxproj benchmark-VS2022.vcxproj.user benchmark.c benchmark.h benchmark.sln benchmark.vcproj benchmark.vcxproj include.am
src
port
Espressif
esp_crt_bundle README.md cacrt_all.pem cacrt_deprecated.pem cacrt_local.pem esp_crt_bundle.c gen_crt_bundle.py pio_install_cryptography.py
README.md esp32_aes.c esp32_mp.c esp32_sha.c esp32_util.c esp_sdk_mem_lib.c esp_sdk_time_lib.c esp_sdk_wifi_lib.c
Renesas README.md renesas_common.c renesas_fspsm_aes.c renesas_fspsm_rsa.c renesas_fspsm_sha.c renesas_fspsm_util.c renesas_rx64_hw_sha.c renesas_rx64_hw_util.c renesas_tsip_aes.c renesas_tsip_rsa.c renesas_tsip_sha.c renesas_tsip_util.c
af_alg afalg_aes.c afalg_hash.c wc_afalg.c
aria aria-crypt.c aria-cryptocb.c
arm armv8-32-aes-asm.S armv8-32-aes-asm_c.c armv8-32-chacha-asm.S armv8-32-chacha-asm_c.c armv8-32-curve25519.S armv8-32-curve25519_c.c armv8-32-mlkem-asm.S armv8-32-mlkem-asm_c.c armv8-32-poly1305-asm.S armv8-32-poly1305-asm_c.c armv8-32-sha256-asm.S armv8-32-sha256-asm_c.c armv8-32-sha3-asm.S armv8-32-sha3-asm_c.c armv8-32-sha512-asm.S armv8-32-sha512-asm_c.c armv8-aes-asm.S armv8-aes-asm_c.c armv8-aes.c armv8-chacha-asm.S armv8-chacha-asm_c.c armv8-curve25519.S armv8-curve25519_c.c armv8-mlkem-asm.S armv8-mlkem-asm_c.c armv8-poly1305-asm.S armv8-poly1305-asm_c.c armv8-sha256-asm.S armv8-sha256-asm_c.c armv8-sha256.c armv8-sha3-asm.S armv8-sha3-asm_c.c armv8-sha512-asm.S armv8-sha512-asm_c.c armv8-sha512.c cryptoCell.c cryptoCellHash.c thumb2-aes-asm.S thumb2-aes-asm_c.c thumb2-chacha-asm.S thumb2-chacha-asm_c.c thumb2-curve25519.S thumb2-curve25519_c.c thumb2-mlkem-asm.S thumb2-mlkem-asm_c.c thumb2-poly1305-asm.S thumb2-poly1305-asm_c.c thumb2-sha256-asm.S thumb2-sha256-asm_c.c thumb2-sha3-asm.S thumb2-sha3-asm_c.c thumb2-sha512-asm.S thumb2-sha512-asm_c.c
atmel README.md atmel.c
autosar README.md cryif.c crypto.c csm.c include.am test.c
caam README.md caam_aes.c caam_doc.pdf caam_driver.c caam_error.c caam_integrity.c caam_qnx.c caam_sha.c wolfcaam_aes.c wolfcaam_cmac.c wolfcaam_ecdsa.c wolfcaam_fsl_nxp.c wolfcaam_hash.c wolfcaam_hmac.c wolfcaam_init.c wolfcaam_qnx.c wolfcaam_rsa.c wolfcaam_seco.c wolfcaam_x25519.c
cavium README.md README_Octeon.md cavium_nitrox.c cavium_octeon_sync.c
cuda README.md aes-cuda.cu
cypress README.md psoc6_crypto.c
devcrypto README.md devcrypto_aes.c devcrypto_ecdsa.c devcrypto_hash.c devcrypto_hmac.c devcrypto_rsa.c devcrypto_x25519.c wc_devcrypto.c
intel README.md quickassist.c quickassist_mem.c quickassist_sync.c
iotsafe iotsafe.c
kcapi README.md kcapi_aes.c kcapi_dh.c kcapi_ecc.c kcapi_hash.c kcapi_hmac.c kcapi_rsa.c
liboqs liboqs.c
maxim README.md max3266x.c maxq10xx.c
mynewt mynewt_port.c
nxp README.md README_SE050.md casper_port.c dcp_port.c hashcrypt_port.c ksdk_port.c se050_port.c
pic32 pic32mz-crypt.c
ppc32 ppc32-sha256-asm.S ppc32-sha256-asm_c.c ppc32-sha256-asm_cr.c
psa README.md psa.c psa_aes.c psa_hash.c psa_pkcbs.c
riscv riscv-64-aes.c riscv-64-chacha.c riscv-64-poly1305.c riscv-64-sha256.c riscv-64-sha3.c riscv-64-sha512.c
rpi_pico README.md pico.c
silabs README.md silabs_aes.c silabs_ecc.c silabs_hash.c silabs_random.c
st README.md STM32MP13.md STM32MP25.md stm32.c stsafe.c
ti ti-aes.c ti-ccm.c ti-des3.c ti-hash.c
tropicsquare README.md tropic01.c
xilinx xil-aesgcm.c xil-sha3.c xil-versal-glue.c xil-versal-trng.c
nrf51.c
ASN_TEMPLATE.md aes.c aes_asm.S aes_asm.asm aes_gcm_asm.S aes_gcm_asm.asm aes_gcm_x86_asm.S aes_xts_asm.S aes_xts_asm.asm arc4.c ascon.c asm.c asn.c asn_orig.c async.c blake2b.c blake2s.c camellia.c chacha.c chacha20_poly1305.c chacha_asm.S chacha_asm.asm cmac.c coding.c compress.c cpuid.c cryptocb.c curve25519.c curve448.c des3.c dh.c dilithium.c dsa.c ecc.c ecc_fp.c eccsi.c ed25519.c ed448.c error.c evp.c evp_pk.c falcon.c fe_448.c fe_low_mem.c fe_operations.c fe_x25519_128.h fe_x25519_asm.S fp_mont_small.i fp_mul_comba_12.i fp_mul_comba_17.i fp_mul_comba_20.i fp_mul_comba_24.i fp_mul_comba_28.i fp_mul_comba_3.i fp_mul_comba_32.i fp_mul_comba_4.i fp_mul_comba_48.i fp_mul_comba_6.i fp_mul_comba_64.i fp_mul_comba_7.i fp_mul_comba_8.i fp_mul_comba_9.i fp_mul_comba_small_set.i fp_sqr_comba_12.i fp_sqr_comba_17.i fp_sqr_comba_20.i fp_sqr_comba_24.i fp_sqr_comba_28.i fp_sqr_comba_3.i fp_sqr_comba_32.i fp_sqr_comba_4.i fp_sqr_comba_48.i fp_sqr_comba_6.i fp_sqr_comba_64.i fp_sqr_comba_7.i fp_sqr_comba_8.i fp_sqr_comba_9.i fp_sqr_comba_small_set.i ge_448.c ge_low_mem.c ge_operations.c hash.c hmac.c hpke.c include.am integer.c kdf.c logging.c md2.c md4.c md5.c memory.c misc.c pkcs12.c pkcs7.c poly1305.c poly1305_asm.S poly1305_asm.asm puf.c pwdbased.c random.c rc2.c ripemd.c rng_bank.c rsa.c sakke.c sha.c sha256.c sha256_asm.S sha3.c sha3_asm.S sha512.c sha512_asm.S signature.c siphash.c sm2.c sm3.c sm3_asm.S sm4.c sp_arm32.c sp_arm64.c sp_armthumb.c sp_c32.c sp_c64.c sp_cortexm.c sp_dsp32.c sp_int.c sp_sm2_arm32.c sp_sm2_arm64.c sp_sm2_armthumb.c sp_sm2_c32.c sp_sm2_c64.c sp_sm2_cortexm.c sp_sm2_x86_64.c sp_sm2_x86_64_asm.S sp_x86_64.c sp_x86_64_asm.S sp_x86_64_asm.asm srp.c tfm.c wc_dsp.c wc_encrypt.c wc_lms.c wc_lms_impl.c wc_mldsa_asm.S wc_mlkem.c wc_mlkem_asm.S wc_mlkem_poly.c wc_pkcs11.c wc_port.c wc_she.c wc_slhdsa.c wc_xmss.c wc_xmss_impl.c wolfentropy.c wolfevent.c wolfmath.c
test README.md include.am test-VS2022.sln test-VS2022.vcxproj test-VS2022.vcxproj.user test.c test.h test.sln test.vcproj test_paths.h.in
wolfssl
openssl aes.h asn1.h asn1t.h bio.h bn.h buffer.h camellia.h cmac.h cms.h compat_types.h conf.h crypto.h des.h dh.h dsa.h ec.h ec25519.h ec448.h ecdh.h ecdsa.h ed25519.h ed448.h engine.h err.h evp.h fips_rand.h hmac.h include.am kdf.h lhash.h md4.h md5.h modes.h obj_mac.h objects.h ocsp.h opensslconf.h opensslv.h ossl_typ.h pem.h pkcs12.h pkcs7.h rand.h rc4.h ripemd.h rsa.h safestack.h sha.h sha3.h srp.h ssl.h ssl23.h stack.h tls1.h txt_db.h ui.h x509.h x509_vfy.h x509v3.h
wolfcrypt
port
Espressif esp-sdk-lib.h esp32-crypt.h esp_crt_bundle.h
Renesas renesas-fspsm-crypt.h renesas-fspsm-types.h renesas-rx64-hw-crypt.h renesas-tsip-crypt.h renesas_cmn.h renesas_fspsm_internal.h renesas_sync.h renesas_tsip_internal.h renesas_tsip_types.h
af_alg afalg_hash.h wc_afalg.h
aria aria-crypt.h aria-cryptocb.h
arm cryptoCell.h
atmel atmel.h
autosar CryIf.h Crypto.h Csm.h StandardTypes.h
caam caam_driver.h caam_error.h caam_qnx.h wolfcaam.h wolfcaam_aes.h wolfcaam_cmac.h wolfcaam_ecdsa.h wolfcaam_fsl_nxp.h wolfcaam_hash.h wolfcaam_qnx.h wolfcaam_rsa.h wolfcaam_seco.h wolfcaam_sha.h wolfcaam_x25519.h
cavium cavium_nitrox.h cavium_octeon_sync.h
cypress psoc6_crypto.h
devcrypto wc_devcrypto.h
intel quickassist.h quickassist_mem.h quickassist_sync.h
iotsafe iotsafe.h
kcapi kcapi_dh.h kcapi_ecc.h kcapi_hash.h kcapi_hmac.h kcapi_rsa.h wc_kcapi.h
liboqs liboqs.h
maxim max3266x-cryptocb.h max3266x.h maxq10xx.h
nxp casper_port.h dcp_port.h hashcrypt_port.h ksdk_port.h se050_port.h
pic32 pic32mz-crypt.h
psa psa.h
riscv riscv-64-asm.h
rpi_pico pico.h
silabs silabs_aes.h silabs_ecc.h silabs_hash.h silabs_random.h
st stm32.h stsafe.h
ti ti-ccm.h ti-hash.h
tropicsquare tropic01.h
xilinx xil-sha3.h xil-versal-glue.h xil-versal-trng.h
nrf51.h
aes.h arc4.h ascon.h asn.h asn_public.h async.h blake2-impl.h blake2-int.h blake2.h camellia.h chacha.h chacha20_poly1305.h cmac.h coding.h compress.h cpuid.h cryptocb.h curve25519.h curve448.h des3.h dh.h dilithium.h dsa.h ecc.h eccsi.h ed25519.h ed448.h error-crypt.h falcon.h fe_448.h fe_operations.h fips_test.h ge_448.h ge_operations.h hash.h hmac.h hpke.h include.am integer.h kdf.h libwolfssl_sources.h libwolfssl_sources_asm.h logging.h md2.h md4.h md5.h mem_track.h memory.h misc.h mpi_class.h mpi_superclass.h oid_sum.h pkcs11.h pkcs12.h pkcs7.h poly1305.h puf.h pwdbased.h random.h rc2.h ripemd.h rng_bank.h rsa.h sakke.h selftest.h settings.h sha.h sha256.h sha3.h sha512.h signature.h siphash.h sm2.h sm3.h sm4.h sp.h sp_int.h srp.h tfm.h types.h visibility.h wc_encrypt.h wc_lms.h wc_mlkem.h wc_pkcs11.h wc_port.h wc_she.h wc_slhdsa.h wc_xmss.h wolfentropy.h wolfevent.h wolfmath.h
callbacks.h certs_test.h certs_test_sm.h crl.h error-ssl.h include.am internal.h ocsp.h options.h.in quic.h sniffer.h sniffer_error.h sniffer_error.rc ssl.h test.h version.h version.h.in wolfio.h
wrapper
Ada
examples
src aes_verify_main.adb rsa_verify_main.adb sha256_main.adb spark_sockets.adb spark_sockets.ads spark_terminal.adb spark_terminal.ads tls_client.adb tls_client.ads tls_client_main.adb tls_server.adb tls_server.ads tls_server_main.adb
.gitignore alire.toml examples.gpr
tests
src
support test_support.adb test_support.ads tests_root_suite.adb tests_root_suite.ads
aes_bindings_tests.adb aes_bindings_tests.ads rsa_verify_bindings_tests.adb rsa_verify_bindings_tests.ads sha256_bindings_tests.adb sha256_bindings_tests.ads tests.adb
.gitignore README.md alire.toml tests.gpr valgrind.supp
.gitignore README.md ada_binding.c alire.toml default.gpr include.am restricted.adc user_settings.h wolfssl-full_runtime.adb wolfssl-full_runtime.ads wolfssl.adb wolfssl.ads wolfssl.gpr
CSharp
wolfCrypt-Test
Properties AssemblyInfo.cs
App.config wolfCrypt-Test.cs wolfCrypt-Test.csproj
wolfSSL-DTLS-PSK-Server
Properties AssemblyInfo.cs
App.config wolfSSL-DTLS-PSK-Server.cs wolfSSL-DTLS-PSK-Server.csproj
wolfSSL-DTLS-Server
Properties AssemblyInfo.cs
App.config wolfSSL-DTLS-Server.cs wolfSSL-DTLS-Server.csproj
wolfSSL-Example-IOCallbacks
Properties AssemblyInfo.cs
App.config wolfSSL-Example-IOCallbacks.cs wolfSSL-Example-IOCallbacks.csproj
wolfSSL-TLS-Client
Properties AssemblyInfo.cs
App.config wolfSSL-TLS-Client.cs wolfSSL-TLS-Client.csproj
wolfSSL-TLS-PSK-Client
Properties AssemblyInfo.cs
App.config wolfSSL-TLS-PSK-Client.cs wolfSSL-TLS-PSK-Client.csproj
wolfSSL-TLS-PSK-Server
Properties AssemblyInfo.cs
App.config wolfSSL-TLS-PSK-Server.cs wolfSSL-TLS-PSK-Server.csproj
wolfSSL-TLS-Server
Properties AssemblyInfo.cs
App.config wolfSSL-TLS-Server.cs wolfSSL-TLS-Server.csproj
wolfSSL-TLS-ServerThreaded
Properties AssemblyInfo.cs
App.config wolfSSL-TLS-ServerThreaded.cs wolfSSL-TLS-ServerThreaded.csproj
wolfSSL_CSharp
Properties AssemblyInfo.cs Resources.Designer.cs Resources.resx
X509.cs wolfCrypt.cs wolfSSL.cs wolfSSL_CSharp.csproj
README.md include.am user_settings.h wolfSSL_CSharp.sln wolfssl.vcxproj
python README.md
rust
wolfssl-wolfcrypt
src aes.rs blake2.rs chacha20_poly1305.rs cmac.rs cmac_mac.rs curve25519.rs dh.rs dilithium.rs ecc.rs ecdsa.rs ed25519.rs ed448.rs fips.rs hkdf.rs hmac.rs hmac_mac.rs kdf.rs lib.rs lms.rs mlkem.rs mlkem_kem.rs pbkdf2_password_hash.rs prf.rs random.rs rsa.rs rsa_pkcs1v15.rs sha.rs sha_digest.rs sys.rs
tests
common mod.rs
test_aes.rs test_blake2.rs test_chacha20_poly1305.rs test_cmac.rs test_cmac_mac.rs test_curve25519.rs test_dh.rs test_dilithium.rs test_ecc.rs test_ecdsa.rs test_ed25519.rs test_ed448.rs test_hkdf.rs test_hmac.rs test_hmac_mac.rs test_kdf.rs test_lms.rs test_mlkem.rs test_mlkem_kem.rs test_pbkdf2_password_hash.rs test_prf.rs test_random.rs test_rsa.rs test_rsa_pkcs1v15.rs test_sha.rs test_sha_digest.rs test_wolfcrypt.rs
CHANGELOG.md Cargo.lock Cargo.toml Makefile README.md build.rs headers.h
Makefile README.md include.am
include.am
zephyr
samples
wolfssl_benchmark
boards native_sim.conf nrf5340dk_nrf5340_cpuapp.conf nrf5340dk_nrf5340_cpuapp_ns.conf
CMakeLists.txt README install_test.sh prj.conf sample.yaml zephyr_legacy.conf zephyr_v4.1.conf
wolfssl_test
boards native_sim.conf nrf5340dk_nrf5340_cpuapp.conf nrf5340dk_nrf5340_cpuapp_ns.conf
CMakeLists.txt README install_test.sh prj-no-malloc.conf prj.conf sample.yaml zephyr_legacy.conf zephyr_v4.1.conf
wolfssl_tls_sock
boards native_sim.conf
src tls_sock.c
CMakeLists.txt README install_sample.sh prj-no-malloc.conf prj.conf sample.yaml zephyr_legacy.conf zephyr_v4.1.conf
wolfssl_tls_thread
boards native_sim.conf nrf5340dk_nrf5340_cpuapp.conf nrf5340dk_nrf5340_cpuapp_ns.conf
src tls_threaded.c
CMakeLists.txt README install_sample.sh prj.conf sample.yaml zephyr_legacy.conf zephyr_v4.1.conf
wolfssl options.h
CMakeLists.txt Kconfig Kconfig.tls-generic README.md include.am module.yml user_settings-no-malloc.h user_settings.h zephyr_init.c
.codespellexcludelines .cyignore .editorconfig .gitignore .wolfssl_known_macro_extras AUTHORS CMakeLists.txt CMakePresets.json CMakeSettings.json COPYING ChangeLog.md INSTALL LICENSING LPCExpresso.cproject LPCExpresso.project Makefile.am README README-async.md README.md SCRIPTS-LIST SECURITY-POLICY.md SECURITY-REPORT-TEMPLATE.md Vagrantfile autogen.sh commit-tests.sh configure.ac fips-check.sh fips-hash.sh gencertbuf.pl input pull_to_vagrant.sh quit resource.h stamp-h.in valgrind-bash.supp valgrind-error.sh wnr-example.conf wolfssl-VS2022.vcxproj wolfssl.rc wolfssl.vcproj wolfssl.vcxproj wolfssl64.sln
.clangd .gitignore DOCS.md Makefile README.md assert.c core.c crypto.c env.c fs.c http.c ini.c json.c log.c luna.h main.c makext.mk path.c process.c request.c sqlite.c stash.c template.c util.c
wolfssl/src/sniffer.c raw
   1/* sniffer.c
   2 *
   3 * Copyright (C) 2006-2026 wolfSSL Inc.
   4 *
   5 * This file is part of wolfSSL.
   6 *
   7 * wolfSSL is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License as published by
   9 * the Free Software Foundation; either version 3 of the License, or
  10 * (at your option) any later version.
  11 *
  12 * wolfSSL is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 * GNU General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU General Public License
  18 * along with this program; if not, write to the Free Software
  19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
  20 */
  21
  22#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
  23
  24#ifdef WOLFSSL_ASYNC_CRYPT
  25    #include <wolfssl/wolfcrypt/async.h>
  26#endif
  27
  28/* Build Options:
  29 * WOLFSSL_SNIFFER_NO_RECOVERY: Do not track missed data count.
  30 * SNIFFER_SINGLE_SESSION_CACHE: Do not cache more than one session.
  31 */
  32
  33
  34/* xctime */
  35#ifndef XCTIME
  36   #define XCTIME ctime
  37#endif
  38
  39/* only in this file, to avoid confusing future ports leave
  40 * these defines here. Do not move to wc_port.h */
  41#ifdef USER_CUSTOM_SNIFFX
  42    /* To be implemented in user_settings.h */
  43#elif defined(FUSION_RTOS)
  44    #include <fcl_network.h>
  45    #define XINET_NTOA FNS_INET_NTOA
  46    #define XINET_ATON FNS_INET_ATON
  47    #define XINET_PTON(a,b,c,d) FNS_INET_PTON((a),(b),(c),(d),NULL)
  48    #define XINET_NTOP(a,b,c,d) FNS_INET_NTOP((a),(b),(c),(d),NULL)
  49    #define XINET_ADDR FNS_INET_ADDR
  50    #define XHTONS FNS_HTONS
  51    #define XNTOHS FNS_NTOHS
  52    #define XHTONL FNS_HTONL
  53    #define XNTOHL FNS_NTOHL
  54    #define XINADDR_NONE FNS_INADDR_NONE
  55#else
  56    /* default */
  57    #define XINET_NTOA inet_ntoa
  58    #define XINET_ATON inet_aton
  59#ifdef FREESCALE_MQX
  60    #define XINET_PTON(a,b,c,d) inet_pton((a),(b),(c),(d))
  61#else
  62    #define XINET_PTON(a,b,c) inet_pton((a),(b),(c))
  63#endif
  64    #define XINET_NTOP inet_ntop
  65    #define XINET_ADDR inet_addr
  66    #define XHTONS htons
  67    #define XNTOHS ntohs
  68    #define XHTONL htonl
  69    #define XNTOHL ntohl
  70#ifdef FREESCALE_MQX
  71    #define XINADDR_NONE INADDR_BROADCAST
  72#else
  73    #define XINADDR_NONE INADDR_NONE
  74#endif
  75#endif
  76
  77#if !defined(WOLFCRYPT_ONLY) && !defined(NO_FILESYSTEM)
  78#ifdef WOLFSSL_SNIFFER
  79
  80#include <time.h>
  81
  82#ifdef FUSION_RTOS
  83    #include <fns_inet.h>
  84    #ifdef TCP_PROTOCOL
  85        #undef TCP_PROTOCOL
  86    #endif
  87#elif !defined(FREESCALE_MQX)
  88    #ifndef _WIN32
  89        #include <arpa/inet.h>
  90    #else
  91        #include <ws2tcpip.h>
  92    #endif
  93#endif
  94
  95#ifdef _WIN32
  96    #define SNPRINTF _snprintf
  97#else
  98    #define SNPRINTF snprintf
  99#endif
 100
 101#include <wolfssl/internal.h>
 102#include <wolfssl/error-ssl.h>
 103#include <wolfssl/sniffer.h>
 104#include <wolfssl/sniffer_error.h>
 105
 106#ifndef NO_RSA
 107    #include <wolfssl/wolfcrypt/rsa.h>
 108#endif
 109#ifndef NO_DH
 110    #include <wolfssl/wolfcrypt/dh.h>
 111#endif
 112#if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
 113    #include <wolfssl/wolfcrypt/ecc.h>
 114#endif
 115#ifdef HAVE_CURVE25519
 116    #include <wolfssl/wolfcrypt/curve25519.h>
 117#endif
 118
 119#ifdef NO_INLINE
 120    #include <wolfssl/wolfcrypt/misc.h>
 121#else
 122    #define WOLFSSL_MISC_INCLUDED
 123    #include <wolfcrypt/src/misc.c>
 124#endif
 125
 126#ifdef WOLF_CRYPTO_CB
 127    #include <wolfssl/wolfcrypt/cryptocb.h>
 128    #ifdef HAVE_INTEL_QA_SYNC
 129        #include <wolfssl/wolfcrypt/port/intel/quickassist_sync.h>
 130    #endif
 131    #ifdef HAVE_CAVIUM_OCTEON_SYNC
 132        #include <wolfssl/wolfcrypt/port/cavium/cavium_octeon_sync.h>
 133    #endif
 134#endif
 135
 136#define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; }
 137
 138#ifndef WOLFSSL_SNIFFER_TIMEOUT
 139    #define WOLFSSL_SNIFFER_TIMEOUT 900
 140    /* Cache unclosed Sessions for 15 minutes since last used */
 141#endif
 142
 143/* Misc constants */
 144enum {
 145    MAX_SERVER_ADDRESS = 128, /* maximum server address length */
 146    MAX_SERVER_NAME    = 128, /* maximum server name length */
 147    MAX_ERROR_LEN      = 80,  /* maximum error length */
 148    ETHER_IF_ADDR_LEN  = 6,   /* ethernet interface address length */
 149    LOCAL_IF_ADDR_LEN  = 4,   /* localhost interface address length, !windows */
 150    TCP_PROTO          = 6,   /* TCP_PROTOCOL */
 151    IP_HDR_SZ          = 20,  /* IPv4 header length, min */
 152    IP6_HDR_SZ         = 40,  /* IPv6 header length, min */
 153    TCP_HDR_SZ         = 20,  /* TCP header length, min */
 154    IPV4               = 4,   /* IP version 4 */
 155    IPV6               = 6,   /* IP version 6 */
 156    TCP_PROTOCOL       = 6,   /* TCP Protocol id */
 157    NO_NEXT_HEADER     = 59,  /* IPv6 no headers follow */
 158    TRACE_MSG_SZ       = 80,  /* Trace Message buffer size */
 159    HASH_SIZE          = 499, /* Session Hash Table Rows */
 160    PSEUDO_HDR_SZ      = 12,  /* TCP Pseudo Header size in bytes */
 161    STREAM_INFO_SZ     = 44,  /* SnifferStreamInfo size in bytes */
 162    FATAL_ERROR_STATE  = 1,   /* SnifferSession fatal error state */
 163    TICKET_HINT_LEN    = 4,   /* Session Ticket Hint length */
 164    TICKET_HINT_AGE_LEN= 4,   /* Session Ticket Age add length */
 165    EXT_TYPE_SZ        = 2,   /* Extension type length */
 166    MAX_INPUT_SZ       = MAX_RECORD_SIZE + COMP_EXTRA + MAX_MSG_EXTRA +
 167                         MTU_EXTRA,  /* Max input sz of reassembly */
 168
 169    /* TLS Extensions */
 170    EXT_SERVER_NAME                = 0x0000, /* a.k.a. SNI  */
 171    EXT_MAX_FRAGMENT_LENGTH        = 0x0001,
 172    EXT_TRUSTED_CA_KEYS            = 0x0003,
 173    EXT_TRUNCATED_HMAC             = 0x0004,
 174    EXT_STATUS_REQUEST             = 0x0005, /* a.k.a. OCSP stapling   */
 175    EXT_SUPPORTED_GROUPS           = 0x000a, /* a.k.a. Supported Curves */
 176    EXT_EC_POINT_FORMATS           = 0x000b,
 177    EXT_SIGNATURE_ALGORITHMS       = 0x000d,
 178    EXT_APPLICATION_LAYER_PROTOCOL = 0x0010, /* a.k.a. ALPN */
 179    EXT_STATUS_REQUEST_V2          = 0x0011, /* a.k.a. OCSP stapling v2 */
 180    EXT_ENCRYPT_THEN_MAC           = 0x0016, /* RFC 7366 */
 181    EXT_MASTER_SECRET              = 0x0017, /* Extended Master Secret Extension ID */
 182    EXT_TICKET_ID                  = 0x0023, /* Session Ticket Extension ID */
 183    EXT_PRE_SHARED_KEY             = 0x0029,
 184    EXT_EARLY_DATA                 = 0x002a,
 185    EXT_SUPPORTED_VERSIONS         = 0x002b,
 186    EXT_COOKIE                     = 0x002c,
 187    EXT_PSK_KEY_EXCHANGE_MODES     = 0x002d,
 188    EXT_POST_HANDSHAKE_AUTH        = 0x0031,
 189    EXT_SIGNATURE_ALGORITHMS_CERT  = 0x0032,
 190    EXT_KEY_SHARE                  = 0x0033,
 191    EXT_RENEGOTIATION_INFO         = 0xff01
 192};
 193
 194
 195#ifdef _WIN32
 196
 197static HMODULE dllModule;  /* for error string resources */
 198
 199BOOL APIENTRY DllMain( HMODULE hModule,
 200                       DWORD  ul_reason_for_call,
 201                       LPVOID lpReserved
 202                     )
 203{
 204    static int didInit = 0;
 205
 206    switch (ul_reason_for_call)
 207    {
 208    case DLL_PROCESS_ATTACH:
 209        if (didInit == 0) {
 210            dllModule = hModule;
 211            ssl_InitSniffer();
 212            didInit = 1;
 213        }
 214        break;
 215    case DLL_THREAD_ATTACH:
 216        break;
 217    case DLL_THREAD_DETACH:
 218        break;
 219    case DLL_PROCESS_DETACH:
 220        if (didInit) {
 221            ssl_FreeSniffer();
 222            didInit = 0;
 223        }
 224        break;
 225    }
 226    return TRUE;
 227}
 228
 229#endif /* _WIN32 */
 230
 231
 232static WC_THREADSHARED int TraceOn = 0;         /* Trace is off by default */
 233static WC_THREADSHARED XFILE TraceFile = 0;
 234
 235
 236/* windows uses .rc table for this */
 237#ifndef _WIN32
 238
 239static const char* const msgTable[] =
 240{
 241    /* 1 */
 242    "Out of Memory",
 243    "New SSL Sniffer Server Registered",
 244    "Checking IP Header",
 245    "SSL Sniffer Server Not Registered",
 246    "Checking TCP Header",
 247
 248    /* 6 */
 249    "SSL Sniffer Server Port Not Registered",
 250    "RSA Private Decrypt Error",
 251    "RSA Private Decode Error",
 252    "Set Cipher Spec Error",
 253    "Server Hello Input Malformed",
 254
 255    /* 11 */
 256    "Couldn't Resume Session Error",
 257    "Server Did Resumption",
 258    "Client Hello Input Malformed",
 259    "Client Trying to Resume",
 260    "Handshake Input Malformed",
 261
 262    /* 16 */
 263    "Got Hello Verify msg",
 264    "Got Server Hello msg",
 265    "Got Cert Request msg",
 266    "Got Server Key Exchange msg",
 267    "Got Cert msg",
 268
 269    /* 21 */
 270    "Got Server Hello Done msg",
 271    "Got Finished msg",
 272    "Got Client Hello msg",
 273    "Got Client Key Exchange msg",
 274    "Got Cert Verify msg",
 275
 276    /* 26 */
 277    "Got Unknown Handshake msg",
 278    "New SSL Sniffer Session created",
 279    "Couldn't create new SSL",
 280    "Got a Packet to decode",
 281    "No data present",
 282
 283    /* 31 */
 284    "Session Not Found",
 285    "Got an Old Client Hello msg",
 286    "Old Client Hello Input Malformed",
 287    "Old Client Hello OK",
 288    "Bad Old Client Hello",
 289
 290    /* 36 */
 291    "Bad Record Header",
 292    "Record Header Input Malformed",
 293    "Got a HandShake msg",
 294    "Bad HandShake msg",
 295    "Got a Change Cipher Spec msg",
 296
 297    /* 41 */
 298    "Got Application Data msg",
 299    "Bad Application Data",
 300    "Got an Alert msg",
 301    "Another msg to Process",
 302    "Removing Session From Table",
 303
 304    /* 46 */
 305    "Bad Key File",
 306    "Wrong IP Version",
 307    "Wrong Protocol type",
 308    "Packet Short for header processing",
 309    "Got Unknown Record Type",
 310
 311    /* 51 */
 312    "Can't Open Trace File",
 313    "Session in Fatal Error State",
 314    "Partial SSL record received",
 315    "Buffer Error, malformed input",
 316    "Added to Partial Input",
 317
 318    /* 56 */
 319    "Received a Duplicate Packet",
 320    "Received an Out of Order Packet",
 321    "Received an Overlap Duplicate Packet",
 322    "Received an Overlap Reassembly Begin Duplicate Packet",
 323    "Received an Overlap Reassembly End Duplicate Packet",
 324
 325    /* 61 */
 326    "Missed the Client Hello Entirely",
 327    "Got Hello Request msg",
 328    "Got Session Ticket msg",
 329    "Bad Input",
 330    "Bad Decrypt Type",
 331
 332    /* 66 */
 333    "Bad Finished Message Processing",
 334    "Bad Compression Type",
 335    "Bad DeriveKeys Error",
 336    "Saw ACK for Missing Packet Error",
 337    "Bad Decrypt Operation",
 338
 339    /* 71 */
 340    "Decrypt Keys Not Set Up",
 341    "Late Key Load Error",
 342    "Got Certificate Status msg",
 343    "RSA Key Missing Error",
 344    "Secure Renegotiation Not Supported",
 345
 346    /* 76 */
 347    "Get Session Stats Failure",
 348    "Reassembly Buffer Size Exceeded",
 349    "Dropping Lost Fragment",
 350    "Dropping Partial Record",
 351    "Clear ACK Fault",
 352
 353    /* 81 */
 354    "Bad Decrypt Size",
 355    "Extended Master Secret Hash Error",
 356    "Handshake Message Split Across TLS Records",
 357    "ECC Private Decode Error",
 358    "ECC Public Decode Error",
 359
 360    /* 86 */
 361    "Watch callback not set",
 362    "Watch hash failed",
 363    "Watch callback failed",
 364    "Bad Certificate Message",
 365    "Store data callback not set",
 366
 367    /* 91 */
 368    "No data destination Error",
 369    "Store data callback failed",
 370    "Loading chain input",
 371    "Got encrypted extension",
 372    "Got Hello Retry Request",
 373
 374    /* 96 */
 375    "Setting up keys",
 376    "Unsupported TLS Version",
 377    "Server Client Key Mismatch",
 378
 379    /* 99 */
 380    "Invalid or missing keylog file",
 381};
 382
 383
 384/* *nix version uses table above */
 385static void GetError(int idx, char* str)
 386{
 387    if (str == NULL ||
 388            idx <= 0 || idx > (int)(sizeof(msgTable)/sizeof(const char* const)))
 389        return;
 390    XSTRNCPY(str, msgTable[idx - 1], MAX_ERROR_LEN-1);
 391    str[MAX_ERROR_LEN-1] = '\0';
 392}
 393
 394
 395#else /* _WIN32 */
 396
 397
 398/* Windows version uses .rc table */
 399static void GetError(int idx, char* buffer)
 400{
 401    if (buffer == NULL)
 402        return;
 403    if (!LoadStringA(dllModule, idx, buffer, MAX_ERROR_LEN))
 404        buffer[0] = 0;
 405}
 406
 407
 408#endif /* _WIN32 */
 409
 410
 411/* Packet Buffer for reassembly list and ready list */
 412typedef struct PacketBuffer {
 413    word32  begin;      /* relative sequence begin */
 414    word32  end;        /* relative sequence end   */
 415    byte*   data;       /* actual data             */
 416    struct PacketBuffer* next; /* next on reassembly list or ready list */
 417} PacketBuffer;
 418
 419
 420#ifdef HAVE_SNI
 421
 422/* NamedKey maps a SNI name to a specific private key */
 423typedef struct NamedKey {
 424    char             name[MAX_SERVER_NAME];      /* server DNS name */
 425    word32           nameSz;                     /* size of server DNS name */
 426    byte*            key;                        /* DER private key */
 427    word32           keySz;                      /* size of DER private key */
 428    int              isEphemeralKey;
 429    struct NamedKey* next;                       /* for list */
 430} NamedKey;
 431
 432#endif
 433
 434/* Sniffer Server holds info for each server/port monitored */
 435typedef struct SnifferServer {
 436    WOLFSSL_CTX*   ctx;                          /* SSL context */
 437    char           address[MAX_SERVER_ADDRESS];  /* passed in server address */
 438    IpAddrInfo     server;                       /* network order address */
 439    int            port;                         /* server port */
 440#ifdef HAVE_SNI
 441    NamedKey*      namedKeys;                    /* mapping of names and keys */
 442    wolfSSL_Mutex  namedKeysMutex;               /* mutex for namedKey list */
 443#endif
 444#if defined(WOLFSSL_SNIFFER_KEYLOGFILE)
 445    byte           useKeyLogFile; /* True if session secrets are coming from a
 446                                     keylog file */
 447#endif /* WOLFSSL_SNIFFER_KEYLOGFILE */
 448
 449    struct SnifferServer* next;                  /* for list */
 450} SnifferServer;
 451
 452/* Session Flags */
 453typedef struct Flags {
 454    byte           side;            /* which end is current packet headed */
 455    byte           serverCipherOn;  /* indicates whether cipher is active */
 456    byte           clientCipherOn;  /* indicates whether cipher is active */
 457    byte           resuming;        /* did this session come from resumption */
 458    byte           clientHello;     /* processed client hello yet, for SSLv2 */
 459    byte           finCount;        /* get both FINs before removing */
 460    byte           fatalError;      /* fatal error state */
 461    byte           cliAckFault;     /* client acked unseen data from server */
 462    byte           srvAckFault;     /* server acked unseen data from client */
 463    byte           cliSkipPartial;  /* client skips partial data to catch up */
 464    byte           srvSkipPartial;  /* server skips partial data to catch up */
 465#ifdef HAVE_EXTENDED_MASTER
 466    byte           expectEms;       /* expect extended master secret */
 467#endif
 468    byte           gotFinished;     /* processed finished */
 469    byte           secRenegEn;      /* secure renegotiation enabled */
 470#ifdef WOLFSSL_ASYNC_CRYPT
 471    byte           wasPolled;
 472#endif
 473#ifdef SNIFFER_SINGLE_SESSION_CACHE
 474    byte           cached;          /* have we cached this session yet */
 475#endif
 476} Flags;
 477
 478
 479/* Out of Order FIN capture */
 480typedef struct FinCapture {
 481    word32 cliFinSeq;               /* client relative sequence FIN  0 is no */
 482    word32 srvFinSeq;               /* server relative sequence FIN, 0 is no */
 483    byte   cliCounted;              /* did we count yet, detects duplicates */
 484    byte   srvCounted;              /* did we count yet, detects duplicates */
 485} FinCapture;
 486
 487
 488typedef struct HsHashes {
 489#ifndef NO_OLD_TLS
 490#ifndef NO_SHA
 491    wc_Sha hashSha;
 492#endif
 493#ifndef NO_MD5
 494    wc_Md5 hashMd5;
 495#endif
 496#endif /* !NO_OLD_TLS */
 497#ifndef NO_SHA256
 498    wc_Sha256 hashSha256;
 499#endif
 500#ifdef WOLFSSL_SHA384
 501    wc_Sha384 hashSha384;
 502#endif
 503} HsHashes;
 504
 505typedef struct KeyShareInfo {
 506    word16      named_group;
 507    int         key_len;
 508    const byte* key;
 509
 510    /* additional info */
 511    int         dh_key_bits;
 512    int         curve_id;
 513} KeyShareInfo;
 514
 515/* Sniffer Session holds info for each client/server SSL/TLS session */
 516typedef struct SnifferSession {
 517    SnifferServer* context;         /* server context */
 518    WOLFSSL*       sslServer;       /* SSL server side decode */
 519    WOLFSSL*       sslClient;       /* SSL client side decode */
 520    IpAddrInfo     server;          /* server address in network byte order */
 521    IpAddrInfo     client;          /* client address in network byte order */
 522    word16         srvPort;         /* server port */
 523    word16         cliPort;         /* client port */
 524    word32         cliSeqStart;     /* client start sequence */
 525    word32         srvSeqStart;     /* server start sequence */
 526    word32         cliSeqLast;      /* client last sequence */
 527    word32         srvSeqLast;      /* server last sequence */
 528    word32         cliExpected;     /* client expected sequence (relative) */
 529    word32         srvExpected;     /* server expected sequence (relative) */
 530    FinCapture     finCapture;      /* retain out of order FIN s */
 531    Flags          flags;           /* session flags */
 532    time_t         lastUsed;        /* last used ticks */
 533    word32         keySz;           /* size of the private key */
 534    PacketBuffer*  cliReassemblyList; /* client out of order packets */
 535    PacketBuffer*  srvReassemblyList; /* server out of order packets */
 536    word32         cliReassemblyMemory; /* client packet memory used */
 537    word32         srvReassemblyMemory; /* server packet memory used */
 538    struct SnifferSession* next;    /* for hash table list */
 539    byte*          ticketID;        /* mac ID of session ticket */
 540#ifdef HAVE_MAX_FRAGMENT
 541    byte*          tlsFragBuf;
 542    word32         tlsFragOffset;
 543    word32         tlsFragSize;
 544#endif
 545#ifdef HAVE_SNI
 546    const char*    sni;             /* server name indication */
 547#endif
 548#ifdef HAVE_EXTENDED_MASTER
 549    HsHashes*      hash;
 550#endif
 551#ifdef WOLFSSL_TLS13
 552    byte*          cliKeyShare;
 553    word32         cliKeyShareSz;
 554    KeyShareInfo   srvKs;
 555    KeyShareInfo   cliKs;
 556#endif
 557#ifdef WOLFSSL_ASYNC_CRYPT
 558    void*          userCtx;
 559    word32         pendSeq; /* when WC_PENDING_E is returned capture sequence */
 560#endif
 561    int            error;   /* store the last set error number */
 562    byte           verboseErr; /* Last set error is helpful and should
 563                                *  not be overwritten by FATAL_ERROR_STATE */
 564} SnifferSession;
 565
 566
 567/* Sniffer Server List and mutex */
 568static THREAD_LS_T SnifferServer* ServerList = NULL;
 569#ifndef HAVE_C___ATOMIC
 570static WC_THREADSHARED wolfSSL_Mutex ServerListMutex WOLFSSL_MUTEX_INITIALIZER_CLAUSE(ServerListMutex);
 571#endif
 572
 573/* Session Hash Table, mutex, and count */
 574static THREAD_LS_T SnifferSession* SessionTable[HASH_SIZE];
 575#ifndef HAVE_C___ATOMIC
 576static WC_THREADSHARED wolfSSL_Mutex SessionMutex WOLFSSL_MUTEX_INITIALIZER_CLAUSE(SessionMutex);
 577#endif
 578static THREAD_LS_T int SessionCount = 0;
 579
 580static WC_THREADSHARED int RecoveryEnabled    = 0;  /* global switch */
 581static WC_THREADSHARED int MaxRecoveryMemory  = -1;
 582                                           /* per session max recovery memory */
 583#ifndef WOLFSSL_SNIFFER_NO_RECOVERY
 584/* Recovery of missed data switches and stats */
 585static WC_THREADSHARED wolfSSL_Mutex RecoveryMutex WOLFSSL_MUTEX_INITIALIZER_CLAUSE(RecoveryMutex); /* for stats */
 586/* # of sessions with missed data */
 587static WC_THREADSHARED word32 MissedDataSessions = 0;
 588#endif
 589
 590/* Connection Info Callback */
 591static WC_THREADSHARED SSLConnCb ConnectionCb;
 592static WC_THREADSHARED void*     ConnectionCbCtx = NULL;
 593
 594#ifdef WOLFSSL_SNIFFER_STATS
 595/* Sessions Statistics */
 596static WC_THREADSHARED SSLStats SnifferStats;
 597static WC_THREADSHARED wolfSSL_Mutex StatsMutex WOLFSSL_MUTEX_INITIALIZER_CLAUSE(StatsMutex);
 598#endif
 599
 600#ifdef WOLFSSL_SNIFFER_KEY_CALLBACK
 601static WC_THREADSHARED SSLKeyCb KeyCb;
 602static WC_THREADSHARED void*    KeyCbCtx = NULL;
 603#endif
 604
 605#ifdef WOLFSSL_SNIFFER_WATCH
 606/* Watch Key Callback */
 607static WC_THREADSHARED SSLWatchCb WatchCb;
 608static WC_THREADSHARED void*      WatchCbCtx = NULL;
 609#endif
 610
 611#ifdef WOLFSSL_SNIFFER_STORE_DATA_CB
 612/* Store Data Callback */
 613static WC_THREADSHARED SSLStoreDataCb StoreDataCb;
 614#endif
 615
 616
 617#ifndef WOLFSSL_SNIFFER_NO_RECOVERY
 618static void UpdateMissedDataSessions(void)
 619{
 620    wc_LockMutex(&RecoveryMutex);
 621    MissedDataSessions += 1;
 622    wc_UnLockMutex(&RecoveryMutex);
 623}
 624#endif
 625
 626#ifdef WOLFSSL_SNIFFER_STATS
 627    #ifdef HAVE_C___ATOMIC
 628        #define LOCK_STAT() WC_DO_NOTHING
 629        #define UNLOCK_STAT() WC_DO_NOTHING
 630        #define NOLOCK_ADD_TO_STAT(x,y) ({ TraceStat(#x, y); \
 631            __atomic_fetch_add(&x, y, __ATOMIC_RELAXED); })
 632    #else
 633        #define LOCK_STAT() wc_LockMutex(&StatsMutex)
 634        #define UNLOCK_STAT() wc_UnLockMutex(&StatsMutex)
 635        #define NOLOCK_ADD_TO_STAT(x,y) ({ TraceStat(#x, y); x += y; })
 636    #endif
 637    #define NOLOCK_INC_STAT(x) NOLOCK_ADD_TO_STAT(x,1)
 638    #define ADD_TO_STAT(x,y) do { LOCK_STAT(); \
 639        NOLOCK_ADD_TO_STAT(x,y); UNLOCK_STAT(); } while (0)
 640    #define INC_STAT(x) do { LOCK_STAT(); \
 641        NOLOCK_INC_STAT(x); UNLOCK_STAT(); } while (0)
 642#endif /* WOLFSSL_SNIFFER_STATS */
 643
 644#ifdef HAVE_C___ATOMIC
 645    #define LOCK_SESSION() WC_DO_NOTHING
 646    #define UNLOCK_SESSION() WC_DO_NOTHING
 647    #define LOCK_SERVER_LIST() WC_DO_NOTHING
 648    #define UNLOCK_SERVER_LIST() WC_DO_NOTHING
 649#else
 650    #define LOCK_SESSION() wc_LockMutex(&SessionMutex)
 651    #define UNLOCK_SESSION() wc_UnLockMutex(&SessionMutex)
 652    #define LOCK_SERVER_LIST() wc_LockMutex(&ServerListMutex)
 653    #define UNLOCK_SERVER_LIST() wc_UnLockMutex(&ServerListMutex)
 654#endif
 655
 656
 657#if defined(WOLF_CRYPTO_CB) || defined(WOLFSSL_ASYNC_CRYPT)
 658    static WC_THREADSHARED int CryptoDeviceId = INVALID_DEVID;
 659#endif
 660
 661#if defined(WOLFSSL_SNIFFER_KEYLOGFILE)
 662static int addSecretNode(unsigned char* clientRandom,
 663                         int type,
 664                         unsigned char* masterSecret,
 665                         char* error);
 666static void hexToBin(const char* hex, unsigned char* bin, int binLength);
 667static int parseKeyLogFile(const char* fileName, char* error);
 668static unsigned char* findSecret(unsigned char* clientRandom, int type);
 669static void freeSecretList(void);
 670static int snifferSecretCb(unsigned char* client_random,
 671                           int type,
 672                           unsigned char* output_secret);
 673static void setSnifferSecretCb(SnifferSession* session);
 674static int addKeyLogSnifferServerHelper(const char* address,
 675                                        int port,
 676                                        char* error);
 677#endif /* WOLFSSL_SNIFFER_KEYLOGFILE */
 678
 679
 680/* Initialize overall Sniffer */
 681void ssl_InitSniffer_ex(int devId)
 682{
 683    wolfSSL_Init();
 684#ifndef WOLFSSL_MUTEX_INITIALIZER
 685#ifndef HAVE_C___ATOMIC
 686    wc_InitMutex(&ServerListMutex);
 687    wc_InitMutex(&SessionMutex);
 688#endif
 689#ifndef WOLFSSL_SNIFFER_NO_RECOVERY
 690    wc_InitMutex(&RecoveryMutex);
 691#endif
 692#ifdef WOLFSSL_SNIFFER_STATS
 693    XMEMSET(&SnifferStats, 0, sizeof(SSLStats));
 694    wc_InitMutex(&StatsMutex);
 695#endif
 696#endif /* !WOLFSSL_MUTEX_INITIALIZER */
 697
 698#ifdef WOLFSSL_SNIFFER_STATS
 699    XMEMSET(&SnifferStats, 0, sizeof(SSLStats));
 700#endif
 701#if defined(WOLF_CRYPTO_CB) || defined(WOLFSSL_ASYNC_CRYPT)
 702    CryptoDeviceId = devId;
 703#endif
 704    (void)devId;
 705}
 706
 707static int GetDevId(void)
 708{
 709    int devId = INVALID_DEVID;
 710
 711#ifdef WOLF_CRYPTO_CB
 712    #ifdef HAVE_INTEL_QA_SYNC
 713    devId = wc_CryptoCb_InitIntelQa();
 714    if (devId == INVALID_DEVID) {
 715        fprintf(stderr, "Couldn't init the Intel QA\n");
 716    }
 717    #endif
 718    #ifdef HAVE_CAVIUM_OCTEON_SYNC
 719    devId = wc_CryptoCb_InitOcteon();
 720    if (devId == INVALID_DEVID) {
 721        fprintf(stderr, "Couldn't init the Octeon\n");
 722    }
 723    #endif
 724#endif
 725
 726    return devId;
 727}
 728
 729void ssl_InitSniffer(void)
 730{
 731    int devId = GetDevId();
 732
 733#ifdef WOLFSSL_ASYNC_CRYPT
 734    if (wolfAsync_DevOpen(&devId) < 0) {
 735        fprintf(stderr, "Async device open failed\nRunning without async\n");
 736        devId = INVALID_DEVID;
 737    }
 738#endif /* WOLFSSL_ASYNC_CRYPT */
 739
 740    (void)devId;
 741
 742    ssl_InitSniffer_ex(devId);
 743}
 744
 745void ssl_InitSniffer_ex2(int threadNum)
 746{
 747    int devId = GetDevId();
 748
 749#ifdef WOLFSSL_ASYNC_CRYPT
 750#ifndef WC_NO_ASYNC_THREADING
 751    if (wolfAsync_DevOpenThread(&devId, &threadNum) < 0)
 752#else
 753    if (wolfAsync_DevOpen(&devId) < 0)
 754#endif
 755    {
 756        fprintf(stderr, "Async device open failed\nRunning without async\n");
 757        devId = INVALID_DEVID;
 758    }
 759#endif /* WOLFSSL_ASYNC_CRYPT */
 760
 761    (void)devId;
 762    (void)threadNum;
 763
 764    ssl_InitSniffer_ex(devId);
 765}
 766
 767#ifdef HAVE_SNI
 768
 769/* Free Named Key and the zero out the private key it holds */
 770static void FreeNamedKey(NamedKey* in)
 771{
 772    if (in) {
 773        if (in->key) {
 774            ForceZero(in->key, in->keySz);
 775            XFREE(in->key, NULL, DYNAMIC_TYPE_X509);
 776        }
 777        XFREE(in, NULL, DYNAMIC_TYPE_SNIFFER_NAMED_KEY);
 778    }
 779}
 780
 781
 782static void FreeNamedKeyList(NamedKey* in)
 783{
 784    NamedKey* next;
 785
 786    while (in) {
 787        next = in->next;
 788        FreeNamedKey(in);
 789        in = next;
 790    }
 791}
 792
 793#endif
 794
 795
 796/* Free Sniffer Server's resources/self */
 797static void FreeSnifferServer(SnifferServer* srv)
 798{
 799    if (srv) {
 800#ifdef HAVE_SNI
 801        wc_LockMutex(&srv->namedKeysMutex);
 802        FreeNamedKeyList(srv->namedKeys);
 803        wc_UnLockMutex(&srv->namedKeysMutex);
 804        wc_FreeMutex(&srv->namedKeysMutex);
 805#endif
 806        wolfSSL_CTX_free(srv->ctx);
 807    }
 808    XFREE(srv, NULL, DYNAMIC_TYPE_SNIFFER_SERVER);
 809}
 810
 811
 812/* free PacketBuffer's resources/self */
 813static void FreePacketBuffer(PacketBuffer* del)
 814{
 815    if (del) {
 816        XFREE(del->data, NULL, DYNAMIC_TYPE_SNIFFER_PB_BUFFER);
 817        XFREE(del, NULL, DYNAMIC_TYPE_SNIFFER_PB);
 818    }
 819}
 820
 821
 822/* remove PacketBuffer List */
 823static void FreePacketList(PacketBuffer* in)
 824{
 825    if (in) {
 826        PacketBuffer* del;
 827        PacketBuffer* packet = in;
 828
 829        while (packet) {
 830            del = packet;
 831            packet = packet->next;
 832            FreePacketBuffer(del);
 833        }
 834    }
 835}
 836
 837
 838/* Free Sniffer Session's resources/self */
 839static void FreeSnifferSession(SnifferSession* session)
 840{
 841    if (session) {
 842        wolfSSL_free(session->sslClient);
 843        wolfSSL_free(session->sslServer);
 844
 845        FreePacketList(session->cliReassemblyList);
 846        FreePacketList(session->srvReassemblyList);
 847
 848        XFREE(session->ticketID, NULL, DYNAMIC_TYPE_SNIFFER_TICKET_ID);
 849#ifdef HAVE_EXTENDED_MASTER
 850        XFREE(session->hash, NULL, DYNAMIC_TYPE_HASHES);
 851#endif
 852#ifdef WOLFSSL_TLS13
 853        XFREE(session->cliKeyShare, NULL, DYNAMIC_TYPE_TMP_BUFFER);
 854#endif
 855#ifdef HAVE_MAX_FRAGMENT
 856        XFREE(session->tlsFragBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
 857        session->tlsFragBuf = NULL;
 858#endif
 859    }
 860    XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION);
 861}
 862
 863
 864/* Free overall Sniffer */
 865void ssl_FreeSniffer(void)
 866{
 867    SnifferServer*  srv;
 868    SnifferServer*  removeServer;
 869    SnifferSession* session;
 870    SnifferSession* removeSession;
 871    int i;
 872
 873    LOCK_SERVER_LIST();
 874    LOCK_SESSION();
 875
 876    /* Free sessions (wolfSSL objects) first */
 877    for (i = 0; i < HASH_SIZE; i++) {
 878        session = SessionTable[i];
 879        while (session) {
 880            removeSession = session;
 881            session = session->next;
 882            FreeSnifferSession(removeSession);
 883        }
 884    }
 885    XMEMSET(SessionTable, 0, sizeof(SessionTable));
 886    SessionCount = 0;
 887
 888    /* Then server (wolfSSL_CTX) */
 889    srv = ServerList;
 890    while (srv) {
 891        removeServer = srv;
 892        srv = srv->next;
 893        FreeSnifferServer(removeServer);
 894    }
 895    ServerList = NULL;
 896
 897
 898
 899    UNLOCK_SESSION();
 900    UNLOCK_SERVER_LIST();
 901
 902#if defined(WOLFSSL_SNIFFER_KEYLOGFILE)
 903    freeSecretList();
 904#endif /* WOLFSSL_SNIFFER_KEYLOGFILE */
 905
 906
 907#ifndef WOLFSSL_MUTEX_INITIALIZER
 908#ifndef WOLFSSL_SNIFFER_NO_RECOVERY
 909    wc_FreeMutex(&RecoveryMutex);
 910#endif
 911#ifndef HAVE_C___ATOMIC
 912    wc_FreeMutex(&SessionMutex);
 913    wc_FreeMutex(&ServerListMutex);
 914#endif
 915#endif /* !WOLFSSL_MUTEX_INITIALIZER */
 916
 917#ifdef WOLF_CRYPTO_CB
 918    #ifdef HAVE_INTEL_QA_SYNC
 919    wc_CryptoCb_CleanupIntelQa(&CryptoDeviceId);
 920    #endif
 921    #ifdef HAVE_CAVIUM_OCTEON_SYNC
 922    wc_CryptoCb_CleanupOcteon(&CryptoDeviceId);
 923    #endif
 924#endif
 925#ifdef WOLFSSL_ASYNC_CRYPT
 926    wolfAsync_DevClose(&CryptoDeviceId);
 927#endif
 928
 929    if (TraceFile) {
 930        TraceOn = 0;
 931        XFCLOSE(TraceFile);
 932        TraceFile = NULL;
 933    }
 934
 935    wolfSSL_Cleanup();
 936}
 937
 938
 939#ifdef HAVE_EXTENDED_MASTER
 940
 941static int HashInit(HsHashes* hash)
 942{
 943    int ret = 0;
 944
 945    XMEMSET(hash, 0, sizeof(HsHashes));
 946
 947#ifndef NO_OLD_TLS
 948#ifndef NO_SHA
 949    if (ret == 0)
 950        ret = wc_InitSha(&hash->hashSha);
 951#endif
 952#ifndef NO_MD5
 953    if (ret == 0)
 954        ret = wc_InitMd5(&hash->hashMd5);
 955#endif
 956#endif /* !NO_OLD_TLS */
 957#ifndef NO_SHA256
 958    if (ret == 0)
 959        ret = wc_InitSha256(&hash->hashSha256);
 960#endif
 961#ifdef WOLFSSL_SHA384
 962    if (ret == 0)
 963        ret = wc_InitSha384(&hash->hashSha384);
 964#endif
 965
 966    return ret;
 967}
 968
 969static int HashUpdate(HsHashes* hash, const byte* input, int sz)
 970{
 971    int ret = 0;
 972
 973    input -= HANDSHAKE_HEADER_SZ;
 974    sz += HANDSHAKE_HEADER_SZ;
 975
 976#ifndef NO_OLD_TLS
 977#ifndef NO_SHA
 978    if (ret == 0)
 979        ret = wc_ShaUpdate(&hash->hashSha, input, sz);
 980#endif
 981#ifndef NO_MD5
 982    if (ret == 0)
 983        ret = wc_Md5Update(&hash->hashMd5, input, sz);
 984#endif
 985#endif /* !NO_OLD_TLS */
 986#ifndef NO_SHA256
 987    if (ret == 0)
 988        ret = wc_Sha256Update(&hash->hashSha256, input, sz);
 989#endif
 990#ifdef WOLFSSL_SHA384
 991    if (ret == 0)
 992        ret = wc_Sha384Update(&hash->hashSha384, input, sz);
 993#endif
 994
 995    return ret;
 996}
 997
 998static int HashCopy(HS_Hashes* d, HsHashes* s)
 999{
1000#ifndef NO_OLD_TLS
1001#ifndef NO_SHA
1002    XMEMCPY(&d->hashSha, &s->hashSha, sizeof(wc_Sha));
1003#endif
1004#ifndef NO_MD5
1005    XMEMCPY(&d->hashMd5, &s->hashMd5, sizeof(wc_Md5));
1006#endif
1007#endif /* !NO_OLD_TLS */
1008#ifndef NO_SHA256
1009    XMEMCPY(&d->hashSha256, &s->hashSha256, sizeof(wc_Sha256));
1010#endif
1011#ifdef WOLFSSL_SHA384
1012    XMEMCPY(&d->hashSha384, &s->hashSha384, sizeof(wc_Sha384));
1013#endif
1014
1015    return 0;
1016}
1017
1018#endif
1019
1020
1021/* Initialize a SnifferServer */
1022static void InitSnifferServer(SnifferServer* sniffer)
1023{
1024    XMEMSET(sniffer, 0, sizeof(SnifferServer));
1025}
1026
1027
1028/* Initialize session flags */
1029static void InitFlags(Flags* flags)
1030{
1031    XMEMSET(flags, 0, sizeof(Flags));
1032}
1033
1034
1035/* Initialize FIN Capture */
1036static void InitFinCapture(FinCapture* cap)
1037{
1038    XMEMSET(cap, 0, sizeof(FinCapture));
1039}
1040
1041
1042/* Initialize a Sniffer Session */
1043static void InitSession(SnifferSession* session)
1044{
1045    XMEMSET(session, 0, sizeof(SnifferSession));
1046    InitFlags(&session->flags);
1047    InitFinCapture(&session->finCapture);
1048}
1049
1050
1051/* IP Info from IP Header */
1052typedef struct IpInfo {
1053    int    length;        /* length of this header */
1054    int    total;         /* total length of fragment */
1055    IpAddrInfo src;       /* network order source address */
1056    IpAddrInfo dst;       /* network order destination address */
1057} IpInfo;
1058
1059
1060/* TCP Info from TCP Header */
1061typedef struct TcpInfo {
1062    int    srcPort;       /* source port */
1063    int    dstPort;       /* destination port */
1064    int    length;        /* length of this header */
1065    word32 sequence;      /* sequence number */
1066    word32 ackNumber;     /* ack number */
1067    byte   fin;           /* FIN set */
1068    byte   rst;           /* RST set */
1069    byte   syn;           /* SYN set */
1070    byte   ack;           /* ACK set */
1071} TcpInfo;
1072
1073
1074/* Tcp Pseudo Header for Checksum calculation */
1075typedef struct TcpPseudoHdr {
1076    word32  src;        /* source address */
1077    word32  dst;        /* destination address */
1078    byte    rsv;        /* reserved, always 0 */
1079    byte    protocol;   /* IP protocol */
1080    word16  length;     /* tcp header length + data length (doesn't include */
1081                        /* pseudo header length) network order */
1082} TcpPseudoHdr;
1083
1084
1085#ifdef WOLFSSL_ENCRYPTED_KEYS
1086/* Password Setting Callback */
1087static int SetPassword(char* passwd, int sz, int rw, void* userdata)
1088{
1089    (void)rw;
1090    XSTRNCPY(passwd, (const char*)userdata, sz);
1091    return (int)XSTRLEN((const char*)userdata);
1092}
1093#endif
1094
1095/* Ethernet Header */
1096typedef struct EthernetHdr {
1097    byte   dst[ETHER_IF_ADDR_LEN];    /* destination host address */
1098    byte   src[ETHER_IF_ADDR_LEN];    /* source  host address */
1099    word16 type;                      /* IP, ARP, etc */
1100} EthernetHdr;
1101
1102
1103/* IPv4 Header */
1104typedef struct IpHdr {
1105    byte    ver_hl;              /* version/header length */
1106    byte    tos;                 /* type of service */
1107    word16  length;              /* total length */
1108    word16  id;                  /* identification */
1109    word16  offset;              /* fragment offset field */
1110    byte    ttl;                 /* time to live */
1111    byte    protocol;            /* protocol */
1112    word16  sum;                 /* checksum */
1113    word32  src;                 /* source address */
1114    word32  dst;                 /* destination address */
1115} IpHdr;
1116
1117
1118/* IPv6 Header */
1119typedef struct Ip6Hdr {
1120    byte    ver_hl;              /* version/traffic class high */
1121    byte    tc_fl;               /* traffic class low/flow label high */
1122    word16  fl;                  /* flow label low */
1123    word16  length;              /* payload length */
1124    byte    next_header;         /* next header (6 for TCP, any other skip) */
1125    byte    hl;                  /* hop limit */
1126    byte    src[16];             /* source address */
1127    byte    dst[16];             /* destination address */
1128} Ip6Hdr;
1129
1130
1131/* IPv6 extension header */
1132typedef struct Ip6ExtHdr {
1133    byte next_header;            /* next header (6 for TCP, any other skip) */
1134    byte length;                 /* length in 8-octet units - 1 */
1135    byte reserved[6];
1136} Ip6ExtHdr;
1137
1138
1139#define IP_HL(ip)      ( (((ip)->ver_hl) & 0x0f) * 4)
1140#define IP_V(ip)       ( ((ip)->ver_hl) >> 4)
1141
1142/* TCP Header */
1143typedef struct TcpHdr {
1144    word16  srcPort;            /* source port */
1145    word16  dstPort;            /* destination port */
1146    word32  sequence;           /* sequence number */
1147    word32  ack;                /* acknowledgment number */
1148    byte    offset;             /* data offset, reserved */
1149    byte    flags;              /* option flags */
1150    word16  window;             /* window */
1151    word16  sum;                /* checksum */
1152    word16  urgent;             /* urgent pointer */
1153} TcpHdr;
1154
1155#define TCP_LEN(tcp)  ( (((tcp)->offset & 0xf0) >> 4) * 4)
1156#define TCP_FIN 0x01
1157#define TCP_SYN 0x02
1158#define TCP_RST 0x04
1159#define TCP_ACK 0x10
1160
1161
1162
1163
1164
1165/* Use platform specific GetError to write to trace file if tracing */
1166static void TraceError(int idx, char* error)
1167{
1168    if (TraceOn) {
1169        char myBuffer[MAX_ERROR_LEN];
1170        if (error == NULL) {
1171            error = myBuffer;
1172            GetError(idx, myBuffer);
1173        }
1174        XFPRINTF(TraceFile, "\t%s\n", error);
1175#ifdef DEBUG_SNIFFER
1176        XFPRINTF(stderr,    "\t%s\n", error);
1177#endif
1178    }
1179}
1180
1181static void Trace(int idx)
1182{
1183    TraceError(idx, NULL);
1184}
1185
1186
1187/* Show TimeStamp for beginning of packet Trace */
1188static void TraceHeader(void)
1189{
1190    if (TraceOn) {
1191        time_t ticks = wc_Time(NULL);
1192        XFPRINTF(TraceFile, "\n%s", XCTIME(&ticks));
1193    }
1194}
1195
1196
1197/* Show Set Server info for Trace */
1198static void TraceSetServer(const char* srv, int port, const char* keyFile)
1199{
1200    if (TraceOn) {
1201        XFPRINTF(TraceFile, "\tTrying to install a new Sniffer Server with\n");
1202        if (keyFile != NULL) {
1203            XFPRINTF(TraceFile, "\tserver: %s, port: %d, keyFile: %s\n",
1204                     srv, port, keyFile);
1205        }
1206        else {
1207            XFPRINTF(TraceFile, "\tserver: %s, port: %d\n",
1208                     srv, port);
1209        }
1210    }
1211}
1212
1213
1214#ifdef HAVE_SNI
1215
1216/* Show Set Named Server info for Trace */
1217static void TraceSetNamedServer(const char* name,
1218                                 const char* srv, int port, const char* keyFile)
1219{
1220    if (TraceOn) {
1221        XFPRINTF(TraceFile, "\tTrying to install a new Sniffer Server with\n");
1222        XFPRINTF(TraceFile, "\tname: %s, server: %s, port: %d, keyFile: %s\n",
1223        name ? name : "",
1224        srv ? srv : "",
1225        port,
1226        keyFile ? keyFile : "");
1227    }
1228}
1229
1230#endif
1231
1232
1233/* Trace got packet number */
1234static void TracePacket(void)
1235{
1236    if (TraceOn) {
1237        static word32 packetNumber = 0;
1238        XFPRINTF(TraceFile, "\tGot a Packet to decode, packet %u\n",
1239                ++packetNumber);
1240    }
1241}
1242
1243
1244/* Convert network byte order address into human readable */
1245static const char* IpToS(int version, void* src, char* dst)
1246{
1247    return XINET_NTOP(version, src, dst, TRACE_MSG_SZ);
1248}
1249
1250
1251/* Show destination and source address from Ip Hdr for packet Trace */
1252static void TraceIP(IpHdr* iphdr)
1253{
1254    if (TraceOn) {
1255        char src[TRACE_MSG_SZ];
1256        char dst[TRACE_MSG_SZ];
1257        XFPRINTF(TraceFile, "\tdst:%s src:%s\n",
1258                IpToS(AF_INET, &iphdr->dst, dst),
1259                IpToS(AF_INET, &iphdr->src, src));
1260    }
1261}
1262
1263
1264/* Show destination and source address from Ip6Hdr for packet Trace */
1265static void TraceIP6(Ip6Hdr* iphdr)
1266{
1267    if (TraceOn) {
1268        char src[TRACE_MSG_SZ];
1269        char dst[TRACE_MSG_SZ];
1270        XFPRINTF(TraceFile, "\tdst: %s src: %s\n",
1271                IpToS(AF_INET6, iphdr->dst, dst),
1272                IpToS(AF_INET6, iphdr->src, src));
1273    }
1274}
1275
1276
1277/* Show destination and source port from Tcp Hdr for packet Trace */
1278static void TraceTcp(TcpHdr* tcphdr)
1279{
1280    if (TraceOn) {
1281        XFPRINTF(TraceFile, "\tdstPort:%u srcPort:%u\n", XNTOHS(tcphdr->dstPort),
1282                XNTOHS(tcphdr->srcPort));
1283    }
1284}
1285
1286
1287/* Show sequence and payload length for Trace */
1288static void TraceSequence(word32 seq, int len)
1289{
1290    if (TraceOn) {
1291        XFPRINTF(TraceFile, "\tSequence:%u, payload length:%d\n", seq, len);
1292    }
1293}
1294
1295
1296/* Show sequence and payload length for Trace */
1297static void TraceAck(word32 acknowledgement, word32 expected)
1298{
1299    if (TraceOn) {
1300        XFPRINTF(TraceFile, "\tAck:%u Expected:%u\n", acknowledgement,
1301                 expected);
1302    }
1303}
1304
1305
1306/* Show relative expected and relative received sequences */
1307static void TraceRelativeSequence(word32 expected, word32 got)
1308{
1309    if (TraceOn) {
1310        XFPRINTF(TraceFile, "\tExpected sequence:%u, received sequence:%u\n",
1311                expected, got);
1312    }
1313}
1314
1315
1316/* Show server sequence startup from SYN */
1317static void TraceServerSyn(word32 seq)
1318{
1319    if (TraceOn) {
1320        XFPRINTF(TraceFile, "\tServer SYN, Sequence Start:%u\n", seq);
1321    }
1322}
1323
1324
1325/* Show client sequence startup from SYN */
1326static void TraceClientSyn(word32 seq)
1327{
1328    if (TraceOn) {
1329        XFPRINTF(TraceFile, "\tClient SYN, Sequence Start:%u\n", seq);
1330    }
1331}
1332
1333
1334/* Show client FIN capture */
1335static void TraceClientFin(word32 finSeq, word32 relSeq)
1336{
1337    if (TraceOn) {
1338        XFPRINTF(TraceFile, "\tClient FIN capture:%u, current SEQ:%u\n",
1339                finSeq, relSeq);
1340    }
1341}
1342
1343
1344/* Show server FIN capture */
1345static void TraceServerFin(word32 finSeq, word32 relSeq)
1346{
1347    if (TraceOn) {
1348        XFPRINTF(TraceFile, "\tServer FIN capture:%u, current SEQ:%u\n",
1349                finSeq, relSeq);
1350    }
1351}
1352
1353
1354/* Show number of SSL data bytes decoded, could be 0 (ok) */
1355static void TraceGotData(int bytes)
1356{
1357    if (TraceOn) {
1358        XFPRINTF(TraceFile, "\t%d bytes of SSL App data processed\n", bytes);
1359    }
1360}
1361
1362
1363/* Show bytes added to old SSL App data */
1364static void TraceAddedData(int newBytes, int existingBytes)
1365{
1366    if (TraceOn) {
1367        XFPRINTF(TraceFile,
1368                "\t%d bytes added to %d existing bytes in User Buffer\n",
1369                newBytes, existingBytes);
1370    }
1371}
1372
1373
1374/* Show Stale Session */
1375static void TraceStaleSession(void)
1376{
1377    if (TraceOn) {
1378        XFPRINTF(TraceFile, "\tFound a stale session\n");
1379    }
1380}
1381
1382
1383/* Show Finding Stale Sessions */
1384static void TraceFindingStale(void)
1385{
1386    if (TraceOn) {
1387        XFPRINTF(TraceFile, "\tTrying to find Stale Sessions\n");
1388    }
1389}
1390
1391
1392/* Show Removed Session */
1393static void TraceRemovedSession(void)
1394{
1395    if (TraceOn) {
1396        XFPRINTF(TraceFile, "\tRemoved it\n");
1397    }
1398}
1399
1400
1401/* Show SSLInfo if provided and is valid. */
1402static void TraceSessionInfo(SSLInfo* sslInfo)
1403{
1404    if (TraceOn) {
1405        if (sslInfo != NULL && sslInfo->isValid) {
1406            XFPRINTF(TraceFile,
1407                    "\tver:(%u %u) suiteId:(%02x %02x) suiteName:(%s) "
1408                    #ifdef HAVE_SNI
1409                    "sni:(%s) "
1410                    #endif
1411                    "keySize:(%u)\n",
1412                    sslInfo->protocolVersionMajor,
1413                    sslInfo->protocolVersionMinor,
1414                    sslInfo->serverCipherSuite0,
1415                    sslInfo->serverCipherSuite,
1416                    sslInfo->serverCipherSuiteName,
1417                    #ifdef HAVE_SNI
1418                    sslInfo->serverNameIndication,
1419                    #endif
1420                    sslInfo->keySize);
1421        }
1422    }
1423}
1424
1425
1426#ifdef WOLFSSL_SNIFFER_STATS
1427
1428/* Show value added to a named statistic. */
1429static void TraceStat(const char* name, int add)
1430{
1431    if (TraceOn) {
1432        XFPRINTF(TraceFile, "\tAdding %d to %s\n", add, name);
1433    }
1434}
1435
1436#endif
1437
1438
1439/* Set user error string */
1440static void SetError(int idx, char* error, SnifferSession* session, int fatal)
1441{
1442    GetError(idx, error);
1443    TraceError(idx, error);
1444    if (session)
1445        session->error = idx;
1446    if (session && fatal == FATAL_ERROR_STATE)
1447        session->flags.fatalError = 1;
1448}
1449
1450
1451/* Compare IpAddrInfo structs */
1452static WC_INLINE int MatchAddr(IpAddrInfo l, IpAddrInfo r)
1453{
1454    if (l.version == r.version) {
1455        if (l.version == IPV4)
1456            return (l.ip4 == r.ip4);
1457        else if (l.version == IPV6)
1458            return (0 == XMEMCMP(l.ip6, r.ip6, sizeof(l.ip6)));
1459    }
1460    return 0;
1461}
1462
1463
1464#ifndef WOLFSSL_SNIFFER_WATCH
1465
1466/* See if this IPV4 network order address has been registered */
1467/* return 1 is true, 0 is false */
1468static int IsServerRegistered(word32 addr)
1469{
1470    int ret = 0;     /* false */
1471    SnifferServer* sniffer;
1472
1473    LOCK_SERVER_LIST();
1474
1475    sniffer = ServerList;
1476    while (sniffer) {
1477        if (sniffer->server.ip4 == addr) {
1478            ret = 1;
1479            break;
1480        }
1481        sniffer = sniffer->next;
1482    }
1483
1484    UNLOCK_SERVER_LIST();
1485
1486    return ret;
1487}
1488
1489
1490/* See if this port has been registered to watch */
1491/* See if this IPV4 network order address has been registered */
1492/* return 1 is true, 0 is false */
1493static int IsServerRegistered6(byte* addr)
1494{
1495    int ret = 0;     /* false */
1496    SnifferServer* sniffer;
1497
1498    LOCK_SERVER_LIST();
1499
1500    sniffer = ServerList;
1501    while (sniffer) {
1502        if (sniffer->server.version == IPV6 &&
1503                0 == XMEMCMP(sniffer->server.ip6, addr, sizeof(sniffer->server.ip6))) {
1504            ret = 1;
1505            break;
1506        }
1507        sniffer = sniffer->next;
1508    }
1509
1510    UNLOCK_SERVER_LIST();
1511
1512    return ret;
1513}
1514
1515
1516/* See if this port has been registered to watch */
1517/* return 1 is true, 0 is false */
1518static int IsPortRegistered(word32 port)
1519{
1520    int ret = 0;    /* false */
1521    SnifferServer* sniffer;
1522
1523    LOCK_SERVER_LIST();
1524
1525    sniffer = ServerList;
1526    while (sniffer) {
1527        if (sniffer->port == (int)port) {
1528            ret = 1;
1529            break;
1530        }
1531        sniffer = sniffer->next;
1532    }
1533
1534    UNLOCK_SERVER_LIST();
1535
1536    return ret;
1537}
1538
1539#endif
1540
1541
1542/* Get SnifferServer from IP and Port */
1543static SnifferServer* GetSnifferServer(IpInfo* ipInfo, TcpInfo* tcpInfo)
1544{
1545    SnifferServer* sniffer;
1546
1547    LOCK_SERVER_LIST();
1548
1549    sniffer = ServerList;
1550
1551#ifndef WOLFSSL_SNIFFER_WATCH
1552    while (sniffer) {
1553        if (sniffer->port == tcpInfo->srcPort &&
1554                MatchAddr(sniffer->server, ipInfo->src))
1555            break;
1556        if (sniffer->port == tcpInfo->dstPort &&
1557                MatchAddr(sniffer->server, ipInfo->dst))
1558            break;
1559
1560        if (sniffer->next)
1561            sniffer = sniffer->next;
1562        else
1563           break;
1564    }
1565#else
1566    (void)ipInfo;
1567    (void)tcpInfo;
1568#endif
1569
1570    UNLOCK_SERVER_LIST();
1571
1572    return sniffer;
1573}
1574
1575
1576/* Hash the Session Info, return hash row */
1577static word32 SessionHash(IpInfo* ipInfo, TcpInfo* tcpInfo)
1578{
1579    word32 hash = 1;
1580
1581    if (ipInfo->src.version == IPV4) {
1582        hash *= ipInfo->src.ip4 * ipInfo->dst.ip4;
1583    }
1584    else if (ipInfo->src.version == IPV6) {
1585        word32* x;
1586        word32  y;
1587        x = (word32*)ipInfo->src.ip6;
1588        y = x[0] ^ x[1] ^ x[2] ^ x[3];
1589        hash *= y;
1590        x = (word32*)ipInfo->dst.ip6;
1591        y = x[0] ^ x[1] ^ x[2] ^ x[3];
1592        hash *= y;
1593    }
1594    hash *= tcpInfo->srcPort * tcpInfo->dstPort;
1595
1596    return hash % HASH_SIZE;
1597}
1598
1599
1600/* Get Existing SnifferSession from IP and Port */
1601static SnifferSession* GetSnifferSession(IpInfo* ipInfo, TcpInfo* tcpInfo)
1602{
1603    SnifferSession* session;
1604    time_t          currTime = wc_Time(NULL);
1605    word32          row = SessionHash(ipInfo, tcpInfo);
1606
1607    LOCK_SESSION();
1608    session = SessionTable[row];
1609    while (session) {
1610        if (MatchAddr(session->server, ipInfo->src) &&
1611            MatchAddr(session->client, ipInfo->dst) &&
1612                    session->srvPort == tcpInfo->srcPort &&
1613                    session->cliPort == tcpInfo->dstPort)
1614            break;
1615
1616        if (MatchAddr(session->client, ipInfo->src) &&
1617            MatchAddr(session->server, ipInfo->dst) &&
1618                    session->cliPort == tcpInfo->srcPort &&
1619                    session->srvPort == tcpInfo->dstPort)
1620            break;
1621
1622        session = session->next;
1623    }
1624
1625    if (session)
1626        session->lastUsed= currTime; /* keep session alive, remove stale will */
1627                                     /* leave alone */
1628    UNLOCK_SESSION();
1629
1630    /* determine side */
1631    if (session) {
1632        if (MatchAddr(ipInfo->dst, session->server) &&
1633            tcpInfo->dstPort == session->srvPort) {
1634
1635            session->flags.side = WOLFSSL_SERVER_END;
1636        }
1637        else {
1638            session->flags.side = WOLFSSL_CLIENT_END;
1639        }
1640    }
1641
1642    return session;
1643}
1644
1645
1646#if defined(HAVE_SNI) || defined(WOLFSSL_SNIFFER_WATCH)
1647
1648static int LoadKeyFile(byte** keyBuf, word32* keyBufSz,
1649                const char* keyFile, int keySz, int typeKey,
1650                const char* password)
1651{
1652    byte* loadBuf;
1653    long fileSz = 0;
1654    XFILE file;
1655    int ret = -1;
1656
1657    if (keyBuf == NULL || keyBufSz == NULL || keyFile == NULL) {
1658        return WOLFSSL_FATAL_ERROR;
1659    }
1660
1661    if (keySz == 0) {
1662        /* load from file */
1663        file = XFOPEN(keyFile, "rb");
1664        if (file == XBADFILE) return WOLFSSL_FATAL_ERROR;
1665        if(XFSEEK(file, 0, XSEEK_END) != 0) {
1666            XFCLOSE(file);
1667            return WOLFSSL_FATAL_ERROR;
1668        }
1669        fileSz = XFTELL(file);
1670        if (fileSz > MAX_WOLFSSL_FILE_SIZE || fileSz < 0) {
1671            XFCLOSE(file);
1672            return WOLFSSL_FATAL_ERROR;
1673        }
1674        if(XFSEEK(file, 0, XSEEK_SET) != 0) {
1675            XFCLOSE(file);
1676            return WOLFSSL_FATAL_ERROR;
1677        }
1678
1679        loadBuf = (byte*)XMALLOC(fileSz, NULL, DYNAMIC_TYPE_FILE);
1680        if (loadBuf == NULL) {
1681            XFCLOSE(file);
1682            return WOLFSSL_FATAL_ERROR;
1683        }
1684
1685        ret = (int)XFREAD(loadBuf, 1, fileSz, file);
1686        XFCLOSE(file);
1687
1688        if (ret != fileSz) {
1689            XFREE(loadBuf, NULL, DYNAMIC_TYPE_FILE);
1690            return WOLFSSL_FATAL_ERROR;
1691        }
1692    }
1693    else {
1694        /* use buffer directly */
1695        loadBuf = (byte*)XMALLOC(keySz, NULL, DYNAMIC_TYPE_FILE);
1696        if (loadBuf == NULL) {
1697            return WOLFSSL_FATAL_ERROR;
1698        }
1699        fileSz = keySz;
1700        XMEMCPY(loadBuf, keyFile, fileSz);
1701    }
1702
1703    if (typeKey == WOLFSSL_FILETYPE_PEM) {
1704        byte* saveBuf   = (byte*)XMALLOC(fileSz, NULL, DYNAMIC_TYPE_X509);
1705        int   saveBufSz = 0;
1706
1707        ret = -1;
1708        if (saveBuf != NULL) {
1709            saveBufSz = wc_KeyPemToDer(loadBuf, (int)fileSz,
1710                                                saveBuf, (int)fileSz, password);
1711            if (saveBufSz < 0) {
1712                saveBufSz = 0;
1713                XFREE(saveBuf, NULL, DYNAMIC_TYPE_X509);
1714                saveBuf = NULL;
1715            }
1716            else
1717                ret = 0;
1718        }
1719
1720        ForceZero(loadBuf, (word32)fileSz);
1721        XFREE(loadBuf, NULL, DYNAMIC_TYPE_FILE);
1722
1723        if (saveBuf) {
1724            *keyBuf = saveBuf;
1725            *keyBufSz = (word32)saveBufSz;
1726        }
1727    }
1728    else {
1729        *keyBuf = loadBuf;
1730        *keyBufSz = (word32)fileSz;
1731    }
1732
1733    if (ret < 0) {
1734        return WOLFSSL_FATAL_ERROR;
1735    }
1736
1737    return ret;
1738}
1739
1740#endif
1741
1742
1743#ifdef WOLFSSL_SNIFFER_WATCH
1744
1745static int CreateWatchSnifferServer(char* error)
1746{
1747    SnifferServer* sniffer;
1748
1749    sniffer = (SnifferServer*)XMALLOC(sizeof(SnifferServer), NULL,
1750            DYNAMIC_TYPE_SNIFFER_SERVER);
1751    if (sniffer == NULL) {
1752        SetError(MEMORY_STR, error, NULL, 0);
1753        return WOLFSSL_FATAL_ERROR;
1754    }
1755    InitSnifferServer(sniffer);
1756    sniffer->ctx = wolfSSL_CTX_new(wolfSSLv23_client_method());
1757    if (!sniffer->ctx) {
1758        SetError(MEMORY_STR, error, NULL, 0);
1759        FreeSnifferServer(sniffer);
1760        return WOLFSSL_FATAL_ERROR;
1761    }
1762#if defined(WOLF_CRYPTO_CB) || defined(WOLFSSL_ASYNC_CRYPT)
1763    if (CryptoDeviceId != INVALID_DEVID)
1764        wolfSSL_CTX_SetDevId(sniffer->ctx, CryptoDeviceId);
1765#endif
1766
1767    /* add to server list */
1768    LOCK_SERVER_LIST();
1769    sniffer->next = ServerList;
1770    ServerList = sniffer;
1771    UNLOCK_SERVER_LIST();
1772
1773    return 0;
1774}
1775
1776#endif
1777
1778
1779/* Caller locks ServerListMutex */
1780static int SetNamedPrivateKey(const char* name, const char* address, int port,
1781    const char* keyFile, int keySz, int typeKey, const char* password,
1782    char* error, int isEphemeralKey)
1783{
1784    SnifferServer* sniffer;
1785    int            ret;
1786    int            type = (typeKey == FILETYPE_PEM) ? WOLFSSL_FILETYPE_PEM :
1787                                                      WOLFSSL_FILETYPE_ASN1;
1788    int            isNew = 0;
1789    IpAddrInfo     serverIp;
1790
1791#ifdef HAVE_SNI
1792    NamedKey* namedKey = NULL;
1793#endif
1794
1795    (void)name;
1796#ifdef HAVE_SNI
1797    if (name != NULL) {
1798        namedKey = (NamedKey*)XMALLOC(sizeof(NamedKey),
1799                NULL, DYNAMIC_TYPE_SNIFFER_NAMED_KEY);
1800        if (namedKey == NULL) {
1801            SetError(MEMORY_STR, error, NULL, 0);
1802            return WOLFSSL_FATAL_ERROR;
1803        }
1804        XMEMSET(namedKey, 0, sizeof(NamedKey));
1805
1806        namedKey->nameSz = (word32)XSTRLEN(name);
1807        if (namedKey->nameSz > sizeof(namedKey->name)-1)
1808            namedKey->nameSz = sizeof(namedKey->name)-1;
1809        XSTRNCPY(namedKey->name, name, namedKey->nameSz);
1810        namedKey->name[MAX_SERVER_NAME-1] = '\0';
1811        namedKey->isEphemeralKey = isEphemeralKey;
1812        ret = LoadKeyFile(&namedKey->key, &namedKey->keySz,
1813                          keyFile, keySz, type, password);
1814        if (ret < 0) {
1815            SetError(KEY_FILE_STR, error, NULL, 0);
1816            FreeNamedKey(namedKey);
1817            return WOLFSSL_FATAL_ERROR;
1818        }
1819    }
1820#endif
1821
1822    serverIp.version = IPV4;
1823    serverIp.ip4 = XINET_ADDR(address);
1824    if (serverIp.ip4 == XINADDR_NONE) {
1825    #ifdef FUSION_RTOS
1826        if (XINET_PTON(AF_INET6, address, serverIp.ip6,
1827                       sizeof(serverIp.ip6)) == 1)
1828    #elif defined(FREESCALE_MQX)
1829        if (XINET_PTON(AF_INET6, address, serverIp.ip6,
1830                       sizeof(serverIp.ip6)) == RTCS_OK)
1831    #else
1832        if (XINET_PTON(AF_INET6, address, serverIp.ip6) == 1)
1833    #endif
1834        {
1835            serverIp.version = IPV6;
1836        }
1837    }
1838
1839    sniffer = ServerList;
1840    while (sniffer != NULL &&
1841            (!MatchAddr(sniffer->server, serverIp) || sniffer->port != port)) {
1842        sniffer = sniffer->next;
1843    }
1844
1845    if (sniffer == NULL) {
1846        isNew = 1;
1847        sniffer = (SnifferServer*)XMALLOC(sizeof(SnifferServer),
1848                NULL, DYNAMIC_TYPE_SNIFFER_SERVER);
1849        if (sniffer == NULL) {
1850            SetError(MEMORY_STR, error, NULL, 0);
1851#ifdef HAVE_SNI
1852            FreeNamedKey(namedKey);
1853#endif
1854            return WOLFSSL_FATAL_ERROR;
1855        }
1856        InitSnifferServer(sniffer);
1857
1858        XSTRNCPY(sniffer->address, address, MAX_SERVER_ADDRESS-1);
1859        sniffer->address[MAX_SERVER_ADDRESS-1] = '\0';
1860        sniffer->server = serverIp;
1861        sniffer->port = port;
1862
1863        sniffer->ctx = wolfSSL_CTX_new(wolfSSLv23_client_method());
1864        if (!sniffer->ctx) {
1865            SetError(MEMORY_STR, error, NULL, 0);
1866#ifdef HAVE_SNI
1867            FreeNamedKey(namedKey);
1868#endif
1869            FreeSnifferServer(sniffer);
1870            return WOLFSSL_FATAL_ERROR;
1871        }
1872    #if defined(WOLF_CRYPTO_CB) || defined(WOLFSSL_ASYNC_CRYPT)
1873        if (CryptoDeviceId != INVALID_DEVID)
1874            wolfSSL_CTX_SetDevId(sniffer->ctx, CryptoDeviceId);
1875    #endif
1876    }
1877
1878    if (name == NULL) {
1879        if (password) {
1880    #ifdef WOLFSSL_ENCRYPTED_KEYS
1881            wolfSSL_CTX_set_default_passwd_cb(sniffer->ctx, SetPassword);
1882            wolfSSL_CTX_set_default_passwd_cb_userdata(
1883                                                 sniffer->ctx, (void*)password);
1884    #endif
1885        }
1886
1887    #ifdef WOLFSSL_STATIC_EPHEMERAL
1888        if (isEphemeralKey) {
1889            /* auto detect key type with WC_PK_TYPE_NONE */
1890            /* keySz == 0 mean load file */
1891            ret = wolfSSL_CTX_set_ephemeral_key(sniffer->ctx, WC_PK_TYPE_NONE,
1892                keyFile, keySz, type);
1893            if (ret == 0)
1894                ret = WOLFSSL_SUCCESS;
1895        }
1896        else
1897    #endif
1898        {
1899            if (keySz == 0) {
1900                ret = wolfSSL_CTX_use_PrivateKey_file(sniffer->ctx, keyFile, type);
1901            }
1902            else {
1903                ret = wolfSSL_CTX_use_PrivateKey_buffer(sniffer->ctx,
1904                                            (const byte*)keyFile, keySz, type);
1905            }
1906        }
1907        if (ret != WOLFSSL_SUCCESS) {
1908            SetError(KEY_FILE_STR, error, NULL, 0);
1909            if (isNew)
1910                FreeSnifferServer(sniffer);
1911            return WOLFSSL_FATAL_ERROR;
1912        }
1913    #ifdef WOLF_CRYPTO_CB
1914        wolfSSL_CTX_SetDevId(sniffer->ctx, CryptoDeviceId);
1915    #endif
1916    }
1917#ifdef HAVE_SNI
1918    else {
1919        wc_LockMutex(&sniffer->namedKeysMutex);
1920        namedKey->next = sniffer->namedKeys;
1921        sniffer->namedKeys = namedKey;
1922        wc_UnLockMutex(&sniffer->namedKeysMutex);
1923    }
1924#endif
1925
1926    if (isNew) {
1927        sniffer->next = ServerList;
1928        ServerList = sniffer;
1929    }
1930
1931#ifndef WOLFSSL_STATIC_EPHEMERAL
1932    (void)isEphemeralKey;
1933#endif
1934
1935    return 0;
1936}
1937
1938
1939#ifdef HAVE_SNI
1940/* Sets the private key for a specific name, server and port  */
1941/* returns 0 on success, -1 on error */
1942int ssl_SetNamedPrivateKey(const char* name,
1943                           const char* address, int port,
1944                           const char* keyFile, int typeKey,
1945                           const char* password, char* error)
1946{
1947    int ret;
1948
1949    TraceHeader();
1950    TraceSetNamedServer(name, address, port, keyFile);
1951
1952    LOCK_SERVER_LIST();
1953    ret = SetNamedPrivateKey(name, address, port, keyFile, 0,
1954                             typeKey, password, error, 0);
1955    UNLOCK_SERVER_LIST();
1956
1957    if (ret == 0)
1958        Trace(NEW_SERVER_STR);
1959
1960    return ret;
1961}
1962
1963int ssl_SetNamedPrivateKeyBuffer(const char* name,
1964                                 const char* address, int port,
1965                                 const char* keyBuf, int keySz, int typeKey,
1966                                 const char* password, char* error)
1967{
1968    int ret;
1969
1970    TraceHeader();
1971    TraceSetNamedServer(name, address, port, NULL);
1972
1973    LOCK_SERVER_LIST();
1974    ret = SetNamedPrivateKey(name, address, port, keyBuf, keySz,
1975                             typeKey, password, error, 0);
1976    UNLOCK_SERVER_LIST();
1977
1978    if (ret == 0)
1979        Trace(NEW_SERVER_STR);
1980
1981    return ret;
1982}
1983#endif /* HAVE_SNI */
1984
1985/* Sets the private key for a specific server and port  */
1986/* returns 0 on success, -1 on error */
1987int ssl_SetPrivateKey(const char* address, int port,
1988                      const char* keyFile, int typeKey,
1989                      const char* password, char* error)
1990{
1991    int ret;
1992
1993    TraceHeader();
1994    TraceSetServer(address, port, keyFile);
1995
1996    LOCK_SERVER_LIST();
1997    ret = SetNamedPrivateKey(NULL, address, port, keyFile, 0,
1998                             typeKey, password, error, 0);
1999    UNLOCK_SERVER_LIST();
2000
2001    if (ret == 0)
2002        Trace(NEW_SERVER_STR);
2003
2004    return ret;
2005}
2006
2007int ssl_SetPrivateKeyBuffer(const char* address, int port,
2008                            const char* keyBuf, int keySz, int typeKey,
2009                            const char* password, char* error)
2010{
2011    int ret;
2012
2013    TraceHeader();
2014    TraceSetServer(address, port, "from buffer");
2015
2016    LOCK_SERVER_LIST();
2017    ret = SetNamedPrivateKey(NULL, address, port, keyBuf, keySz,
2018                             typeKey, password, error, 0);
2019    UNLOCK_SERVER_LIST();
2020
2021    if (ret == 0)
2022        Trace(NEW_SERVER_STR);
2023
2024    return ret;
2025}
2026
2027#ifdef WOLFSSL_STATIC_EPHEMERAL
2028#ifdef HAVE_SNI
2029/* Sets the ephemeral key for a specific name, server and port  */
2030/* returns 0 on success, -1 on error */
2031int ssl_SetNamedEphemeralKey(const char* name,
2032                             const char* address, int port,
2033                             const char* keyFile, int typeKey,
2034                             const char* password, char* error)
2035{
2036    int ret;
2037
2038    TraceHeader();
2039    TraceSetNamedServer(name, address, port, keyFile);
2040
2041    LOCK_SERVER_LIST();
2042    ret = SetNamedPrivateKey(name, address, port, keyFile, 0,
2043                             typeKey, password, error, 1);
2044    UNLOCK_SERVER_LIST();
2045
2046    if (ret == 0)
2047        Trace(NEW_SERVER_STR);
2048
2049    return ret;
2050}
2051
2052int ssl_SetNamedEphemeralKeyBuffer(const char* name,
2053                                   const char* address, int port,
2054                                   const char* keyBuf, int keySz, int typeKey,
2055                                   const char* password, char* error)
2056{
2057    int ret;
2058
2059    TraceHeader();
2060    TraceSetNamedServer(name, address, port, NULL);
2061
2062    LOCK_SERVER_LIST();
2063    ret = SetNamedPrivateKey(name, address, port, keyBuf, keySz,
2064                             typeKey, password, error, 1);
2065    UNLOCK_SERVER_LIST();
2066
2067    if (ret == 0)
2068        Trace(NEW_SERVER_STR);
2069
2070    return ret;
2071}
2072#endif /* HAVE_SNI */
2073
2074/* Sets the ephemeral key for a specific server and port  */
2075/* returns 0 on success, -1 on error */
2076int ssl_SetEphemeralKey(const char* address, int port,
2077                        const char* keyFile, int typeKey,
2078                        const char* password, char* error)
2079{
2080    int ret;
2081
2082    TraceHeader();
2083    TraceSetServer(address, port, keyFile);
2084
2085    LOCK_SERVER_LIST();
2086    ret = SetNamedPrivateKey(NULL, address, port, keyFile, 0,
2087                             typeKey, password, error, 1);
2088    UNLOCK_SERVER_LIST();
2089
2090    if (ret == 0)
2091        Trace(NEW_SERVER_STR);
2092
2093    return ret;
2094}
2095
2096int ssl_SetEphemeralKeyBuffer(const char* address, int port,
2097                              const char* keyBuf, int keySz, int typeKey,
2098                              const char* password, char* error)
2099{
2100    int ret;
2101
2102    TraceHeader();
2103    TraceSetServer(address, port, "from buffer");
2104
2105    LOCK_SERVER_LIST();
2106    ret = SetNamedPrivateKey(NULL, address, port, keyBuf, keySz,
2107                             typeKey, password, error, 1);
2108    UNLOCK_SERVER_LIST();
2109
2110    if (ret == 0)
2111        Trace(NEW_SERVER_STR);
2112
2113    return ret;
2114}
2115#endif /* WOLFSSL_STATIC_EPHEMERAL */
2116
2117/* Check IP Header for IPV6, TCP, and a registered server address */
2118/* returns 0 on success, -1 on error */
2119static int CheckIp6Hdr(Ip6Hdr* iphdr, IpInfo* info, int length, char* error)
2120{
2121    int        version = IP_V(iphdr);
2122    int        exthdrsz = IP6_HDR_SZ;
2123
2124    if (length < IP6_HDR_SZ) {
2125        SetError(BAD_IPVER_STR, error, NULL, 0);
2126        return WOLFSSL_FATAL_ERROR;
2127    }
2128
2129    TraceIP6(iphdr);
2130    Trace(IP_CHECK_STR);
2131
2132    if (version != IPV6) {
2133        SetError(BAD_IPVER_STR, error, NULL, 0);
2134        return WOLFSSL_FATAL_ERROR;
2135    }
2136
2137    /* Here, we need to move onto next header if not TCP. */
2138    if (iphdr->next_header != TCP_PROTOCOL) {
2139        Ip6ExtHdr* exthdr = (Ip6ExtHdr*)((byte*)iphdr + IP6_HDR_SZ);
2140        do {
2141            int hdrsz = (exthdr->length + 1) * 8;
2142            if (hdrsz > length - exthdrsz) {
2143                SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
2144                return WOLFSSL_FATAL_ERROR;
2145            }
2146            exthdrsz += hdrsz;
2147            exthdr = (Ip6ExtHdr*)((byte*)exthdr + hdrsz);
2148        }
2149        while (exthdrsz < length &&
2150                exthdr->next_header != TCP_PROTOCOL &&
2151                exthdr->next_header != NO_NEXT_HEADER);
2152        if (exthdrsz >= length) {
2153            SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
2154            return WOLFSSL_FATAL_ERROR;
2155        }
2156    }
2157
2158#ifndef WOLFSSL_SNIFFER_WATCH
2159    if (!IsServerRegistered6(iphdr->src) && !IsServerRegistered6(iphdr->dst)) {
2160        SetError(SERVER_NOT_REG_STR, error, NULL, 0);
2161        return WOLFSSL_FATAL_ERROR;
2162    }
2163#endif
2164
2165    info->length = exthdrsz;
2166    info->total = XNTOHS(iphdr->length) + info->length;
2167    /* IPv6 doesn't include its own header size in the length like v4. */
2168    info->src.version = IPV6;
2169    XMEMCPY(info->src.ip6, iphdr->src, sizeof(info->src.ip6));
2170    info->dst.version = IPV6;
2171    XMEMCPY(info->dst.ip6, iphdr->dst, sizeof(info->dst.ip6));
2172
2173    return 0;
2174}
2175
2176
2177/* Check IP Header for IPV4, TCP, and a registered server address */
2178/* If header IPv6, pass to CheckIp6Hdr(). */
2179/* returns 0 on success, -1 on error */
2180static int CheckIpHdr(IpHdr* iphdr, IpInfo* info, int length, char* error,
2181                      int trace)
2182{
2183    int version = IP_V(iphdr);
2184
2185    if (version == IPV6)
2186        return CheckIp6Hdr((Ip6Hdr*)iphdr, info, length, error);
2187
2188    if (length < IP_HDR_SZ) {
2189        SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
2190        return WOLFSSL_FATAL_ERROR;
2191    }
2192
2193    if (trace) {
2194        TraceIP(iphdr);
2195        Trace(IP_CHECK_STR);
2196    }
2197
2198    if (version != IPV4) {
2199        SetError(BAD_IPVER_STR, error, NULL, 0);
2200        return WOLFSSL_FATAL_ERROR;
2201    }
2202
2203    if (iphdr->protocol != TCP_PROTOCOL) {
2204        SetError(BAD_PROTO_STR, error, NULL, 0);
2205        return WOLFSSL_FATAL_ERROR;
2206    }
2207
2208    info->length  = IP_HL(iphdr);
2209    info->total   = XNTOHS(iphdr->length);
2210    info->src.version = IPV4;
2211    info->src.ip4 = iphdr->src;
2212    info->dst.version = IPV4;
2213    info->dst.ip4 = iphdr->dst;
2214
2215    if (info->total == 0)
2216        info->total = length;  /* reassembled may be off */
2217
2218    return 0;
2219}
2220
2221
2222/* Check TCP Header for a registered port */
2223/* returns 0 on success, -1 on error */
2224static int CheckTcpHdr(TcpHdr* tcphdr, TcpInfo* info, char* error, int trace)
2225{
2226    if (trace) {
2227        TraceTcp(tcphdr);
2228        Trace(TCP_CHECK_STR);
2229    }
2230
2231    info->srcPort   = XNTOHS(tcphdr->srcPort);
2232    info->dstPort   = XNTOHS(tcphdr->dstPort);
2233    info->length    = TCP_LEN(tcphdr);
2234    info->sequence  = XNTOHL(tcphdr->sequence);
2235    info->fin       = tcphdr->flags & TCP_FIN;
2236    info->rst       = tcphdr->flags & TCP_RST;
2237    info->syn       = tcphdr->flags & TCP_SYN;
2238    info->ack       = tcphdr->flags & TCP_ACK;
2239    if (info->ack)
2240        info->ackNumber = XNTOHL(tcphdr->ack);
2241
2242    (void)error;
2243
2244    return 0;
2245}
2246
2247
2248/* Decode Record Layer Header */
2249static int GetRecordHeader(const byte* input, RecordLayerHeader* rh, int* size)
2250{
2251    XMEMCPY(rh, input, RECORD_HEADER_SZ);
2252    *size = (rh->length[0] << 8) | rh->length[1];
2253
2254    /* make sure length is valid */
2255    if (*size > (MAX_RECORD_SIZE + COMP_EXTRA + MAX_MSG_EXTRA))
2256        return LENGTH_ERROR;
2257    /* make sure the record type is valid */
2258    if (rh->type < change_cipher_spec ||
2259    #ifdef WOLFSSL_DTLS13
2260        rh->type > ack
2261    #else
2262        rh->type > dtls12_cid
2263    #endif
2264        ) {
2265        return UNKNOWN_RECORD_TYPE;
2266    }
2267    /* make sure version is valid */
2268    if (rh->pvMajor > SSLv3_MAJOR || rh->pvMinor > TLSv1_3_MINOR) {
2269        return VERSION_ERROR;
2270    }
2271
2272    return 0;
2273}
2274
2275
2276/* Copies the session's information to the provided sslInfo. Skip copy if
2277 * SSLInfo is not provided. */
2278static void CopySessionInfo(SnifferSession* session, SSLInfo* sslInfo)
2279{
2280    if (NULL != sslInfo) {
2281        XMEMSET(sslInfo, 0, sizeof(SSLInfo));
2282
2283        /* Pass back Session Info after we have processed the Server Hello. */
2284        if (0 != session->sslServer->options.cipherSuite) {
2285            const char* pCipher;
2286
2287            sslInfo->isValid = 1;
2288            sslInfo->protocolVersionMajor = session->sslServer->version.major;
2289            sslInfo->protocolVersionMinor = session->sslServer->version.minor;
2290            sslInfo->serverCipherSuite0 =
2291                        session->sslServer->options.cipherSuite0;
2292            sslInfo->serverCipherSuite =
2293                        session->sslServer->options.cipherSuite;
2294
2295            pCipher = wolfSSL_get_cipher(session->sslServer);
2296            if (NULL != pCipher) {
2297                XSTRNCPY((char*)sslInfo->serverCipherSuiteName, pCipher,
2298                         sizeof(sslInfo->serverCipherSuiteName) - 1);
2299                sslInfo->serverCipherSuiteName
2300                         [sizeof(sslInfo->serverCipherSuiteName) - 1] = '\0';
2301            }
2302            sslInfo->keySize = session->keySz;
2303        #ifdef HAVE_SNI
2304            if (NULL != session->sni) {
2305                XSTRNCPY((char*)sslInfo->serverNameIndication,
2306                    session->sni, sizeof(sslInfo->serverNameIndication) - 1);
2307                sslInfo->serverNameIndication
2308                         [sizeof(sslInfo->serverNameIndication) - 1] = '\0';
2309            }
2310        #endif
2311            TraceSessionInfo(sslInfo);
2312        }
2313    }
2314}
2315
2316
2317/* Call the session connection start callback. */
2318static void CallConnectionCb(SnifferSession* session)
2319{
2320    if (ConnectionCb != NULL) {
2321        SSLInfo info;
2322        CopySessionInfo(session, &info);
2323        ConnectionCb((const void*)session, &info, ConnectionCbCtx);
2324    }
2325}
2326
2327#ifdef SHOW_SECRETS
2328static void PrintSecret(const char* desc, const byte* buf, int sz)
2329{
2330    int i;
2331    printf("%s: ", desc);
2332    for (i = 0; i < sz; i++) {
2333        printf("%02x", buf[i]);
2334    }
2335    printf("\n");
2336}
2337
2338static void ShowTlsSecrets(SnifferSession* session)
2339{
2340    PrintSecret("server master secret", session->sslServer->arrays->masterSecret, SECRET_LEN);
2341    PrintSecret("client master secret", session->sslClient->arrays->masterSecret, SECRET_LEN);
2342    printf("server suite = %d\n", session->sslServer->options.cipherSuite);
2343    printf("client suite = %d\n", session->sslClient->options.cipherSuite);
2344}
2345#endif /* SHOW_SECRETS */
2346
2347typedef struct {
2348    int type;
2349    union {
2350    #ifndef NO_RSA
2351        RsaKey rsa;
2352    #endif
2353    #if !defined(NO_DH) && defined(WOLFSSL_DH_EXTRA)
2354        struct {
2355            word32 pLen; /* modulus length */
2356            word32 privKeySz;
2357            byte   privKey[WC_DH_PRIV_MAX_SZ]; /* max for TLS */
2358            DhKey  key;
2359        } dh;
2360    #endif
2361    #ifdef HAVE_ECC
2362        ecc_key ecc;
2363    #endif
2364    #ifdef HAVE_CURVE25519
2365        curve25519_key x25519;
2366    #endif
2367    #ifdef HAVE_CURVE448
2368        curve448_key x448;
2369    #endif
2370    } priv;
2371
2372#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
2373    union {
2374        /* RSA is for static RSA only */
2375        /* DH does not use public DhKey for Agree */
2376    #ifdef HAVE_ECC
2377        ecc_key ecc;
2378    #endif
2379    #ifdef HAVE_CURVE25519
2380        curve25519_key x25519;
2381    #endif
2382    #ifdef HAVE_CURVE448
2383        curve448_key x448;
2384    #endif
2385    } pub;
2386#endif
2387    byte initPriv:1;
2388    byte initPub:1;
2389} SnifferKey;
2390
2391typedef struct SetupKeysArgs {
2392#ifdef WOLFSSL_ASYNC_CRYPT
2393    SnifferKey* key;
2394#else
2395    SnifferKey  key[1];
2396#endif
2397    DerBuffer*  keyBuf;
2398    int         length;
2399    byte        keyBufFree:1;
2400    byte        keyLocked:1;
2401} SetupKeysArgs;
2402
2403static void FreeSetupKeysArgs(WOLFSSL* ssl, void* pArgs)
2404{
2405    SetupKeysArgs* args = (SetupKeysArgs*)pArgs;
2406
2407    if (args == NULL) {
2408        return;
2409    }
2410    (void)ssl;
2411#ifdef WOLFSSL_ASYNC_CRYPT
2412    if (args->key != NULL)
2413#endif
2414    {
2415    #ifndef NO_RSA
2416        if (args->key->type == WC_PK_TYPE_RSA) {
2417            if (args->key->initPriv) {
2418                wc_FreeRsaKey(&args->key->priv.rsa);
2419            }
2420        }
2421    #endif
2422    #if !defined(NO_DH) && defined(WOLFSSL_DH_EXTRA)
2423        if (args->key->type == WC_PK_TYPE_DH) {
2424            if (args->key->initPriv) {
2425                wc_FreeDhKey(&args->key->priv.dh.key);
2426            }
2427        }
2428    #endif
2429    #ifdef HAVE_ECC
2430        if (args->key->type == WC_PK_TYPE_ECDH) {
2431            if (args->key->initPriv) {
2432                wc_ecc_free(&args->key->priv.ecc);
2433            }
2434            if (args->key->initPub) {
2435                wc_ecc_free(&args->key->pub.ecc);
2436            }
2437        }
2438    #endif
2439    #ifdef HAVE_CURVE25519
2440        if (args->key->type == WC_PK_TYPE_CURVE25519) {
2441            if (args->key->initPriv) {
2442                wc_curve25519_free(&args->key->priv.x25519);
2443            }
2444            if (args->key->initPub) {
2445                wc_curve25519_free(&args->key->pub.x25519);
2446            }
2447        }
2448    #endif
2449    #ifdef HAVE_CURVE448
2450        if (args->key->type == WC_PK_TYPE_CURVE448) {
2451            if (args->key->initPriv) {
2452                wc_curve448_free(&args->key->priv.x448);
2453            }
2454            if (args->key->initPub) {
2455                wc_curve448_free(&args->key->pub.x448);
2456            }
2457        }
2458    #endif
2459        args->key->type = WC_PK_TYPE_NONE;
2460        args->key->initPriv = 0; args->key->initPub = 0;
2461
2462        /* Scrub the raw DH private exponent (and any other key material
2463         * embedded in the union) before release. wc_FreeDhKey above only
2464         * clears the mp_int DhKey, not the separate privKey byte array.
2465         * Use ForceZero (rather than XMEMSET) so the wipe cannot be
2466         * elided by the optimizer. */
2467        ForceZero(args->key, sizeof(*args->key));
2468#ifdef WOLFSSL_ASYNC_CRYPT
2469        XFREE(args->key, NULL, DYNAMIC_TYPE_SNIFFER_KEY);
2470        args->key = NULL;
2471#endif
2472    }
2473
2474    if (args->keyBuf != NULL && args->keyBufFree) {
2475        FreeDer(&args->keyBuf);
2476        args->keyBufFree = 0;
2477    }
2478}
2479
2480/* Process Keys */
2481static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
2482    char* error, KeyShareInfo* ksInfo)
2483{
2484    word32 idx;
2485    int ret;
2486    int devId = INVALID_DEVID;
2487    WOLFSSL_CTX* ctx = session->context->ctx;
2488    WOLFSSL* ssl = session->sslServer;
2489
2490#ifdef WOLFSSL_ASYNC_CRYPT
2491    SetupKeysArgs* args = NULL;
2492    WOLFSSL_ASSERT_SIZEOF_GE(ssl->async->args, *args);
2493#else
2494    SetupKeysArgs  args[1];
2495#endif
2496
2497    Trace(SNIFFER_KEY_SETUP_STR);
2498
2499    if (session->sslServer->arrays == NULL ||
2500        session->sslClient->arrays == NULL) {
2501        /* Secret's have already been established and released.
2502         * This can happen with secure renegotiation. */
2503        return 0;
2504    }
2505
2506#ifdef WOLFSSL_ASYNC_CRYPT
2507    if (ssl->async == NULL) {
2508        ssl->async = (struct WOLFSSL_ASYNC*)
2509                XMALLOC(sizeof(struct WOLFSSL_ASYNC), ssl->heap,
2510                        DYNAMIC_TYPE_ASYNC);
2511        if (ssl->async == NULL)
2512            ERROR_OUT(MEMORY_E, exit_sk);
2513    }
2514    args = (SetupKeysArgs*)ssl->async->args;
2515
2516    ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
2517    if (ret != WC_NO_ERR_TRACE(WC_NO_PENDING_E)) {
2518        /* Check for error */
2519        if (ret < 0)
2520            goto exit_sk;
2521    }
2522    else
2523#endif
2524    {
2525        /* Reset state */
2526        ret = 0;
2527        ssl->options.asyncState = TLS_ASYNC_BEGIN;
2528        XMEMSET(args, 0, sizeof(SetupKeysArgs));
2529    #ifdef WOLFSSL_ASYNC_CRYPT
2530        ssl->async->freeArgs = FreeSetupKeysArgs;
2531    #endif
2532    #ifdef WOLFSSL_ASYNC_CRYPT
2533        args->key = (SnifferKey*)XMALLOC(sizeof(SnifferKey), NULL,
2534            DYNAMIC_TYPE_SNIFFER_KEY);
2535    #endif
2536    }
2537
2538#if defined(WOLF_CRYPTO_CB) || defined(WOLFSSL_ASYNC_CRYPT)
2539    devId = CryptoDeviceId;
2540#endif
2541
2542#ifdef WOLFSSL_ASYNC_CRYPT
2543    if (args->key == NULL) {
2544        ERROR_OUT(MEMORY_E, exit_sk);
2545    }
2546#endif
2547
2548    #if defined(WOLFSSL_SNIFFER_KEYLOGFILE)
2549    if (session->context->useKeyLogFile) {
2550        ret = 0;
2551        XMEMSET(args, 0, sizeof(SetupKeysArgs));
2552
2553        /* We want to skip all the key setup and go right to master secret generation, which is
2554         * where we inject the master secret obtained from the keylog file */
2555        ssl->options.asyncState = TLS_ASYNC_FINALIZE;
2556    }
2557    #endif
2558
2559    switch (ssl->options.asyncState) {
2560    case TLS_ASYNC_BEGIN:
2561    {
2562    #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
2563        int useCurveId = 0;
2564        if (ksInfo && ksInfo->curve_id != 0) {
2565            useCurveId = ksInfo->curve_id;
2566        }
2567    #endif
2568
2569    #if defined(WOLFSSL_STATIC_EPHEMERAL) && !defined(SINGLE_THREADED)
2570        if (ctx->staticKELockInit &&
2571            wc_LockMutex(&ctx->staticKELock) == 0) {
2572            args->keyLocked = 1;
2573        }
2574    #endif
2575
2576    #ifndef NO_RSA
2577        /* Static RSA */
2578        if (ksInfo == NULL && ssl->buffers.key) {
2579            ret = wc_InitRsaKey_ex(&args->key->priv.rsa, NULL, devId);
2580            if (ret == 0) {
2581                args->key->type = WC_PK_TYPE_RSA;
2582                args->key->initPriv = 1;
2583                args->keyBuf = ssl->buffers.key;
2584            #ifdef WOLFSSL_ASYNC_CRYPT
2585                ret = wolfSSL_AsyncInit(ssl, &args->key->priv.rsa.asyncDev,
2586                    WC_ASYNC_FLAG_CALL_AGAIN);
2587            #endif
2588            }
2589            if (ret == 0) {
2590                idx = 0;
2591                ret = wc_RsaPrivateKeyDecode(args->keyBuf->buffer, &idx,
2592                    &args->key->priv.rsa, args->keyBuf->length);
2593                if (ret != 0) {
2594                #ifndef HAVE_ECC
2595                    SetError(RSA_DECODE_STR, error, session,
2596                        FATAL_ERROR_STATE);
2597                    break;
2598                #else
2599                    /* If we can do ECC, this isn't fatal. Not loading a key
2600                     * later will be fatal, though. */
2601                    SetError(RSA_DECODE_STR, error, session, 0);
2602                    args->keyBuf = NULL;
2603                #endif
2604                }
2605            }
2606
2607            if (ret == 0) {
2608                args->length = wc_RsaEncryptSize(&args->key->priv.rsa);
2609                if (IsTLS(session->sslServer)) {
2610                    input += 2;     /* tls pre length */
2611                }
2612
2613                if (args->length > *sslBytes) {
2614                    SetError(PARTIAL_INPUT_STR, error, session,
2615                        FATAL_ERROR_STATE);
2616                    ret = WOLFSSL_FATAL_ERROR;
2617                }
2618            }
2619
2620        #ifdef WC_RSA_BLINDING
2621            if (ret == 0) {
2622                ret = wc_RsaSetRNG(&args->key->priv.rsa,
2623                    session->sslServer->rng);
2624                if (ret != 0) {
2625                    SetError(RSA_DECRYPT_STR, error, session,
2626                        FATAL_ERROR_STATE);
2627                }
2628            }
2629        #endif
2630
2631            if (ret == 0) {
2632                session->keySz = args->length * WOLFSSL_BIT_SIZE;
2633                /* length is the key size in bytes */
2634                session->sslServer->arrays->preMasterSz = SECRET_LEN;
2635            }
2636        }
2637    #endif /* !NO_RSA */
2638
2639    #if !defined(NO_DH) && defined(WOLFSSL_DH_EXTRA)
2640        /* Static DH Key */
2641        if (ksInfo && ksInfo->dh_key_bits != 0 && args->keyBuf == NULL) {
2642        #ifdef HAVE_PUBLIC_FFDHE
2643            const DhParams* params;
2644        #endif
2645
2646            /* try and load static ephemeral */
2647        #ifdef WOLFSSL_STATIC_EPHEMERAL
2648            args->keyBuf = ssl->staticKE.dhKey;
2649            if (args->keyBuf == NULL)
2650                args->keyBuf = ctx->staticKE.dhKey;
2651        #endif
2652
2653            ret = 0;
2654        #ifdef WOLFSSL_SNIFFER_KEY_CALLBACK
2655            if (KeyCb != NULL) {
2656                if (args->keyBuf == NULL) {
2657                    ret = AllocDer(&args->keyBuf, FILE_BUFFER_SIZE,
2658                        PRIVATEKEY_TYPE, NULL);
2659                    if (ret == 0)
2660                        args->keyBufFree = 1;
2661                }
2662                ret = KeyCb(session, ksInfo->named_group,
2663                    session->srvKs.key, session->srvKs.key_len,
2664                    session->cliKs.key, session->cliKs.key_len,
2665                    args->keyBuf, KeyCbCtx, error);
2666                if (ret != 0) {
2667                    SetError(-1, error, session, FATAL_ERROR_STATE);
2668                }
2669            }
2670        #endif
2671            if (ret == 0 && args->keyBuf == NULL) {
2672                ret = BUFFER_E;
2673            }
2674
2675        #ifdef HAVE_PUBLIC_FFDHE
2676            if (ret == 0) {
2677                /* get DH params */
2678                switch (ksInfo->named_group) {
2679                #ifdef HAVE_FFDHE_2048
2680                    case WOLFSSL_FFDHE_2048:
2681                        params = wc_Dh_ffdhe2048_Get();
2682                        args->key->priv.dh.privKeySz = 29;
2683                        break;
2684                #endif
2685                #ifdef HAVE_FFDHE_3072
2686                    case WOLFSSL_FFDHE_3072:
2687                        params = wc_Dh_ffdhe3072_Get();
2688                        args->key->priv.dh.privKeySz = 34;
2689                        break;
2690                #endif
2691                #ifdef HAVE_FFDHE_4096
2692                    case WOLFSSL_FFDHE_4096:
2693                        params = wc_Dh_ffdhe4096_Get();
2694                        args->key->priv.dh.privKeySz = 39;
2695                        break;
2696                #endif
2697                #ifdef HAVE_FFDHE_6144
2698                    case WOLFSSL_FFDHE_6144:
2699                        params = wc_Dh_ffdhe6144_Get();
2700                        args->key->priv.dh.privKeySz = 46;
2701                        break;
2702                #endif
2703                #ifdef HAVE_FFDHE_8192
2704                    case WOLFSSL_FFDHE_8192:
2705                        params = wc_Dh_ffdhe8192_Get();
2706                        args->key->priv.dh.privKeySz = 52;
2707                        break;
2708                #endif
2709                    default:
2710                        ret = BAD_FUNC_ARG;
2711                }
2712            }
2713        #endif
2714
2715            if (ret == 0) {
2716                ret = wc_InitDhKey_ex(&args->key->priv.dh.key, NULL, devId);
2717                if (ret == 0) {
2718                    args->key->type = WC_PK_TYPE_DH;
2719                    args->key->initPriv = 1;
2720                #ifdef WOLFSSL_ASYNC_CRYPT
2721                    ret = wolfSSL_AsyncInit(ssl,
2722                        &args->key->priv.dh.key.asyncDev, WC_ASYNC_FLAG_NONE);
2723                #endif
2724                }
2725            }
2726            if (ret == 0) {
2727        #ifdef HAVE_PUBLIC_FFDHE
2728                ret = wc_DhSetKey(&args->key->priv.dh.key,
2729                    (byte*)params->p, params->p_len,
2730                    (byte*)params->g, params->g_len);
2731                args->key->priv.dh.pLen = params->p_len;
2732        #else
2733                ret = wc_DhSetNamedKey(&args->key->priv.dh.key,
2734                    ksInfo->named_group);
2735                if (ret == 0) {
2736                    args->key->priv.dh.privKeySz =
2737                        wc_DhGetNamedKeyMinSize(ksInfo->named_group);
2738                    ret = wc_DhGetNamedKeyParamSize(ksInfo->named_group,
2739                            &args->key->priv.dh.pLen, NULL, NULL);
2740                }
2741        #endif
2742            }
2743            if (ret == 0) {
2744                idx = 0;
2745                ret = wc_DhKeyDecode(args->keyBuf->buffer, &idx,
2746                    &args->key->priv.dh.key, args->keyBuf->length);
2747            }
2748            if (ret == 0) {
2749                ret = wc_DhExportKeyPair(&args->key->priv.dh.key,
2750                    args->key->priv.dh.privKey, &args->key->priv.dh.privKeySz,
2751                    NULL, NULL);
2752            }
2753        }
2754    #endif /* !NO_DH && WOLFSSL_DH_EXTRA */
2755
2756    #ifdef HAVE_ECC
2757        /* Static ECC Key */
2758        if (useCurveId >= 0 && args->keyBuf == NULL
2759        #ifdef HAVE_CURVE25519
2760            && useCurveId != ECC_X25519
2761        #endif
2762        #ifdef HAVE_CURVE448
2763            && useCurveId != ECC_X448
2764        #endif
2765        ) {
2766            /* try and load static ephemeral */
2767        #ifdef WOLFSSL_STATIC_EPHEMERAL
2768            args->keyBuf = ssl->staticKE.ecKey;
2769            if (args->keyBuf == NULL)
2770                args->keyBuf = ctx->staticKE.ecKey;
2771        #endif
2772
2773            /* try static ECC */
2774            if (args->keyBuf == NULL) {
2775                args->keyBuf = session->sslServer->buffers.key;
2776            }
2777
2778            ret = 0;
2779        #ifdef WOLFSSL_SNIFFER_KEY_CALLBACK
2780            if (KeyCb != NULL && ksInfo) {
2781                if (args->keyBuf == NULL) {
2782                    ret = AllocDer(&args->keyBuf, FILE_BUFFER_SIZE,
2783                        PRIVATEKEY_TYPE, NULL);
2784                    if (ret == 0)
2785                        args->keyBufFree = 1;
2786                }
2787                ret = KeyCb(session, ksInfo->named_group,
2788                    session->srvKs.key, session->srvKs.key_len,
2789                    session->cliKs.key, session->cliKs.key_len,
2790                    args->keyBuf, KeyCbCtx, error);
2791                if (ret != 0) {
2792                    SetError(-1, error, session, FATAL_ERROR_STATE);
2793                }
2794            }
2795        #endif
2796
2797            if (ret == 0 && args->keyBuf == NULL) {
2798                ret = BUFFER_E;
2799            }
2800            if (ret == 0) {
2801                ret = wc_ecc_init_ex(&args->key->priv.ecc, NULL, devId);
2802                if (ret == 0) {
2803                    args->key->type = WC_PK_TYPE_ECDH;
2804                    args->key->initPriv = 1;
2805                #ifdef WOLFSSL_ASYNC_CRYPT
2806                    ret = wolfSSL_AsyncInit(ssl, &args->key->priv.ecc.asyncDev,
2807                        WC_ASYNC_FLAG_CALL_AGAIN);
2808                #endif
2809                }
2810        }
2811        #if defined(ECC_TIMING_RESISTANT) && (!defined(HAVE_FIPS) || \
2812            (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION != 2))) && \
2813            !defined(HAVE_SELFTEST)
2814            if (ret == 0) {
2815                ret = wc_ecc_set_rng(&args->key->priv.ecc,
2816                    session->sslServer->rng);
2817            }
2818        #endif
2819            if (ret == 0) {
2820                idx = 0;
2821                ret = wc_EccPrivateKeyDecode(args->keyBuf->buffer, &idx,
2822                    &args->key->priv.ecc, args->keyBuf->length);
2823                if (ret != 0) {
2824                    SetError(ECC_DECODE_STR, error, session, FATAL_ERROR_STATE);
2825                }
2826            }
2827
2828            if (ret == 0) {
2829                args->length = wc_ecc_size(&args->key->priv.ecc) * 2 + 1;
2830                /* The length should be 2 times the key size (x and y), plus 1
2831                * for the type byte. */
2832                if (!IsAtLeastTLSv1_3(session->sslServer->version)) {
2833                    input += 1; /* Don't include the TLS length for the key. */
2834                }
2835
2836                if (args->length > *sslBytes) {
2837                    SetError(PARTIAL_INPUT_STR, error, session,
2838                        FATAL_ERROR_STATE);
2839                    ret = WOLFSSL_FATAL_ERROR;
2840                }
2841
2842                /* if curve not provided in key share data, then use private
2843                 * key curve */
2844                if (useCurveId == 0 && args->key->priv.ecc.dp) {
2845                    /* this is for the static ECC case */
2846                    useCurveId = args->key->priv.ecc.dp->id;
2847                }
2848            }
2849            if (ret == 0) {
2850                ret = wc_ecc_init(&args->key->pub.ecc);
2851                if (ret == 0)
2852                    args->key->initPub = 1;
2853            }
2854            if (ret == 0) {
2855                ret = wc_ecc_import_x963_ex(input, args->length,
2856                    &args->key->pub.ecc, useCurveId);
2857                if (ret != 0) {
2858                    SetError(ECC_PUB_DECODE_STR, error, session,
2859                        FATAL_ERROR_STATE);
2860                }
2861            }
2862            if (ret == 0) {
2863                session->keySz = ((args->length - 1) / 2) * WOLFSSL_BIT_SIZE;
2864                /* Length is in bytes. Subtract 1 for the ECC key type. Divide
2865                * by two as the key is in (x,y) coordinates, where x and y are
2866                * the same size, the key size. Convert from bytes to bits. */
2867                session->sslServer->arrays->preMasterSz = ENCRYPT_LEN;
2868            }
2869        }
2870    #endif /* HAVE_ECC */
2871
2872    #ifdef HAVE_CURVE25519
2873        /* Static Curve25519 Key */
2874        if (useCurveId == ECC_X25519) {
2875            /* try and load static ephemeral */
2876        #ifdef WOLFSSL_STATIC_EPHEMERAL
2877            args->keyBuf = ssl->staticKE.x25519Key;
2878            if (args->keyBuf == NULL)
2879                args->keyBuf = ctx->staticKE.x25519Key;
2880        #endif
2881
2882            ret = 0;
2883        #ifdef WOLFSSL_SNIFFER_KEY_CALLBACK
2884            if (KeyCb != NULL && ksInfo) {
2885                if (args->keyBuf == NULL) {
2886                    ret = AllocDer(&args->keyBuf, FILE_BUFFER_SIZE,
2887                        PRIVATEKEY_TYPE, NULL);
2888                    if (ret == 0)
2889                        args->keyBufFree = 1;
2890                }
2891                ret = KeyCb(session, ksInfo->named_group,
2892                    session->srvKs.key, session->srvKs.key_len,
2893                    session->cliKs.key, session->cliKs.key_len,
2894                    args->keyBuf, KeyCbCtx, error);
2895                if (ret != 0) {
2896                    SetError(-1, error, session, FATAL_ERROR_STATE);
2897                    break;
2898                }
2899            }
2900        #endif
2901
2902            if (ret == 0 && args->keyBuf == NULL) {
2903                ret = BUFFER_E;
2904            }
2905            if (ret == 0) {
2906                ret = wc_curve25519_init_ex(&args->key->priv.x25519, NULL,
2907                    devId);
2908                if (ret == 0) {
2909                    args->key->type = WC_PK_TYPE_CURVE25519;
2910                    args->key->initPriv = 1;
2911                #ifdef WOLFSSL_ASYNC_CRYPT
2912                    ret = wolfSSL_AsyncInit(ssl,
2913                        &args->key->priv.x25519.asyncDev,
2914                        WC_ASYNC_FLAG_CALL_AGAIN);
2915                #endif
2916                }
2917            }
2918            if (ret == 0) {
2919                idx = 0;
2920                ret = wc_Curve25519PrivateKeyDecode(args->keyBuf->buffer, &idx,
2921                    &args->key->priv.x25519, args->keyBuf->length);
2922                if (ret != 0) {
2923                    SetError(ECC_DECODE_STR, error, session, FATAL_ERROR_STATE);
2924                }
2925            }
2926
2927            if (ret == 0) {
2928                args->length = CURVE25519_KEYSIZE;
2929                if (args->length > *sslBytes) {
2930                    SetError(PARTIAL_INPUT_STR, error, session,
2931                        FATAL_ERROR_STATE);
2932                    ret = WOLFSSL_FATAL_ERROR;
2933                }
2934            }
2935            if (ret == 0) {
2936                ret = wc_curve25519_init(&args->key->pub.x25519);
2937                if (ret == 0)
2938                    args->key->initPub = 1;
2939            }
2940            if (ret == 0) {
2941                ret = wc_curve25519_import_public_ex(input, args->length,
2942                    &args->key->pub.x25519, EC25519_LITTLE_ENDIAN);
2943                if (ret != 0) {
2944                    SetError(ECC_PUB_DECODE_STR, error, session,
2945                        FATAL_ERROR_STATE);
2946                }
2947            }
2948
2949            if (ret == 0) {
2950                /* For Curve25519 length is always 32 */
2951                session->keySz = CURVE25519_KEYSIZE;
2952                session->sslServer->arrays->preMasterSz = ENCRYPT_LEN;
2953            }
2954        }
2955    #endif /* HAVE_CURVE25519 */
2956
2957    #ifdef HAVE_CURVE448
2958        /* Static Curve448 Key */
2959        if (useCurveId == ECC_X448) {
2960            /* try and load static ephemeral */
2961        #ifdef WOLFSSL_STATIC_EPHEMERAL
2962            args->keyBuf = ssl->staticKE.x448Key;
2963            if (args->keyBuf == NULL)
2964                args->keyBuf = ctx->staticKE.x448Key;
2965        #endif
2966
2967            ret = 0;
2968        #ifdef WOLFSSL_SNIFFER_KEY_CALLBACK
2969            if (KeyCb != NULL && ksInfo) {
2970                if (args->keyBuf == NULL) {
2971                    ret = AllocDer(&args->keyBuf, FILE_BUFFER_SIZE,
2972                        PRIVATEKEY_TYPE, NULL);
2973                    if (ret == 0)
2974                        args->keyBufFree = 1;
2975                }
2976                ret = KeyCb(session, ksInfo->named_group,
2977                    session->srvKs.key, session->srvKs.key_len,
2978                    session->cliKs.key, session->cliKs.key_len,
2979                    args->keyBuf, KeyCbCtx, error);
2980                if (ret != 0) {
2981                    SetError(-1, error, session, FATAL_ERROR_STATE);
2982                    break;
2983                }
2984            }
2985        #endif
2986
2987            if (ret == 0 && args->keyBuf == NULL) {
2988                ret = BUFFER_E;
2989            }
2990            if (ret == 0) {
2991                ret = wc_curve448_init(&args->key->priv.x448);
2992                if (ret == 0) {
2993                    args->key->type = WC_PK_TYPE_CURVE448;
2994                    args->key->initPriv = 1;
2995                #ifdef WOLFSSL_ASYNC_CRYPT
2996                    ret = wolfSSL_AsyncInit(ssl, &args->key->priv.x448.asyncDev,
2997                        WC_ASYNC_FLAG_CALL_AGAIN);
2998                #endif
2999                }
3000            }
3001            if (ret == 0) {
3002                idx = 0;
3003                ret = wc_Curve448PrivateKeyDecode(args->keyBuf->buffer, &idx,
3004                    &args->key->priv.x448, args->keyBuf->length);
3005                if (ret != 0) {
3006                    SetError(ECC_DECODE_STR, error, session, FATAL_ERROR_STATE);
3007                }
3008            }
3009
3010            if (ret == 0) {
3011                args->length = CURVE448_KEY_SIZE;
3012                if (args->length > *sslBytes) {
3013                    SetError(PARTIAL_INPUT_STR, error, session,
3014                        FATAL_ERROR_STATE);
3015                    ret = WOLFSSL_FATAL_ERROR;
3016                }
3017            }
3018            if (ret == 0) {
3019                ret = wc_curve448_init(&args->key->pub.x448);
3020                if (ret == 0)
3021                    args->key->initPub = 1;
3022            }
3023            if (ret == 0) {
3024                ret = wc_curve448_import_public_ex(input, args->length,
3025                    &args->key->pub.x448, EC448_LITTLE_ENDIAN);
3026                if (ret != 0) {
3027                    SetError(ECC_PUB_DECODE_STR, error, session,
3028                        FATAL_ERROR_STATE);
3029                }
3030            }
3031
3032            if (ret == 0) {
3033                session->keySz = CURVE448_KEY_SIZE;
3034                session->sslServer->arrays->preMasterSz = ENCRYPT_LEN;
3035            }
3036        }
3037    #endif /* HAVE_CURVE448 */
3038
3039    #if defined(WOLFSSL_STATIC_EPHEMERAL) && !defined(SINGLE_THREADED)
3040        if (args->keyLocked) {
3041            wc_UnLockMutex(&ctx->staticKELock);
3042        }
3043    #endif
3044
3045        /* make sure a key type was found */
3046        if (args->key->type == WC_PK_TYPE_NONE) {
3047            ret = NOT_COMPILED_IN;
3048        }
3049
3050        /* check for errors before moving to next state */
3051        if (ret < 0) {
3052            break;
3053        }
3054
3055        /* Advance state and proceed */
3056        ssl->options.asyncState = TLS_ASYNC_DO;
3057    } /* case TLS_ASYNC_BEGIN */
3058    FALL_THROUGH;
3059
3060    case TLS_ASYNC_DO:
3061    {
3062    #ifdef WOLFSSL_ASYNC_CRYPT
3063        WC_ASYNC_DEV* asyncDev = NULL;
3064    #endif
3065    #ifndef NO_RSA
3066        if (args->key->type == WC_PK_TYPE_RSA) {
3067            ret = wc_RsaPrivateDecrypt(input, args->length,
3068                    session->sslServer->arrays->preMasterSecret,
3069                    session->sslServer->arrays->preMasterSz,
3070                    &args->key->priv.rsa);
3071        #ifdef WOLFSSL_ASYNC_CRYPT
3072            asyncDev = &args->key->priv.rsa.asyncDev;
3073        #endif
3074        }
3075    #endif /* !NO_RSA */
3076    #if !defined(NO_DH) && defined(WOLFSSL_DH_EXTRA)
3077        if (args->key->type == WC_PK_TYPE_DH) {
3078            /* Derive secret from private key and peer's public key */
3079            ret = wc_DhAgree(&args->key->priv.dh.key,
3080                session->sslServer->arrays->preMasterSecret,
3081                &session->sslServer->arrays->preMasterSz,
3082                args->key->priv.dh.privKey, args->key->priv.dh.privKeySz,
3083                input, *sslBytes);
3084        #ifdef WOLFSSL_ASYNC_CRYPT
3085            asyncDev = &args->key->priv.dh.key.asyncDev;
3086        #endif
3087        }
3088    #endif /* !NO_DH && WOLFSSL_DH_EXTRA */
3089    #ifdef HAVE_ECC
3090        if (args->key->type == WC_PK_TYPE_ECDH) {
3091            ret = wc_ecc_shared_secret(&args->key->priv.ecc,
3092                &args->key->pub.ecc,
3093                session->sslServer->arrays->preMasterSecret,
3094                &session->sslServer->arrays->preMasterSz);
3095        #ifdef WOLFSSL_ASYNC_CRYPT
3096            asyncDev = &args->key->priv.ecc.asyncDev;
3097        #endif
3098        }
3099    #endif /* HAVE_ECC */
3100    #ifdef HAVE_CURVE25519
3101        if (args->key->type == WC_PK_TYPE_CURVE25519) {
3102            ret = wc_curve25519_shared_secret_ex(&args->key->priv.x25519,
3103                &args->key->pub.x25519,
3104                session->sslServer->arrays->preMasterSecret,
3105                &session->sslServer->arrays->preMasterSz,
3106                EC25519_LITTLE_ENDIAN);
3107        #ifdef WOLFSSL_ASYNC_CRYPT
3108            asyncDev = &args->key->priv.x25519.asyncDev;
3109        #endif
3110        }
3111    #endif /* HAVE_CURVE25519 */
3112    #ifdef HAVE_CURVE448
3113        if (args->key->type == WC_PK_TYPE_CURVE448) {
3114            ret = wc_curve448_shared_secret_ex(&args->key->priv.x448,
3115                &args->key->pub.x448,
3116                session->sslServer->arrays->preMasterSecret,
3117                &session->sslServer->arrays->preMasterSz, EC448_LITTLE_ENDIAN);
3118        #ifdef WOLFSSL_ASYNC_CRYPT
3119            asyncDev = &args->key->priv.x448.asyncDev;
3120        #endif
3121        }
3122    #endif /* HAVE_CURVE448 */
3123
3124    #ifdef WOLFSSL_ASYNC_CRYPT
3125        if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
3126            /* Handle async pending response */
3127            ret = wolfSSL_AsyncPush(ssl, asyncDev);
3128            break;
3129        }
3130    #endif /* WOLFSSL_ASYNC_CRYPT */
3131
3132        /* check for errors before moving to next state */
3133        if (ret < 0) {
3134            break;
3135        }
3136
3137        /* Advance state and proceed */
3138        ssl->options.asyncState = TLS_ASYNC_VERIFY;
3139    } /* case TLS_ASYNC_DO */
3140    FALL_THROUGH;
3141
3142    case TLS_ASYNC_VERIFY:
3143    {
3144    #ifndef NO_RSA
3145        if (args->key->type == WC_PK_TYPE_RSA) {
3146            if (ret != SECRET_LEN) {
3147                SetError(RSA_DECRYPT_STR, error, session, FATAL_ERROR_STATE);
3148                ret = RSA_BUFFER_E;
3149            }
3150        }
3151    #endif /* !NO_RSA */
3152    #if !defined(NO_DH) && defined(WOLFSSL_DH_EXTRA)
3153        if (args->key->type == WC_PK_TYPE_DH) {
3154            /* left-padded with zeros up to the size of the prime */
3155            if (args->key->priv.dh.pLen >
3156                                      session->sslServer->arrays->preMasterSz) {
3157                word32 diff = args->key->priv.dh.pLen -
3158                              session->sslServer->arrays->preMasterSz;
3159                XMEMMOVE(session->sslServer->arrays->preMasterSecret + diff,
3160                        session->sslServer->arrays->preMasterSecret,
3161                        session->sslServer->arrays->preMasterSz);
3162                XMEMSET(session->sslServer->arrays->preMasterSecret, 0, diff);
3163                session->sslServer->arrays->preMasterSz=args->key->priv.dh.pLen;
3164            }
3165        }
3166    #endif /* !NO_DH && WOLFSSL_DH_EXTRA */
3167
3168        /* check for errors before moving to next state */
3169        if (ret < 0) {
3170            break;
3171        }
3172
3173        /* Advance state and proceed */
3174        ssl->options.asyncState = TLS_ASYNC_FINALIZE;
3175    } /* case TLS_ASYNC_VERIFY */
3176    FALL_THROUGH;
3177
3178    case TLS_ASYNC_FINALIZE:
3179    {
3180    #if defined(WOLFSSL_SNIFFER_KEYLOGFILE)
3181        if (!session->context->useKeyLogFile)
3182    #endif /* !WOLFSSL_SNIFFER_KEYLOGFILE */
3183        {
3184            /* store for client side as well */
3185            XMEMCPY(session->sslClient->arrays->preMasterSecret,
3186                    session->sslServer->arrays->preMasterSecret,
3187                    session->sslServer->arrays->preMasterSz);
3188            session->sslClient->arrays->preMasterSz =
3189                session->sslServer->arrays->preMasterSz;
3190        }
3191
3192    #ifdef SHOW_SECRETS
3193        PrintSecret("pre master secret",
3194                    session->sslServer->arrays->preMasterSecret,
3195                    session->sslServer->arrays->preMasterSz);
3196    #endif
3197
3198        if (SetCipherSpecs(session->sslServer) != 0) {
3199            SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
3200            session->verboseErr = 1;
3201            ret = WOLFSSL_FATAL_ERROR; break;
3202        }
3203
3204        if (SetCipherSpecs(session->sslClient) != 0) {
3205            SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
3206            session->verboseErr = 1;
3207            ret = WOLFSSL_FATAL_ERROR; break;
3208        }
3209
3210    #ifdef WOLFSSL_TLS13
3211        /* TLS v1.3 derive handshake key */
3212        if (IsAtLeastTLSv1_3(session->sslServer->version)) {
3213            ret  = DeriveEarlySecret(session->sslServer);
3214            ret += DeriveEarlySecret(session->sslClient);
3215            ret += DeriveHandshakeSecret(session->sslServer);
3216            ret += DeriveHandshakeSecret(session->sslClient);
3217            ret += DeriveTls13Keys(session->sslServer, handshake_key,
3218                ENCRYPT_AND_DECRYPT_SIDE, 1);
3219            ret += DeriveTls13Keys(session->sslClient, handshake_key,
3220                ENCRYPT_AND_DECRYPT_SIDE, 1);
3221        #ifdef WOLFSSL_EARLY_DATA
3222            ret += SetKeysSide(session->sslServer, DECRYPT_SIDE_ONLY);
3223            ret += SetKeysSide(session->sslClient, DECRYPT_SIDE_ONLY);
3224        #else
3225            ret += SetKeysSide(session->sslServer, ENCRYPT_AND_DECRYPT_SIDE);
3226            ret += SetKeysSide(session->sslClient, ENCRYPT_AND_DECRYPT_SIDE);
3227        #endif
3228        }
3229        else
3230    #endif /* WOLFSSL_TLS13 */
3231        {
3232            ret  = MakeMasterSecret(session->sslServer);
3233            ret += MakeMasterSecret(session->sslClient);
3234            ret += SetKeysSide(session->sslServer, ENCRYPT_AND_DECRYPT_SIDE);
3235            ret += SetKeysSide(session->sslClient, ENCRYPT_AND_DECRYPT_SIDE);
3236        }
3237        if (ret != 0) {
3238            SetError(BAD_DERIVE_STR, error, session, FATAL_ERROR_STATE);
3239            ret = WOLFSSL_FATAL_ERROR; break;
3240        }
3241
3242    #ifdef SHOW_SECRETS
3243        #ifdef WOLFSSL_TLS13
3244        if (!IsAtLeastTLSv1_3(session->sslServer->version))
3245        #endif
3246        {
3247            ShowTlsSecrets(session);
3248        }
3249    #endif
3250
3251        CallConnectionCb(session);
3252
3253        break;
3254    } /* case TLS_ASYNC_FINALIZE */
3255
3256    default:
3257        ret = INPUT_CASE_ERROR;
3258    } /* switch(ssl->options.asyncState) */
3259
3260#ifdef WOLFSSL_ASYNC_CRYPT
3261exit_sk:
3262
3263    /* Handle async pending response */
3264    if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
3265        return ret;
3266    }
3267#endif /* WOLFSSL_ASYNC_CRYPT */
3268
3269#ifdef WOLFSSL_SNIFFER_STATS
3270    if (ret < 0)
3271        INC_STAT(SnifferStats.sslKeyFails);
3272#endif
3273
3274    /* Final cleanup */
3275#ifdef WOLFSSL_ASYNC_CRYPT
3276    FreeAsyncCtx(ssl, 1);
3277#else
3278    FreeSetupKeysArgs(ssl, args);
3279#endif
3280#ifndef WOLFSSL_STATIC_EPHEMERAL
3281    (void)ctx;
3282#endif
3283
3284    return ret;
3285}
3286
3287/* Process Client Key Exchange */
3288static int ProcessClientKeyExchange(const byte* input, int* sslBytes,
3289                            SnifferSession* session, char* error)
3290{
3291    int ret;
3292
3293#ifndef WOLFSSL_STATIC_EPHEMERAL
3294    if (session->sslServer->buffers.key == NULL ||
3295        session->sslServer->buffers.key->buffer == NULL ||
3296        session->sslServer->buffers.key->length == 0) {
3297
3298        SetError(RSA_KEY_MISSING_STR, error, session, FATAL_ERROR_STATE);
3299        return WOLFSSL_FATAL_ERROR;
3300    }
3301#endif
3302
3303    ret = SetupKeys(input, sslBytes, session, error, NULL);
3304
3305    return ret;
3306}
3307
3308#ifdef WOLFSSL_TLS13
3309static int ProcessKeyShare(KeyShareInfo* info, const byte* input, int len,
3310    word16 filter_group)
3311{
3312    int idx = 0;
3313    while (idx < len) {
3314        /* clear info (reset dh_key_bits and curve_id) */
3315        XMEMSET(info, 0, sizeof(KeyShareInfo));
3316
3317        /* Named group and public key */
3318        if (idx + OPAQUE16_LEN > len) {
3319            return WOLFSSL_FATAL_ERROR;
3320        }
3321        info->named_group = (word16)((input[idx] << 8) | input[idx+1]);
3322        idx += OPAQUE16_LEN;
3323        info->key_len = 0;
3324        info->key = NULL;
3325        /* If key was provided... (a hello_retry_request will not send a key) */
3326        if (idx + 2 <= len) {
3327            info->key_len = (word16)((input[idx] << 8) | input[idx+1]);
3328            idx += OPAQUE16_LEN;
3329            if (info->key_len == 0 || info->key_len > len - idx) {
3330                return WOLFSSL_FATAL_ERROR;
3331            }
3332            info->key = &input[idx];
3333            idx += info->key_len;
3334        }
3335
3336        switch (info->named_group) {
3337    #ifndef NO_DH
3338        #ifdef HAVE_FFDHE_2048
3339            case WOLFSSL_FFDHE_2048:
3340                info->dh_key_bits = 2048;
3341                break;
3342        #endif
3343        #ifdef HAVE_FFDHE_3072
3344            case WOLFSSL_FFDHE_3072:
3345                info->dh_key_bits = 3072;
3346                break;
3347        #endif
3348        #ifdef HAVE_FFDHE_4096
3349            case WOLFSSL_FFDHE_4096:
3350                info->dh_key_bits = 4096;
3351                break;
3352        #endif
3353        #ifdef HAVE_FFDHE_6144
3354            case WOLFSSL_FFDHE_6144:
3355                info->dh_key_bits = 6144;
3356                break;
3357        #endif
3358        #ifdef HAVE_FFDHE_8192
3359            case WOLFSSL_FFDHE_8192:
3360                info->dh_key_bits = 8192;
3361                break;
3362        #endif
3363    #endif /* !NO_DH */
3364    #ifdef HAVE_ECC
3365        #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES)
3366            #ifndef NO_ECC_SECP
3367            case WOLFSSL_ECC_SECP256R1:
3368                info->curve_id = ECC_SECP256R1;
3369                break;
3370            #endif /* !NO_ECC_SECP */
3371            #ifdef WOLFSSL_SM2
3372            case WOLFSSL_ECC_SM2P256V1:
3373                info->curve_id = ECC_SM2P256V1;
3374                break;
3375            #endif /* WOLFSSL_SM2 */
3376            #ifdef HAVE_ECC_BRAINPOOL
3377            case WOLFSSL_ECC_BRAINPOOLP256R1TLS13:
3378                info->curve_id = ECC_BRAINPOOLP256R1;
3379                break;
3380            #endif /* HAVE_ECC_BRAINPOOL */
3381        #endif
3382        #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)
3383            #ifndef NO_ECC_SECP
3384            case WOLFSSL_ECC_SECP384R1:
3385                info->curve_id = ECC_SECP384R1;
3386                break;
3387            #endif /* !NO_ECC_SECP */
3388            #ifdef HAVE_ECC_BRAINPOOL
3389            case WOLFSSL_ECC_BRAINPOOLP384R1TLS13:
3390                info->curve_id = ECC_BRAINPOOLP384R1;
3391                break;
3392            #endif /* HAVE_ECC_BRAINPOOL */
3393        #endif
3394        #if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES)
3395            #ifdef HAVE_ECC_BRAINPOOL
3396            case WOLFSSL_ECC_BRAINPOOLP512R1TLS13:
3397                info->curve_id = ECC_BRAINPOOLP512R1;
3398                break;
3399            #endif /* HAVE_ECC_BRAINPOOL */
3400        #endif
3401        #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)
3402            #ifndef NO_ECC_SECP
3403            case WOLFSSL_ECC_SECP521R1:
3404                info->curve_id = ECC_SECP521R1;
3405                break;
3406            #endif /* !NO_ECC_SECP */
3407        #endif
3408    #endif /* HAVE_ECC */
3409        #ifdef HAVE_CURVE25519
3410            case WOLFSSL_ECC_X25519:
3411                info->curve_id = ECC_X25519;
3412                break;
3413        #endif
3414        #ifdef HAVE_CURVE448
3415            case WOLFSSL_ECC_X448:
3416                info->curve_id = ECC_X448;
3417                break;
3418        #endif
3419            default:
3420                /* do not throw error here, keep iterating the client key share */
3421                break;
3422        }
3423
3424        if (filter_group == 0 || filter_group == info->named_group) {
3425            return 0;
3426        }
3427    }
3428    return NO_PEER_KEY; /* unsupported key type */
3429}
3430
3431static int ProcessServerKeyShare(SnifferSession* session, const byte* input, int len,
3432    char* error)
3433{
3434    int ret;
3435
3436    if (session->cliKeyShare == NULL || session->cliKeyShareSz == 0) {
3437        /* session->cliKeyShareSz could not be provided yet if the client_hello
3438            did not send a key share to force a hello_retry_request */
3439        return 0;
3440    }
3441
3442    /* Get server_hello key share (and key) */
3443    ret = ProcessKeyShare(&session->srvKs, input, len, 0);
3444    if (ret == 0 && session->srvKs.key_len > 0) {
3445        /* Get client_hello key share */
3446        ret = ProcessKeyShare(&session->cliKs, session->cliKeyShare,
3447            session->cliKeyShareSz, session->srvKs.named_group);
3448    }
3449    if (ret != 0) {
3450        SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
3451        return WOLFSSL_FATAL_ERROR;
3452    }
3453
3454    return ret;
3455}
3456#endif /* WOLFSSL_TLS13 */
3457
3458/* Process Session Ticket */
3459static int ProcessSessionTicket(const byte* input, int* sslBytes,
3460                                SnifferSession* session, char* error)
3461{
3462    word16 len;
3463
3464#ifdef WOLFSSL_TLS13
3465    WOLFSSL* ssl;
3466
3467    if (session->flags.side == WOLFSSL_SERVER_END)
3468        ssl = session->sslServer;
3469    else
3470        ssl = session->sslClient;
3471#endif
3472
3473    /* make sure can read through hint len */
3474    if (TICKET_HINT_LEN > *sslBytes) {
3475        SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
3476        return WOLFSSL_FATAL_ERROR;
3477    }
3478    input     += TICKET_HINT_LEN; /* skip over hint len */
3479    *sslBytes -= TICKET_HINT_LEN;
3480
3481#ifdef WOLFSSL_TLS13
3482    /* TLS v1.3 has hint age and nonce */
3483    if (IsAtLeastTLSv1_3(ssl->version)) {
3484        /* make sure can read through hint age and nonce len */
3485        if (TICKET_HINT_AGE_LEN + OPAQUE8_LEN > *sslBytes) {
3486            SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
3487            return WOLFSSL_FATAL_ERROR;
3488        }
3489        input     += TICKET_HINT_AGE_LEN; /* skip over hint age */
3490        *sslBytes -= TICKET_HINT_AGE_LEN;
3491
3492        /* ticket nonce */
3493        len = input[0];
3494        if (len > MAX_TICKET_NONCE_STATIC_SZ || len + OPAQUE8_LEN > *sslBytes) {
3495            SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
3496            return WOLFSSL_FATAL_ERROR;
3497        }
3498        input += OPAQUE8_LEN;
3499        *sslBytes -= OPAQUE8_LEN;
3500    #ifdef HAVE_SESSION_TICKET
3501        /* store nonce in server for DeriveResumptionPSK */
3502        session->sslServer->session->ticketNonce.len = len;
3503        if (len > 0)
3504            XMEMCPY(session->sslServer->session->ticketNonce.data, input, len);
3505    #endif
3506        input += len;
3507        *sslBytes -= len;
3508    }
3509#endif
3510
3511    /* make sure can read through len */
3512    if (OPAQUE16_LEN > *sslBytes) {
3513        SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
3514        return WOLFSSL_FATAL_ERROR;
3515    }
3516
3517    len = (word16)((input[0] << 8) | input[1]);
3518    input     += OPAQUE16_LEN;
3519    *sslBytes -= OPAQUE16_LEN;
3520
3521    /* make sure can read through ticket */
3522    if (len > *sslBytes) {
3523        SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
3524        return WOLFSSL_FATAL_ERROR;
3525    }
3526
3527#ifdef WOLFSSL_TLS13
3528    /* TLS v1.3 has hint age and nonce */
3529    if (IsAtLeastTLSv1_3(ssl->version)) {
3530        /* Note: Must use server session for sessions */
3531    #ifdef HAVE_SESSION_TICKET
3532        WOLFSSL_SESSION* sess;
3533        if (SetTicket(session->sslServer, input, len) != 0) {
3534            SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
3535            return WOLFSSL_FATAL_ERROR;
3536        }
3537
3538        /* set haveSessionId to use the wolfSession cache */
3539        session->sslServer->options.haveSessionId = 1;
3540
3541    #ifdef SNIFFER_SINGLE_SESSION_CACHE
3542        /* Use the wolf Session cache to retain resumption secret */
3543        if (session->flags.cached == 0) {
3544    #endif /* SNIFFER_SINGLE_SESSION_CACHE */
3545            sess = wolfSSL_GetSession(session->sslServer, NULL, 0);
3546            if (sess == NULL) {
3547                SetupSession(session->sslServer);
3548                AddSession(session->sslServer); /* don't re add */
3549            #ifdef WOLFSSL_SNIFFER_STATS
3550                INC_STAT(SnifferStats.sslResumptionInserts);
3551            #endif
3552            }
3553    #ifdef SNIFFER_SINGLE_SESSION_CACHE
3554            session->flags.cached = 1;
3555        }
3556    #endif /* SNIFFER_SINGLE_SESSION_CACHE */
3557    #endif /* HAVE_SESSION_TICKET */
3558    }
3559    else
3560#endif /* WOLFSSL_TLS13 */
3561    {
3562        /* capture last part of sessionID as macID (32 bytes) */
3563        if (len < ID_LEN) {
3564            SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
3565            return WOLFSSL_FATAL_ERROR;
3566        }
3567        /* store session with macID as sessionID */
3568        session->sslServer->options.haveSessionId = 1;
3569        if (session->sslServer->arrays) {
3570            XMEMCPY(session->sslServer->arrays->sessionID,
3571                input + len - ID_LEN, ID_LEN);
3572            session->sslServer->arrays->sessionIDSz = ID_LEN;
3573        }
3574    }
3575
3576    return 0;
3577}
3578
3579static int DoResume(SnifferSession* session, char* error)
3580{
3581    int ret = 0;
3582    WOLFSSL_SESSION* resume;
3583
3584#ifdef WOLFSSL_TLS13
3585    if (IsAtLeastTLSv1_3(session->sslServer->version)) {
3586        resume = wolfSSL_GetSession(session->sslServer,
3587                                    session->sslServer->session->masterSecret, 0);
3588        if (resume == NULL) {
3589            /* TLS v1.3 with hello_retry uses session_id even for new session,
3590                so ignore error here */
3591            return 0;
3592        }
3593    }
3594    else
3595#endif
3596    {
3597    #ifdef HAVE_SESSION_TICKET
3598        /* make sure "useTicket" is not set, otherwise the session will not be
3599         * properly retrieved */
3600        session->sslServer->options.useTicket = 0;
3601    #endif
3602        resume = wolfSSL_GetSession(session->sslServer,
3603                                    session->sslServer->arrays->masterSecret, 0);
3604        if (resume == NULL) {
3605        #ifdef WOLFSSL_SNIFFER_STATS
3606            INC_STAT(SnifferStats.sslResumeMisses);
3607        #endif
3608            SetError(BAD_SESSION_RESUME_STR, error, session, FATAL_ERROR_STATE);
3609            return WOLFSSL_FATAL_ERROR;
3610        }
3611    }
3612
3613    /* make sure client has master secret too */
3614#ifdef WOLFSSL_TLS13
3615    if (IsAtLeastTLSv1_3(session->sslServer->version)) {
3616        XMEMCPY(session->sslClient->session->masterSecret,
3617                session->sslServer->session->masterSecret, SECRET_LEN);
3618    }
3619    else
3620#endif
3621    {
3622        XMEMCPY(session->sslClient->arrays->masterSecret,
3623                session->sslServer->arrays->masterSecret, SECRET_LEN);
3624    }
3625    session->flags.resuming = 1;
3626
3627    Trace(SERVER_DID_RESUMPTION_STR);
3628#ifdef WOLFSSL_SNIFFER_STATS
3629    INC_STAT(SnifferStats.sslResumedConns);
3630#endif
3631    if (SetCipherSpecs(session->sslServer) != 0) {
3632        SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
3633        session->verboseErr = 1;
3634        return WOLFSSL_FATAL_ERROR;
3635    }
3636
3637    if (SetCipherSpecs(session->sslClient) != 0) {
3638        SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
3639        session->verboseErr = 1;
3640        return WOLFSSL_FATAL_ERROR;
3641    }
3642
3643#ifdef WOLFSSL_TLS13
3644    if (IsAtLeastTLSv1_3(session->sslServer->version)) {
3645    #ifdef HAVE_SESSION_TICKET
3646        /* Resumption PSK is resumption master secret. */
3647        session->sslServer->arrays->psk_keySz = session->sslServer->specs.hash_size;
3648        session->sslClient->arrays->psk_keySz = session->sslClient->specs.hash_size;
3649        ret  = DeriveResumptionPSK(session->sslServer,
3650            session->sslServer->session->ticketNonce.data,
3651            session->sslServer->session->ticketNonce.len,
3652            session->sslServer->arrays->psk_key);
3653        /* Copy resumption PSK to client */
3654        XMEMCPY(session->sslClient->arrays->psk_key,
3655            session->sslServer->arrays->psk_key,
3656            session->sslServer->arrays->psk_keySz);
3657    #endif
3658        /* handshake key setup below and traffic keys done in SetupKeys */
3659    }
3660    else
3661#endif
3662    {
3663        if (IsTLS(session->sslServer)) {
3664            ret =  DeriveTlsKeys(session->sslServer);
3665            ret += DeriveTlsKeys(session->sslClient);
3666        }
3667        else {
3668#ifndef NO_OLD_TLS
3669            ret =  DeriveKeys(session->sslServer);
3670            ret += DeriveKeys(session->sslClient);
3671#endif
3672        }
3673        ret += SetKeysSide(session->sslServer, ENCRYPT_AND_DECRYPT_SIDE);
3674        ret += SetKeysSide(session->sslClient, ENCRYPT_AND_DECRYPT_SIDE);
3675    }
3676
3677    if (ret != 0) {
3678        SetError(BAD_DERIVE_STR, error, session, FATAL_ERROR_STATE);
3679        return WOLFSSL_FATAL_ERROR;
3680    }
3681
3682    return ret;
3683}
3684
3685/* Process Server Hello */
3686static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
3687                              SnifferSession* session, char* error)
3688{
3689    int             ret = 0;
3690    ProtocolVersion pv;
3691    byte            b, b0;
3692    int             toRead = VERSION_SZ + RAN_LEN + ENUM_LEN;
3693    int             doResume = 0;
3694    const byte*     inputHello = input;
3695    int             initialBytes = *sslBytes;
3696
3697    (void)msgSz;
3698
3699    /* make sure we didn't miss ClientHello */
3700    if (session->flags.clientHello == 0 || session->sslClient->arrays == NULL) {
3701        SetError(MISSED_CLIENT_HELLO_STR, error, session, 0);
3702        return 0; /* do not throw error, just ignore packet */
3703    }
3704
3705    /* make sure can read through session len */
3706    if (toRead > *sslBytes) {
3707        SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
3708        return WOLFSSL_FATAL_ERROR;
3709    }
3710
3711    XMEMCPY(&pv, input, VERSION_SZ);
3712    input     += VERSION_SZ;
3713    *sslBytes -= VERSION_SZ;
3714
3715    session->sslServer->version = pv;
3716    session->sslClient->version = pv;
3717    if (pv.minor >= TLSv1_MINOR) {
3718        session->sslServer->options.tls = 1;
3719        session->sslClient->options.tls = 1;
3720    }
3721
3722    XMEMCPY(session->sslServer->arrays->serverRandom, input, RAN_LEN);
3723    XMEMCPY(session->sslClient->arrays->serverRandom, input, RAN_LEN);
3724    input     += RAN_LEN;
3725    *sslBytes -= RAN_LEN;
3726
3727    b = *input++;
3728    *sslBytes -= 1;
3729
3730    /* make sure can read through compression */
3731    if ( (b + SUITE_LEN + ENUM_LEN) > *sslBytes) {
3732        SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
3733        return WOLFSSL_FATAL_ERROR;
3734    }
3735    if (b) {
3736    #ifdef WOLFSSL_TLS13
3737        XMEMCPY(session->sslServer->session->sessionID, input, ID_LEN);
3738        session->sslServer->session->sessionIDSz = ID_LEN;
3739    #endif
3740        XMEMCPY(session->sslServer->arrays->sessionID, input, ID_LEN);
3741        session->sslServer->arrays->sessionIDSz = ID_LEN;
3742        session->sslServer->options.haveSessionId = 1;
3743    }
3744    input     += b;
3745    *sslBytes -= b;
3746
3747    /* cipher suite */
3748    b0 = *input++;  /* first byte, ECC or not */
3749    session->sslServer->options.cipherSuite0 = b0;
3750    session->sslClient->options.cipherSuite0 = b0;
3751    b = *input++;
3752    session->sslServer->options.cipherSuite = b;
3753    session->sslClient->options.cipherSuite = b;
3754    *sslBytes -= SUITE_LEN;
3755
3756#ifdef WOLFSSL_SNIFFER_STATS
3757    {
3758        const CipherSuiteInfo* suites = GetCipherNames();
3759        int suitesSz = GetCipherNamesSize();
3760        int match = 0;
3761
3762        while (suitesSz) {
3763            if (b0 == suites->cipherSuite0 && b == suites->cipherSuite) {
3764                match = 1;
3765                break;
3766            }
3767            suites++;
3768            suitesSz--;
3769        }
3770        if (!match)
3771            INC_STAT(SnifferStats.sslCiphersUnsupported);
3772    }
3773#endif /* WOLFSSL_SNIFFER_STATS */
3774
3775    /* compression */
3776    b = *input++;
3777    *sslBytes -= ENUM_LEN;
3778
3779    if (b) {
3780        SetError(BAD_COMPRESSION_STR, error, session, FATAL_ERROR_STATE);
3781        return WOLFSSL_FATAL_ERROR;
3782    }
3783
3784    /* extensions */
3785    if ((initialBytes - *sslBytes) < msgSz) {
3786        word16 len;
3787
3788        /* skip extensions until extended master secret */
3789        /* make sure can read len */
3790        if (SUITE_LEN > *sslBytes) {
3791            SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
3792            return WOLFSSL_FATAL_ERROR;
3793        }
3794        len = (word16)((input[0] << 8) | input[1]);
3795        input     += SUITE_LEN;
3796        *sslBytes -= SUITE_LEN;
3797        /* make sure can read through all extensions */
3798        if (len > *sslBytes) {
3799            SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
3800            return WOLFSSL_FATAL_ERROR;
3801        }
3802
3803        while (len >= EXT_TYPE_SZ + LENGTH_SZ) {
3804            word16 extType;
3805            word16 extLen;
3806
3807            extType    = (word16)((input[0] << 8) | input[1]);
3808            input     += EXT_TYPE_SZ;
3809            *sslBytes -= EXT_TYPE_SZ;
3810
3811            extLen     = (word16)((input[0] << 8) | input[1]);
3812            input     += LENGTH_SZ;
3813            *sslBytes -= LENGTH_SZ;
3814
3815            /* make sure can read through individual extension */
3816            if (extLen > *sslBytes) {
3817                SetError(SERVER_HELLO_INPUT_STR, error, session,
3818                         FATAL_ERROR_STATE);
3819                return WOLFSSL_FATAL_ERROR;
3820            }
3821        #ifdef DEBUG_SNIFFER
3822            printf("\tserver_hello ext: 0x%02x (len %d)\n", extType, extLen);
3823        #endif
3824
3825            switch (extType) {
3826        #ifdef WOLFSSL_TLS13
3827            case EXT_KEY_SHARE:
3828                ret = ProcessServerKeyShare(session, input, extLen, error);
3829                if (ret != 0) {
3830                    SetError(SERVER_HELLO_INPUT_STR, error, session,
3831                        FATAL_ERROR_STATE);
3832                    return WOLFSSL_FATAL_ERROR;
3833                }
3834                break;
3835        #endif
3836        #ifdef HAVE_SESSION_TICKET
3837            case EXT_PRE_SHARED_KEY:
3838                /* indicates we want to use resumption */
3839                session->sslServer->options.resuming = 1;
3840                session->sslClient->options.resuming = 1;
3841            #ifdef WOLFSSL_TLS13
3842                /* default nonce to len = 1, data = 0 */
3843                session->sslServer->session->ticketNonce.len = 1;
3844                session->sslServer->session->ticketNonce.data[0] = 0;
3845                session->sslClient->session->ticketNonce.len = 1;
3846                session->sslClient->session->ticketNonce.data[0] = 0;
3847            #endif
3848                break;
3849        #endif
3850        #ifdef HAVE_MAX_FRAGMENT
3851            case EXT_MAX_FRAGMENT_LENGTH:
3852            {
3853                word16 max_fragment = MAX_RECORD_SIZE;
3854                if (extLen != 1) {
3855                    SetError(SERVER_HELLO_INPUT_STR, error, session,
3856                             FATAL_ERROR_STATE);
3857                    return WOLFSSL_FATAL_ERROR;
3858                }
3859                switch (input[0]) {
3860                    case WOLFSSL_MFL_2_8 : max_fragment =  256; break;
3861                    case WOLFSSL_MFL_2_9 : max_fragment =  512; break;
3862                    case WOLFSSL_MFL_2_10: max_fragment = 1024; break;
3863                    case WOLFSSL_MFL_2_11: max_fragment = 2048; break;
3864                    case WOLFSSL_MFL_2_12: max_fragment = 4096; break;
3865                    case WOLFSSL_MFL_2_13: max_fragment = 8192; break;
3866                    default: break;
3867                }
3868                session->sslServer->max_fragment = max_fragment;
3869                session->sslClient->max_fragment = max_fragment;
3870                break;
3871            }
3872        #endif
3873            case EXT_SUPPORTED_VERSIONS:
3874                if (extLen != 2) {
3875                    SetError(SERVER_HELLO_INPUT_STR, error, session,
3876                             FATAL_ERROR_STATE);
3877                    return WOLFSSL_FATAL_ERROR;
3878                }
3879                session->sslServer->version.major = input[0];
3880                session->sslServer->version.minor = input[1];
3881                session->sslClient->version.major = input[0];
3882                session->sslClient->version.minor = input[1];
3883                if (IsAtLeastTLSv1_3(session->sslServer->version)) {
3884                    /* The server side handshake encryption is on for future packets */
3885                    session->flags.serverCipherOn = 1;
3886                }
3887                break;
3888            case EXT_MASTER_SECRET:
3889            #ifdef HAVE_EXTENDED_MASTER
3890                session->flags.expectEms = 1;
3891            #endif
3892                break;
3893            case EXT_RENEGOTIATION_INFO:
3894                session->flags.secRenegEn = 1;
3895                break;
3896            } /* switch (extType) */
3897
3898            input     += extLen;
3899            *sslBytes -= extLen;
3900            len       -= extLen + EXT_TYPE_SZ + LENGTH_SZ;
3901        }
3902    }
3903
3904    if (IsAtLeastTLSv1_3(session->sslServer->version)) {
3905#ifndef WOLFSSL_TLS13
3906        SetError(UNSUPPORTED_TLS_VER_STR, error, session, FATAL_ERROR_STATE);
3907        session->verboseErr = 1;
3908        return WOLFSSL_FATAL_ERROR;
3909#endif
3910    }
3911    else {
3912#ifdef WOLFSSL_NO_TLS12
3913        SetError(UNSUPPORTED_TLS_VER_STR, error, session, FATAL_ERROR_STATE);
3914        session->verboseErr = 1;
3915        return WOLFSSL_FATAL_ERROR;
3916#endif
3917    }
3918
3919#ifdef HAVE_EXTENDED_MASTER
3920    if (!session->flags.expectEms) {
3921        XFREE(session->hash, NULL, DYNAMIC_TYPE_HASHES);
3922        session->hash = NULL;
3923    }
3924#endif
3925
3926    if (session->sslServer->options.haveSessionId) {
3927        if (session->sslServer->arrays->sessionIDSz == ID_LEN &&
3928                session->sslClient->arrays->sessionIDSz == ID_LEN &&
3929                XMEMCMP(session->sslServer->arrays->sessionID,
3930                        session->sslClient->arrays->sessionID, ID_LEN) == 0) {
3931            doResume = 1;
3932        }
3933    }
3934    else if (session->sslClient->options.haveSessionId == 0 &&
3935             session->sslServer->options.haveSessionId == 0 &&
3936             session->ticketID) {
3937        doResume = 1;
3938    }
3939
3940    if (session->ticketID && doResume) {
3941        /* use ticketID to retrieve from session, prefer over sessionID */
3942        XMEMCPY(session->sslServer->arrays->sessionID,session->ticketID,ID_LEN);
3943        session->sslServer->arrays->sessionIDSz = ID_LEN;
3944        session->sslServer->options.haveSessionId = 1;  /* may not have
3945                                                           actual sessionID */
3946    }
3947
3948#ifdef WOLFSSL_TLS13
3949    /* Is TLS v1.3 hello_retry_request? */
3950    if (IsAtLeastTLSv1_3(session->sslServer->version) && session->srvKs.key_len == 0) {
3951        Trace(GOT_HELLO_RETRY_REQ_STR);
3952
3953        /* do not compute keys yet */
3954        session->flags.serverCipherOn = 0;
3955
3956        /* make sure the mac and digest size are set */
3957        SetCipherSpecs(session->sslServer);
3958        SetCipherSpecs(session->sslClient);
3959
3960        /* reset hashes */
3961        RestartHandshakeHash(session->sslServer);
3962        RestartHandshakeHash(session->sslClient);
3963
3964        doResume = 0;
3965    }
3966#endif
3967
3968#ifdef WOLFSSL_ASYNC_CRYPT
3969    if (session->sslServer->error != WC_NO_ERR_TRACE(WC_PENDING_E) &&
3970        session->pendSeq == 0)
3971#endif
3972    {
3973        /* hash server_hello */
3974        HashRaw(session->sslServer, inputHello - HANDSHAKE_HEADER_SZ,
3975            initialBytes + HANDSHAKE_HEADER_SZ);
3976        HashRaw(session->sslClient, inputHello - HANDSHAKE_HEADER_SZ,
3977            initialBytes + HANDSHAKE_HEADER_SZ);
3978    }
3979
3980    if (doResume) {
3981        ret = DoResume(session, error);
3982        if (ret != 0) {
3983            return ret;
3984        }
3985    }
3986    else {
3987#ifdef WOLFSSL_SNIFFER_STATS
3988        INC_STAT(SnifferStats.sslStandardConns);
3989#endif
3990    }
3991
3992#ifdef SHOW_SECRETS
3993    printf("cipher suite = 0x%02x\n", session->sslServer->options.cipherSuite);
3994    PrintSecret("server random", session->sslServer->arrays->serverRandom, RAN_LEN);
3995#endif
3996
3997#ifdef WOLFSSL_TLS13
3998    /* Setup handshake keys */
3999    if (IsAtLeastTLSv1_3(session->sslServer->version) && session->srvKs.key_len > 0) {
4000        ret = SetupKeys(session->cliKs.key, &session->cliKs.key_len,
4001            session, error, &session->cliKs);
4002        if (ret != 0) {
4003        #ifdef WOLFSSL_ASYNC_CRYPT
4004            if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
4005                return ret;
4006            }
4007        #endif
4008            SetError(KEY_MISMATCH_STR, error, session, FATAL_ERROR_STATE);
4009            session->verboseErr = 1;
4010            return ret;
4011        }
4012
4013        if (session->flags.side == WOLFSSL_SERVER_END)
4014            session->flags.serverCipherOn = 1;
4015        else
4016            session->flags.clientCipherOn = 1;
4017    }
4018#endif
4019
4020    return 0;
4021}
4022
4023#ifdef HAVE_SNI
4024/* Function return value must be 0 for success */
4025static int LoadNamedKey(SnifferSession* session, const byte* name, word16 nameSz)
4026{
4027    int ret = 0;
4028    WOLFSSL* ssl = session->sslServer;
4029    NamedKey* namedKey;
4030
4031    wc_LockMutex(&session->context->namedKeysMutex);
4032    namedKey = session->context->namedKeys;
4033    while (namedKey != NULL) {
4034        if (nameSz == namedKey->nameSz &&
4035                    XSTRNCMP((char*)name, namedKey->name, nameSz) == 0) {
4036        #ifdef WOLFSSL_STATIC_EPHEMERAL
4037            if (namedKey->isEphemeralKey) {
4038                /* auto detect key type with WC_PK_TYPE_NONE */
4039                ret = wolfSSL_set_ephemeral_key(ssl,
4040                    WC_PK_TYPE_NONE, (const char*)namedKey->key,
4041                    namedKey->keySz, WOLFSSL_FILETYPE_ASN1);
4042            }
4043            else
4044        #endif
4045            {
4046                ret = wolfSSL_use_PrivateKey_buffer(ssl,
4047                    namedKey->key, namedKey->keySz,
4048                    WOLFSSL_FILETYPE_ASN1);
4049                /* translate return code */
4050                ret = (ret == WOLFSSL_SUCCESS) ? 0 : -1;
4051            }
4052            if (ret == 0) {
4053                session->sni = namedKey->name;
4054            }
4055            break;
4056        }
4057        namedKey = namedKey->next;
4058    }
4059    wc_UnLockMutex(&session->context->namedKeysMutex);
4060    return ret;
4061}
4062#endif
4063
4064/* Process normal Client Hello */
4065static int ProcessClientHello(const byte* input, int* sslBytes,
4066                              SnifferSession* session, char* error)
4067{
4068    int ret = 0;
4069    byte   bLen;
4070    word16 len;
4071    int    toRead = VERSION_SZ + RAN_LEN + ENUM_LEN;
4072    const byte* inputHello = input;
4073    int inputHelloSz = *sslBytes;
4074    WOLFSSL* ssl = session->sslServer;
4075    int didHash = 0;
4076
4077    session->flags.clientHello = 1;  /* don't process again */
4078
4079    /* make sure can read up to session len */
4080    if (toRead > *sslBytes) {
4081        SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
4082        return WOLFSSL_FATAL_ERROR;
4083    }
4084
4085    /* skip, get negotiated one from server hello */
4086    input     += VERSION_SZ;
4087    *sslBytes -= VERSION_SZ;
4088
4089    /* for secure renegotiation server arrays can be NULL */
4090    if (session->sslServer->arrays)
4091        XMEMCPY(session->sslServer->arrays->clientRandom, input, RAN_LEN);
4092    if (session->sslClient->arrays)
4093        XMEMCPY(session->sslClient->arrays->clientRandom, input, RAN_LEN);
4094
4095    input     += RAN_LEN;
4096    *sslBytes -= RAN_LEN;
4097
4098    /* store session in case trying to resume */
4099    bLen = *input++;
4100    *sslBytes -= ENUM_LEN;
4101    if (bLen) {
4102        if (ID_LEN > *sslBytes) {
4103            SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
4104            return WOLFSSL_FATAL_ERROR;
4105        }
4106        Trace(CLIENT_RESUME_TRY_STR);
4107#ifdef WOLFSSL_TLS13
4108        XMEMCPY(session->sslClient->session->sessionID, input, ID_LEN);
4109        session->sslClient->session->sessionIDSz = ID_LEN;
4110#endif
4111        if (session->sslClient->arrays) {
4112            XMEMCPY(session->sslClient->arrays->sessionID, input, ID_LEN);
4113            session->sslClient->arrays->sessionIDSz = ID_LEN;
4114        }
4115        session->sslClient->options.haveSessionId = 1;
4116    }
4117
4118#ifdef SHOW_SECRETS
4119    if (ssl->arrays)
4120        PrintSecret("client random", ssl->arrays->clientRandom, RAN_LEN);
4121#endif
4122
4123    input     += bLen;
4124    *sslBytes -= bLen;
4125
4126    /* skip cipher suites */
4127    /* make sure can read len */
4128    if (SUITE_LEN > *sslBytes) {
4129        SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
4130        return WOLFSSL_FATAL_ERROR;
4131    }
4132    len = (word16)((input[0] << 8) | input[1]);
4133    input     += SUITE_LEN;
4134    *sslBytes -= SUITE_LEN;
4135    /* make sure can read suites + comp len */
4136    if (len + ENUM_LEN > *sslBytes) {
4137        SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
4138        return WOLFSSL_FATAL_ERROR;
4139    }
4140    input     += len;
4141    *sslBytes -= len;
4142
4143    /* skip compression */
4144    bLen       = *input++;
4145    *sslBytes -= ENUM_LEN;
4146    /* make sure can read len */
4147    if (bLen > *sslBytes) {
4148        SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
4149        return WOLFSSL_FATAL_ERROR;
4150    }
4151    input     += bLen;
4152    *sslBytes -= bLen;
4153
4154    if (*sslBytes == 0) {
4155        /* no extensions */
4156        return 0;
4157    }
4158
4159    /* skip extensions until session ticket */
4160    /* make sure can read len */
4161    if (SUITE_LEN > *sslBytes) {
4162        SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
4163        return WOLFSSL_FATAL_ERROR;
4164    }
4165    len = (word16)((input[0] << 8) | input[1]);
4166    input     += SUITE_LEN;
4167    *sslBytes -= SUITE_LEN;
4168    /* make sure can read through all extensions */
4169    if (len > *sslBytes) {
4170        SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
4171        return WOLFSSL_FATAL_ERROR;
4172    }
4173
4174    while (len >= EXT_TYPE_SZ + LENGTH_SZ) {
4175        word16 extType;
4176        word16 extLen;
4177
4178        extType    = (word16)((input[0] << 8) | input[1]);
4179        input     += EXT_TYPE_SZ;
4180        *sslBytes -= EXT_TYPE_SZ;
4181
4182        extLen     = (word16)((input[0] << 8) | input[1]);
4183        input     += LENGTH_SZ;
4184        *sslBytes -= LENGTH_SZ;
4185
4186        /* make sure can read through individual extension */
4187        if (extLen > *sslBytes) {
4188            SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
4189            return WOLFSSL_FATAL_ERROR;
4190        }
4191
4192    #ifdef DEBUG_SNIFFER
4193        printf("\tclient_hello ext: 0x%02x (len %d)\n", extType, extLen);
4194    #endif
4195
4196        switch (extType) {
4197    #ifdef HAVE_SNI
4198        case EXT_SERVER_NAME:
4199        {
4200            word16 listLen = 0, offset = 0;
4201
4202            if (extLen < OPAQUE16_LEN)
4203                return BUFFER_ERROR;
4204
4205            ato16(input + offset, &listLen);
4206            offset += OPAQUE16_LEN;
4207
4208            if (extLen < offset + listLen)
4209                return BUFFER_ERROR;
4210
4211            while (listLen > ENUM_LEN + OPAQUE16_LEN) {
4212                byte   sniType = input[offset++];
4213                word16 sniLen;
4214
4215                ato16(input + offset, &sniLen);
4216                offset += OPAQUE16_LEN;
4217
4218                if (extLen < offset + sniLen)
4219                    return BUFFER_ERROR;
4220
4221                if (sniType == WOLFSSL_SNI_HOST_NAME) {
4222                    ret = LoadNamedKey(session, input + offset, sniLen);
4223                    if (ret < 0) {
4224                        /* don't treat this as fatal error */
4225                        SetError(CLIENT_HELLO_LATE_KEY_STR, error, session, 0);
4226                        break;
4227                    }
4228                }
4229                offset  += sniLen;
4230                listLen -= min(ENUM_LEN + OPAQUE16_LEN + sniLen, listLen);
4231            }
4232            break;
4233        }
4234    #endif
4235    #ifdef WOLFSSL_TLS13
4236        case EXT_KEY_SHARE:
4237        {
4238            word16 ksLen = 0;
4239            if (extLen < OPAQUE16_LEN) {
4240                SetError(BUFFER_ERROR_STR, error, session, FATAL_ERROR_STATE);
4241                return BUFFER_ERROR;
4242            }
4243
4244            ksLen = (word16)((input[0] << 8) | input[1]);
4245            if (ksLen + OPAQUE16_LEN > extLen) {
4246                SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
4247                return WOLFSSL_FATAL_ERROR;
4248            }
4249            /* cache key share data till server_hello */
4250            session->cliKeyShareSz = ksLen;
4251            if (ksLen > 0) {
4252                session->cliKeyShare = (byte*)XMALLOC(ksLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
4253                if (session->cliKeyShare == NULL) {
4254                    SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
4255                    break;
4256                }
4257                XMEMCPY(session->cliKeyShare, &input[2], ksLen);
4258            }
4259            break;
4260        }
4261        #ifdef HAVE_SESSION_TICKET
4262        case EXT_PRE_SHARED_KEY:
4263        {
4264            word16 idsLen, idLen, bindersLen, idx = 0;
4265            word32 ticketAge;
4266            const byte *identity, *binders;
4267
4268            if (extLen < OPAQUE16_LEN) {
4269                SetError(BUFFER_ERROR_STR, error, session, FATAL_ERROR_STATE);
4270                return BUFFER_ERROR;
4271            }
4272
4273            idsLen = (word16)((input[idx] << 8) | input[idx+1]);
4274            if ((word32)idsLen + OPAQUE16_LEN + idx > (word32)extLen) {
4275                SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
4276                return WOLFSSL_FATAL_ERROR;
4277            }
4278            idx += OPAQUE16_LEN;
4279
4280            /* PSK identity */
4281            idLen = (word16)((input[idx] << 8) | input[idx+1]);
4282            if ((word32)idLen + OPAQUE16_LEN + idx > (word32)extLen) {
4283                SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
4284                return WOLFSSL_FATAL_ERROR;
4285            }
4286            idx += OPAQUE16_LEN;
4287            identity = &input[idx];
4288            idx += idLen;
4289
4290            /* Obfuscated Ticket Age 32-bits */
4291            if ((word32)idx + OPAQUE32_LEN > (word32)extLen) {
4292                SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
4293                return WOLFSSL_FATAL_ERROR;
4294            }
4295            ticketAge = (word32)((input[idx] << 24) | (input[idx+1] << 16) |
4296                                 (input[idx+2] << 8) | input[idx+3]);
4297            (void)ticketAge; /* not used */
4298            idx += OPAQUE32_LEN;
4299
4300            /* binders - all binders */
4301            if ((word32)idx + OPAQUE16_LEN > (word32)extLen) {
4302                SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
4303                return WOLFSSL_FATAL_ERROR;
4304            }
4305            bindersLen = (word16)((input[idx] << 8) | input[idx+1]);
4306            if ((word32)bindersLen + OPAQUE16_LEN + idx > (word32)extLen) {
4307                SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
4308                return WOLFSSL_FATAL_ERROR;
4309            }
4310            idx += OPAQUE16_LEN;
4311            binders = &input[idx];
4312            bindersLen += OPAQUE16_LEN; /* includes 2 bytes for total len */
4313            (void)binders; /* not used */
4314
4315            /* Hash data up to binders for deriving binders in PSK extension. */
4316            HashRaw(session->sslServer, inputHello - HANDSHAKE_HEADER_SZ,
4317                inputHelloSz - bindersLen + HANDSHAKE_HEADER_SZ);
4318            HashRaw(session->sslClient, inputHello - HANDSHAKE_HEADER_SZ,
4319                inputHelloSz - bindersLen + HANDSHAKE_HEADER_SZ);
4320
4321            /* call to decrypt session ticket */
4322            if (DoClientTicket(ssl, identity, idLen) != WOLFSSL_TICKET_RET_OK) {
4323                /* we aren't decrypting the resumption, since we know the master secret */
4324                /* ignore errors */
4325            }
4326            ssl->options.resuming  = 1;
4327
4328            /* Hash the rest of the ClientHello. */
4329            HashRaw(session->sslServer, inputHello + inputHelloSz - bindersLen, bindersLen);
4330            HashRaw(session->sslClient, inputHello + inputHelloSz - bindersLen, bindersLen);
4331            didHash = 1;
4332            break;
4333        }
4334        #endif /* HAVE_SESSION_TICKET */
4335    #endif /* WOLFSSL_TLS13 */
4336        case EXT_SUPPORTED_VERSIONS:
4337            break;
4338        case EXT_TICKET_ID:
4339            /* make sure can read through ticket if there is a non blank one */
4340            if (extLen && extLen < ID_LEN) {
4341                SetError(CLIENT_HELLO_INPUT_STR, error, session,
4342                         FATAL_ERROR_STATE);
4343                return WOLFSSL_FATAL_ERROR;
4344            }
4345            if (extLen) {
4346                if (session->ticketID == NULL) {
4347                    session->ticketID = (byte*)XMALLOC(ID_LEN,
4348                            NULL, DYNAMIC_TYPE_SNIFFER_TICKET_ID);
4349                    if (session->ticketID == 0) {
4350                        SetError(MEMORY_STR, error, session,
4351                                 FATAL_ERROR_STATE);
4352                        return WOLFSSL_FATAL_ERROR;
4353                    }
4354                }
4355
4356            #ifdef HAVE_SESSION_TICKET
4357                /* do not set "ssl->options.useTicket", since the sniffer uses
4358                 * the cache differently for retaining the master secret only */
4359            #endif
4360                XMEMCPY(session->ticketID, input + extLen - ID_LEN, ID_LEN);
4361            }
4362            break;
4363        }
4364
4365        input     += extLen;
4366        *sslBytes -= extLen;
4367        len       -= extLen + EXT_TYPE_SZ + LENGTH_SZ;
4368    }
4369
4370    if (!didHash) {
4371        HashRaw(session->sslServer, inputHello - HANDSHAKE_HEADER_SZ,
4372            inputHelloSz + HANDSHAKE_HEADER_SZ);
4373        HashRaw(session->sslClient, inputHello - HANDSHAKE_HEADER_SZ,
4374            inputHelloSz + HANDSHAKE_HEADER_SZ);
4375    }
4376
4377    (void)ssl;
4378
4379    return ret;
4380}
4381
4382
4383#ifdef WOLFSSL_SNIFFER_WATCH
4384
4385static int KeyWatchCall(SnifferSession* session, const byte* data, int dataSz,
4386    char* error)
4387{
4388    int ret;
4389    wc_Sha256 sha;
4390    byte digest[WC_SHA256_DIGEST_SIZE];
4391
4392    if (WatchCb == NULL) {
4393        SetError(WATCH_CB_MISSING_STR, error, session, FATAL_ERROR_STATE);
4394        return WOLFSSL_FATAL_ERROR;
4395    }
4396
4397    ret = wc_InitSha256(&sha);
4398    if (ret == 0)
4399        ret = wc_Sha256Update(&sha, data, dataSz);
4400    if (ret == 0)
4401        ret = wc_Sha256Final(&sha, digest);
4402    if (ret != 0) {
4403        SetError(WATCH_HASH_STR, error, session, FATAL_ERROR_STATE);
4404        return WOLFSSL_FATAL_ERROR;
4405    }
4406
4407    ret = WatchCb((void*)session, digest, sizeof(digest),
4408            data, dataSz, WatchCbCtx, error);
4409    if (ret != 0) {
4410#ifdef WOLFSSL_SNIFFER_STATS
4411        INC_STAT(SnifferStats.sslKeysUnmatched);
4412#endif
4413        SetError(WATCH_FAIL_STR, error, session, FATAL_ERROR_STATE);
4414        ret = WOLFSSL_FATAL_ERROR;
4415    }
4416    else {
4417#ifdef WOLFSSL_SNIFFER_STATS
4418        INC_STAT(SnifferStats.sslKeyMatches);
4419#endif
4420    }
4421    return ret;
4422}
4423
4424/* Process Certificate */
4425static int ProcessCertificate(const byte* input, int* sslBytes,
4426        SnifferSession* session, char* error)
4427{
4428    word32 certChainSz;
4429    word32 certSz;
4430
4431    /* If the receiver is the server, this is the client certificate message,
4432     * and it should be ignored at this point. */
4433    if (session->flags.side == WOLFSSL_SERVER_END)
4434        return 0;
4435
4436    if (*sslBytes < CERT_HEADER_SZ) {
4437        SetError(BAD_CERT_MSG_STR, error, session, FATAL_ERROR_STATE);
4438        return WOLFSSL_FATAL_ERROR;
4439    }
4440
4441#ifdef WOLFSSL_TLS13
4442    if (IsAtLeastTLSv1_3(session->sslServer->version)) {
4443        /* skip 1 byte (Request context len) */
4444        input += OPAQUE8_LEN;
4445        *sslBytes -= OPAQUE8_LEN;
4446    }
4447#endif
4448
4449    ato24(input, &certChainSz);
4450    *sslBytes -= CERT_HEADER_SZ;
4451    input += CERT_HEADER_SZ;
4452
4453    if (*sslBytes < (int)certChainSz) {
4454        SetError(BAD_CERT_MSG_STR, error, session, FATAL_ERROR_STATE);
4455        return WOLFSSL_FATAL_ERROR;
4456    }
4457
4458    ato24(input, &certSz);
4459    input += OPAQUE24_LEN;
4460    if (*sslBytes < (int)certSz) {
4461        SetError(BAD_CERT_MSG_STR, error, session, FATAL_ERROR_STATE);
4462        return WOLFSSL_FATAL_ERROR;
4463    }
4464
4465    *sslBytes -= certChainSz;
4466
4467    return KeyWatchCall(session, input, certSz, error);
4468}
4469
4470#endif /* WOLFSSL_SNIFFER_WATCH */
4471
4472
4473/* Process Finished */
4474static int ProcessFinished(const byte* input, int size, int* sslBytes,
4475                           SnifferSession* session, char* error)
4476{
4477    WOLFSSL* ssl;
4478    word32 inOutIdx = 0;
4479    int    ret;
4480
4481    if (session->flags.side == WOLFSSL_SERVER_END)
4482        ssl = session->sslServer;
4483    else
4484        ssl = session->sslClient;
4485
4486#ifdef WOLFSSL_TLS13
4487    if (IsAtLeastTLSv1_3(ssl->version)) {
4488        ret = DoTls13Finished(ssl, input, &inOutIdx, (word32)size,
4489            (word32)*sslBytes, SNIFF);
4490
4491        ssl->options.handShakeState = HANDSHAKE_DONE;
4492        ssl->options.handShakeDone  = 1;
4493    }
4494    else
4495#endif
4496    {
4497        ret = DoFinished(ssl, input, &inOutIdx, (word32)size,
4498            (word32)*sslBytes, SNIFF);
4499    }
4500    *sslBytes -= (int)inOutIdx;
4501
4502    if (ret < 0) {
4503        SetError(BAD_FINISHED_MSG, error, session, FATAL_ERROR_STATE);
4504        return ret;
4505    }
4506
4507    if (ret == 0
4508    #ifdef SNIFFER_SINGLE_SESSION_CACHE
4509            && session->flags.cached == 0
4510    #endif
4511            ) {
4512        if (session->sslServer->options.haveSessionId) {
4513        #ifndef NO_SESSION_CACHE
4514            WOLFSSL_SESSION* sess = wolfSSL_GetSession(session->sslServer, NULL, 0);
4515            if (sess == NULL) {
4516                SetupSession(session->sslServer);
4517                AddSession(session->sslServer); /* don't re add */
4518            #ifdef WOLFSSL_SNIFFER_STATS
4519                INC_STAT(SnifferStats.sslResumptionInserts);
4520            #endif
4521            }
4522            #ifdef SNIFFER_SINGLE_SESSION_CACHE
4523                session->flags.cached = 1;
4524            #endif
4525        #endif
4526         }
4527    }
4528
4529#ifdef WOLFSSL_TLS13
4530    /* Derive TLS v1.3 traffic keys */
4531    if (IsAtLeastTLSv1_3(ssl->version)) {
4532        if (!session->flags.gotFinished) {
4533            /* When either side gets "finished" derive master secret and keys */
4534            ret  = DeriveMasterSecret(session->sslServer);
4535            ret += DeriveMasterSecret(session->sslClient);
4536        #ifdef WOLFSSL_EARLY_DATA
4537            ret += DeriveTls13Keys(session->sslServer, traffic_key, ENCRYPT_AND_DECRYPT_SIDE, ssl->earlyData == no_early_data);
4538            ret += DeriveTls13Keys(session->sslClient, traffic_key, ENCRYPT_AND_DECRYPT_SIDE, ssl->earlyData == no_early_data);
4539        #else
4540            ret += DeriveTls13Keys(session->sslServer, traffic_key, ENCRYPT_AND_DECRYPT_SIDE, 1);
4541            ret += DeriveTls13Keys(session->sslClient, traffic_key, ENCRYPT_AND_DECRYPT_SIDE, 1);
4542        #endif
4543
4544            if (ret != 0) {
4545                SetError(BAD_FINISHED_MSG, error, session, FATAL_ERROR_STATE);
4546                return WOLFSSL_FATAL_ERROR;
4547            }
4548
4549            session->flags.gotFinished = 1;
4550        #ifdef SHOW_SECRETS
4551            ShowTlsSecrets(session);
4552        #endif
4553        }
4554
4555        if (session->flags.side == WOLFSSL_SERVER_END) {
4556            /* finished from client to server */
4557            ret  = SetKeysSide(session->sslServer, DECRYPT_SIDE_ONLY);
4558            ret += SetKeysSide(session->sslClient, ENCRYPT_SIDE_ONLY);
4559
4560        #ifdef HAVE_SESSION_TICKET
4561            /* derive resumption secret for next session - on finished (from client) */
4562            ret += DeriveResumptionSecret(session->sslClient,
4563                session->sslClient->session->masterSecret);
4564
4565            /* copy resumption secret to server */
4566            XMEMCPY(session->sslServer->session->masterSecret,
4567                    session->sslClient->session->masterSecret, SECRET_LEN);
4568            #ifdef SHOW_SECRETS
4569            PrintSecret("resumption secret",
4570                session->sslClient->session->masterSecret, SECRET_LEN);
4571            #endif
4572        #endif
4573        }
4574        else {
4575            /* finished from server to client */
4576            ret  = SetKeysSide(session->sslServer, ENCRYPT_SIDE_ONLY);
4577            ret += SetKeysSide(session->sslClient, DECRYPT_SIDE_ONLY);
4578        }
4579
4580        if (ret != 0) {
4581            SetError(BAD_FINISHED_MSG, error, session, FATAL_ERROR_STATE);
4582            return WOLFSSL_FATAL_ERROR;
4583        }
4584    }
4585#endif
4586
4587    /* Do not free handshake resources yet if secure renegotiation */
4588    if (session->flags.secRenegEn == 0) {
4589        /* If receiving a finished message from one side, free the resources
4590         * from the other side's tracker. */
4591        if (session->flags.side == WOLFSSL_SERVER_END)
4592            FreeHandshakeResources(session->sslClient);
4593        else
4594            FreeHandshakeResources(session->sslServer);
4595    }
4596
4597    return ret;
4598}
4599
4600
4601/* Process HandShake input */
4602static int DoHandShake(const byte* input, int* sslBytes,
4603                       SnifferSession* session, char* error, word16 rhSize)
4604{
4605    byte type;
4606    int  size;
4607    int  ret = 0;
4608    WOLFSSL* ssl;
4609    int startBytes;
4610
4611    (void)rhSize;
4612
4613#ifdef HAVE_MAX_FRAGMENT
4614    if (session->tlsFragBuf) {
4615        if (session->tlsFragOffset + rhSize > session->tlsFragSize) {
4616            SetError(HANDSHAKE_INPUT_STR, error, session, FATAL_ERROR_STATE);
4617            return WOLFSSL_FATAL_ERROR;
4618        }
4619        XMEMCPY(session->tlsFragBuf + session->tlsFragOffset, input, rhSize);
4620        session->tlsFragOffset += rhSize;
4621        *sslBytes -= rhSize;
4622
4623        if (session->tlsFragOffset < session->tlsFragSize) {
4624            return 0;
4625        }
4626
4627        /* reassembled complete fragment */
4628        input = session->tlsFragBuf;
4629        *sslBytes = session->tlsFragSize;
4630        rhSize = session->tlsFragSize;
4631    }
4632#endif
4633
4634    if (*sslBytes < HANDSHAKE_HEADER_SZ) {
4635        SetError(HANDSHAKE_INPUT_STR, error, session, FATAL_ERROR_STATE);
4636        return WOLFSSL_FATAL_ERROR;
4637    }
4638    type = input[0];
4639    size = (input[1] << 16) | (input[2] << 8) | input[3];
4640
4641    input     += HANDSHAKE_HEADER_SZ;
4642    *sslBytes -= HANDSHAKE_HEADER_SZ;
4643    startBytes = *sslBytes;
4644
4645    if (*sslBytes < size) {
4646        Trace(SPLIT_HANDSHAKE_MSG_STR);
4647        *sslBytes = 0;
4648        return ret;
4649    }
4650
4651    if (session->flags.side == WOLFSSL_SERVER_END)
4652        ssl = session->sslServer;
4653    else
4654        ssl = session->sslClient;
4655
4656#ifdef HAVE_MAX_FRAGMENT
4657    if (rhSize < size) {
4658        /* partial fragment, let's reassemble */
4659        if (session->tlsFragBuf == NULL) {
4660            session->tlsFragOffset = 0;
4661            session->tlsFragSize = size + HANDSHAKE_HEADER_SZ;
4662            session->tlsFragBuf = (byte*)XMALLOC(session->tlsFragSize, NULL, DYNAMIC_TYPE_TMP_BUFFER);
4663            if (session->tlsFragBuf == NULL) {
4664                SetError(MEMORY_STR, error, NULL, 0);
4665                return 0;
4666            }
4667
4668            /* include the handshake header */
4669            input -= HANDSHAKE_HEADER_SZ;
4670            *sslBytes += HANDSHAKE_HEADER_SZ;
4671        }
4672
4673        if (session->tlsFragOffset + rhSize > session->tlsFragSize) {
4674            SetError(HANDSHAKE_INPUT_STR, error, session, FATAL_ERROR_STATE);
4675            return WOLFSSL_FATAL_ERROR;
4676        }
4677        XMEMCPY(session->tlsFragBuf + session->tlsFragOffset, input, rhSize);
4678        session->tlsFragOffset += rhSize;
4679        *sslBytes -= rhSize;
4680        return 0;
4681    }
4682#endif
4683
4684#ifdef WOLFSSL_TLS13
4685    if (type != client_hello && type != server_hello
4686    #ifdef WOLFSSL_ASYNC_CRYPT
4687        && session->sslServer->error != WC_NO_ERR_TRACE(WC_PENDING_E)
4688        && session->pendSeq == 0
4689    #endif
4690    ) {
4691        /* For resumption the hash is before / after client_hello PSK binder */
4692        /* hash the packet including header */
4693        /* TLS v1.3 requires the hash for the handshake and transfer key derivation */
4694        /* we hash even for non TLS v1.3, since we don't know if its actually
4695            TLS v1.3 till later at EXT_SUPPORTED_VERSIONS in server_hello */
4696        /* hello retry request restarts hash prior to server_hello hash calc */
4697        HashRaw(session->sslServer, input - HANDSHAKE_HEADER_SZ, size + HANDSHAKE_HEADER_SZ);
4698        HashRaw(session->sslClient, input - HANDSHAKE_HEADER_SZ, size + HANDSHAKE_HEADER_SZ);
4699    }
4700#endif
4701#ifdef HAVE_EXTENDED_MASTER
4702    if (session->hash) {
4703        if (HashUpdate(session->hash, input, size) != 0) {
4704            SetError(EXTENDED_MASTER_HASH_STR, error,
4705                     session, FATAL_ERROR_STATE);
4706            ret = WOLFSSL_FATAL_ERROR;
4707            goto exit;
4708        }
4709    }
4710#endif
4711
4712    switch (type) {
4713        case hello_verify_request:
4714            Trace(GOT_HELLO_VERIFY_STR);
4715            break;
4716        case hello_request:
4717            Trace(GOT_HELLO_REQUEST_STR);
4718            break;
4719        case session_ticket:
4720            Trace(GOT_SESSION_TICKET_STR);
4721            ret = ProcessSessionTicket(input, sslBytes, session, error);
4722            break;
4723        case server_hello:
4724            Trace(GOT_SERVER_HELLO_STR);
4725            ret = ProcessServerHello(size, input, sslBytes, session, error);
4726            break;
4727        case certificate_request:
4728            Trace(GOT_CERT_REQ_STR);
4729            break;
4730        case server_key_exchange:
4731            Trace(GOT_SERVER_KEY_EX_STR);
4732
4733#if defined(WOLFSSL_SNIFFER_KEYLOGFILE)
4734            if (!session->context->useKeyLogFile)
4735#endif /* WOLFSSL_SNIFFER_KEYLOGFILE */
4736            {
4737                /* can't know temp key passively */
4738                SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
4739                session->verboseErr = 1;
4740                ret = WOLFSSL_FATAL_ERROR;
4741
4742#if defined(WOLFSSL_SNIFFER_STATS)
4743                INC_STAT(SnifferStats.sslEphemeralMisses);
4744#endif /* WOLFSSL_SNIFFER_STATS */
4745            }
4746            break;
4747        case encrypted_extensions:
4748            Trace(GOT_ENC_EXT_STR);
4749            ssl->msgsReceived.got_encrypted_extensions = 1;
4750            break;
4751        case certificate:
4752            Trace(GOT_CERT_STR);
4753            if (session->flags.side == WOLFSSL_SERVER_END) {
4754#ifdef WOLFSSL_SNIFFER_STATS
4755                INC_STAT(SnifferStats.sslClientAuthConns);
4756#endif
4757            }
4758#ifdef WOLFSSL_SNIFFER_WATCH
4759            ret = ProcessCertificate(input, sslBytes, session, error);
4760#endif
4761            break;
4762        case server_hello_done:
4763            Trace(GOT_SERVER_HELLO_DONE_STR);
4764            break;
4765        case finished:
4766            Trace(GOT_FINISHED_STR);
4767            ret = ProcessFinished(input, size, sslBytes, session, error);
4768            break;
4769        case client_hello:
4770            Trace(GOT_CLIENT_HELLO_STR);
4771            ret = ProcessClientHello(input, sslBytes, session, error);
4772            break;
4773        case client_key_exchange:
4774            Trace(GOT_CLIENT_KEY_EX_STR);
4775#ifdef HAVE_EXTENDED_MASTER
4776            if (session->flags.expectEms) {
4777                /* on async reentry the session->hash is already copied
4778                 * and free'd */
4779                if (session->hash != NULL) {
4780                    if (HashCopy(session->sslServer->hsHashes,
4781                                session->hash) == 0 &&
4782                        HashCopy(session->sslClient->hsHashes,
4783                                session->hash) == 0) {
4784
4785                        session->sslServer->options.haveEMS = 1;
4786                        session->sslClient->options.haveEMS = 1;
4787                    }
4788                    else {
4789                        SetError(EXTENDED_MASTER_HASH_STR, error,
4790                                session, FATAL_ERROR_STATE);
4791                        ret = WOLFSSL_FATAL_ERROR;
4792                    }
4793                    XMEMSET(session->hash, 0, sizeof(HsHashes));
4794                    XFREE(session->hash, NULL, DYNAMIC_TYPE_HASHES);
4795                    session->hash = NULL;
4796                }
4797            }
4798            else {
4799                session->sslServer->options.haveEMS = 0;
4800                session->sslClient->options.haveEMS = 0;
4801            }
4802#endif
4803            if (ret == 0) {
4804                ret = ProcessClientKeyExchange(input, sslBytes, session, error);
4805            #ifdef WOLFSSL_ASYNC_CRYPT
4806                if (ret == WC_NO_ERR_TRACE(WC_PENDING_E))
4807                    return ret;
4808            #endif
4809                if (ret != 0) {
4810                    SetError(KEY_MISMATCH_STR, error, session, FATAL_ERROR_STATE);
4811                    session->verboseErr = 1;
4812                }
4813            }
4814            break;
4815        case certificate_verify:
4816            Trace(GOT_CERT_VER_STR);
4817            break;
4818        case certificate_status:
4819            Trace(GOT_CERT_STATUS_STR);
4820            break;
4821        default:
4822            SetError(GOT_UNKNOWN_HANDSHAKE_STR, error, session, 0);
4823            ret = WOLFSSL_FATAL_ERROR;
4824            break;
4825    }
4826
4827#ifdef HAVE_EXTENDED_MASTER
4828exit:
4829#endif
4830#ifdef HAVE_MAX_FRAGMENT
4831    XFREE(session->tlsFragBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
4832    session->tlsFragBuf = NULL;
4833#endif
4834
4835    *sslBytes = startBytes - size;  /* actual bytes of full process */
4836
4837    return ret;
4838}
4839
4840/* For ciphers that use AEAD use the encrypt routine to
4841 * bypass the auth tag checking */
4842static int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input,
4843                           word16 sz)
4844{
4845    int ret = 0;
4846
4847    (void)plain;
4848    (void)input;
4849    (void)sz;
4850
4851    switch (ssl->specs.bulk_cipher_algorithm)
4852    {
4853    #ifndef NO_RC4
4854        case wolfssl_rc4:
4855            wc_Arc4Process(ssl->decrypt.arc4, plain, input, sz);
4856            break;
4857    #endif
4858
4859    #ifndef NO_DES3
4860        case wolfssl_triple_des:
4861        #ifdef WOLFSSL_ASYNC_CRYPT
4862            /* initialize event */
4863            ret = wolfSSL_AsyncInit(ssl, &ssl->decrypt.des3->asyncDev,
4864                WC_ASYNC_FLAG_CALL_AGAIN);
4865            if (ret != 0)
4866                break;
4867        #endif
4868
4869            ret = wc_Des3_CbcDecrypt(ssl->decrypt.des3, plain, input, sz);
4870        #ifdef WOLFSSL_ASYNC_CRYPT
4871            if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
4872                ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.des3->asyncDev);
4873            }
4874        #endif
4875            break;
4876    #endif
4877
4878    #if !defined(NO_AES) && defined(HAVE_AES_CBC)
4879        case wolfssl_aes:
4880        #ifdef WOLFSSL_ASYNC_CRYPT
4881            /* initialize event */
4882            ret = wolfSSL_AsyncInit(ssl, &ssl->decrypt.aes->asyncDev,
4883                WC_ASYNC_FLAG_CALL_AGAIN);
4884            if (ret != 0)
4885                break;
4886        #endif
4887            ret = wc_AesCbcDecrypt(ssl->decrypt.aes, plain, input, sz);
4888        #ifdef WOLFSSL_ASYNC_CRYPT
4889            if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
4890                ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.aes->asyncDev);
4891            }
4892        #endif
4893            break;
4894    #endif
4895
4896    #if defined(HAVE_AESGCM) || defined(HAVE_AESCCM)
4897        case wolfssl_aes_gcm:
4898        case wolfssl_aes_ccm: /* GCM AEAD macros use same size as CCM */
4899        {
4900            /* For ciphers that use AEAD use the encrypt routine to
4901             * bypass the auth tag checking */
4902            wc_AesAuthEncryptFunc aes_auth_fn;
4903
4904        #ifdef WOLFSSL_ASYNC_CRYPT
4905            /* initialize event */
4906            ret = wolfSSL_AsyncInit(ssl, &ssl->decrypt.aes->asyncDev,
4907                WC_ASYNC_FLAG_CALL_AGAIN);
4908            if (ret != 0)
4909                break;
4910        #endif
4911
4912        #if defined(HAVE_AESGCM) && defined(HAVE_AESCCM)
4913            aes_auth_fn = (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm)
4914                            ? wc_AesGcmEncrypt : wc_AesCcmEncrypt;
4915        #elif defined(HAVE_AESGCM)
4916            aes_auth_fn = wc_AesGcmEncrypt;
4917        #else
4918            aes_auth_fn = wc_AesCcmEncrypt;
4919        #endif
4920
4921            XMEMSET(ssl->decrypt.additional, 0, AEAD_AUTH_DATA_SZ);
4922
4923            XMEMCPY(ssl->decrypt.nonce, ssl->keys.aead_dec_imp_IV, AESGCM_IMP_IV_SZ);
4924            XMEMCPY(ssl->decrypt.nonce + AESGCM_IMP_IV_SZ, input, AESGCM_EXP_IV_SZ);
4925
4926            if (sz < AESGCM_EXP_IV_SZ + ssl->specs.aead_mac_size) {
4927                ret = BUFFER_ERROR;
4928            }
4929
4930            if (ret == 0) {
4931                ret = aes_auth_fn(ssl->decrypt.aes,
4932                       plain,
4933                       input + AESGCM_EXP_IV_SZ,
4934                       sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size,
4935                       ssl->decrypt.nonce, AESGCM_NONCE_SZ,
4936                       ssl->decrypt.additional, AEAD_AUTH_DATA_SZ,
4937                       NULL, 0);
4938                if (ret < 0) {
4939                #ifdef WOLFSSL_ASYNC_CRYPT
4940                    if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
4941                        ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.aes->asyncDev);
4942                    }
4943                #endif
4944                }
4945            }
4946        }
4947        break;
4948    #endif /* HAVE_AESGCM || HAVE_AESCCM */
4949
4950    #ifdef HAVE_ARIA
4951        case wolfssl_aria_gcm:
4952            if (sz < AESGCM_EXP_IV_SZ + ssl->specs.aead_mac_size) {
4953                ret = BUFFER_ERROR;
4954            }
4955
4956            if (ret == 0) {
4957                ret = wc_AriaDecrypt(ssl->decrypt.aria,
4958                            plain,
4959                            (byte *)input + AESGCM_EXP_IV_SZ,
4960                            sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size,
4961                            ssl->decrypt.nonce, AESGCM_NONCE_SZ,
4962                            ssl->decrypt.additional, ssl->specs.aead_mac_size,
4963                            NULL, 0);
4964            }
4965            break;
4966    #endif
4967
4968    #ifdef HAVE_CAMELLIA
4969        case wolfssl_camellia:
4970            ret = wc_CamelliaCbcDecrypt(ssl->decrypt.cam, plain, input, sz);
4971            break;
4972    #endif
4973
4974    #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) && \
4975        !defined(NO_CHAPOL_AEAD)
4976        case wolfssl_chacha:
4977            ret = ChachaAEADDecrypt(ssl, plain, input, sz);
4978            break;
4979    #endif
4980
4981    #ifdef HAVE_NULL_CIPHER
4982        case wolfssl_cipher_null:
4983            if (input != plain) {
4984                XMEMMOVE(plain, input, sz);
4985            }
4986            break;
4987    #endif
4988
4989        default:
4990            WOLFSSL_MSG("wolfSSL Decrypt programming error");
4991            ret = DECRYPT_ERROR;
4992    }
4993
4994    return ret;
4995}
4996
4997static int DecryptTls(WOLFSSL* ssl, byte* plain, const byte* input,
4998                           word16 sz)
4999{
5000    int ret = 0;
5001
5002#ifdef WOLFSSL_ASYNC_CRYPT
5003    if (ssl->decrypt.state != CIPHER_STATE_BEGIN) {
5004        ret = wolfSSL_AsyncPop(ssl, &ssl->decrypt.state);
5005        if (ret != WC_NO_ERR_TRACE(WC_NO_PENDING_E)) {
5006            /* check for still pending */
5007            if (ret == WC_NO_ERR_TRACE(WC_PENDING_E))
5008                return ret;
5009
5010            ssl->error = 0; /* clear async */
5011
5012            /* let failures through so CIPHER_STATE_END logic is run */
5013        }
5014    }
5015    else
5016#endif
5017    {
5018        /* Reset state */
5019        ret = 0;
5020        ssl->decrypt.state = CIPHER_STATE_BEGIN;
5021    }
5022
5023    switch (ssl->decrypt.state) {
5024        case CIPHER_STATE_BEGIN:
5025        {
5026            if (ssl->decrypt.setup == 0) {
5027                WOLFSSL_MSG("Decrypt ciphers not setup");
5028                return DECRYPT_ERROR;
5029            }
5030
5031        #if defined(HAVE_AESGCM) || defined(HAVE_AESCCM)
5032            /* make sure AES GCM/CCM memory is allocated */
5033            /* free for these happens in FreeCiphers */
5034            if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_ccm ||
5035                ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) {
5036                /* make sure auth iv and auth are allocated */
5037                if (ssl->decrypt.additional == NULL)
5038                    ssl->decrypt.additional = (byte*)XMALLOC(AEAD_AUTH_DATA_SZ,
5039                                            ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
5040                if (ssl->decrypt.nonce == NULL)
5041                    ssl->decrypt.nonce = (byte*)XMALLOC(AESGCM_NONCE_SZ,
5042                                            ssl->heap, DYNAMIC_TYPE_AES_BUFFER);
5043                if (ssl->decrypt.additional == NULL ||
5044                         ssl->decrypt.nonce == NULL) {
5045                    return MEMORY_E;
5046                }
5047            }
5048        #endif /* HAVE_AESGCM || HAVE_AESCCM */
5049
5050            /* Advance state and proceed */
5051            ssl->decrypt.state = CIPHER_STATE_DO;
5052        }
5053        FALL_THROUGH;
5054        case CIPHER_STATE_DO:
5055        {
5056            ret = DecryptDo(ssl, plain, input, sz);
5057
5058            /* Advance state */
5059            ssl->decrypt.state = CIPHER_STATE_END;
5060
5061        #ifdef WOLFSSL_ASYNC_CRYPT
5062            /* If pending, return now */
5063            if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
5064                return ret;
5065            }
5066        #endif
5067        }
5068        FALL_THROUGH;
5069        case CIPHER_STATE_END:
5070        {
5071        #if defined(HAVE_AESGCM) || defined(HAVE_AESCCM)
5072            /* make sure AES GCM/CCM nonce is cleared */
5073            if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_ccm ||
5074                ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) {
5075                if (ssl->decrypt.nonce)
5076                    ForceZero(ssl->decrypt.nonce, AESGCM_NONCE_SZ);
5077
5078                if (ret < 0)
5079                    ret = VERIFY_MAC_ERROR;
5080            }
5081        #endif /* HAVE_AESGCM || HAVE_AESCCM */
5082            break;
5083        }
5084
5085        default:
5086            break;
5087    }
5088
5089    /* Reset state */
5090    ssl->decrypt.state = CIPHER_STATE_BEGIN;
5091
5092    return ret;
5093}
5094
5095
5096/* Decrypt input message into output, adjust output steam if needed */
5097static const byte* DecryptMessage(WOLFSSL* ssl, const byte* input, word32 sz,
5098                byte* output, int* error, int* advance, RecordLayerHeader* rh)
5099{
5100    int ivExtra = 0;
5101    int ret;
5102
5103#ifdef WOLFSSL_TLS13
5104    if (IsAtLeastTLSv1_3(ssl->version)) {
5105        if (sz <= ssl->specs.aead_mac_size) {
5106            *error = BUFFER_ERROR;
5107            return NULL;
5108        }
5109        ret = DecryptTls13(ssl, output, input, sz, (byte*)rh, RECORD_HEADER_SZ);
5110    }
5111    else
5112#endif
5113    {
5114        XMEMCPY(&ssl->curRL, rh, RECORD_HEADER_SZ);
5115        ret = DecryptTls(ssl, output, input, sz);
5116    }
5117#ifdef WOLFSSL_ASYNC_CRYPT
5118    /* for async the symmetric operations are blocking */
5119    if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
5120        do {
5121            ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
5122        } while (ret == 0);
5123        if (ret >= 0) {
5124            /* remove from event queue list */
5125            ret = wolfSSL_AsyncPop(ssl, NULL);
5126        }
5127    }
5128#endif
5129    if (ret != 0) {
5130        *error = ret;
5131        return NULL;
5132    }
5133
5134    ssl->curSize = sz;
5135    ssl->keys.encryptSz = sz;
5136    if (ssl->options.tls1_1 && ssl->specs.cipher_type == block) {
5137        output += ssl->specs.block_size; /* go past TLSv1.1 IV */
5138        ivExtra = ssl->specs.block_size;
5139        *advance = ssl->specs.block_size;
5140    }
5141
5142    if (ssl->specs.cipher_type == aead) {
5143        *advance = ssl->specs.aead_mac_size;
5144        ssl->keys.padSz = ssl->specs.aead_mac_size;
5145    }
5146    else
5147        ssl->keys.padSz = ssl->specs.hash_size;
5148
5149    if (ssl->specs.cipher_type == block) {
5150        /* last pad bytes indicates length */
5151        word32 pad = 0;
5152        if ((int)sz > ivExtra) {
5153            /* get value of last pad byte */
5154            pad = *(output + sz - ivExtra - 1) + 1;
5155        }
5156        ssl->keys.padSz += pad;
5157    }
5158
5159#ifdef WOLFSSL_TLS13
5160    if (IsAtLeastTLSv1_3(ssl->version)) {
5161        word16 i = (word16)(sz - ssl->keys.padSz);
5162        if (i == 0) {
5163            *error = BUFFER_ERROR;
5164            return NULL;
5165        }
5166        /* Remove padding from end of plain text. */
5167        for (--i; i > 0; i--) {
5168            if (output[i] != 0)
5169                break;
5170        }
5171        /* Get the real content type from the end of the data. */
5172        rh->type = output[i];
5173        ssl->keys.padSz = sz - i;
5174    }
5175#endif
5176    (void)rh;
5177
5178    return output;
5179}
5180
5181
5182/* remove session from table, use rowHint if no info (means we have a lock) */
5183static void RemoveSession(SnifferSession* session, IpInfo* ipInfo,
5184                        TcpInfo* tcpInfo, word32 rowHint)
5185{
5186    SnifferSession* previous = 0;
5187    SnifferSession* current;
5188    word32          row = rowHint;
5189#ifndef HAVE_C___ATOMIC
5190    int             haveLock = 0;
5191#endif
5192    Trace(REMOVE_SESSION_STR);
5193
5194    if (ipInfo && tcpInfo)
5195        row = SessionHash(ipInfo, tcpInfo);
5196#ifndef HAVE_C___ATOMIC
5197    else
5198        haveLock = 1;
5199#endif
5200
5201    if (row >= HASH_SIZE)
5202        return;
5203
5204#ifndef HAVE_C___ATOMIC
5205    if (!haveLock) {
5206        LOCK_SESSION();
5207    }
5208#endif
5209
5210    current = SessionTable[row];
5211
5212    while (current) {
5213        if (current == session) {
5214            if (previous)
5215                previous->next = current->next;
5216            else
5217                SessionTable[row] = current->next;
5218            FreeSnifferSession(session);
5219            TraceRemovedSession();
5220            break;
5221        }
5222        previous = current;
5223        current  = current->next;
5224    }
5225
5226#ifndef HAVE_C___ATOMIC
5227    if (!haveLock) {
5228        UNLOCK_SESSION();
5229    }
5230#endif
5231}
5232
5233
5234/* Remove stale sessions from the Session Table, have a lock */
5235static void RemoveStaleSessions(void)
5236{
5237    word32 i;
5238    SnifferSession* session;
5239
5240    for (i = 0; i < HASH_SIZE; i++) {
5241        session = SessionTable[i];
5242        while (session) {
5243            SnifferSession* next = session->next;
5244            if (wc_Time(NULL) >= session->lastUsed + WOLFSSL_SNIFFER_TIMEOUT) {
5245                TraceStaleSession();
5246                RemoveSession(session, NULL, NULL, i);
5247            }
5248            session = next;
5249        }
5250    }
5251}
5252
5253void ssl_RemoveStaleSessions(void)
5254{
5255    LOCK_SESSION();
5256    RemoveStaleSessions();
5257    UNLOCK_SESSION();
5258}
5259
5260/* Create a new Sniffer Session */
5261static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo,
5262                                     char* error)
5263{
5264    SnifferSession* session = 0;
5265    int row;
5266
5267    Trace(NEW_SESSION_STR);
5268    /* create a new one */
5269    session = (SnifferSession*)XMALLOC(sizeof(SnifferSession),
5270            NULL, DYNAMIC_TYPE_SNIFFER_SESSION);
5271    if (session == NULL) {
5272        SetError(MEMORY_STR, error, NULL, 0);
5273        return NULL;
5274    }
5275    InitSession(session);
5276#ifdef HAVE_EXTENDED_MASTER
5277    {
5278        HsHashes* newHash = (HsHashes*)XMALLOC(sizeof(HsHashes),
5279                NULL, DYNAMIC_TYPE_HASHES);
5280        if (newHash == NULL) {
5281            SetError(MEMORY_STR, error, NULL, 0);
5282            XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION);
5283            return NULL;
5284        }
5285        if (HashInit(newHash) != 0) {
5286            SetError(EXTENDED_MASTER_HASH_STR, error, NULL, 0);
5287            XFREE(newHash, NULL, DYNAMIC_TYPE_HASHES);
5288            XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION);
5289            return NULL;
5290        }
5291        session->hash = newHash;
5292    }
5293#endif
5294    session->server  = ipInfo->dst;
5295    session->client  = ipInfo->src;
5296    session->srvPort = (word16)tcpInfo->dstPort;
5297    session->cliPort = (word16)tcpInfo->srcPort;
5298    session->cliSeqStart = tcpInfo->sequence;
5299    session->cliExpected = 1;  /* relative */
5300    session->lastUsed= wc_Time(NULL);
5301    session->keySz = 0;
5302    session->error = 0;
5303    session->verboseErr = 0;
5304#ifdef HAVE_SNI
5305    session->sni = NULL;
5306#endif
5307
5308    session->context = GetSnifferServer(ipInfo, tcpInfo);
5309    if (session->context == NULL) {
5310        SetError(SERVER_NOT_REG_STR, error, NULL, 0);
5311        XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION);
5312        return NULL;
5313    }
5314
5315    session->sslServer = wolfSSL_new(session->context->ctx);
5316    if (session->sslServer == NULL) {
5317        SetError(BAD_NEW_SSL_STR, error, session, FATAL_ERROR_STATE);
5318        XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION);
5319        return NULL;
5320    }
5321    session->sslClient = wolfSSL_new(session->context->ctx);
5322    if (session->sslClient == NULL) {
5323        wolfSSL_free(session->sslServer);
5324        session->sslServer = 0;
5325
5326        SetError(BAD_NEW_SSL_STR, error, session, FATAL_ERROR_STATE);
5327        XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION);
5328        return NULL;
5329    }
5330    /* put server back into server mode */
5331    session->sslServer->options.side = WOLFSSL_SERVER_END;
5332
5333#if defined(WOLFSSL_SNIFFER_KEYLOGFILE)
5334    if (session->context->useKeyLogFile) {
5335        setSnifferSecretCb(session);
5336    }
5337#endif /* WOLFSSL_SNIFFER_KEYLOGFILE */
5338
5339
5340    row = SessionHash(ipInfo, tcpInfo);
5341
5342    /* add it to the session table */
5343    LOCK_SESSION();
5344
5345    session->next = SessionTable[row];
5346    SessionTable[row] = session;
5347
5348    SessionCount++;
5349
5350    if ( (SessionCount % HASH_SIZE) == 0) {
5351        TraceFindingStale();
5352        RemoveStaleSessions();
5353    }
5354
5355    UNLOCK_SESSION();
5356
5357    /* CreateSession is called in response to a SYN packet, we know this
5358     * is headed to the server. Also we know the server is one we care
5359     * about as we've passed the GetSnifferServer() successfully. */
5360    session->flags.side = WOLFSSL_SERVER_END;
5361
5362    return session;
5363}
5364
5365
5366#ifdef OLD_HELLO_ALLOWED
5367
5368/* Process Old Client Hello Input */
5369static int DoOldHello(SnifferSession* session, const byte* sslFrame,
5370                      int* rhSize, int* sslBytes, char* error)
5371{
5372    const byte* input = sslFrame;
5373    byte        b0, b1;
5374    word32      idx = 0;
5375    int         ret;
5376
5377    Trace(GOT_OLD_CLIENT_HELLO_STR);
5378    session->flags.clientHello = 1;    /* don't process again */
5379    b0 = *input++;
5380    b1 = *input++;
5381    *sslBytes -= 2;
5382    *rhSize = ((b0 & 0x7f) << 8) | b1;
5383
5384    if (*rhSize > *sslBytes) {
5385        SetError(OLD_CLIENT_INPUT_STR, error, session, FATAL_ERROR_STATE);
5386        return WOLFSSL_FATAL_ERROR;
5387    }
5388
5389    ret = ProcessOldClientHello(session->sslServer, input, &idx, *sslBytes,
5390                                (word16)*rhSize);
5391    if (ret < 0 && ret != WC_NO_ERR_TRACE(MATCH_SUITE_ERROR)) {
5392        SetError(BAD_OLD_CLIENT_STR, error, session, FATAL_ERROR_STATE);
5393        return WOLFSSL_FATAL_ERROR;
5394    }
5395
5396    Trace(OLD_CLIENT_OK_STR);
5397    XMEMCPY(session->sslClient->arrays->clientRandom,
5398           session->sslServer->arrays->clientRandom, RAN_LEN);
5399
5400    *sslBytes -= *rhSize;
5401    return 0;
5402}
5403
5404#endif /* OLD_HELLO_ALLOWED */
5405
5406
5407#if 0
5408/* Calculate the TCP checksum, see RFC 1071 */
5409/* return 0 for success, -1 on error */
5410/* can be called from decode() with
5411   TcpChecksum(&ipInfo, &tcpInfo, sslBytes, packet + ipInfo.length);
5412   could also add a 64bit version if type available and using this
5413*/
5414static int TcpChecksum(IpInfo* ipInfo, TcpInfo* tcpInfo, int dataLen,
5415                const byte* packet)
5416{
5417    TcpPseudoHdr  pseudo;
5418    int           count = PSEUDO_HDR_SZ;
5419    const word16* data = (word16*)&pseudo;
5420    word32        sum = 0;
5421    word16        checksum;
5422
5423    pseudo.src = ipInfo->src.ip4;
5424    pseudo.dst = ipInfo->dst.ip4;
5425    pseudo.rsv = 0;
5426    pseudo.protocol = TCP_PROTO;
5427    pseudo.length = htons(tcpInfo->length + dataLen);
5428
5429    /* pseudo header sum */
5430    while (count >= 2) {
5431        sum   += *data++;
5432        count -= 2;
5433    }
5434
5435    count = tcpInfo->length + dataLen;
5436    data = (word16*)packet;
5437
5438    /* main sum */
5439    while (count > 1) {
5440        sum   += *data++;
5441        count -=2;
5442    }
5443
5444    /* get left-over, if any */
5445    packet = (byte*)data;
5446    if (count > 0) {
5447        sum += *packet;
5448    }
5449
5450    /* fold 32bit sum into 16 bits */
5451    while (sum >> 16)
5452        sum = (sum & 0xffff) + (sum >> 16);
5453
5454    checksum = (word16)~sum;
5455    /* checksum should now equal 0, since included already calcd checksum */
5456    /* field, but tcp checksum offloading could negate calculation */
5457    if (checksum == 0)
5458        return 0;
5459    return WOLFSSL_FATAL_ERROR;
5460}
5461#endif
5462
5463
5464/* Check IP and TCP headers, set payload */
5465/* returns 0 on success, -1 on error */
5466static int CheckHeaders(IpInfo* ipInfo, TcpInfo* tcpInfo, const byte* packet,
5467    int length, const byte** sslFrame, int* sslBytes, char* error,
5468    int checkReg, int trace)
5469{
5470    IpHdr* iphdr = (IpHdr*)packet;
5471    TcpHdr* tcphdr;
5472    int version;
5473
5474    if (trace) {
5475        TraceHeader();
5476        TracePacket();
5477    }
5478
5479    /* ip header */
5480    if (length < IP_HDR_SZ) {
5481        SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
5482        return WOLFSSL_FATAL_ERROR;
5483    }
5484
5485    version = IP_V(iphdr);
5486    if (version != IPV6 && version != IPV4) {
5487        /* Is this VLAN IEEE 802.1Q Frame? TPID = 0x8100 */
5488        if (packet[2] == 0x81 && packet[3] == 0x00) {
5489            /* trim VLAN header and try again */
5490            packet += 8;
5491            length -= 8;
5492            if (length < IP_HDR_SZ) {
5493                SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
5494                return WOLFSSL_FATAL_ERROR;
5495            }
5496            iphdr = (IpHdr*)packet;
5497            version = IP_V(iphdr);
5498        }
5499    }
5500
5501    if (CheckIpHdr(iphdr, ipInfo, length, error, trace) != 0)
5502        return WOLFSSL_FATAL_ERROR;
5503
5504#ifndef WOLFSSL_SNIFFER_WATCH
5505    if (checkReg &&
5506           !IsServerRegistered(iphdr->src) && !IsServerRegistered(iphdr->dst)) {
5507        SetError(SERVER_NOT_REG_STR, error, NULL, 0);
5508        return WOLFSSL_FATAL_ERROR;
5509    }
5510#endif
5511
5512    /* tcp header */
5513    if (length < (ipInfo->length + TCP_HDR_SZ)) {
5514        SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
5515        return WOLFSSL_FATAL_ERROR;
5516    }
5517    tcphdr = (TcpHdr*)(packet + ipInfo->length);
5518    if (CheckTcpHdr(tcphdr, tcpInfo, error, trace) != 0)
5519        return WOLFSSL_FATAL_ERROR;
5520
5521#ifndef WOLFSSL_SNIFFER_WATCH
5522    if (checkReg &&
5523         !IsPortRegistered(tcpInfo->srcPort) &&
5524            !IsPortRegistered(tcpInfo->dstPort)) {
5525        SetError(SERVER_PORT_NOT_REG_STR, error, NULL, 0);
5526        return WOLFSSL_FATAL_ERROR;
5527    }
5528#endif
5529
5530    /* setup */
5531    *sslFrame = packet + ipInfo->length + tcpInfo->length;
5532    if (*sslFrame > packet + length) {
5533        SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
5534        return WOLFSSL_FATAL_ERROR;
5535    }
5536
5537    /* We only care about the data in the TCP/IP record. There may be extra
5538     * data after the IP record for the FCS for Ethernet. */
5539    *sslBytes = (int)(packet + ipInfo->total - *sslFrame);
5540
5541    /* Ensure sslBytes does not exceed the actual size. */
5542    if (*sslBytes > (int)(length - (ipInfo->length + tcpInfo->length))) {
5543        SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
5544        return WOLFSSL_FATAL_ERROR;
5545    }
5546
5547    (void)checkReg;
5548
5549    return 0;
5550}
5551
5552
5553/* Create or Find existing session */
5554/* returns 0 on success (continue), -1 on error, 1 on success (end) */
5555static int CheckSession(IpInfo* ipInfo, TcpInfo* tcpInfo, int sslBytes,
5556                        SnifferSession** session, char* error)
5557{
5558    /* create a new SnifferSession on client SYN */
5559    if (tcpInfo->syn && !tcpInfo->ack) {
5560    #ifdef WOLFSSL_ASYNC_CRYPT
5561        /* if session already exists and is pending do not create another */
5562        *session = GetSnifferSession(ipInfo, tcpInfo);
5563        if (*session != NULL) {
5564            if ((*session)->pendSeq != 0) {
5565                return WC_PENDING_E;
5566            }
5567        }
5568    #endif
5569
5570        TraceClientSyn(tcpInfo->sequence);
5571#ifdef WOLFSSL_SNIFFER_STATS
5572        INC_STAT(SnifferStats.sslEncryptedConns);
5573#endif
5574        *session = CreateSession(ipInfo, tcpInfo, error);
5575        if (*session == NULL) {
5576            *session = GetSnifferSession(ipInfo, tcpInfo);
5577            /* already had existing, so OK */
5578            if (*session)
5579                return 1;
5580
5581            SetError(MEMORY_STR, error, NULL, 0);
5582            return WOLFSSL_FATAL_ERROR;
5583        }
5584        return 1;
5585    }
5586    /* get existing sniffer session */
5587    else {
5588        *session = GetSnifferSession(ipInfo, tcpInfo);
5589        if (*session == NULL) {
5590            /* don't worry about extraneous RST or duplicate FINs */
5591            if (tcpInfo->fin || tcpInfo->rst)
5592                return 1;
5593            /* don't worry about duplicate ACKs either */
5594            if (sslBytes == 0 && tcpInfo->ack)
5595                return 1;
5596
5597#ifdef WOLFSSL_SNIFFER_STATS
5598            LOCK_STAT();
5599            NOLOCK_INC_STAT(SnifferStats.sslDecryptedPackets);
5600            NOLOCK_ADD_TO_STAT(SnifferStats.sslDecryptedBytes, sslBytes);
5601            UNLOCK_STAT();
5602#endif
5603
5604            SetError(BAD_SESSION_STR, error, NULL, 0);
5605            return WOLFSSL_FATAL_ERROR;
5606        }
5607    }
5608    return 0;
5609}
5610
5611
5612/* Create a Packet Buffer from *begin - end, adjust new *begin and bytesLeft */
5613static PacketBuffer* CreateBuffer(word32* begin, word32 end, const byte* data,
5614                                  int* bytesLeft)
5615{
5616    PacketBuffer* pb;
5617    int added = (int)(end - *begin + 1);
5618
5619    if (added <= 0) {
5620        return NULL;
5621    }
5622
5623    pb = (PacketBuffer*)XMALLOC(sizeof(PacketBuffer),
5624            NULL, DYNAMIC_TYPE_SNIFFER_PB);
5625    if (pb == NULL) return NULL;
5626
5627    pb->next  = 0;
5628    pb->begin = *begin;
5629    pb->end   = end;
5630    pb->data  = (byte*)XMALLOC(added, NULL, DYNAMIC_TYPE_SNIFFER_PB_BUFFER);
5631
5632    if (pb->data == NULL) {
5633        XFREE(pb, NULL, DYNAMIC_TYPE_SNIFFER_PB);
5634        return NULL;
5635    }
5636    XMEMCPY(pb->data, data, added);
5637
5638    *bytesLeft -= added;
5639    *begin      = pb->end + 1;
5640
5641    return pb;
5642}
5643
5644/* Add sslFrame to Reassembly List */
5645/* returns 1 (end) on success, -1, on error */
5646static int AddToReassembly(byte from, word32 seq, const byte* sslFrame,
5647                           int sslBytes, SnifferSession* session, char* error)
5648{
5649    PacketBuffer*  add;
5650    PacketBuffer** front = (from == WOLFSSL_SERVER_END) ?
5651                       &session->cliReassemblyList: &session->srvReassemblyList;
5652    PacketBuffer*  curr = *front;
5653    PacketBuffer*  prev = curr;
5654
5655    word32* reassemblyMemory = (from == WOLFSSL_SERVER_END) ?
5656                  &session->cliReassemblyMemory : &session->srvReassemblyMemory;
5657    word32  startSeq = seq;
5658    int     added;
5659    int     bytesLeft = sslBytes;  /* could be overlapping fragment */
5660
5661    /* if list is empty add full frame to front */
5662    if (!curr) {
5663        if (MaxRecoveryMemory != -1 &&
5664                      (int)(*reassemblyMemory + sslBytes) > MaxRecoveryMemory) {
5665            SetError(REASSEMBLY_MAX_STR, error, session, FATAL_ERROR_STATE);
5666            return WOLFSSL_FATAL_ERROR;
5667        }
5668        add = CreateBuffer(&seq, seq + sslBytes - 1, sslFrame, &bytesLeft);
5669        if (add == NULL) {
5670            SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
5671            return WOLFSSL_FATAL_ERROR;
5672        }
5673        *front = add;
5674        *reassemblyMemory += sslBytes;
5675        return 1;
5676    }
5677
5678    /* add to front if before current front, up to next->begin */
5679    if (seq < curr->begin) {
5680        word32 end = seq + sslBytes - 1;
5681
5682        if (end >= curr->begin)
5683            end = curr->begin - 1;
5684
5685        if (MaxRecoveryMemory != -1 &&
5686                      (int)(*reassemblyMemory + sslBytes) > MaxRecoveryMemory) {
5687            SetError(REASSEMBLY_MAX_STR, error, session, FATAL_ERROR_STATE);
5688            return WOLFSSL_FATAL_ERROR;
5689        }
5690        add = CreateBuffer(&seq, end, sslFrame, &bytesLeft);
5691        if (add == NULL) {
5692            SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
5693            return WOLFSSL_FATAL_ERROR;
5694        }
5695        add->next = curr;
5696        *front = add;
5697        *reassemblyMemory += sslBytes;
5698    }
5699
5700    /* while we have bytes left, try to find a gap to fill */
5701    while (bytesLeft > 0) {
5702        /* get previous packet in list */
5703        while (curr && (seq >= curr->begin)) {
5704            prev = curr;
5705            curr = curr->next;
5706        }
5707
5708        /* don't add  duplicate data */
5709        if (prev->end >= seq) {
5710            if ( (seq + bytesLeft - 1) <= prev->end)
5711                return 1;
5712            seq = prev->end + 1;
5713            bytesLeft = startSeq + sslBytes - seq;
5714        }
5715
5716        if (!curr)
5717            /* we're at the end */
5718            added = bytesLeft;
5719        else
5720            /* we're in between two frames */
5721            added = min(bytesLeft, (int)(curr->begin - seq));
5722
5723        /* data already there */
5724        if (added <= 0)
5725            continue;
5726
5727        if (MaxRecoveryMemory != -1 &&
5728                         (int)(*reassemblyMemory + added) > MaxRecoveryMemory) {
5729            SetError(REASSEMBLY_MAX_STR, error, session, FATAL_ERROR_STATE);
5730            return WOLFSSL_FATAL_ERROR;
5731        }
5732        add = CreateBuffer(&seq, seq + added - 1, &sslFrame[seq - startSeq],
5733                           &bytesLeft);
5734        if (add == NULL) {
5735            SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
5736            return WOLFSSL_FATAL_ERROR;
5737        }
5738        add->next  = prev->next;
5739        prev->next = add;
5740        *reassemblyMemory += added;
5741    }
5742    return 1;
5743}
5744
5745/* Add out of order FIN capture */
5746/* returns 1 for success (end) */
5747static int AddFinCapture(SnifferSession* session, word32 sequence)
5748{
5749    if (session->flags.side == WOLFSSL_SERVER_END) {
5750        if (session->finCapture.cliCounted == 0)
5751            session->finCapture.cliFinSeq = sequence;
5752    }
5753    else {
5754        if (session->finCapture.srvCounted == 0)
5755            session->finCapture.srvFinSeq = sequence;
5756    }
5757    return 1;
5758}
5759
5760/* Adjust incoming sequence based on side */
5761/* returns 0 on success (continue), -1 on error, 1 on success (end) */
5762static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session,
5763                          int* sslBytes, const byte** sslFrame, char* error)
5764{
5765    int ret = 0;
5766    word32  seqStart = (session->flags.side == WOLFSSL_SERVER_END) ?
5767                                    session->cliSeqStart : session->srvSeqStart;
5768    word32* seqLast = (session->flags.side == WOLFSSL_SERVER_END) ?
5769                                    &session->cliSeqLast : &session->srvSeqLast;
5770    word32  real     = tcpInfo->sequence - seqStart;
5771    word32* expected = (session->flags.side == WOLFSSL_SERVER_END) ?
5772                                  &session->cliExpected : &session->srvExpected;
5773    PacketBuffer* reassemblyList = (session->flags.side == WOLFSSL_SERVER_END) ?
5774                        session->cliReassemblyList : session->srvReassemblyList;
5775    byte  skipPartial = (session->flags.side == WOLFSSL_SERVER_END) ?
5776                                session->flags.srvSkipPartial :
5777                                session->flags.cliSkipPartial;
5778
5779    /* handle rollover of sequence */
5780    if (tcpInfo->sequence < seqStart)
5781        real = 0xffffffffU - seqStart + tcpInfo->sequence + 1;
5782
5783    TraceRelativeSequence(*expected, real);
5784
5785    if (real < *expected) {
5786        int overlap = *expected - real;
5787
5788        if (real + *sslBytes > *expected) {
5789        #ifdef WOLFSSL_ASYNC_CRYPT
5790            if (session->sslServer->error != WC_NO_ERR_TRACE(WC_PENDING_E) &&
5791                session->pendSeq != tcpInfo->sequence)
5792        #endif
5793            {
5794                Trace(OVERLAP_DUPLICATE_STR);
5795            }
5796
5797            /* The following conditional block is duplicated below. It is the
5798             * same action but for a different setup case. If changing this
5799             * block be sure to also update the block below. */
5800            if (reassemblyList) {
5801                word32 newEnd;
5802
5803                /* adjust to expected, remove duplicate */
5804                *sslFrame += overlap;
5805                *sslBytes = (*sslBytes > overlap) ? *sslBytes - overlap : 0;
5806
5807                newEnd = *expected + *sslBytes;
5808                if (newEnd > reassemblyList->begin) {
5809                    int covered_data_len;
5810
5811                    Trace(OVERLAP_REASSEMBLY_BEGIN_STR);
5812
5813                    /* remove bytes already on reassembly list */
5814                    covered_data_len = newEnd - reassemblyList->begin;
5815                    *sslFrame += covered_data_len;
5816                    *sslBytes = (*sslBytes > covered_data_len) ?
5817                                 *sslBytes - covered_data_len : 0;
5818                }
5819                if ((*sslBytes  > 0) && (newEnd > reassemblyList->end)) {
5820                    Trace(OVERLAP_REASSEMBLY_END_STR);
5821
5822                    /* may be past reassembly list end (could have more on list)
5823                       so try to add what's past the front->end */
5824                    AddToReassembly(session->flags.side, reassemblyList->end + 1,
5825                             *sslFrame + (reassemblyList->end - *expected + 1),
5826                                 newEnd - reassemblyList->end, session, error);
5827                }
5828            }
5829            else if (*sslBytes > 0) {
5830                if (real + *sslBytes - 1 > *seqLast) {
5831                    /* fix segment overlap */
5832                #ifdef DEBUG_SNIFFER
5833                    WOLFSSL* ssl = (session->flags.side == WOLFSSL_SERVER_END) ?
5834                                    session->sslServer : session->sslClient;
5835                    printf("\tSegment %d overlap (%d -> %d)\n",
5836                        *sslBytes,
5837                        ssl->buffers.inputBuffer.length - overlap,
5838                        ssl->buffers.inputBuffer.length + *sslBytes - overlap - 1);
5839                #endif
5840                    *sslBytes -= overlap;
5841                    *sslFrame += overlap;
5842                }
5843
5844                /* DUP overlap, allow */
5845                skipPartial = 0; /* do not reset sslBytes */
5846            }
5847            ret = 0;
5848        }
5849        else {
5850            /* This can happen with unseen acks, out of order packets, or
5851             * possible spurious retransmission. */
5852            if (*sslBytes > 0) {
5853                /* If packet has data attempt to process packet, if hasn't
5854                 * already been received */
5855                if (
5856                #ifdef WOLFSSL_ASYNC_CRYPT
5857                    session->sslServer->error != WC_NO_ERR_TRACE(WC_PENDING_E) &&
5858                    session->pendSeq != tcpInfo->sequence &&
5859                #endif
5860                    real + *sslBytes -1 <= *seqLast) {
5861                    Trace(DUPLICATE_STR);
5862                    ret = 1;
5863                }
5864                else {
5865                    /* DUP: allow */
5866                    skipPartial = 0; /* do not reset sslBytes */
5867                    ret = 0;
5868                }
5869            }
5870            else {
5871                /* DUP empty, ignore */
5872                ret = 1;
5873            }
5874        }
5875    }
5876    else if (real > *expected) {
5877        Trace(OUT_OF_ORDER_STR);
5878        if (*sslBytes > 0) {
5879            int addResult = AddToReassembly(session->flags.side, real,
5880                                          *sslFrame, *sslBytes, session, error);
5881            ret = (skipPartial) ? 0 : addResult;
5882        }
5883        else if (tcpInfo->fin) {
5884            ret = AddFinCapture(session, real);
5885        }
5886    }
5887    else if (*sslBytes > 0) {
5888        if (skipPartial) {
5889            AddToReassembly(session->flags.side, real,
5890                                          *sslFrame, *sslBytes, session, error);
5891            ret = 0;
5892        }
5893        /* The following conditional block is duplicated above. It is the
5894         * same action but for a different setup case. If changing this
5895         * block be sure to also update the block above. */
5896        else if (reassemblyList) {
5897            word32 newEnd = *expected + *sslBytes;
5898
5899            if (newEnd > reassemblyList->begin) {
5900                int covered_data_len;
5901
5902                Trace(OVERLAP_REASSEMBLY_BEGIN_STR);
5903
5904                /* remove bytes already on reassembly list */
5905                covered_data_len = newEnd - reassemblyList->begin;
5906                *sslFrame += covered_data_len;
5907                *sslBytes = (*sslBytes > covered_data_len) ?
5908                             *sslBytes - covered_data_len : 0;
5909            }
5910            if ((*sslBytes > 0) && (newEnd > reassemblyList->end)) {
5911                Trace(OVERLAP_REASSEMBLY_END_STR);
5912
5913                /* may be past reassembly list end (could have more on list)
5914                   so try to add what's past the front->end */
5915                AddToReassembly(session->flags.side, reassemblyList->end + 1,
5916                         *sslFrame + (reassemblyList->end - *expected + 1),
5917                             newEnd - reassemblyList->end, session, error);
5918            }
5919        }
5920    }
5921    else {
5922        /* no data present */
5923    }
5924
5925    if (ret == 0) {
5926        /* got expected sequence */
5927        *expected += *sslBytes;
5928        if (tcpInfo->fin)
5929            *expected += 1;
5930    }
5931    if (*sslBytes > 0) {
5932        *seqLast = real + *sslBytes - 1;
5933    }
5934    if (*sslBytes > 0 && skipPartial) {
5935        *sslBytes = 0;
5936    }
5937
5938    return ret;
5939}
5940
5941
5942static int FindNextRecordInAssembly(SnifferSession* session,
5943                                    const byte** sslFrame, int* sslBytes,
5944                                    const byte** end, char* error)
5945{
5946    PacketBuffer**     front = (session->flags.side == WOLFSSL_SERVER_END) ?
5947                                    &session->cliReassemblyList :
5948                                    &session->srvReassemblyList;
5949    PacketBuffer*       curr = *front;
5950    PacketBuffer*       prev = NULL;
5951    byte*        skipPartial = (session->flags.side == WOLFSSL_SERVER_END) ?
5952                                    &session->flags.srvSkipPartial :
5953                                    &session->flags.cliSkipPartial;
5954    int* reassemblyMemory = (session->flags.side == WOLFSSL_SERVER_END) ?
5955                                    (int*)&session->cliReassemblyMemory :
5956                                    (int*)&session->srvReassemblyMemory;
5957    WOLFSSL*             ssl = (session->flags.side == WOLFSSL_SERVER_END) ?
5958                                    session->sslServer :
5959                                    session->sslClient;
5960    ProtocolVersion       pv = ssl->version;
5961    word32*         expected = (session->flags.side == WOLFSSL_SERVER_END) ?
5962                                    &session->cliExpected :
5963                                    &session->srvExpected;
5964
5965    while (curr != NULL) {
5966        *expected = curr->end + 1;
5967
5968        if (curr->data[0] == application_data &&
5969            curr->data[1] == pv.major &&
5970            curr->data[2] == pv.minor) {
5971
5972            if (ssl->buffers.inputBuffer.length > 0)
5973                Trace(DROPPING_PARTIAL_RECORD);
5974
5975            *sslBytes = (int)(curr->end - curr->begin + 1);
5976            if ( *sslBytes > (int)ssl->buffers.inputBuffer.bufferSize) {
5977                if (GrowInputBuffer(ssl, *sslBytes, 0) < 0) {
5978                    SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
5979                    return WOLFSSL_FATAL_ERROR;
5980                }
5981            }
5982
5983            XMEMCPY(ssl->buffers.inputBuffer.buffer, curr->data, *sslBytes);
5984
5985            *front = curr->next;
5986            *reassemblyMemory -= *sslBytes;
5987            FreePacketBuffer(curr);
5988
5989            ssl->buffers.inputBuffer.length = *sslBytes;
5990            *sslFrame = ssl->buffers.inputBuffer.buffer;
5991            *end = *sslFrame + *sslBytes;
5992            *skipPartial = 0;
5993
5994            return 0;
5995        }
5996        else if (ssl->specs.cipher_type == block) {
5997            int ivPos = (int)(curr->end - curr->begin -
5998                                                     ssl->specs.block_size + 1);
5999            if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes) {
6000#ifndef NO_AES
6001                if (ivPos >= 0)
6002                    wc_AesSetIV(ssl->decrypt.aes, curr->data + ivPos);
6003#endif
6004            }
6005            else if (ssl->specs.bulk_cipher_algorithm == wolfssl_triple_des) {
6006#ifndef NO_DES3
6007                if (ivPos >= 0)
6008                    wc_Des3_SetIV(ssl->decrypt.des3, curr->data + ivPos);
6009#endif
6010            }
6011        }
6012
6013        Trace(DROPPING_LOST_FRAG_STR);
6014#ifdef WOLFSSL_SNIFFER_STATS
6015        INC_STAT(SnifferStats.sslDecodeFails);
6016#endif
6017        prev = curr;
6018        curr = curr->next;
6019        *reassemblyMemory -= (int)(prev->end - prev->begin + 1);
6020        FreePacketBuffer(prev);
6021    }
6022
6023    *front = curr;
6024
6025    return 0;
6026}
6027
6028
6029static int FixSequence(TcpInfo* tcpInfo, SnifferSession* session)
6030{
6031    word32*   expected = (session->flags.side == WOLFSSL_SERVER_END) ?
6032                                &session->srvExpected : &session->cliExpected;
6033    word32    seqStart = (session->flags.side == WOLFSSL_SERVER_END) ?
6034                                session->srvSeqStart : session->cliSeqStart;
6035    PacketBuffer* list = (session->flags.side == WOLFSSL_SERVER_END) ?
6036                                session->srvReassemblyList :
6037                                session->cliReassemblyList;
6038    byte*  skipPartial = (session->flags.side != WOLFSSL_SERVER_END) ?
6039                                &session->flags.srvSkipPartial :
6040                                &session->flags.cliSkipPartial;
6041
6042    *skipPartial = 1;
6043
6044    if (list != NULL)
6045        *expected = list->begin;
6046    else
6047        *expected = tcpInfo->ackNumber - seqStart;
6048
6049    return 1;
6050}
6051
6052
6053/* Check latest ack number for missing packets
6054   return 0 ok, <0 on error */
6055static int CheckAck(TcpInfo* tcpInfo, SnifferSession* session)
6056{
6057    if (tcpInfo->ack) {
6058        word32  seqStart = (session->flags.side == WOLFSSL_SERVER_END) ?
6059                                     session->srvSeqStart :session->cliSeqStart;
6060        word32  real     = tcpInfo->ackNumber - seqStart;
6061        word32  expected = (session->flags.side == WOLFSSL_SERVER_END) ?
6062                                  session->srvExpected : session->cliExpected;
6063
6064        /* handle rollover of sequence */
6065        if (tcpInfo->ackNumber < seqStart)
6066            real = 0xffffffffU - seqStart + tcpInfo->ackNumber + 1;
6067
6068        TraceAck(real, expected);
6069
6070        if (real > expected)
6071            return WOLFSSL_FATAL_ERROR;  /* we missed a packet, ACKing data we never saw */
6072    }
6073    return 0;
6074}
6075
6076
6077/* Check TCP Sequence status */
6078/* returns 0 on success (continue), -1 on error, 1 on success (end) */
6079static int CheckSequence(IpInfo* ipInfo, TcpInfo* tcpInfo,
6080                         SnifferSession* session, int* sslBytes,
6081                         const byte** sslFrame, char* error)
6082{
6083    int actualLen;
6084    byte* ackFault = (session->flags.side == WOLFSSL_SERVER_END) ?
6085                        &session->flags.cliAckFault :
6086                        &session->flags.srvAckFault;
6087
6088#ifdef WOLFSSL_ASYNC_CRYPT
6089    if (session->sslServer->error == 0 && session->pendSeq != 0 &&
6090        session->pendSeq == tcpInfo->sequence) {
6091        return 0; /* ready to process, but skip sequence checking below (already done) */
6092    }
6093    /* check if this session is pending */
6094    else if (session->pendSeq != 0 && session->pendSeq != tcpInfo->sequence) {
6095        return WC_PENDING_E;
6096    }
6097#endif
6098
6099    /* init SEQ from server to client - if not ack fault */
6100    if (tcpInfo->syn && tcpInfo->ack && !*ackFault) {
6101        session->srvSeqStart = tcpInfo->sequence;
6102        session->srvExpected = 1;
6103        TraceServerSyn(tcpInfo->sequence);
6104        return 1;
6105    }
6106
6107    /* adjust potential ethernet trailer */
6108    actualLen = ipInfo->total - ipInfo->length - tcpInfo->length;
6109    if (*sslBytes > actualLen) {
6110        *sslBytes = actualLen;
6111    }
6112
6113    TraceSequence(tcpInfo->sequence, *sslBytes);
6114    if (CheckAck(tcpInfo, session) < 0) {
6115        if (!RecoveryEnabled) {
6116        #ifndef WOLFSSL_SNIFFER_NO_RECOVERY
6117            UpdateMissedDataSessions();
6118        #endif
6119            SetError(ACK_MISSED_STR, error, session, FATAL_ERROR_STATE);
6120            return WOLFSSL_FATAL_ERROR;
6121        }
6122        else {
6123            SetError(ACK_MISSED_STR, error, session, 0);
6124            if (*ackFault == 0) {
6125                *ackFault = 1;
6126            #ifndef WOLFSSL_SNIFFER_NO_RECOVERY
6127                UpdateMissedDataSessions();
6128            #endif
6129            }
6130            return FixSequence(tcpInfo, session);
6131        }
6132    }
6133
6134    if (*ackFault) {
6135        Trace(CLEAR_ACK_FAULT);
6136        *ackFault = 0;
6137    }
6138
6139    return AdjustSequence(tcpInfo, session, sslBytes, sslFrame, error);
6140}
6141
6142
6143/* Check Status before record processing */
6144/* returns 0 on success (continue), -1 on error, 1 on success (end) */
6145static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo,
6146                          const byte** sslFrame, SnifferSession** pSession,
6147                          int* sslBytes, const byte** end, char* error)
6148{
6149    word32 length;
6150    SnifferSession* session = *pSession;
6151    WOLFSSL* ssl = (session->flags.side == WOLFSSL_SERVER_END) ?
6152                                  session->sslServer : session->sslClient;
6153    byte skipPartial = (session->flags.side == WOLFSSL_SERVER_END) ?
6154                        session->flags.srvSkipPartial :
6155                        session->flags.cliSkipPartial;
6156
6157#ifdef WOLFSSL_ASYNC_CRYPT
6158    /* if this is a pending async packet do not "grow" on partial (we already did) */
6159    if (session->pendSeq == tcpInfo->sequence) {
6160        if (session->sslServer->error == WC_NO_ERR_TRACE(WC_PENDING_E)) {
6161            return 0; /* don't check pre-record again */
6162        }
6163        /* if record check already done then restore, otherwise process normal */
6164        if (ssl->buffers.inputBuffer.length > 0) {
6165            *sslBytes = ssl->buffers.inputBuffer.length;
6166            *sslFrame = ssl->buffers.inputBuffer.buffer;
6167            *end = *sslFrame + *sslBytes;
6168            return 0;
6169        }
6170    }
6171#endif
6172
6173    /* remove SnifferSession on 2nd FIN or RST */
6174    if (tcpInfo->fin || tcpInfo->rst) {
6175        /* flag FIN and RST */
6176        if (tcpInfo->fin)
6177            session->flags.finCount += 1;
6178        else if (tcpInfo->rst)
6179            session->flags.finCount += 2;
6180
6181        if (session->flags.finCount >= 2) {
6182            RemoveSession(session, ipInfo, tcpInfo, 0);
6183            *pSession = NULL;
6184            return 1;
6185        }
6186    }
6187
6188    if (session->flags.fatalError == FATAL_ERROR_STATE) {
6189        SetError(FATAL_ERROR_STR, error, NULL, 0);
6190        return WOLFSSL_FATAL_ERROR;
6191    }
6192
6193    if (skipPartial) {
6194        if (FindNextRecordInAssembly(session,
6195                                     sslFrame, sslBytes, end, error) < 0) {
6196            return WOLFSSL_FATAL_ERROR;
6197        }
6198    }
6199
6200    if (*sslBytes <= 0) {
6201        Trace(NO_DATA_STR);
6202        return 1;
6203    }
6204
6205    /* if current partial data, add to end of partial */
6206    /* if skipping, the data is already at the end of partial */
6207    length = ssl->buffers.inputBuffer.length;
6208    if ( !skipPartial && length ) {
6209        Trace(PARTIAL_ADD_STR);
6210
6211        if ( (*sslBytes + length) > ssl->buffers.inputBuffer.bufferSize) {
6212            if (GrowInputBuffer(ssl, *sslBytes, length) < 0) {
6213                SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
6214                return WOLFSSL_FATAL_ERROR;
6215            }
6216        }
6217        XMEMCPY(&ssl->buffers.inputBuffer.buffer[length],
6218                *sslFrame, *sslBytes);
6219        *sslBytes += length;
6220        ssl->buffers.inputBuffer.length = *sslBytes;
6221        *sslFrame = ssl->buffers.inputBuffer.buffer;
6222        *end = *sslFrame + *sslBytes;
6223    }
6224
6225    if (session->flags.clientHello == 0 && **sslFrame != handshake) {
6226        /* Sanity check the packet for an old style client hello. */
6227        int rhSize = (((*sslFrame)[0] & 0x7f) << 8) | ((*sslFrame)[1]);
6228
6229        if ((rhSize <= (*sslBytes - 2)) &&
6230            (*sslFrame)[2] == OLD_HELLO_ID && (*sslFrame)[3] == SSLv3_MAJOR) {
6231#ifdef OLD_HELLO_ALLOWED
6232        int ret = DoOldHello(session, *sslFrame, &rhSize, sslBytes, error);
6233        if (ret < 0)
6234            return WOLFSSL_FATAL_ERROR;  /* error already set */
6235        if (*sslBytes <= 0)
6236            return 1;
6237#endif
6238        }
6239        else {
6240#ifdef STARTTLS_ALLOWED
6241            if (ssl->buffers.inputBuffer.dynamicFlag) {
6242                ssl->buffers.inputBuffer.length = 0;
6243                ShrinkInputBuffer(ssl, NO_FORCED_FREE);
6244            }
6245            return 1;
6246#endif
6247        }
6248    }
6249
6250    return 0;
6251}
6252
6253
6254/* See if input on the reassembly list is ready for consuming */
6255/* returns 1 for TRUE, 0 for FALSE */
6256static int HaveMoreInput(SnifferSession* session, const byte** sslFrame,
6257                         int* sslBytes, const byte** end, char* error)
6258{
6259    /* sequence and reassembly based on from, not to */
6260    int            moreInput = 0;
6261    PacketBuffer** front = (session->flags.side == WOLFSSL_SERVER_END) ?
6262                      &session->cliReassemblyList : &session->srvReassemblyList;
6263    word32*        expected = (session->flags.side == WOLFSSL_SERVER_END) ?
6264                                  &session->cliExpected : &session->srvExpected;
6265    /* buffer is on receiving end */
6266    word32*          length = (session->flags.side == WOLFSSL_SERVER_END) ?
6267                               &session->sslServer->buffers.inputBuffer.length :
6268                               &session->sslClient->buffers.inputBuffer.length;
6269    byte**         myBuffer = (session->flags.side == WOLFSSL_SERVER_END) ?
6270                               &session->sslServer->buffers.inputBuffer.buffer :
6271                               &session->sslClient->buffers.inputBuffer.buffer;
6272    word32*      bufferSize = (session->flags.side == WOLFSSL_SERVER_END) ?
6273                           &session->sslServer->buffers.inputBuffer.bufferSize :
6274                           &session->sslClient->buffers.inputBuffer.bufferSize;
6275    WOLFSSL*           ssl  = (session->flags.side == WOLFSSL_SERVER_END) ?
6276                            session->sslServer : session->sslClient;
6277    word32*     reassemblyMemory = (session->flags.side == WOLFSSL_SERVER_END) ?
6278                  &session->cliReassemblyMemory : &session->srvReassemblyMemory;
6279
6280    while (*front && ((*front)->begin == *expected) ) {
6281        int room = (int)(*bufferSize - *length);
6282        int packetLen = (int)((*front)->end - (*front)->begin + 1);
6283
6284        if (packetLen > room && *bufferSize < MAX_INPUT_SZ) {
6285            if (GrowInputBuffer(ssl, packetLen, *length) < 0) {
6286                SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
6287                return 0;
6288            }
6289            room = *bufferSize - *length;   /* bufferSize is now bigger */
6290        }
6291
6292        if (packetLen <= room) {
6293            PacketBuffer* del = *front;
6294            byte*         buf = *myBuffer;
6295
6296            XMEMCPY(&buf[*length], (*front)->data, packetLen);
6297            *length   += packetLen;
6298            *expected += packetLen;
6299
6300            /* remove used packet */
6301            *front = (*front)->next;
6302
6303            *reassemblyMemory -= packetLen;
6304            FreePacketBuffer(del);
6305
6306            moreInput = 1;
6307        }
6308        else
6309            break;
6310    }
6311    if (moreInput) {
6312        *sslFrame = *myBuffer;
6313        *sslBytes = *length;
6314        *end      = *myBuffer + *length;
6315    }
6316    return moreInput;
6317}
6318
6319
6320
6321/* Process Message(s) from sslFrame */
6322/* return Number of bytes on success, 0 for no data yet, and -1 on error */
6323static int ProcessMessage(const byte* sslFrame, SnifferSession* session,
6324                          int sslBytes, byte** data, const byte* end,
6325                          void* ctx, char* error)
6326{
6327    const byte*       sslBegin = sslFrame;
6328    const byte*       recordEnd;   /* end of record indicator */
6329    const byte*       inRecordEnd; /* indicator from input stream not decrypt */
6330    RecordLayerHeader rh;
6331    int               rhSize;
6332    int               ret;
6333    int               errCode = 0;
6334    int               decoded = 0;      /* bytes stored for user in data */
6335    int               notEnough;        /* notEnough bytes yet flag */
6336    int               decrypted = 0;    /* was current msg decrypted */
6337    WOLFSSL*          ssl = (session->flags.side == WOLFSSL_SERVER_END) ?
6338                            session->sslServer : session->sslClient;
6339doMessage:
6340
6341    notEnough = 0;
6342    rhSize = 0;
6343    if (sslBytes < 0) {
6344        SetError(PACKET_HDR_SHORT_STR, error, session, FATAL_ERROR_STATE);
6345        return WOLFSSL_FATAL_ERROR;
6346    }
6347    if (sslBytes >= RECORD_HEADER_SZ) {
6348        if (GetRecordHeader(sslFrame, &rh, &rhSize) != 0) {
6349            /* ignore packet if record header errors */
6350            SetError(BAD_RECORD_HDR_STR, error, session, 0);
6351            return 0;
6352        }
6353    }
6354    else {
6355        notEnough = 1;
6356    }
6357
6358    if (notEnough || rhSize > (sslBytes - RECORD_HEADER_SZ)) {
6359        /* don't have enough input yet to process full SSL record */
6360        Trace(PARTIAL_INPUT_STR);
6361
6362        /* store partial if not there already or we advanced */
6363        if (ssl->buffers.inputBuffer.length == 0 || sslBegin != sslFrame) {
6364            if (sslBytes > (int)ssl->buffers.inputBuffer.bufferSize) {
6365                if (GrowInputBuffer(ssl, sslBytes, 0) < 0) {
6366                    SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
6367                    return WOLFSSL_FATAL_ERROR;
6368                }
6369            }
6370            XMEMMOVE(ssl->buffers.inputBuffer.buffer, sslFrame, sslBytes);
6371            ssl->buffers.inputBuffer.length = sslBytes;
6372        }
6373        if (HaveMoreInput(session, &sslFrame, &sslBytes, &end, error))
6374            goto doMessage;
6375        return decoded;
6376    }
6377    sslFrame += RECORD_HEADER_SZ;
6378    sslBytes -= RECORD_HEADER_SZ;
6379    recordEnd = sslFrame + rhSize;   /* may have more than one record */
6380    inRecordEnd = recordEnd;
6381
6382    /* Make sure cipher is on for client, if we get an application data packet
6383     * and handshake is done for server. This workaround is required if client
6384     * handshake packets were missed, retransmitted or sent out of order. */
6385    if ((enum ContentType)rh.type == application_data &&
6386                  ssl->options.handShakeDone && session->flags.serverCipherOn) {
6387        session->flags.clientCipherOn = 1;
6388        session->sslClient->options.handShakeState = HANDSHAKE_DONE;
6389        session->sslClient->options.handShakeDone  = 1;
6390    }
6391
6392    /* decrypt if needed */
6393    if ((session->flags.side == WOLFSSL_SERVER_END &&
6394                                               session->flags.serverCipherOn)
6395     || (session->flags.side == WOLFSSL_CLIENT_END &&
6396                                               session->flags.clientCipherOn)) {
6397        int ivAdvance = 0;  /* TLSv1.1 advance amount */
6398
6399        /* change_cipher_spec is not encrypted */
6400        if (rh.type == change_cipher_spec) {
6401            goto doPart;
6402        }
6403        if (ssl->decrypt.setup != 1) {
6404            SetError(DECRYPT_KEYS_NOT_SETUP, error, session, FATAL_ERROR_STATE);
6405            return WOLFSSL_FATAL_ERROR;
6406        }
6407        if (CheckAvailableSize(ssl, rhSize) < 0) {
6408            SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
6409            return WOLFSSL_FATAL_ERROR;
6410        }
6411
6412        sslFrame = DecryptMessage(ssl, sslFrame, rhSize,
6413                                  ssl->buffers.outputBuffer.buffer, &errCode,
6414                                  &ivAdvance, &rh);
6415        recordEnd = sslFrame - ivAdvance + rhSize;  /* sslFrame moved so
6416                                                       should recordEnd */
6417        decrypted = 1;
6418
6419#ifdef WOLFSSL_SNIFFER_STATS
6420        if (errCode != 0) {
6421            INC_STAT(SnifferStats.sslKeyFails);
6422        }
6423        else {
6424            LOCK_STAT();
6425            NOLOCK_INC_STAT(SnifferStats.sslDecryptedPackets);
6426            NOLOCK_ADD_TO_STAT(SnifferStats.sslDecryptedBytes, sslBytes);
6427            UNLOCK_STAT();
6428        }
6429#endif
6430        if (errCode != 0) {
6431            if ((enum ContentType)rh.type == application_data) {
6432                SetError(BAD_DECRYPT, error, session, FATAL_ERROR_STATE);
6433                return WOLFSSL_FATAL_ERROR;
6434            }
6435            /* do not end session for failures on handshake packets */
6436            return 0;
6437        }
6438    }
6439
6440doPart:
6441
6442    switch ((enum ContentType)rh.type) {
6443        case handshake:
6444            {
6445                int startIdx = sslBytes;
6446                int used;
6447
6448                Trace(GOT_HANDSHAKE_STR);
6449                ret = DoHandShake(sslFrame, &sslBytes, session, error, rhSize);
6450            #ifdef WOLFSSL_ASYNC_CRYPT
6451                if (ret == WC_NO_ERR_TRACE(WC_PENDING_E))
6452                    return ret;
6453            #endif
6454                if (ret != 0 || sslBytes > startIdx) {
6455                    if (session->flags.fatalError == 0)
6456                        SetError(BAD_HANDSHAKE_STR, error, session,
6457                                 FATAL_ERROR_STATE);
6458                    return WOLFSSL_FATAL_ERROR;
6459                }
6460
6461                /* DoHandShake now fully decrements sslBytes to remaining */
6462                used = startIdx - sslBytes;
6463                sslFrame += used;
6464                if (decrypted)
6465                    sslFrame += ssl->keys.padSz;
6466            }
6467            break;
6468        case change_cipher_spec:
6469            if (session->flags.side == WOLFSSL_SERVER_END) {
6470            #ifdef WOLFSSL_TLS13
6471                if (IsAtLeastTLSv1_3(session->sslServer->version) && session->srvKs.key_len == 0) {
6472                    session->flags.serverCipherOn = 0;
6473                }
6474                else
6475            #endif
6476                {
6477                    session->flags.serverCipherOn = 1;
6478                }
6479            }
6480            else
6481                session->flags.clientCipherOn = 1;
6482            Trace(GOT_CHANGE_CIPHER_STR);
6483            ssl->options.handShakeState = HANDSHAKE_DONE;
6484            ssl->options.handShakeDone  = 1;
6485
6486            sslFrame += 1;
6487            sslBytes -= 1;
6488
6489            break;
6490        case application_data:
6491            Trace(GOT_APP_DATA_STR);
6492            {
6493                word32 inOutIdx = 0;
6494                int    ivExtra  = 0;
6495
6496                ret = DoApplicationData(ssl, (byte*)sslFrame, &inOutIdx, SNIFF);
6497                if (ret == 0) {
6498                    ret = ssl->buffers.clearOutputBuffer.length;
6499                #ifndef WOLFSSL_AEAD_ONLY
6500                    if (ssl->specs.cipher_type == block) {
6501                        if (ssl->options.tls1_1)
6502                            ivExtra = ssl->specs.block_size;
6503                    }
6504                    else
6505                #endif
6506                    if (ssl->specs.cipher_type == aead) {
6507                        if (!ssl->options.tls1_3 &&
6508                            ssl->specs.bulk_cipher_algorithm != wolfssl_chacha)
6509                            ivExtra = AESGCM_EXP_IV_SZ;
6510                    }
6511
6512                    ret -= ivExtra;
6513
6514                #if defined(HAVE_ENCRYPT_THEN_MAC) && \
6515                    !defined(WOLFSSL_AEAD_ONLY)
6516                    if (ssl->options.startedETMRead)
6517                        ret -= MacSize(ssl);
6518                #endif
6519                    TraceGotData(ret);
6520                    if (ret > 0) {  /* may be blank message */
6521                        if (data != NULL) {
6522                            byte* tmpData;  /* don't leak on realloc free */
6523                            /* add an extra byte at end of allocation in case
6524                             * user wants to null terminate plaintext */
6525                            tmpData = (byte*)XREALLOC(*data, decoded + ret + 1,
6526                                    NULL, DYNAMIC_TYPE_TMP_BUFFER);
6527                            if (tmpData == NULL) {
6528                                ForceZero(*data, decoded);
6529                                XFREE(*data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
6530                                *data = NULL;
6531                                SetError(MEMORY_STR, error, session,
6532                                         FATAL_ERROR_STATE);
6533                                return WOLFSSL_FATAL_ERROR;
6534                            }
6535                            *data = tmpData;
6536                            XMEMCPY(*data + decoded,
6537                                    ssl->buffers.clearOutputBuffer.buffer, ret);
6538                        }
6539                        else {
6540#ifdef WOLFSSL_SNIFFER_STORE_DATA_CB
6541                            if (StoreDataCb) {
6542                                const byte* buf;
6543                                word32 offset = 0;
6544                                word32 bufSz;
6545                                int stored;
6546
6547                                buf = ssl->buffers.clearOutputBuffer.buffer;
6548                                bufSz = ssl->buffers.clearOutputBuffer.length;
6549                                do {
6550                                    stored = StoreDataCb(buf, bufSz, offset,
6551                                            ctx);
6552                                    if (stored <= 0) {
6553                                        return WOLFSSL_FATAL_ERROR;
6554                                    }
6555                                    offset += stored;
6556                                } while (offset < bufSz);
6557                            }
6558                            else {
6559                                SetError(STORE_DATA_CB_MISSING_STR, error,
6560                                        session, FATAL_ERROR_STATE);
6561                                return WOLFSSL_FATAL_ERROR;
6562                            }
6563#else
6564                            (void)ctx;
6565                            SetError(NO_DATA_DEST_STR, error, session,
6566                                    FATAL_ERROR_STATE);
6567                            return WOLFSSL_FATAL_ERROR;
6568#endif
6569                        }
6570                        TraceAddedData(ret, decoded);
6571                        decoded += ret;
6572                        ssl->buffers.clearOutputBuffer.length = 0;
6573                    }
6574                    else if (ret < 0){
6575                    #ifdef DEBUG_SNIFFER
6576                        printf("Invalid data offset calculation! "
6577                            "ret %d, inOutIdx %d, ivExtra %d\n",
6578                            ret, inOutIdx, ivExtra);
6579                    #endif
6580                        /* set error, but do not treat fatal */
6581                        SetError(BAD_APP_DATA_STR, error, session, 0);
6582                        return WOLFSSL_FATAL_ERROR;
6583                    }
6584                }
6585                else {
6586                    /* set error, but do not treat fatal */
6587                    SetError(BAD_APP_DATA_STR, error, session, 0);
6588                    return WOLFSSL_FATAL_ERROR;
6589                }
6590                if (ssl->buffers.outputBuffer.dynamicFlag)
6591                    ShrinkOutputBuffer(ssl);
6592
6593                sslFrame += inOutIdx;
6594                sslBytes -= inOutIdx;
6595            }
6596            break;
6597        case alert:
6598            Trace(GOT_ALERT_STR);
6599#ifdef WOLFSSL_SNIFFER_STATS
6600            INC_STAT(SnifferStats.sslAlerts);
6601#endif
6602            sslFrame += rhSize;
6603            sslBytes -= rhSize;
6604            break;
6605#ifdef WOLFSSL_DTLS13
6606        case ack:
6607            /* TODO */
6608#endif /* WOLFSSL_DTLS13 */
6609        case dtls12_cid:
6610        case no_type:
6611        default:
6612            SetError(GOT_UNKNOWN_RECORD_STR, error, session, FATAL_ERROR_STATE);
6613            return WOLFSSL_FATAL_ERROR;
6614    }
6615
6616    /* do we have another msg in record (if app data did we decode bytes?) */
6617    if (sslFrame < recordEnd && ((enum ContentType)rh.type != application_data ||
6618        ((enum ContentType)rh.type == application_data && decoded))) {
6619        Trace(ANOTHER_MSG_STR);
6620        goto doPart;
6621    }
6622
6623    /* back to input stream instead of potential decrypt buffer */
6624    recordEnd = inRecordEnd;
6625
6626    /* do we have more records ? */
6627    if (recordEnd < end) {
6628        Trace(ANOTHER_MSG_STR);
6629        sslFrame = recordEnd;
6630        sslBytes = (int)(end - recordEnd);
6631        goto doMessage;
6632    }
6633
6634    /* clear used input */
6635    ssl->buffers.inputBuffer.length = 0;
6636
6637    /* could have more input ready now */
6638    if (HaveMoreInput(session, &sslFrame, &sslBytes, &end, error))
6639        goto doMessage;
6640
6641    if (ssl->buffers.inputBuffer.dynamicFlag)
6642        ShrinkInputBuffer(ssl, NO_FORCED_FREE);
6643
6644    return decoded;
6645}
6646
6647
6648/* See if we need to process any pending FIN captures */
6649/* Return 0=normal, else = session removed */
6650static int CheckFinCapture(IpInfo* ipInfo, TcpInfo* tcpInfo,
6651                            SnifferSession* session)
6652{
6653    int ret = 0;
6654    if (session->finCapture.cliFinSeq && session->finCapture.cliFinSeq <=
6655                                         session->cliExpected) {
6656        if (session->finCapture.cliCounted == 0) {
6657            session->flags.finCount += 1;
6658            session->finCapture.cliCounted = 1;
6659            TraceClientFin(session->finCapture.cliFinSeq, session->cliExpected);
6660        }
6661    }
6662
6663    if (session->finCapture.srvFinSeq && session->finCapture.srvFinSeq <=
6664                                         session->srvExpected) {
6665        if (session->finCapture.srvCounted == 0) {
6666            session->flags.finCount += 1;
6667            session->finCapture.srvCounted = 1;
6668            TraceServerFin(session->finCapture.srvFinSeq, session->srvExpected);
6669        }
6670    }
6671
6672    if (session->flags.finCount >= 2) {
6673        RemoveSession(session, ipInfo, tcpInfo, 0);
6674        ret = 1;
6675    }
6676    return ret;
6677}
6678
6679
6680/* If session is in fatal error state free resources now
6681   return true if removed, 0 otherwise */
6682static int RemoveFatalSession(IpInfo* ipInfo, TcpInfo* tcpInfo,
6683                              SnifferSession* session, char* error)
6684{
6685    if (session && session->flags.fatalError == FATAL_ERROR_STATE) {
6686        if (!session->verboseErr) {
6687            SetError(FATAL_ERROR_STR, error, NULL, 0);
6688        }
6689        RemoveSession(session, ipInfo, tcpInfo, 0);
6690        return 1;
6691    }
6692    return 0;
6693}
6694
6695int ssl_DecodePacket_GetStream(SnifferStreamInfo* info, const byte* packet,
6696        int length, char* error )
6697{
6698    TcpInfo           tcpInfo;
6699    IpInfo            ipInfo;
6700    const byte*       sslFrame = NULL;
6701    int               sslBytes = 0;
6702
6703    XMEMSET(&tcpInfo, 0, sizeof(tcpInfo));
6704    XMEMSET(&ipInfo, 0, sizeof(ipInfo));
6705
6706    if (CheckHeaders(&ipInfo, &tcpInfo, packet, length, &sslFrame, &sslBytes,
6707            error, 0, 0) != 0) {
6708        return WOLFSSL_SNIFFER_ERROR;
6709    }
6710
6711    info->src     = ipInfo.src;
6712    info->dst     = ipInfo.dst;
6713    info->srcPort = tcpInfo.srcPort;
6714    info->dstPort = tcpInfo.dstPort;
6715
6716    return 0;
6717}
6718
6719/* Passes in an IP/TCP packet for decoding (ethernet/localhost frame) removed */
6720/* returns Number of bytes on success, 0 for no data yet, and
6721 * WOLFSSL_SNIFFER_ERROR on error and WOLFSSL_SNIFFER_FATAL_ERROR on fatal state
6722 * error
6723 */
6724static int ssl_DecodePacketInternal(const byte* packet, int length, int isChain,
6725                                    byte** data, SSLInfo* sslInfo,
6726                                    void* ctx, char* error, int asyncOkay)
6727{
6728    TcpInfo           tcpInfo;
6729    IpInfo            ipInfo;
6730    byte*             tmpPacket = NULL;        /* Assemble the chain */
6731    const byte*       sslFrame;
6732    const byte*       end;
6733    int               sslBytes;                /* ssl bytes unconsumed */
6734    int               ret;
6735    SnifferSession*   session = NULL;
6736
6737    if (isChain) {
6738#ifdef WOLFSSL_SNIFFER_CHAIN_INPUT
6739        struct iovec* chain;
6740        word32 i;
6741        size_t totalLength;
6742
6743        word32 chainSz = (word32)length;
6744
6745        chain = (struct iovec*)packet;
6746        totalLength = 0;
6747        for (i = 0; i < chainSz; i++) {
6748            size_t prev = totalLength;
6749            totalLength += chain[i].iov_len;
6750            if (totalLength < prev || totalLength > (size_t)INT_MAX) {
6751                SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
6752                return WOLFSSL_SNIFFER_ERROR;
6753            }
6754        }
6755        length = (int)totalLength;
6756
6757        tmpPacket = (byte*)XMALLOC(length, NULL, DYNAMIC_TYPE_SNIFFER_CHAIN_BUFFER);
6758        if (tmpPacket == NULL) return MEMORY_E;
6759
6760        length = 0;
6761        for (i = 0; i < chainSz; i++) {
6762            XMEMCPY(tmpPacket+length,chain[i].iov_base,chain[i].iov_len);
6763            length += (int)chain[i].iov_len;
6764        }
6765        packet = (const byte*)tmpPacket;
6766#else
6767        SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
6768        return WOLFSSL_SNIFFER_ERROR;
6769#endif
6770    }
6771
6772    if (CheckHeaders(&ipInfo, &tcpInfo, packet, length, &sslFrame, &sslBytes,
6773                     error, 1, 1) != 0) {
6774        ret = WOLFSSL_SNIFFER_ERROR;
6775        goto exit_decode;
6776    }
6777
6778    end = sslFrame + sslBytes;
6779
6780    ret = CheckSession(&ipInfo, &tcpInfo, sslBytes, &session, error);
6781    if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) {
6782        ret = WOLFSSL_SNIFFER_FATAL_ERROR;
6783        goto exit_decode;
6784    }
6785#ifdef WOLFSSL_ASYNC_CRYPT
6786    else if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
6787        ret = WC_PENDING_E;
6788        goto exit_decode;
6789    }
6790#endif
6791    else if (ret == -1) {
6792        ret = WOLFSSL_SNIFFER_ERROR;
6793        goto exit_decode;
6794    }
6795    else if (ret ==  1) {
6796#ifdef WOLFSSL_SNIFFER_STATS
6797        if (sslBytes > 0) {
6798            LOCK_STAT();
6799            NOLOCK_INC_STAT(SnifferStats.sslEncryptedPackets);
6800            NOLOCK_ADD_TO_STAT(SnifferStats.sslEncryptedBytes, sslBytes);
6801            UNLOCK_STAT();
6802        }
6803        else {
6804            INC_STAT(SnifferStats.sslDecryptedPackets);
6805        }
6806#endif
6807        ret = 0;
6808        goto exit_decode; /* done for now */
6809    }
6810
6811#ifdef WOLFSSL_ASYNC_CRYPT
6812    session->userCtx = ctx;
6813#endif
6814
6815    ret = CheckSequence(&ipInfo, &tcpInfo, session, &sslBytes, &sslFrame,error);
6816    if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) {
6817        ret = WOLFSSL_SNIFFER_FATAL_ERROR;
6818        goto exit_decode;
6819    }
6820    else if (ret == -1) {
6821        ret = WOLFSSL_SNIFFER_ERROR;
6822        goto exit_decode;
6823    }
6824    else if (ret ==  1) {
6825#ifdef WOLFSSL_SNIFFER_STATS
6826        INC_STAT(SnifferStats.sslDecryptedPackets);
6827#endif
6828        ret = 0;
6829        goto exit_decode; /* done for now */
6830    }
6831    else if (ret != 0) {
6832        goto exit_decode; /* return specific error case */
6833    }
6834
6835    ret = CheckPreRecord(&ipInfo, &tcpInfo, &sslFrame, &session, &sslBytes,
6836                         &end, error);
6837    if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) {
6838        ret = WOLFSSL_SNIFFER_FATAL_ERROR;
6839        goto exit_decode;
6840    }
6841    else if (ret == -1) {
6842        ret = WOLFSSL_SNIFFER_ERROR;
6843        goto exit_decode;
6844    }
6845    else if (ret ==  1) {
6846#ifdef WOLFSSL_SNIFFER_STATS
6847        INC_STAT(SnifferStats.sslDecryptedPackets);
6848#endif
6849        ret = 0;
6850        goto exit_decode; /* done for now */
6851    }
6852
6853#ifdef WOLFSSL_ASYNC_CRYPT
6854    /* make sure this server was polled */
6855    if (asyncOkay &&
6856        session->sslServer->error == WC_NO_ERR_TRACE(WC_PENDING_E) &&
6857        !session->flags.wasPolled) {
6858        ret = WC_PENDING_E;
6859        goto exit_decode;
6860    }
6861#endif
6862
6863#ifdef WOLFSSL_SNIFFER_STATS
6864    #ifdef WOLFSSL_ASYNC_CRYPT
6865    if (session->sslServer->error != WC_NO_ERR_TRACE(WC_PENDING_E))
6866    #endif
6867    {
6868        if (sslBytes > 0) {
6869            LOCK_STAT();
6870            NOLOCK_INC_STAT(SnifferStats.sslEncryptedPackets);
6871            NOLOCK_ADD_TO_STAT(SnifferStats.sslEncryptedBytes, sslBytes);
6872            UNLOCK_STAT();
6873        }
6874        else {
6875            INC_STAT(SnifferStats.sslDecryptedPackets);
6876        }
6877    }
6878#endif
6879
6880#ifdef WOLFSSL_ASYNC_CRYPT
6881    do {
6882#endif
6883        ret = ProcessMessage(sslFrame, session, sslBytes, data, end, ctx, error);
6884        session->sslServer->error = ret;
6885#ifdef WOLFSSL_ASYNC_CRYPT
6886        /* capture the seq pending for this session */
6887        if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
6888            session->flags.wasPolled = 0;
6889            session->pendSeq = tcpInfo.sequence;
6890            if (!asyncOkay || CryptoDeviceId == INVALID_DEVID) {
6891                /* If devId has not been set then we need to block here by
6892                 * polling and looping */
6893                wolfSSL_AsyncPoll(session->sslServer, WOLF_POLL_FLAG_CHECK_HW);
6894            }
6895            else {
6896                goto exit_decode; /* return to caller */
6897            }
6898        }
6899        else {
6900            session->pendSeq = 0;
6901        }
6902    } while (ret == WC_NO_ERR_TRACE(WC_PENDING_E));
6903#else
6904    (void)asyncOkay;
6905#endif
6906
6907    if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) {
6908        ret = WOLFSSL_SNIFFER_FATAL_ERROR;
6909        goto exit_decode;
6910    }
6911    if (CheckFinCapture(&ipInfo, &tcpInfo, session) == 0) {
6912        CopySessionInfo(session, sslInfo);
6913    }
6914
6915exit_decode:
6916    if (isChain) {
6917        XFREE(tmpPacket, NULL, DYNAMIC_TYPE_SNIFFER_CHAIN_BUFFER);
6918    }
6919    return ret;
6920}
6921
6922
6923/* Passes in an IP/TCP packet for decoding (ethernet/localhost frame) removed */
6924/* returns Number of bytes on success, 0 for no data yet, WOLFSSL_SNIFFER_ERROR.
6925 * on error and WOLFSSL_SNIFFER_FATAL_ERROR on fatal state error */
6926/* Also returns Session Info if available */
6927int ssl_DecodePacketWithSessionInfo(const unsigned char* packet, int length,
6928    unsigned char** data, SSLInfo* sslInfo, char* error)
6929{
6930    return ssl_DecodePacketInternal(packet, length, 0, data, sslInfo,
6931            NULL, error, 0);
6932}
6933
6934
6935/* Passes in an IP/TCP packet for decoding (ethernet/localhost frame) removed */
6936/* returns Number of bytes on success, 0 for no data yet, WOLFSSL_SNIFFER_ERROR.
6937 * on error and WOLFSSL_SNIFFER_FATAL_ERROR on fatal state error */
6938int ssl_DecodePacket(const byte* packet, int length, byte** data, char* error)
6939{
6940    return ssl_DecodePacketInternal(packet, length, 0, data, NULL, NULL,
6941            error, 0);
6942}
6943
6944
6945#ifdef WOLFSSL_SNIFFER_STORE_DATA_CB
6946
6947/* returns Number of bytes on success, 0 for no data yet, WOLFSSL_SNIFFER_ERROR.
6948 * on error and WOLFSSL_SNIFFER_FATAL_ERROR on fatal state error */
6949int ssl_DecodePacketWithSessionInfoStoreData(const unsigned char* packet,
6950        int length, void* ctx, SSLInfo* sslInfo, char* error)
6951{
6952    return ssl_DecodePacketInternal(packet, length, 0, NULL, sslInfo,
6953            ctx, error, 0);
6954}
6955
6956#endif
6957
6958
6959#ifdef WOLFSSL_SNIFFER_CHAIN_INPUT
6960
6961/* returns Number of bytes on success, 0 for no data yet, WOLFSSL_SNIFFER_ERROR.
6962 * on error and WOLFSSL_SNIFFER_FATAL_ERROR on fatal state error */
6963int ssl_DecodePacketWithChain(void* vChain, word32 chainSz, byte** data,
6964        char* error)
6965{
6966    return ssl_DecodePacketInternal((const byte*)vChain, chainSz, 1, data,
6967        NULL, NULL, error, 0);
6968}
6969
6970#endif
6971
6972
6973#if defined(WOLFSSL_SNIFFER_CHAIN_INPUT) && \
6974     defined(WOLFSSL_SNIFFER_STORE_DATA_CB)
6975
6976/*
6977 * returns WOLFSSL_SNIFFER_ERROR on error and WOLFSSL_SNIFFER_FATAL_ERROR on
6978 * fatal state error
6979 */
6980int ssl_DecodePacketWithChainSessionInfoStoreData(void* vChain, word32 chainSz,
6981        void* ctx, SSLInfo* sslInfo, char* error)
6982{
6983    return ssl_DecodePacketInternal(vChain, chainSz, 1, NULL, sslInfo,
6984            ctx, error, 0);
6985}
6986
6987#endif
6988
6989
6990/* Deallocator for the decoded data buffer. */
6991/* returns 0 on success, -1 on error */
6992int ssl_FreeDecodeBuffer(byte** data, char* error)
6993{
6994    return ssl_FreeZeroDecodeBuffer(data, 0, error);
6995}
6996
6997
6998/* Deallocator for the decoded data buffer, zeros out buffer. */
6999/* returns 0 on success, -1 on error */
7000int ssl_FreeZeroDecodeBuffer(byte** data, int sz, char* error)
7001{
7002    (void)error;
7003
7004    if (sz < 0) {
7005        return WOLFSSL_FATAL_ERROR;
7006    }
7007
7008    if (data != NULL) {
7009        ForceZero(*data, (word32)sz);
7010        XFREE(*data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
7011        *data = NULL;
7012    }
7013
7014    return 0;
7015}
7016
7017
7018/* Enables (if traceFile)/ Disables debug tracing */
7019/* returns 0 on success, -1 on error */
7020int ssl_Trace(const char* traceFile, char* error)
7021{
7022    if (traceFile) {
7023        /* Don't try to reopen the file */
7024        if (TraceFile == NULL) {
7025            if (XSTRCMP(traceFile, "-") == 0) {
7026                TraceFile = stdout;
7027            } else {
7028                TraceFile = XFOPEN(traceFile, "a");
7029                if (!TraceFile) {
7030                    SetError(BAD_TRACE_FILE_STR, error, NULL, 0);
7031                    return WOLFSSL_FATAL_ERROR;
7032                }
7033            }
7034            TraceOn = 1;
7035        }
7036    }
7037    else
7038        TraceOn = 0;
7039
7040    return 0;
7041}
7042
7043
7044/* Enables/Disables Recovery of missed data if later packets allow
7045 * maxMemory is number of bytes to use for reassembly buffering per session,
7046 * -1 means unlimited
7047 * returns 0 on success, -1 on error */
7048int ssl_EnableRecovery(int onOff, int maxMemory, char* error)
7049{
7050    (void)error;
7051
7052    RecoveryEnabled = onOff;
7053    if (onOff)
7054        MaxRecoveryMemory = maxMemory;
7055
7056    return 0;
7057}
7058
7059
7060
7061#if defined(WOLFSSL_SESSION_STATS) && !defined(NO_SESSION_CACHE)
7062
7063int ssl_GetSessionStats(unsigned int* active,     unsigned int* total,
7064                        unsigned int* peak,       unsigned int* maxSessions,
7065                        unsigned int* missedData, unsigned int* reassemblyMem,
7066                        char* error)
7067{
7068    int ret;
7069
7070    if (missedData) {
7071    #ifndef WOLFSSL_SNIFFER_NO_RECOVERY
7072        wc_LockMutex(&RecoveryMutex);
7073        *missedData = MissedDataSessions;
7074        wc_UnLockMutex(&RecoveryMutex);
7075    #endif
7076    }
7077
7078    if (reassemblyMem) {
7079        SnifferSession* session;
7080        int i;
7081
7082        *reassemblyMem = 0;
7083        LOCK_SESSION();
7084
7085        for (i = 0; i < HASH_SIZE; i++) {
7086            session = SessionTable[i];
7087            while (session) {
7088                *reassemblyMem += session->cliReassemblyMemory;
7089                *reassemblyMem += session->srvReassemblyMemory;
7090                session = session->next;
7091            }
7092        }
7093        UNLOCK_SESSION();
7094    }
7095
7096    ret = wolfSSL_get_session_stats(active, total, peak, maxSessions);
7097
7098    if (ret == WOLFSSL_SUCCESS)
7099        return 0;
7100    else {
7101        SetError(BAD_SESSION_STATS, error, NULL, 0);
7102        return WOLFSSL_FATAL_ERROR;
7103    }
7104}
7105
7106#endif
7107
7108
7109
7110int ssl_SetConnectionCb(SSLConnCb cb)
7111{
7112    ConnectionCb = cb;
7113    return 0;
7114}
7115
7116
7117
7118int ssl_SetConnectionCtx(void* ctx)
7119{
7120    ConnectionCbCtx = ctx;
7121    return 0;
7122}
7123
7124
7125#ifdef WOLFSSL_SNIFFER_STATS
7126
7127/* Resets the statistics tracking global structure.
7128 * returns 0 on success, -1 on error */
7129int ssl_ResetStatistics(void)
7130{
7131    wc_LockMutex(&StatsMutex);
7132    XMEMSET(&SnifferStats, 0, sizeof(SSLStats));
7133    wc_UnLockMutex(&StatsMutex);
7134    return 0;
7135}
7136
7137
7138/* Copies the SSL statistics into the provided stats record.
7139 * returns 0 on success, -1 on error */
7140int ssl_ReadStatistics(SSLStats* stats)
7141{
7142    if (stats == NULL)
7143        return WOLFSSL_FATAL_ERROR;
7144
7145    LOCK_STAT();
7146    XMEMCPY(stats, &SnifferStats, sizeof(SSLStats));
7147    UNLOCK_STAT();
7148    return 0;
7149}
7150
7151/* Copies the SSL statistics into the provided stats record then
7152 * resets the statistics tracking global structure.
7153 * returns 0 on success, -1 on error */
7154int ssl_ReadResetStatistics(SSLStats* stats)
7155{
7156    if (stats == NULL)
7157        return WOLFSSL_FATAL_ERROR;
7158
7159    LOCK_STAT();
7160    XMEMCPY(stats, &SnifferStats, sizeof(SSLStats));
7161    XMEMSET(&SnifferStats, 0, sizeof(SSLStats));
7162    UNLOCK_STAT();
7163    return 0;
7164}
7165
7166#endif /* WOLFSSL_SNIFFER_STATS */
7167
7168
7169#ifdef WOLFSSL_SNIFFER_WATCH
7170
7171int ssl_SetWatchKeyCallback_ex(SSLWatchCb cb, int devId, char* error)
7172{
7173#ifdef WOLF_CRYPTO_CB
7174    if (CryptoDeviceId == INVALID_DEVID)
7175        CryptoDeviceId = devId;
7176#else
7177    (void)devId;
7178#endif
7179    WatchCb = cb;
7180    return CreateWatchSnifferServer(error);
7181}
7182
7183int ssl_SetWatchKeyCallback(SSLWatchCb cb, char* error)
7184{
7185    WatchCb = cb;
7186    return CreateWatchSnifferServer(error);
7187}
7188
7189int ssl_SetWatchKeyCtx(void* ctx, char* error)
7190{
7191    (void)error;
7192    WatchCbCtx = ctx;
7193    return 0;
7194}
7195
7196int ssl_SetWatchKey_buffer(void* vSniffer, const byte* key, word32 keySz,
7197        int keyType, char* error)
7198{
7199    SnifferSession* sniffer;
7200    int ret;
7201
7202    if (vSniffer == NULL) {
7203        return WOLFSSL_FATAL_ERROR;
7204    }
7205    if (key == NULL || keySz == 0) {
7206        return WOLFSSL_FATAL_ERROR;
7207    }
7208
7209    sniffer = (SnifferSession*)vSniffer;
7210    /* Remap the keyType from what the user can use to
7211     * what wolfSSL_use_PrivateKey_buffer expects. */
7212    keyType = (keyType == FILETYPE_PEM) ? WOLFSSL_FILETYPE_PEM :
7213                                          WOLFSSL_FILETYPE_ASN1;
7214
7215#ifdef WOLFSSL_STATIC_EPHEMERAL
7216    /* try setting static ephemeral first */
7217    /* auto detect key type with WC_PK_TYPE_NONE */
7218    ret = wolfSSL_set_ephemeral_key(sniffer->sslServer,
7219        WC_PK_TYPE_NONE, (const char*)key, keySz,
7220            WOLFSSL_FILETYPE_ASN1);
7221    if (ret != 0) {
7222    #ifdef DEBUG_SNIFFER
7223        /* print warnings */
7224        fprintf(stderr, "key watch set ephemeral failed %d\n", ret);
7225    #endif
7226    }
7227#endif
7228
7229    /* always try and load private key */
7230    ret = wolfSSL_use_PrivateKey_buffer(sniffer->sslServer,
7231        key, keySz, keyType);
7232
7233    if (ret != WOLFSSL_SUCCESS) {
7234        SetError(KEY_FILE_STR, error, sniffer, FATAL_ERROR_STATE);
7235        return WOLFSSL_FATAL_ERROR;
7236    }
7237
7238    return 0;
7239}
7240
7241int ssl_SetWatchKey_file(void* vSniffer, const char* keyFile, int keyType,
7242        const char* password, char* error)
7243{
7244    byte* keyBuf = NULL;
7245    word32 keyBufSz = 0;
7246    int ret;
7247
7248    if (vSniffer == NULL) {
7249        return WOLFSSL_FATAL_ERROR;
7250    }
7251    if (keyFile == NULL) {
7252        return WOLFSSL_FATAL_ERROR;
7253    }
7254
7255    /* Remap the keyType from what the user can use to
7256     * what LoadKeyFile expects. */
7257    keyType = (keyType == FILETYPE_PEM) ? WOLFSSL_FILETYPE_PEM :
7258                                          WOLFSSL_FILETYPE_ASN1;
7259
7260    ret = LoadKeyFile(&keyBuf, &keyBufSz, keyFile, 0, keyType, password);
7261    if (ret < 0) {
7262        SetError(KEY_FILE_STR, error, NULL, 0);
7263        if (keyBuf != NULL) {
7264            ForceZero(keyBuf, keyBufSz);
7265        }
7266        XFREE(keyBuf, NULL, DYNAMIC_TYPE_X509);
7267        return WOLFSSL_FATAL_ERROR;
7268    }
7269
7270    ret = ssl_SetWatchKey_buffer(vSniffer, keyBuf, keyBufSz, FILETYPE_DER,
7271            error);
7272    ForceZero(keyBuf, keyBufSz);
7273    XFREE(keyBuf, NULL, DYNAMIC_TYPE_X509);
7274
7275    return ret;
7276}
7277
7278#endif /* WOLFSSL_SNIFFER_WATCH */
7279
7280
7281#ifdef WOLFSSL_SNIFFER_STORE_DATA_CB
7282
7283int ssl_SetStoreDataCallback(SSLStoreDataCb cb)
7284{
7285    StoreDataCb = cb;
7286    return 0;
7287}
7288
7289#endif /* WOLFSSL_SNIFFER_STORE_DATA_CB */
7290
7291#ifdef WOLFSSL_SNIFFER_KEY_CALLBACK
7292int ssl_SetKeyCallback(SSLKeyCb cb, void* cbCtx)
7293{
7294    KeyCb = cb;
7295    KeyCbCtx = cbCtx;
7296    return 0;
7297}
7298#endif
7299
7300#ifdef WOLFSSL_ASYNC_CRYPT
7301
7302int ssl_DecodePacketAsync(void* packet, unsigned int packetSz,
7303    int isChain, unsigned char** data, char* error, SSLInfo* sslInfo,
7304    void* userCtx)
7305{
7306    return ssl_DecodePacketInternal(packet, packetSz, isChain, data, sslInfo,
7307        userCtx, error, 1);
7308}
7309
7310static SnifferSession* FindSession(WOLFSSL* ssl)
7311{
7312    int i;
7313    SnifferSession* session;
7314    for (i = 0; i < HASH_SIZE; i++) {
7315        session = SessionTable[i];
7316        while (session) {
7317            if (session->sslServer == ssl) {
7318                return session;
7319            }
7320            session = session->next;
7321        }
7322    }
7323    return NULL;
7324}
7325
7326int ssl_PollSniffer(WOLF_EVENT** events, int maxEvents, WOLF_EVENT_FLAG flags,
7327    int* pEventCount)
7328{
7329    int ret = 0;
7330    int eventCount = 0;
7331    int i;
7332    SnifferServer* srv;
7333
7334    LOCK_SERVER_LIST();
7335
7336    /* Iterate the open sniffer sessions calling wolfSSL_CTX_AsyncPoll */
7337    srv = ServerList;
7338    while (srv) {
7339        int nMax = maxEvents - eventCount, nReady = 0;
7340        if (nMax <= 0) {
7341            break; /* out of room in events list */
7342        }
7343        ret = wolfSSL_CTX_AsyncPoll(srv->ctx, events + nReady, nMax, flags,
7344                                    &nReady);
7345        if (ret == 0) {
7346            eventCount += nReady;
7347        }
7348        else {
7349        #ifdef DEBUG_SNIFFER
7350            fprintf(stderr, "Sniffer Server %p: Poll error: %d\n", srv, ret);
7351        #endif
7352            break;
7353        }
7354        srv = srv->next;
7355    }
7356
7357    UNLOCK_SERVER_LIST();
7358
7359
7360    /* iterate list and mark polled */
7361    LOCK_SESSION();
7362    for (i=0; i<eventCount; i++) {
7363        WOLFSSL* ssl = (WOLFSSL*)events[i]->context;
7364        SnifferSession* session = FindSession(ssl);
7365        if (session) {
7366            session->flags.wasPolled = 1;
7367            session->sslServer->error = events[i]->ret;
7368        }
7369    }
7370    UNLOCK_SESSION();
7371
7372    *pEventCount = eventCount;
7373
7374    return ret;
7375}
7376#endif
7377
7378
7379#if defined(WOLFSSL_SNIFFER_KEYLOGFILE)
7380
7381/* Maximum length of the NSS Keylog prefix string */
7382#define MAX_PREFIX_LENGTH (31)
7383/* Maximum length (in bytes) required to store the binary representation of
7384 * the "client random" value parsed from keylog file */
7385#define CLIENT_RANDOM_LENGTH (32)
7386/* Maximum length (in bytes) required to store the binary representation of the
7387 * "secret" value parsed from keylog file */
7388#define SECRET_LENGTH (48)
7389
7390typedef struct SecretNode {
7391    unsigned char clientRandom[CLIENT_RANDOM_LENGTH];
7392    unsigned char secrets[SNIFFER_SECRET_NUM_SECRET_TYPES][SECRET_LENGTH];
7393    struct SecretNode* next;
7394} SecretNode;
7395
7396
7397/* Default to the same size hash table as the session table,
7398 * but allow user to override */
7399#ifndef WOLFSSL_SNIFFER_KEYLOGFILE_HASH_TABLE_SIZE
7400#define WOLFSSL_SNIFFER_KEYLOGFILE_HASH_TABLE_SIZE HASH_SIZE
7401#endif
7402
7403static THREAD_LS_T
7404SecretNode*
7405secretHashTable[WOLFSSL_SNIFFER_KEYLOGFILE_HASH_TABLE_SIZE] = {NULL};
7406#ifndef HAVE_C___ATOMIC
7407static WC_THREADSHARED wolfSSL_Mutex secretListMutex WOLFSSL_MUTEX_INITIALIZER_CLAUSE(secretListMutex);
7408#endif
7409
7410static unsigned int secretHashFunction(unsigned char* clientRandom);
7411
7412#ifdef HAVE_C___ATOMIC
7413    #define LOCK_SECRET_LIST() WC_DO_NOTHING
7414    #define UNLOCK_SECRET_LIST() WC_DO_NOTHING
7415#else
7416    #define LOCK_SECRET_LIST() wc_LockMutex(&secretListMutex)
7417    #define UNLOCK_SECRET_LIST() wc_UnLockMutex(&secretListMutex)
7418#endif
7419
7420
7421/*
7422 * Basic polynomial hash function that maps a 32-byte client random value to an
7423 * array index
7424 */
7425static unsigned int secretHashFunction(unsigned char* clientRandom)
7426{
7427    int i = 0;
7428    unsigned int hash = 0;
7429    const int CLIENT_RANDOM_NUM_BITS = CLIENT_RANDOM_LENGTH * 8;
7430
7431    for (i = 0; i < CLIENT_RANDOM_LENGTH; i++) {
7432        hash = (hash * CLIENT_RANDOM_NUM_BITS + clientRandom[i])
7433            % WOLFSSL_SNIFFER_KEYLOGFILE_HASH_TABLE_SIZE;
7434    }
7435
7436    return hash;
7437}
7438
7439
7440/*
7441 * Adds a new secret to the secret table, creating a new node based on the
7442 * client random if necessary. If the client random is already present in the
7443 * list, the requested secret will be updated.
7444 */
7445static int addSecretNode(unsigned char* clientRandom,
7446                         int type,
7447                         unsigned char* secret,
7448                         char* error)
7449{
7450    int idx = 0;
7451    int ret = 0;
7452    SecretNode* node = NULL;
7453
7454    if (type >= SNIFFER_SECRET_NUM_SECRET_TYPES) {
7455        return WOLFSSL_SNIFFER_ERROR;
7456    }
7457
7458    LOCK_SECRET_LIST();
7459
7460    idx = secretHashFunction(clientRandom);
7461    node = secretHashTable[idx];
7462
7463    while(node) {
7464        /* Node already exists, so just add the requested secret */
7465        if (XMEMCMP(node->clientRandom, clientRandom, CLIENT_RANDOM_LENGTH)
7466            == 0)
7467        {
7468            XMEMCPY(node->secrets[type], secret, SECRET_LENGTH);
7469            ret = 0;
7470            goto unlockReturn;
7471        }
7472        node = node ->next;
7473    }
7474
7475    node = (SecretNode*)XMALLOC(sizeof(SecretNode),
7476                                NULL,
7477                                DYNAMIC_TYPE_SNIFFER_KEYLOG_NODE);
7478    if (node == NULL) {
7479        SetError(MEMORY_STR, error, NULL, 0);
7480        ret = WOLFSSL_SNIFFER_ERROR;
7481        goto unlockReturn;
7482    }
7483
7484    XMEMCPY(node->clientRandom, clientRandom, CLIENT_RANDOM_LENGTH);
7485    XMEMCPY(node->secrets[type], secret, SECRET_LENGTH);
7486    node->next = secretHashTable[idx];
7487    secretHashTable[idx] = node;
7488
7489unlockReturn:
7490
7491    UNLOCK_SECRET_LIST();
7492
7493    return ret;
7494}
7495
7496
7497/*
7498 * Looks up a master secret for a given client random from the keylog file
7499 */
7500static unsigned char* findSecret(unsigned char* clientRandom, int type)
7501{
7502    unsigned char* secret = NULL;
7503    SecretNode* node = NULL;
7504    unsigned int idx = 0;
7505
7506    LOCK_SECRET_LIST();
7507
7508    idx = secretHashFunction(clientRandom);
7509    node  = secretHashTable[idx];
7510
7511    while (node != NULL) {
7512        if (XMEMCMP(node->clientRandom,
7513                    clientRandom, CLIENT_RANDOM_LENGTH) == 0) {
7514            secret = node->secrets[type];
7515            break;
7516        }
7517        node = node->next;
7518    }
7519
7520    UNLOCK_SECRET_LIST();
7521
7522    return secret;
7523}
7524
7525
7526static void hexToBin(const char* hex, unsigned char* bin, int binLength)
7527{
7528    int i = 0;
7529    for (i = 0; i < binLength; i++) {
7530        sscanf(hex + 2*i, "%02hhx", &bin[i]);
7531    }
7532}
7533
7534/*
7535 * Helper function to parse secrets from the keylog file into the secret table
7536 */
7537static int parseKeyLogFile(const char* fileName, char* error)
7538{
7539    unsigned char clientRandom[CLIENT_RANDOM_LENGTH];
7540    unsigned char secret[SECRET_LENGTH];
7541    FILE* file = NULL;
7542    int ret = 0;
7543    int  type = 0;
7544    /* +1 for null terminator */
7545    char prefix[MAX_PREFIX_LENGTH + 1] = {0};
7546    /* 2 chars for Hexadecimal representation, plus null terminator */
7547    char clientRandomHex[2 * CLIENT_RANDOM_LENGTH + 1] = {0};
7548    char secretHex[2 * SECRET_LENGTH + 1] = {0};
7549
7550
7551    file = fopen(fileName, "r");
7552    if (file == NULL) {
7553        fprintf(stderr, "Could not open keylog file: %s\n", fileName);
7554        SetError(KEYLOG_FILE_INVALID, error, NULL, 0);
7555        return WOLFSSL_SNIFFER_ERROR;
7556    }
7557
7558    /* Format specifiers for each column should be:
7559     * MAX_PREFIX_LENGTH, 2*CLIENT_RANDOM_LENGTH, and 2*SECRET_LENGTH */
7560    while (fscanf(file, "%31s %64s %96s", prefix, clientRandomHex, secretHex)
7561            == 3) {
7562
7563        if (XSTRCMP(prefix, "CLIENT_RANDOM") == 0) {
7564            type = SNIFFER_SECRET_TLS12_MASTER_SECRET;
7565        }
7566#if defined(WOLFSSL_TLS13)
7567        else if (XSTRCMP(prefix, "CLIENT_EARLY_TRAFFIC_SECRET") == 0) {
7568            type = SNIFFER_SECRET_CLIENT_EARLY_TRAFFIC_SECRET;
7569        }
7570        else if (XSTRCMP(prefix, "CLIENT_HANDSHAKE_TRAFFIC_SECRET") == 0) {
7571            type = SNIFFER_SECRET_CLIENT_HANDSHAKE_TRAFFIC_SECRET;
7572        }
7573        else if (XSTRCMP(prefix, "SERVER_HANDSHAKE_TRAFFIC_SECRET") == 0) {
7574            type = SNIFFER_SECRET_SERVER_HANDSHAKE_TRAFFIC_SECRET;
7575        }
7576        else if (XSTRCMP(prefix, "CLIENT_TRAFFIC_SECRET_0") == 0) {
7577            type = SNIFFER_SECRET_CLIENT_TRAFFIC_SECRET;
7578        }
7579        else if (XSTRCMP(prefix, "SERVER_TRAFFIC_SECRET_0") == 0) {
7580            type = SNIFFER_SECRET_SERVER_TRAFFIC_SECRET;
7581        }
7582#endif /* WOLFSSL_TLS13 */
7583        else {
7584            fprintf(stderr, "unrecognized prefix: %s\n", prefix);
7585            continue;
7586        }
7587
7588        hexToBin(clientRandomHex, clientRandom, CLIENT_RANDOM_LENGTH);
7589        hexToBin(secretHex, secret, SECRET_LENGTH);
7590        ret = addSecretNode(clientRandom, type, secret, error);
7591
7592        if (ret != 0) {
7593            fclose(file);
7594            return ret;
7595        }
7596    }
7597    fclose(file);
7598
7599    return 0;
7600}
7601
7602
7603static void freeSecretList(void)
7604{
7605    int i = 0;
7606
7607    LOCK_SECRET_LIST();
7608
7609    for (i=0; i<WOLFSSL_SNIFFER_KEYLOGFILE_HASH_TABLE_SIZE; i++)
7610    {
7611        SecretNode* current = secretHashTable[i];
7612        SecretNode * next = NULL;
7613
7614        while (current != NULL) {
7615            next = current->next;
7616            XFREE(current, NULL, DYNAMIC_TYPE_SNIFFER_KEYLOG_NODE);
7617            current = next;
7618        }
7619    }
7620
7621    UNLOCK_SECRET_LIST();
7622}
7623
7624
7625/*
7626 * Looks up secret based on client random and copies it to output_secret
7627 */
7628static int snifferSecretCb(unsigned char* client_random,
7629                           int type,
7630                           unsigned char* output_secret)
7631{
7632    unsigned char* secret = NULL;
7633
7634    if (client_random == NULL || output_secret == NULL) {
7635        return WOLFSSL_SNIFFER_FATAL_ERROR;
7636    }
7637
7638    if (type >= SNIFFER_SECRET_NUM_SECRET_TYPES) {
7639        return WOLFSSL_SNIFFER_FATAL_ERROR;
7640    }
7641
7642    /* get secret from secret table based on client random */
7643    secret = findSecret(client_random, type);
7644    if (secret != NULL) {
7645        XMEMCPY(output_secret, secret, SECRET_LENGTH);
7646        return 0;
7647    }
7648
7649    /* didn't find the secret */
7650    return WOLFSSL_SNIFFER_ERROR;
7651}
7652
7653
7654static void setSnifferSecretCb(SnifferSession* session)
7655{
7656    session->context->useKeyLogFile = 1;
7657    session->sslServer->snifferSecretCb = snifferSecretCb;
7658    session->sslClient->snifferSecretCb = snifferSecretCb;
7659}
7660
7661
7662/*
7663 * Helper function that creates a sniffer server object that can decrypt using
7664 * a keylog file, and adds it to the server list
7665 *
7666 * NOTE: the caller is responsible for locking and unlocking the server list
7667 */
7668static int addKeyLogSnifferServerHelper(const char* address,
7669                                        int port,
7670                                        char* error)
7671{
7672    IpAddrInfo     serverIp = {0};
7673    SnifferServer *sniffer = NULL;
7674
7675    TraceHeader();
7676    TraceSetServer(address, port, NULL);
7677
7678    serverIp.version = IPV4;
7679    serverIp.ip4 = XINET_ADDR(address);
7680    if (serverIp.ip4 == XINADDR_NONE) {
7681    #ifdef FUSION_RTOS
7682        if (XINET_PTON(AF_INET6, address, serverIp.ip6,
7683                       sizeof(serverIp.ip6)) == 1)
7684    #elif defined(FREESCALE_MQX)
7685        if (XINET_PTON(AF_INET6, address, serverIp.ip6,
7686                       sizeof(serverIp.ip6)) == RTCS_OK)
7687    #else
7688        if (XINET_PTON(AF_INET6, address, serverIp.ip6) == 1)
7689    #endif
7690        {
7691            serverIp.version = IPV6;
7692        }
7693    }
7694
7695    sniffer = ServerList;
7696    while (sniffer != NULL &&
7697            (!MatchAddr(sniffer->server, serverIp) || sniffer->port != port)) {
7698        sniffer = sniffer->next;
7699    }
7700
7701    if (sniffer == NULL) {
7702        sniffer = (SnifferServer*)XMALLOC(sizeof(SnifferServer),
7703                NULL, DYNAMIC_TYPE_SNIFFER_SERVER);
7704        if (sniffer == NULL) {
7705            SetError(MEMORY_STR, error, NULL, 0);
7706            return WOLFSSL_SNIFFER_ERROR;
7707        }
7708        InitSnifferServer(sniffer);
7709
7710        XSTRNCPY(sniffer->address, address, MAX_SERVER_ADDRESS-1);
7711        sniffer->address[MAX_SERVER_ADDRESS-1] = '\0';
7712        sniffer->server = serverIp;
7713        sniffer->port = port;
7714
7715        sniffer->ctx = wolfSSL_CTX_new(wolfSSLv23_client_method());
7716        if (!sniffer->ctx) {
7717            SetError(MEMORY_STR, error, NULL, 0);
7718            FreeSnifferServer(sniffer);
7719            return WOLFSSL_SNIFFER_ERROR;
7720        }
7721    #if defined(WOLF_CRYPTO_CB) || defined(WOLFSSL_ASYNC_CRYPT)
7722        if (CryptoDeviceId != INVALID_DEVID)
7723            wolfSSL_CTX_SetDevId(sniffer->ctx, CryptoDeviceId);
7724    #endif
7725
7726        sniffer->next = ServerList;
7727        ServerList = sniffer;
7728    }
7729    else {
7730        printf("SESSION ALREADY EXISTS\n");
7731    }
7732
7733    /* Tag the new or existing server as requiring keylog support to
7734     * decrypt, otherwise it won't be usable */
7735    sniffer->useKeyLogFile = 1;
7736
7737    return 0;
7738}
7739
7740/*
7741 * Creates a sniffer server that is able to decrypt using secrets from a
7742 * keylog file, and adds it to the server list
7743 *
7744 * If a server at the address and port already exists, it will be marked
7745 * for keylog file decryption
7746 */
7747int ssl_CreateKeyLogSnifferServer(const char* address, int port, char* error)
7748{
7749    int ret = 0;
7750
7751    if (address == NULL) {
7752        SetError(KEYLOG_FILE_INVALID, error, NULL, 0);
7753        return WOLFSSL_SNIFFER_ERROR;
7754    }
7755
7756    LOCK_SERVER_LIST();
7757
7758    ret = addKeyLogSnifferServerHelper(address, port, error);
7759
7760    UNLOCK_SERVER_LIST();
7761
7762    return ret;
7763}
7764
7765
7766/*
7767 * Loads secrets to decrypt TLS traffic from a keylog file. Only sniffer
7768 * servers registered with ssl_createKeyLogSnifferServer() will be able to
7769 * decrypt using these secrets
7770 */
7771int ssl_LoadSecretsFromKeyLogFile(const char* keylogfile, char* error)
7772{
7773    if (keylogfile == NULL) {
7774        SetError(KEYLOG_FILE_INVALID, error, NULL, 0);
7775        return WOLFSSL_SNIFFER_ERROR;
7776    }
7777
7778    return parseKeyLogFile(keylogfile, error);
7779}
7780
7781#endif /* WOLFSSL_SNIFFER_KEYLOGFILE */
7782
7783
7784/*
7785 * Removes a session from the SessionTable based on client/server IP & ports
7786 * Returns 0 if a session was found and freed, -1 otherwise
7787 */
7788int ssl_RemoveSession(const char* clientIp, int clientPort,
7789                      const char* serverIp, int serverPort,
7790                      char* error)
7791{
7792    IpAddrInfo clientAddr;
7793    IpAddrInfo serverAddr;
7794    IpInfo ipInfo;
7795    TcpInfo tcpInfo;
7796    SnifferSession* session;
7797    int ret = -1;  /* Default to not found */
7798    word32 row;
7799
7800    if (clientIp == NULL || serverIp == NULL) {
7801        SetError(BAD_IPVER_STR, error, NULL, 0);
7802        return ret;
7803    }
7804
7805    /* Set up client IP address */
7806    clientAddr.version = IPV4;
7807    clientAddr.ip4 = XINET_ADDR(clientIp);
7808    if (clientAddr.ip4 == XINADDR_NONE) {
7809    #ifdef FUSION_RTOS
7810        if (XINET_PTON(AF_INET6, clientIp, clientAddr.ip6,
7811                       sizeof(clientAddr.ip6)) == 1)
7812    #elif defined(FREESCALE_MQX)
7813        if (XINET_PTON(AF_INET6, clientIp, clientAddr.ip6,
7814                       sizeof(clientAddr.ip6)) == RTCS_OK)
7815    #else
7816        if (XINET_PTON(AF_INET6, clientIp, clientAddr.ip6) == 1)
7817    #endif
7818        {
7819            clientAddr.version = IPV6;
7820        }
7821        else {
7822            SetError(BAD_IPVER_STR, error, NULL, 0);
7823            return ret;
7824        }
7825    }
7826
7827    /* Set up server IP address */
7828    serverAddr.version = IPV4;
7829    serverAddr.ip4 = XINET_ADDR(serverIp);
7830    if (serverAddr.ip4 == XINADDR_NONE) {
7831    #ifdef FUSION_RTOS
7832        if (XINET_PTON(AF_INET6, serverIp, serverAddr.ip6,
7833                       sizeof(serverAddr.ip6)) == 1)
7834    #elif defined(FREESCALE_MQX)
7835        if (XINET_PTON(AF_INET6, serverIp, serverAddr.ip6,
7836                       sizeof(serverAddr.ip6)) == RTCS_OK)
7837    #else
7838        if (XINET_PTON(AF_INET6, serverIp, serverAddr.ip6) == 1)
7839    #endif
7840        {
7841            serverAddr.version = IPV6;
7842        }
7843        else {
7844            SetError(BAD_IPVER_STR, error, NULL, 0);
7845            return ret;
7846        }
7847    }
7848
7849    XMEMSET(&ipInfo, 0, sizeof(ipInfo));
7850    XMEMSET(&tcpInfo, 0, sizeof(tcpInfo));
7851
7852    /* Set up client->server direction */
7853    ipInfo.src = clientAddr;
7854    ipInfo.dst = serverAddr;
7855    tcpInfo.srcPort = clientPort;
7856    tcpInfo.dstPort = serverPort;
7857
7858    /* Calculate the hash row for this session */
7859    row = SessionHash(&ipInfo, &tcpInfo);
7860
7861    LOCK_SESSION();
7862
7863    /* Search only the specific row in the session table */
7864    session = SessionTable[row];
7865
7866    while (session) {
7867        SnifferSession* next = session->next;
7868
7869        /* Check if this session matches the specified client/server IP/port */
7870        if (MatchAddr(session->client, clientAddr) &&
7871            MatchAddr(session->server, serverAddr) &&
7872            session->cliPort == clientPort &&
7873            session->srvPort == serverPort) {
7874
7875            /* Use RemoveSession to remove and free the session */
7876            RemoveSession(session, NULL, NULL, row);
7877            ret = 0;  /* Session found and freed */
7878            break;
7879        }
7880
7881        session = next;
7882    }
7883
7884    UNLOCK_SESSION();
7885
7886    return ret;
7887}
7888
7889
7890#undef ERROR_OUT
7891
7892#endif /* WOLFSSL_SNIFFER */
7893#endif /* !WOLFCRYPT_ONLY && !NO_FILESYSTEM */