cjson
fuzzing
inputs
test1 test10 test11 test2 test3 test3.bu test3.uf test3.uu test4 test5 test6 test7 test8 test9library_config
cJSONConfig.cmake.in cJSONConfigVersion.cmake.in libcjson.pc.in libcjson_utils.pc.in uninstall.cmaketests
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.expectedjson-patch-tests
.editorconfig .gitignore .npmignore README.md cjson-utils-tests.json package.json spec_tests.json tests.jsonunity
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.pydocs
ThrowTheSwitchCodingStandard.md UnityAssertionsCheatSheetSuitableforPrintingandPossiblyFraming.pdf UnityAssertionsReference.md UnityConfigurationGuide.md UnityGettingStartedGuide.md UnityHelperScriptsGuide.md license.txtexamples
unity_config.hcurl
.github
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.yamlworkflows
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.ymlCMake
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.cmakedocs
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.mdexamples
.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.cinternals
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.mdlibcurl
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.incinclude
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.hlib
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.hvauth
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.hvquic
curl_ngtcp2.c curl_ngtcp2.h curl_quiche.c curl_quiche.h vquic-tls.c vquic-tls.h vquic.c vquic.h vquic_int.hvtls
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.hm4
.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.m4projects
OS400
.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.hWindows
tmpl
.gitattributes README.txt curl-all.sln curl.sln curl.vcxproj curl.vcxproj.filters libcurl.sln libcurl.vcxproj libcurl.vcxproj.filtersvms
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.hscripts
.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 wcurlsrc
.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.htests
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.prmdata
.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 test999http
testenv
__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.pylibtest
.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.hserver
.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.ctunit
.gitignore CMakeLists.txt Makefile.am Makefile.inc README.md tool1394.c tool1604.c tool1621.c tool1622.c tool1623.c tool1720.cunit
.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.cexamples
.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.luainiparser
example
iniexample.c iniwrite.c parse.c twisted-errors.ini twisted-genhuge.py twisted-ofkey.ini twisted-ofval.ini twisted.initest
CMakeLists.txt test_dictionary.c test_iniparser.c unity-config.yml unity_config.hjinjac
libjinjac
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.htest
.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.jinjalibev
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-h1luajit
doc
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.htmldynasm
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.luasrc
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.cjit
.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.luawolfssl
.github
workflows
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.ymlIDE
ARDUINO
Arduino_README_prepend.md README.md include.am keywords.txt library.properties.template wolfssl-arduino.cpp wolfssl-arduino.sh wolfssl.hECLIPSE
Espressif
ESP-IDF
examples
template
CMakeLists.txt Makefile README.md partitions_singleapp_large.csv sdkconfig.defaults sdkconfig.defaults.esp8266wolfssl_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.vgdbprojwolfssl_client
CMakeLists.txt Makefile README.md README_server_sm.md partitions_singleapp_large.csv sdkconfig.defaults sdkconfig.defaults.esp32c2 sdkconfig.defaults.esp8266 wolfssl_client_ESP8266.vgdbprojwolfssl_server
CMakeLists.txt Makefile README.md README_server_sm.md partitions_singleapp_large.csv sdkconfig.defaults sdkconfig.defaults.esp32c2 sdkconfig.defaults.esp8266 wolfssl_server_ESP8266.vgdbprojwolfssl_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.vgdbprojGCC-ARM
Makefile Makefile.bench Makefile.client Makefile.common Makefile.server Makefile.static Makefile.test README.md include.am linker.ld linker_fips.ldIAR-EWARM
embOS
SAMV71_XULT
embOS_SAMV71_XULT_user_settings
user_settings.h user_settings_simple_example.h user_settings_verbose_example.hembOS_wolfcrypt_benchmark_SAMV71_XULT
README_wolfcrypt_benchmark wolfcrypt_benchmark.ewd wolfcrypt_benchmark.ewpINTIME-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.vcxprojMQX
Makefile README-jp.md README.md client-tls.c include.am server-tls.c user_config.h user_settings.hMSVS-2019-AZSPHERE
wolfssl_new_azsphere
.gitignore CMakeLists.txt CMakeSettings.json app_manifest.json applibs_versions.h launch.vs.json main.cNETOS
Makefile.wolfcrypt.inc README.md include.am user_settings.h user_settings.h-cert2425 user_settings.h-cert3389 wolfssl_netos_custom.cPlatformIO
examples
wolfssl_benchmark
CMakeLists.txt README.md platformio.ini sdkconfig.defaults wolfssl_benchmark.code-workspaceROWLEY-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.hzpRenesas
e2studio
RA6M3
README.md README_APRA6M_en.md README_APRA6M_jp.md include.amRX72N
EnvisionKit
Simple
README_EN.md README_JP.mdwolfssl_demo
key_data.c key_data.h user_settings.h wolfssl_demo.c wolfssl_demo.h wolfssl_tsip_unit_test.cSTM32Cube
README.md STM32_Benchmarks.md default_conf.ftl include.am main.c wolfssl_example.c wolfssl_example.hWIN
README.txt include.am test.vcxproj user_settings.h user_settings_dtls.h wolfssl-fips.sln wolfssl-fips.vcxprojWIN-SRTP-KDF-140-3
README.txt include.am resource.h test.vcxproj user_settings.h wolfssl-fips.rc wolfssl-fips.sln wolfssl-fips.vcxprojWIN10
README.txt include.am resource.h test.vcxproj user_settings.h wolfssl-fips.rc wolfssl-fips.sln wolfssl-fips.vcxprojXCODE
Benchmark
include.amXilinxSDK
README.md bench.sh combine.sh eclipse_formatter_profile.xml graph.sh include.am user_settings.h wolfssl_example.capple-universal
wolfssl-multiplatform
iotsafe
Makefile README.md ca-cert.c devices.c devices.h include.am main.c memory-tls.c startup.c target.ld user_settings.hmynewt
README.md apps.wolfcrypttest.pkg.yml crypto.wolfssl.pkg.yml crypto.wolfssl.syscfg.yml include.am setup.shcerts
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.pemcrl
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.pemdilithium
bench_dilithium_level2_key.der bench_dilithium_level3_key.der bench_dilithium_level5_key.der include.amecc
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.cnfed25519
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.pemed448
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.pemexternal
DigiCertGlobalRootCA.pem README.txt ca-digicert-ev.pem ca-globalsign-root.pem ca-google-root.pem ca_collection.pem include.amintermediate
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.conflms
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.ammldsa
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.derocsp
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.derp521
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.pemrpk
client-cert-rpk.der client-ecc-cert-rpk.der include.am server-cert-rpk.der server-ecc-cert-rpk.derrsapss
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.pemslhdsa
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.pemsm2
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.pemstatickeys
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.pemtest
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.p7stest-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.shtest-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.pemxmss
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.amcmake
Config.cmake.in README.md config.in functions.cmake include.am options.h.in wolfssl-config-version.cmake.in wolfssl-targets.cmake.indebian
changelog.in control.in copyright include.am libwolfssl-dev.install libwolfssl.install rules.indoc
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.hheader_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.hexamples
async
Makefile README.md async_client.c async_server.c async_tls.c async_tls.h include.am user_settings.hconfigs
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.hechoclient
echoclient.c echoclient.h echoclient.sln echoclient.vcproj echoclient.vcxproj include.am quitlinuxkm
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.cm4
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.m4mqx
wolfcrypt_benchmark
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.launchwolfcrypt_test
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.launchwolfssl_client
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.launchscripts
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.shsrc
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.ctests
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.hwolfcrypt
benchmark
README.md benchmark-VS2022.sln benchmark-VS2022.vcxproj benchmark-VS2022.vcxproj.user benchmark.c benchmark.h benchmark.sln benchmark.vcproj benchmark.vcxproj include.amsrc
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.pyRenesas
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.carm
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.ccaam
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.cdevcrypto
README.md devcrypto_aes.c devcrypto_ecdsa.c devcrypto_hash.c devcrypto_hmac.c devcrypto_rsa.c devcrypto_x25519.c wc_devcrypto.criscv
riscv-64-aes.c riscv-64-chacha.c riscv-64-poly1305.c riscv-64-sha256.c riscv-64-sha3.c riscv-64-sha512.cwolfssl
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.hwolfcrypt
port
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.hcaam
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.hwrapper
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.adbtests
src
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.adbCSharp
wolfSSL-Example-IOCallbacks
App.config wolfSSL-Example-IOCallbacks.cs wolfSSL-Example-IOCallbacks.csprojwolfSSL-TLS-ServerThreaded
App.config wolfSSL-TLS-ServerThreaded.cs wolfSSL-TLS-ServerThreaded.csprojrust
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.rstests
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.rszephyr
samples
wolfssl_benchmark
CMakeLists.txt README install_test.sh prj.conf sample.yaml zephyr_legacy.conf zephyr_v4.1.confwolfssl_test
CMakeLists.txt README install_test.sh prj-no-malloc.conf prj.conf sample.yaml zephyr_legacy.conf zephyr_v4.1.conf
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 */