cjson
.github
workflows CI.yml ci-fuzz.yml
CONTRIBUTING.md
fuzzing
inputs test1 test10 test11 test2 test3 test3.bu test3.uf test3.uu test4 test5 test6 test7 test8 test9
.gitignore CMakeLists.txt afl-prepare-linux.sh afl.c afl.sh cjson_read_fuzzer.c fuzz_main.c json.dict ossfuzz.sh
library_config cJSONConfig.cmake.in cJSONConfigVersion.cmake.in libcjson.pc.in libcjson_utils.pc.in uninstall.cmake
tests
inputs test1 test1.expected test10 test10.expected test11 test11.expected test2 test2.expected test3 test3.expected test4 test4.expected test5 test5.expected test6 test7 test7.expected test8 test8.expected test9 test9.expected
json-patch-tests .editorconfig .gitignore .npmignore README.md cjson-utils-tests.json package.json spec_tests.json tests.json
unity
auto colour_prompt.rb colour_reporter.rb generate_config.yml generate_module.rb generate_test_runner.rb parse_output.rb stylize_as_junit.rb test_file_filter.rb type_sanitizer.rb unity_test_summary.py unity_test_summary.rb unity_to_junit.py
docs ThrowTheSwitchCodingStandard.md UnityAssertionsCheatSheetSuitableforPrintingandPossiblyFraming.pdf UnityAssertionsReference.md UnityConfigurationGuide.md UnityGettingStartedGuide.md UnityHelperScriptsGuide.md license.txt
examples
example_1
src ProductionCode.c ProductionCode.h ProductionCode2.c ProductionCode2.h
makefile readme.txt
example_2
src ProductionCode.c ProductionCode.h ProductionCode2.c ProductionCode2.h
makefile readme.txt
example_3
helper UnityHelper.c UnityHelper.h
src ProductionCode.c ProductionCode.h ProductionCode2.c ProductionCode2.h
rakefile.rb rakefile_helper.rb readme.txt target_gcc_32.yml
unity_config.h
extras
eclipse error_parsers.txt
fixture
src unity_fixture.c unity_fixture.h unity_fixture_internals.h unity_fixture_malloc_overrides.h
rakefile.rb rakefile_helper.rb readme.txt
release build.info version.info
src unity.c unity.h unity_internals.h
.gitattributes .gitignore .travis.yml README.md
CMakeLists.txt cjson_add.c common.h compare_tests.c json_patch_tests.c minify_tests.c misc_tests.c misc_utils_tests.c old_utils_tests.c parse_array.c parse_examples.c parse_hex4.c parse_number.c parse_object.c parse_string.c parse_value.c parse_with_opts.c print_array.c print_number.c print_object.c print_string.c print_value.c readme_examples.c unity_setup.c
.editorconfig .gitattributes .gitignore .travis.yml CHANGELOG.md CMakeLists.txt CONTRIBUTORS.md LICENSE Makefile README.md SECURITY.md appveyor.yml cJSON.c cJSON.h cJSON_Utils.c cJSON_Utils.h test.c valgrind.supp
curl
.circleci config.yml
.github
ISSUE_TEMPLATE bug_report.yml config.yml docs.yml
scripts cleancmd.pl cmp-config.pl cmp-pkg-config.sh codespell-ignore.words codespell.sh distfiles.sh pyspelling.words pyspelling.yaml randcurl.pl requirements-docs.txt requirements-proselint.txt requirements.txt shellcheck-ci.sh shellcheck.sh spellcheck.curl trimmarkdownheader.pl typos.sh typos.toml verify-examples.pl verify-synopsis.pl yamlcheck.sh yamlcheck.yaml
workflows appveyor-status.yml checkdocs.yml checksrc.yml checkurls.yml codeql.yml configure-vs-cmake.yml curl-for-win.yml distcheck.yml fuzz.yml http3-linux.yml label.yml linux-old.yml linux.yml macos.yml non-native.yml windows.yml
CODEOWNERS CONTRIBUTING.md FUNDING.yml dependabot.yml labeler.yml lock.yml stale.yml
CMake CurlSymbolHiding.cmake CurlTests.c FindBrotli.cmake FindCares.cmake FindGSS.cmake FindGnuTLS.cmake FindLDAP.cmake FindLibbacktrace.cmake FindLibgsasl.cmake FindLibidn2.cmake FindLibpsl.cmake FindLibssh.cmake FindLibssh2.cmake FindLibuv.cmake FindMbedTLS.cmake FindNGHTTP2.cmake FindNGHTTP3.cmake FindNGTCP2.cmake FindNettle.cmake FindQuiche.cmake FindRustls.cmake FindWolfSSL.cmake FindZstd.cmake Macros.cmake OtherTests.cmake PickyWarnings.cmake Utilities.cmake cmake_uninstall.in.cmake curl-config.in.cmake unix-cache.cmake win32-cache.cmake
LICENSES BSD-4-Clause-UC.txt ISC.txt curl.txt
docs
cmdline-opts .gitignore CMakeLists.txt MANPAGE.md Makefile.am Makefile.inc _AUTHORS.md _BUGS.md _DESCRIPTION.md _ENVIRONMENT.md _EXITCODES.md _FILES.md _GLOBBING.md _NAME.md _OPTIONS.md _OUTPUT.md _PROGRESS.md _PROTOCOLS.md _PROXYPREFIX.md _SEEALSO.md _SYNOPSIS.md _URL.md _VARIABLES.md _VERSION.md _WWW.md abstract-unix-socket.md alt-svc.md anyauth.md append.md aws-sigv4.md basic.md ca-native.md cacert.md capath.md cert-status.md cert-type.md cert.md ciphers.md compressed-ssh.md compressed.md config.md connect-timeout.md connect-to.md continue-at.md cookie-jar.md cookie.md create-dirs.md create-file-mode.md crlf.md crlfile.md curves.md data-ascii.md data-binary.md data-raw.md data-urlencode.md data.md delegation.md digest.md disable-eprt.md disable-epsv.md disable.md disallow-username-in-url.md dns-interface.md dns-ipv4-addr.md dns-ipv6-addr.md dns-servers.md doh-cert-status.md doh-insecure.md doh-url.md dump-ca-embed.md dump-header.md ech.md egd-file.md engine.md etag-compare.md etag-save.md expect100-timeout.md fail-early.md fail-with-body.md fail.md false-start.md follow.md form-escape.md form-string.md form.md ftp-account.md ftp-alternative-to-user.md ftp-create-dirs.md ftp-method.md ftp-pasv.md ftp-port.md ftp-pret.md ftp-skip-pasv-ip.md ftp-ssl-ccc-mode.md ftp-ssl-ccc.md ftp-ssl-control.md get.md globoff.md happy-eyeballs-timeout-ms.md haproxy-clientip.md haproxy-protocol.md head.md header.md help.md hostpubmd5.md hostpubsha256.md hsts.md http0.9.md http1.0.md http1.1.md http2-prior-knowledge.md http2.md http3-only.md http3.md ignore-content-length.md insecure.md interface.md ip-tos.md ipfs-gateway.md ipv4.md ipv6.md json.md junk-session-cookies.md keepalive-cnt.md keepalive-time.md key-type.md key.md knownhosts.md krb.md libcurl.md limit-rate.md list-only.md local-port.md location-trusted.md location.md login-options.md mail-auth.md mail-from.md mail-rcpt-allowfails.md mail-rcpt.md mainpage.idx manual.md max-filesize.md max-redirs.md max-time.md metalink.md mptcp.md negotiate.md netrc-file.md netrc-optional.md netrc.md next.md no-alpn.md no-buffer.md no-clobber.md no-keepalive.md no-npn.md no-progress-meter.md no-sessionid.md noproxy.md ntlm-wb.md ntlm.md oauth2-bearer.md out-null.md output-dir.md output.md parallel-immediate.md parallel-max-host.md parallel-max.md parallel.md pass.md path-as-is.md pinnedpubkey.md post301.md post302.md post303.md preproxy.md progress-bar.md proto-default.md proto-redir.md proto.md proxy-anyauth.md proxy-basic.md proxy-ca-native.md proxy-cacert.md proxy-capath.md proxy-cert-type.md proxy-cert.md proxy-ciphers.md proxy-crlfile.md proxy-digest.md proxy-header.md proxy-http2.md proxy-insecure.md proxy-key-type.md proxy-key.md proxy-negotiate.md proxy-ntlm.md proxy-pass.md proxy-pinnedpubkey.md proxy-service-name.md proxy-ssl-allow-beast.md proxy-ssl-auto-client-cert.md proxy-tls13-ciphers.md proxy-tlsauthtype.md proxy-tlspassword.md proxy-tlsuser.md proxy-tlsv1.md proxy-user.md proxy.md proxy1.0.md proxytunnel.md pubkey.md quote.md random-file.md range.md rate.md raw.md referer.md remote-header-name.md remote-name-all.md remote-name.md remote-time.md remove-on-error.md request-target.md request.md resolve.md retry-all-errors.md retry-connrefused.md retry-delay.md retry-max-time.md retry.md sasl-authzid.md sasl-ir.md service-name.md show-error.md show-headers.md sigalgs.md silent.md skip-existing.md socks4.md socks4a.md socks5-basic.md socks5-gssapi-nec.md socks5-gssapi-service.md socks5-gssapi.md socks5-hostname.md socks5.md speed-limit.md speed-time.md ssl-allow-beast.md ssl-auto-client-cert.md ssl-no-revoke.md ssl-reqd.md ssl-revoke-best-effort.md ssl-sessions.md ssl.md sslv2.md sslv3.md stderr.md styled-output.md suppress-connect-headers.md tcp-fastopen.md tcp-nodelay.md telnet-option.md tftp-blksize.md tftp-no-options.md time-cond.md tls-earlydata.md tls-max.md tls13-ciphers.md tlsauthtype.md tlspassword.md tlsuser.md tlsv1.0.md tlsv1.1.md tlsv1.2.md tlsv1.3.md tlsv1.md tr-encoding.md trace-ascii.md trace-config.md trace-ids.md trace-time.md trace.md unix-socket.md upload-file.md upload-flags.md url-query.md url.md use-ascii.md user-agent.md user.md variable.md verbose.md version.md vlan-priority.md write-out.md xattr.md
examples .checksrc .gitignore 10-at-a-time.c CMakeLists.txt Makefile.am Makefile.example Makefile.inc README.md adddocsref.pl address-scope.c altsvc.c anyauthput.c block_ip.c cacertinmem.c certinfo.c chkspeed.c connect-to.c cookie_interface.c crawler.c debug.c default-scheme.c ephiperfifo.c evhiperfifo.c externalsocket.c fileupload.c ftp-delete.c ftp-wildcard.c ftpget.c ftpgetinfo.c ftpgetresp.c ftpsget.c ftpupload.c ftpuploadfrommem.c ftpuploadresume.c getinfo.c getinmemory.c getredirect.c getreferrer.c ghiper.c headerapi.c hiperfifo.c hsts-preload.c htmltidy.c htmltitle.cpp http-options.c http-post.c http2-download.c http2-pushinmemory.c http2-serverpush.c http2-upload.c http3-present.c http3.c httpcustomheader.c httpput-postfields.c httpput.c https.c imap-append.c imap-authzid.c imap-copy.c imap-create.c imap-delete.c imap-examine.c imap-fetch.c imap-list.c imap-lsub.c imap-multi.c imap-noop.c imap-search.c imap-ssl.c imap-store.c imap-tls.c interface.c ipv6.c keepalive.c localport.c log_failed_transfers.c maxconnects.c multi-app.c multi-debugcallback.c multi-double.c multi-event.c multi-formadd.c multi-legacy.c multi-post.c multi-single.c multi-uv.c netrc.c parseurl.c persistent.c pop3-authzid.c pop3-dele.c pop3-list.c pop3-multi.c pop3-noop.c pop3-retr.c pop3-ssl.c pop3-stat.c pop3-tls.c pop3-top.c pop3-uidl.c post-callback.c postinmemory.c postit2-formadd.c postit2.c progressfunc.c protofeats.c range.c resolve.c rtsp-options.c sendrecv.c sepheaders.c sessioninfo.c sftpget.c sftpuploadresume.c shared-connection-cache.c simple.c simplepost.c simplessl.c smooth-gtk-thread.c smtp-authzid.c smtp-expn.c smtp-mail.c smtp-mime.c smtp-multi.c smtp-ssl.c smtp-tls.c smtp-vrfy.c sslbackend.c synctime.c threaded.c unixsocket.c url2file.c urlapi.c usercertinmem.c version-check.pl websocket-cb.c websocket-updown.c websocket.c xmlstream.c
internals BUFQ.md BUFREF.md CHECKSRC.md CLIENT-READERS.md CLIENT-WRITERS.md CODE_STYLE.md CONNECTION-FILTERS.md CREDENTIALS.md CURLX.md DYNBUF.md HASH.md LLIST.md MID.md MQTT.md MULTI-EV.md NEW-PROTOCOL.md PEERS.md PORTING.md RATELIMITS.md README.md SCORECARD.md SPLAY.md STRPARSE.md THRDPOOL-AND-QUEUE.md TIME-KEEPING.md TLS-SESSIONS.md UINT_SETS.md WEBSOCKET.md
libcurl
opts CMakeLists.txt CURLINFO_ACTIVESOCKET.md CURLINFO_APPCONNECT_TIME.md CURLINFO_APPCONNECT_TIME_T.md CURLINFO_CAINFO.md CURLINFO_CAPATH.md CURLINFO_CERTINFO.md CURLINFO_CONDITION_UNMET.md CURLINFO_CONNECT_TIME.md CURLINFO_CONNECT_TIME_T.md CURLINFO_CONN_ID.md CURLINFO_CONTENT_LENGTH_DOWNLOAD.md CURLINFO_CONTENT_LENGTH_DOWNLOAD_T.md CURLINFO_CONTENT_LENGTH_UPLOAD.md CURLINFO_CONTENT_LENGTH_UPLOAD_T.md CURLINFO_CONTENT_TYPE.md CURLINFO_COOKIELIST.md CURLINFO_EARLYDATA_SENT_T.md CURLINFO_EFFECTIVE_METHOD.md CURLINFO_EFFECTIVE_URL.md CURLINFO_FILETIME.md CURLINFO_FILETIME_T.md CURLINFO_FTP_ENTRY_PATH.md CURLINFO_HEADER_SIZE.md CURLINFO_HTTPAUTH_AVAIL.md CURLINFO_HTTPAUTH_USED.md CURLINFO_HTTP_CONNECTCODE.md CURLINFO_HTTP_VERSION.md CURLINFO_LASTSOCKET.md CURLINFO_LOCAL_IP.md CURLINFO_LOCAL_PORT.md CURLINFO_NAMELOOKUP_TIME.md CURLINFO_NAMELOOKUP_TIME_T.md CURLINFO_NUM_CONNECTS.md CURLINFO_OS_ERRNO.md CURLINFO_POSTTRANSFER_TIME_T.md CURLINFO_PRETRANSFER_TIME.md CURLINFO_PRETRANSFER_TIME_T.md CURLINFO_PRIMARY_IP.md CURLINFO_PRIMARY_PORT.md CURLINFO_PRIVATE.md CURLINFO_PROTOCOL.md CURLINFO_PROXYAUTH_AVAIL.md CURLINFO_PROXYAUTH_USED.md CURLINFO_PROXY_ERROR.md CURLINFO_PROXY_SSL_VERIFYRESULT.md CURLINFO_QUEUE_TIME_T.md CURLINFO_REDIRECT_COUNT.md CURLINFO_REDIRECT_TIME.md CURLINFO_REDIRECT_TIME_T.md CURLINFO_REDIRECT_URL.md CURLINFO_REFERER.md CURLINFO_REQUEST_SIZE.md CURLINFO_RESPONSE_CODE.md CURLINFO_RETRY_AFTER.md CURLINFO_RTSP_CLIENT_CSEQ.md CURLINFO_RTSP_CSEQ_RECV.md CURLINFO_RTSP_SERVER_CSEQ.md CURLINFO_RTSP_SESSION_ID.md CURLINFO_SCHEME.md CURLINFO_SIZE_DELIVERED.md CURLINFO_SIZE_DOWNLOAD.md CURLINFO_SIZE_DOWNLOAD_T.md CURLINFO_SIZE_UPLOAD.md CURLINFO_SIZE_UPLOAD_T.md CURLINFO_SPEED_DOWNLOAD.md CURLINFO_SPEED_DOWNLOAD_T.md CURLINFO_SPEED_UPLOAD.md CURLINFO_SPEED_UPLOAD_T.md CURLINFO_SSL_ENGINES.md CURLINFO_SSL_VERIFYRESULT.md CURLINFO_STARTTRANSFER_TIME.md CURLINFO_STARTTRANSFER_TIME_T.md CURLINFO_TLS_SESSION.md CURLINFO_TLS_SSL_PTR.md CURLINFO_TOTAL_TIME.md CURLINFO_TOTAL_TIME_T.md CURLINFO_USED_PROXY.md CURLINFO_XFER_ID.md CURLMINFO_XFERS_ADDED.md CURLMINFO_XFERS_CURRENT.md CURLMINFO_XFERS_DONE.md CURLMINFO_XFERS_PENDING.md CURLMINFO_XFERS_RUNNING.md CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE.md CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE.md CURLMOPT_MAXCONNECTS.md CURLMOPT_MAX_CONCURRENT_STREAMS.md CURLMOPT_MAX_HOST_CONNECTIONS.md CURLMOPT_MAX_PIPELINE_LENGTH.md CURLMOPT_MAX_TOTAL_CONNECTIONS.md CURLMOPT_NETWORK_CHANGED.md CURLMOPT_NOTIFYDATA.md CURLMOPT_NOTIFYFUNCTION.md CURLMOPT_PIPELINING.md CURLMOPT_PIPELINING_SERVER_BL.md CURLMOPT_PIPELINING_SITE_BL.md CURLMOPT_PUSHDATA.md CURLMOPT_PUSHFUNCTION.md CURLMOPT_QUICK_EXIT.md CURLMOPT_RESOLVE_THREADS_MAX.md CURLMOPT_SOCKETDATA.md CURLMOPT_SOCKETFUNCTION.md CURLMOPT_TIMERDATA.md CURLMOPT_TIMERFUNCTION.md CURLOPT_ABSTRACT_UNIX_SOCKET.md CURLOPT_ACCEPTTIMEOUT_MS.md CURLOPT_ACCEPT_ENCODING.md CURLOPT_ADDRESS_SCOPE.md CURLOPT_ALTSVC.md CURLOPT_ALTSVC_CTRL.md CURLOPT_APPEND.md CURLOPT_AUTOREFERER.md CURLOPT_AWS_SIGV4.md CURLOPT_BUFFERSIZE.md CURLOPT_CAINFO.md CURLOPT_CAINFO_BLOB.md CURLOPT_CAPATH.md CURLOPT_CA_CACHE_TIMEOUT.md CURLOPT_CERTINFO.md CURLOPT_CHUNK_BGN_FUNCTION.md CURLOPT_CHUNK_DATA.md CURLOPT_CHUNK_END_FUNCTION.md CURLOPT_CLOSESOCKETDATA.md CURLOPT_CLOSESOCKETFUNCTION.md CURLOPT_CONNECTTIMEOUT.md CURLOPT_CONNECTTIMEOUT_MS.md CURLOPT_CONNECT_ONLY.md CURLOPT_CONNECT_TO.md CURLOPT_CONV_FROM_NETWORK_FUNCTION.md CURLOPT_CONV_FROM_UTF8_FUNCTION.md CURLOPT_CONV_TO_NETWORK_FUNCTION.md CURLOPT_COOKIE.md CURLOPT_COOKIEFILE.md CURLOPT_COOKIEJAR.md CURLOPT_COOKIELIST.md CURLOPT_COOKIESESSION.md CURLOPT_COPYPOSTFIELDS.md CURLOPT_CRLF.md CURLOPT_CRLFILE.md CURLOPT_CURLU.md CURLOPT_CUSTOMREQUEST.md CURLOPT_DEBUGDATA.md CURLOPT_DEBUGFUNCTION.md CURLOPT_DEFAULT_PROTOCOL.md CURLOPT_DIRLISTONLY.md CURLOPT_DISALLOW_USERNAME_IN_URL.md CURLOPT_DNS_CACHE_TIMEOUT.md CURLOPT_DNS_INTERFACE.md CURLOPT_DNS_LOCAL_IP4.md CURLOPT_DNS_LOCAL_IP6.md CURLOPT_DNS_SERVERS.md CURLOPT_DNS_SHUFFLE_ADDRESSES.md CURLOPT_DNS_USE_GLOBAL_CACHE.md CURLOPT_DOH_SSL_VERIFYHOST.md CURLOPT_DOH_SSL_VERIFYPEER.md CURLOPT_DOH_SSL_VERIFYSTATUS.md CURLOPT_DOH_URL.md CURLOPT_ECH.md CURLOPT_EGDSOCKET.md CURLOPT_ERRORBUFFER.md CURLOPT_EXPECT_100_TIMEOUT_MS.md CURLOPT_FAILONERROR.md CURLOPT_FILETIME.md CURLOPT_FNMATCH_DATA.md CURLOPT_FNMATCH_FUNCTION.md CURLOPT_FOLLOWLOCATION.md CURLOPT_FORBID_REUSE.md CURLOPT_FRESH_CONNECT.md CURLOPT_FTPPORT.md CURLOPT_FTPSSLAUTH.md CURLOPT_FTP_ACCOUNT.md CURLOPT_FTP_ALTERNATIVE_TO_USER.md CURLOPT_FTP_CREATE_MISSING_DIRS.md CURLOPT_FTP_FILEMETHOD.md CURLOPT_FTP_SKIP_PASV_IP.md CURLOPT_FTP_SSL_CCC.md CURLOPT_FTP_USE_EPRT.md CURLOPT_FTP_USE_EPSV.md CURLOPT_FTP_USE_PRET.md CURLOPT_GSSAPI_DELEGATION.md CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.md CURLOPT_HAPROXYPROTOCOL.md CURLOPT_HAPROXY_CLIENT_IP.md CURLOPT_HEADER.md CURLOPT_HEADERDATA.md CURLOPT_HEADERFUNCTION.md CURLOPT_HEADEROPT.md CURLOPT_HSTS.md CURLOPT_HSTSREADDATA.md CURLOPT_HSTSREADFUNCTION.md CURLOPT_HSTSWRITEDATA.md CURLOPT_HSTSWRITEFUNCTION.md CURLOPT_HSTS_CTRL.md CURLOPT_HTTP09_ALLOWED.md CURLOPT_HTTP200ALIASES.md CURLOPT_HTTPAUTH.md CURLOPT_HTTPGET.md CURLOPT_HTTPHEADER.md CURLOPT_HTTPPOST.md CURLOPT_HTTPPROXYTUNNEL.md CURLOPT_HTTP_CONTENT_DECODING.md CURLOPT_HTTP_TRANSFER_DECODING.md CURLOPT_HTTP_VERSION.md CURLOPT_IGNORE_CONTENT_LENGTH.md CURLOPT_INFILESIZE.md CURLOPT_INFILESIZE_LARGE.md CURLOPT_INTERFACE.md CURLOPT_INTERLEAVEDATA.md CURLOPT_INTERLEAVEFUNCTION.md CURLOPT_IOCTLDATA.md CURLOPT_IOCTLFUNCTION.md CURLOPT_IPRESOLVE.md CURLOPT_ISSUERCERT.md CURLOPT_ISSUERCERT_BLOB.md CURLOPT_KEEP_SENDING_ON_ERROR.md CURLOPT_KEYPASSWD.md CURLOPT_KRBLEVEL.md CURLOPT_LOCALPORT.md CURLOPT_LOCALPORTRANGE.md CURLOPT_LOGIN_OPTIONS.md CURLOPT_LOW_SPEED_LIMIT.md CURLOPT_LOW_SPEED_TIME.md CURLOPT_MAIL_AUTH.md CURLOPT_MAIL_FROM.md CURLOPT_MAIL_RCPT.md CURLOPT_MAIL_RCPT_ALLOWFAILS.md CURLOPT_MAXAGE_CONN.md CURLOPT_MAXCONNECTS.md CURLOPT_MAXFILESIZE.md CURLOPT_MAXFILESIZE_LARGE.md CURLOPT_MAXLIFETIME_CONN.md CURLOPT_MAXREDIRS.md CURLOPT_MAX_RECV_SPEED_LARGE.md CURLOPT_MAX_SEND_SPEED_LARGE.md CURLOPT_MIMEPOST.md CURLOPT_MIME_OPTIONS.md CURLOPT_NETRC.md CURLOPT_NETRC_FILE.md CURLOPT_NEW_DIRECTORY_PERMS.md CURLOPT_NEW_FILE_PERMS.md CURLOPT_NOBODY.md CURLOPT_NOPROGRESS.md CURLOPT_NOPROXY.md CURLOPT_NOSIGNAL.md CURLOPT_OPENSOCKETDATA.md CURLOPT_OPENSOCKETFUNCTION.md CURLOPT_PASSWORD.md CURLOPT_PATH_AS_IS.md CURLOPT_PINNEDPUBLICKEY.md CURLOPT_PIPEWAIT.md CURLOPT_PORT.md CURLOPT_POST.md CURLOPT_POSTFIELDS.md CURLOPT_POSTFIELDSIZE.md CURLOPT_POSTFIELDSIZE_LARGE.md CURLOPT_POSTQUOTE.md CURLOPT_POSTREDIR.md CURLOPT_PREQUOTE.md CURLOPT_PREREQDATA.md CURLOPT_PREREQFUNCTION.md CURLOPT_PRE_PROXY.md CURLOPT_PRIVATE.md CURLOPT_PROGRESSDATA.md CURLOPT_PROGRESSFUNCTION.md CURLOPT_PROTOCOLS.md CURLOPT_PROTOCOLS_STR.md CURLOPT_PROXY.md CURLOPT_PROXYAUTH.md CURLOPT_PROXYHEADER.md CURLOPT_PROXYPASSWORD.md CURLOPT_PROXYPORT.md CURLOPT_PROXYTYPE.md CURLOPT_PROXYUSERNAME.md CURLOPT_PROXYUSERPWD.md CURLOPT_PROXY_CAINFO.md CURLOPT_PROXY_CAINFO_BLOB.md CURLOPT_PROXY_CAPATH.md CURLOPT_PROXY_CRLFILE.md CURLOPT_PROXY_ISSUERCERT.md CURLOPT_PROXY_ISSUERCERT_BLOB.md CURLOPT_PROXY_KEYPASSWD.md CURLOPT_PROXY_PINNEDPUBLICKEY.md CURLOPT_PROXY_SERVICE_NAME.md CURLOPT_PROXY_SSLCERT.md CURLOPT_PROXY_SSLCERTTYPE.md CURLOPT_PROXY_SSLCERT_BLOB.md CURLOPT_PROXY_SSLKEY.md CURLOPT_PROXY_SSLKEYTYPE.md CURLOPT_PROXY_SSLKEY_BLOB.md CURLOPT_PROXY_SSLVERSION.md CURLOPT_PROXY_SSL_CIPHER_LIST.md CURLOPT_PROXY_SSL_OPTIONS.md CURLOPT_PROXY_SSL_VERIFYHOST.md CURLOPT_PROXY_SSL_VERIFYPEER.md CURLOPT_PROXY_TLS13_CIPHERS.md CURLOPT_PROXY_TLSAUTH_PASSWORD.md CURLOPT_PROXY_TLSAUTH_TYPE.md CURLOPT_PROXY_TLSAUTH_USERNAME.md CURLOPT_PROXY_TRANSFER_MODE.md CURLOPT_PUT.md CURLOPT_QUICK_EXIT.md CURLOPT_QUOTE.md CURLOPT_RANDOM_FILE.md CURLOPT_RANGE.md CURLOPT_READDATA.md CURLOPT_READFUNCTION.md CURLOPT_REDIR_PROTOCOLS.md CURLOPT_REDIR_PROTOCOLS_STR.md CURLOPT_REFERER.md CURLOPT_REQUEST_TARGET.md CURLOPT_RESOLVE.md CURLOPT_RESOLVER_START_DATA.md CURLOPT_RESOLVER_START_FUNCTION.md CURLOPT_RESUME_FROM.md CURLOPT_RESUME_FROM_LARGE.md CURLOPT_RTSP_CLIENT_CSEQ.md CURLOPT_RTSP_REQUEST.md CURLOPT_RTSP_SERVER_CSEQ.md CURLOPT_RTSP_SESSION_ID.md CURLOPT_RTSP_STREAM_URI.md CURLOPT_RTSP_TRANSPORT.md CURLOPT_SASL_AUTHZID.md CURLOPT_SASL_IR.md CURLOPT_SEEKDATA.md CURLOPT_SEEKFUNCTION.md CURLOPT_SERVER_RESPONSE_TIMEOUT.md CURLOPT_SERVER_RESPONSE_TIMEOUT_MS.md CURLOPT_SERVICE_NAME.md CURLOPT_SHARE.md CURLOPT_SOCKOPTDATA.md CURLOPT_SOCKOPTFUNCTION.md CURLOPT_SOCKS5_AUTH.md CURLOPT_SOCKS5_GSSAPI_NEC.md CURLOPT_SOCKS5_GSSAPI_SERVICE.md CURLOPT_SSH_AUTH_TYPES.md CURLOPT_SSH_COMPRESSION.md CURLOPT_SSH_HOSTKEYDATA.md CURLOPT_SSH_HOSTKEYFUNCTION.md CURLOPT_SSH_HOST_PUBLIC_KEY_MD5.md CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256.md CURLOPT_SSH_KEYDATA.md CURLOPT_SSH_KEYFUNCTION.md CURLOPT_SSH_KNOWNHOSTS.md CURLOPT_SSH_PRIVATE_KEYFILE.md CURLOPT_SSH_PUBLIC_KEYFILE.md CURLOPT_SSLCERT.md CURLOPT_SSLCERTTYPE.md CURLOPT_SSLCERT_BLOB.md CURLOPT_SSLENGINE.md CURLOPT_SSLENGINE_DEFAULT.md CURLOPT_SSLKEY.md CURLOPT_SSLKEYTYPE.md CURLOPT_SSLKEY_BLOB.md CURLOPT_SSLVERSION.md CURLOPT_SSL_CIPHER_LIST.md CURLOPT_SSL_CTX_DATA.md CURLOPT_SSL_CTX_FUNCTION.md CURLOPT_SSL_EC_CURVES.md CURLOPT_SSL_ENABLE_ALPN.md CURLOPT_SSL_ENABLE_NPN.md CURLOPT_SSL_FALSESTART.md CURLOPT_SSL_OPTIONS.md CURLOPT_SSL_SESSIONID_CACHE.md CURLOPT_SSL_SIGNATURE_ALGORITHMS.md CURLOPT_SSL_VERIFYHOST.md CURLOPT_SSL_VERIFYPEER.md CURLOPT_SSL_VERIFYSTATUS.md CURLOPT_STDERR.md CURLOPT_STREAM_DEPENDS.md CURLOPT_STREAM_DEPENDS_E.md CURLOPT_STREAM_WEIGHT.md CURLOPT_SUPPRESS_CONNECT_HEADERS.md CURLOPT_TCP_FASTOPEN.md CURLOPT_TCP_KEEPALIVE.md CURLOPT_TCP_KEEPCNT.md CURLOPT_TCP_KEEPIDLE.md CURLOPT_TCP_KEEPINTVL.md CURLOPT_TCP_NODELAY.md CURLOPT_TELNETOPTIONS.md CURLOPT_TFTP_BLKSIZE.md CURLOPT_TFTP_NO_OPTIONS.md CURLOPT_TIMECONDITION.md CURLOPT_TIMEOUT.md CURLOPT_TIMEOUT_MS.md CURLOPT_TIMEVALUE.md CURLOPT_TIMEVALUE_LARGE.md CURLOPT_TLS13_CIPHERS.md CURLOPT_TLSAUTH_PASSWORD.md CURLOPT_TLSAUTH_TYPE.md CURLOPT_TLSAUTH_USERNAME.md CURLOPT_TRAILERDATA.md CURLOPT_TRAILERFUNCTION.md CURLOPT_TRANSFERTEXT.md CURLOPT_TRANSFER_ENCODING.md CURLOPT_UNIX_SOCKET_PATH.md CURLOPT_UNRESTRICTED_AUTH.md CURLOPT_UPKEEP_INTERVAL_MS.md CURLOPT_UPLOAD.md CURLOPT_UPLOAD_BUFFERSIZE.md CURLOPT_UPLOAD_FLAGS.md CURLOPT_URL.md CURLOPT_USERAGENT.md CURLOPT_USERNAME.md CURLOPT_USERPWD.md CURLOPT_USE_SSL.md CURLOPT_VERBOSE.md CURLOPT_WILDCARDMATCH.md CURLOPT_WRITEDATA.md CURLOPT_WRITEFUNCTION.md CURLOPT_WS_OPTIONS.md CURLOPT_XFERINFODATA.md CURLOPT_XFERINFOFUNCTION.md CURLOPT_XOAUTH2_BEARER.md CURLSHOPT_LOCKFUNC.md CURLSHOPT_SHARE.md CURLSHOPT_UNLOCKFUNC.md CURLSHOPT_UNSHARE.md CURLSHOPT_USERDATA.md Makefile.am Makefile.inc
.gitignore ABI.md CMakeLists.txt Makefile.am Makefile.inc curl_easy_cleanup.md curl_easy_duphandle.md curl_easy_escape.md curl_easy_getinfo.md curl_easy_header.md curl_easy_init.md curl_easy_nextheader.md curl_easy_option_by_id.md curl_easy_option_by_name.md curl_easy_option_next.md curl_easy_pause.md curl_easy_perform.md curl_easy_recv.md curl_easy_reset.md curl_easy_send.md curl_easy_setopt.md curl_easy_ssls_export.md curl_easy_ssls_import.md curl_easy_strerror.md curl_easy_unescape.md curl_easy_upkeep.md curl_escape.md curl_formadd.md curl_formfree.md curl_formget.md curl_free.md curl_getdate.md curl_getenv.md curl_global_cleanup.md curl_global_init.md curl_global_init_mem.md curl_global_sslset.md curl_global_trace.md curl_mime_addpart.md curl_mime_data.md curl_mime_data_cb.md curl_mime_encoder.md curl_mime_filedata.md curl_mime_filename.md curl_mime_free.md curl_mime_headers.md curl_mime_init.md curl_mime_name.md curl_mime_subparts.md curl_mime_type.md curl_mprintf.md curl_multi_add_handle.md curl_multi_assign.md curl_multi_cleanup.md curl_multi_fdset.md curl_multi_get_handles.md curl_multi_get_offt.md curl_multi_info_read.md curl_multi_init.md curl_multi_notify_disable.md curl_multi_notify_enable.md curl_multi_perform.md curl_multi_poll.md curl_multi_remove_handle.md curl_multi_setopt.md curl_multi_socket.md curl_multi_socket_action.md curl_multi_socket_all.md curl_multi_strerror.md curl_multi_timeout.md curl_multi_wait.md curl_multi_waitfds.md curl_multi_wakeup.md curl_pushheader_byname.md curl_pushheader_bynum.md curl_share_cleanup.md curl_share_init.md curl_share_setopt.md curl_share_strerror.md curl_slist_append.md curl_slist_free_all.md curl_strequal.md curl_strnequal.md curl_unescape.md curl_url.md curl_url_cleanup.md curl_url_dup.md curl_url_get.md curl_url_set.md curl_url_strerror.md curl_version.md curl_version_info.md curl_ws_meta.md curl_ws_recv.md curl_ws_send.md curl_ws_start_frame.md libcurl-easy.md libcurl-env-dbg.md libcurl-env.md libcurl-errors.md libcurl-multi.md libcurl-security.md libcurl-share.md libcurl-thread.md libcurl-tutorial.md libcurl-url.md libcurl-ws.md libcurl.m4 libcurl.md mksymbolsmanpage.pl symbols-in-versions symbols.pl
tests CI.md FILEFORMAT.md HTTP.md TEST-SUITE.md
.gitignore ALTSVC.md BINDINGS.md BUG-BOUNTY.md BUGS.md CIPHERS-TLS12.md CIPHERS.md CMakeLists.txt CODE_OF_CONDUCT.md CODE_REVIEW.md CONTRIBUTE.md CURL-DISABLE.md CURLDOWN.md DEPRECATE.md DISTROS.md EARLY-RELEASE.md ECH.md EXPERIMENTAL.md FAQ.md FEATURES.md GOVERNANCE.md HELP-US.md HISTORY.md HSTS.md HTTP-COOKIES.md HTTP3.md HTTPSRR.md INFRASTRUCTURE.md INSTALL-CMAKE.md INSTALL.md INTERNALS.md IPFS.md KNOWN_BUGS.md KNOWN_RISKS.md MAIL-ETIQUETTE.md MANUAL.md Makefile.am README.md RELEASE-PROCEDURE.md ROADMAP.md RUSTLS.md SECURITY-ADVISORY.md SPONSORS.md SSL-PROBLEMS.md SSLCERTS.md THANKS THANKS-filter TODO.md TheArtOfHttpScripting.md URL-SYNTAX.md VERIFY.md VERSIONS.md VULN-DISCLOSURE-POLICY.md curl-config.md mk-ca-bundle.md options-in-versions runtests.md testcurl.md wcurl.md
include
curl Makefile.am curl.h curlver.h easy.h header.h mprintf.h multi.h options.h stdcheaders.h system.h typecheck-gcc.h urlapi.h websockets.h
Makefile.am README.md
lib
curlx base64.c base64.h basename.c basename.h dynbuf.c dynbuf.h fopen.c fopen.h inet_ntop.c inet_ntop.h inet_pton.c inet_pton.h multibyte.c multibyte.h nonblock.c nonblock.h snprintf.c snprintf.h strcopy.c strcopy.h strdup.c strdup.h strerr.c strerr.h strparse.c strparse.h timediff.c timediff.h timeval.c timeval.h version_win32.c version_win32.h wait.c wait.h warnless.c warnless.h winapi.c winapi.h
vauth cleartext.c cram.c digest.c digest.h digest_sspi.c gsasl.c krb5_gssapi.c krb5_sspi.c ntlm.c ntlm_sspi.c oauth2.c spnego_gssapi.c spnego_sspi.c vauth.c vauth.h
vquic curl_ngtcp2.c curl_ngtcp2.h curl_quiche.c curl_quiche.h vquic-tls.c vquic-tls.h vquic.c vquic.h vquic_int.h
vssh libssh.c libssh2.c ssh.h vssh.c vssh.h
vtls apple.c apple.h cipher_suite.c cipher_suite.h gtls.c gtls.h hostcheck.c hostcheck.h keylog.c keylog.h mbedtls.c mbedtls.h openssl.c openssl.h rustls.c rustls.h schannel.c schannel.h schannel_int.h schannel_verify.c vtls.c vtls.h vtls_int.h vtls_scache.c vtls_scache.h vtls_spack.c vtls_spack.h wolfssl.c wolfssl.h x509asn1.c x509asn1.h
.gitignore CMakeLists.txt Makefile.am Makefile.inc Makefile.soname altsvc.c altsvc.h amigaos.c amigaos.h arpa_telnet.h asyn-ares.c asyn-base.c asyn-thrdd.c asyn.h bufq.c bufq.h bufref.c bufref.h cf-dns.c cf-dns.h cf-h1-proxy.c cf-h1-proxy.h cf-h2-proxy.c cf-h2-proxy.h cf-haproxy.c cf-haproxy.h cf-https-connect.c cf-https-connect.h cf-ip-happy.c cf-ip-happy.h cf-socket.c cf-socket.h cfilters.c cfilters.h config-mac.h config-os400.h config-riscos.h config-win32.h conncache.c conncache.h connect.c connect.h content_encoding.c content_encoding.h cookie.c cookie.h creds.c creds.h cshutdn.c cshutdn.h curl_addrinfo.c curl_addrinfo.h curl_config-cmake.h.in curl_ctype.h curl_endian.c curl_endian.h curl_fnmatch.c curl_fnmatch.h curl_fopen.c curl_fopen.h curl_get_line.c curl_get_line.h curl_gethostname.c curl_gethostname.h curl_gssapi.c curl_gssapi.h curl_hmac.h curl_ldap.h curl_md4.h curl_md5.h curl_memrchr.c curl_memrchr.h curl_ntlm_core.c curl_ntlm_core.h curl_printf.h curl_range.c curl_range.h curl_sasl.c curl_sasl.h curl_setup.h curl_sha256.h curl_sha512_256.c curl_sha512_256.h curl_share.c curl_share.h curl_sspi.c curl_sspi.h curl_threads.c curl_threads.h curl_trc.c curl_trc.h cw-out.c cw-out.h cw-pause.c cw-pause.h dict.c dict.h dllmain.c dnscache.c dnscache.h doh.c doh.h dynhds.c dynhds.h easy.c easy_lock.h easygetopt.c easyif.h easyoptions.c easyoptions.h escape.c escape.h fake_addrinfo.c fake_addrinfo.h file.c file.h fileinfo.c fileinfo.h formdata.c formdata.h ftp-int.h ftp.c ftp.h ftplistparser.c ftplistparser.h functypes.h getenv.c getinfo.c getinfo.h gopher.c gopher.h hash.c hash.h headers.c headers.h hmac.c hostip.c hostip.h hostip4.c hostip6.c hsts.c hsts.h http.c http.h http1.c http1.h http2.c http2.h http_aws_sigv4.c http_aws_sigv4.h http_chunks.c http_chunks.h http_digest.c http_digest.h http_negotiate.c http_negotiate.h http_ntlm.c http_ntlm.h http_proxy.c http_proxy.h httpsrr.c httpsrr.h idn.c idn.h if2ip.c if2ip.h imap.c imap.h ldap.c libcurl.def libcurl.rc libcurl.vers.in llist.c llist.h macos.c macos.h md4.c md5.c memdebug.c mime.c mime.h mprintf.c mqtt.c mqtt.h multi.c multi_ev.c multi_ev.h multi_ntfy.c multi_ntfy.h multihandle.h multiif.h netrc.c netrc.h noproxy.c noproxy.h openldap.c optiontable.pl parsedate.c parsedate.h peer.c peer.h pingpong.c pingpong.h pop3.c pop3.h progress.c progress.h protocol.c protocol.h psl.c psl.h rand.c rand.h ratelimit.c ratelimit.h request.c request.h rtsp.c rtsp.h select.c select.h sendf.c sendf.h setopt.c setopt.h setup-os400.h setup-vms.h setup-win32.h sha256.c sigpipe.h slist.c slist.h smb.c smb.h smtp.c smtp.h sockaddr.h socketpair.c socketpair.h socks.c socks.h socks_gssapi.c socks_sspi.c splay.c splay.h strcase.c strcase.h strequal.c strerror.c strerror.h system_win32.c system_win32.h telnet.c telnet.h tftp.c tftp.h thrdpool.c thrdpool.h thrdqueue.c thrdqueue.h transfer.c transfer.h uint-bset.c uint-bset.h uint-hash.c uint-hash.h uint-spbset.c uint-spbset.h uint-table.c uint-table.h url.c url.h urlapi-int.h urlapi.c urldata.h version.c ws.c ws.h
m4 .gitignore curl-amissl.m4 curl-apple-sectrust.m4 curl-compilers.m4 curl-confopts.m4 curl-functions.m4 curl-gnutls.m4 curl-mbedtls.m4 curl-openssl.m4 curl-override.m4 curl-reentrant.m4 curl-rustls.m4 curl-schannel.m4 curl-sysconfig.m4 curl-wolfssl.m4 xc-am-iface.m4 xc-cc-check.m4 xc-lt-iface.m4 xc-val-flgs.m4 zz40-xc-ovr.m4 zz50-xc-ovr.m4
projects
OS400
rpg-examples HEADERAPI HTTPPOST INMEMORY SIMPLE1 SIMPLE2 SMTPSRCMBR
.checksrc README.OS400 ccsidcurl.c ccsidcurl.h config400.default curl.cmd curl.inc.in curlcl.c curlmain.c initscript.sh make-docs.sh make-include.sh make-lib.sh make-src.sh make-tests.sh makefile.sh os400sys.c os400sys.h
Windows
tmpl .gitattributes README.txt curl-all.sln curl.sln curl.vcxproj curl.vcxproj.filters libcurl.sln libcurl.vcxproj libcurl.vcxproj.filters
.gitignore README.md generate.bat
vms Makefile.am backup_gnv_curl_src.com build_curl-config_script.com build_gnv_curl.com build_gnv_curl_pcsi_desc.com build_gnv_curl_pcsi_text.com build_gnv_curl_release_notes.com build_libcurl_pc.com build_vms.com clean_gnv_curl.com compare_curl_source.com config_h.com curl_crtl_init.c curl_gnv_build_steps.txt curl_release_note_start.txt curl_startup.com curlmsg.h curlmsg.msg curlmsg.sdl curlmsg_vms.h generate_config_vms_h_curl.com generate_vax_transfer.com gnv_conftest.c_first gnv_curl_configure.sh gnv_libcurl_symbols.opt gnv_link_curl.com macro32_exactcase.patch make_gnv_curl_install.sh make_pcsi_curl_kit_name.com pcsi_gnv_curl_file_list.txt pcsi_product_gnv_curl.com readme report_openssl_version.c setup_gnv_curl_build.com stage_curl_install.com vms_eco_level.h
Makefile.am README.md
scripts .checksrc CMakeLists.txt Makefile.am badwords badwords-all badwords.txt cd2cd cd2nroff cdall checksrc-all.pl checksrc.pl cmakelint.sh completion.pl contributors.sh contrithanks.sh coverage.sh delta dmaketgz extract-unit-protos firefox-db2pem.sh installcheck.sh maketgz managen mdlinkcheck mk-ca-bundle.pl mk-unity.pl nroff2cd perlcheck.sh pythonlint.sh randdisable release-notes.pl release-tools.sh schemetable.c singleuse.pl spacecheck.pl top-complexity top-length verify-release wcurl
src
toolx tool_time.c tool_time.h
.checksrc .gitignore CMakeLists.txt Makefile.am Makefile.inc config2setopts.c config2setopts.h curl.rc curlinfo.c mk-file-embed.pl mkhelp.pl slist_wc.c slist_wc.h terminal.c terminal.h tool_cb_dbg.c tool_cb_dbg.h tool_cb_hdr.c tool_cb_hdr.h tool_cb_prg.c tool_cb_prg.h tool_cb_rea.c tool_cb_rea.h tool_cb_see.c tool_cb_see.h tool_cb_soc.c tool_cb_soc.h tool_cb_wrt.c tool_cb_wrt.h tool_cfgable.c tool_cfgable.h tool_dirhie.c tool_dirhie.h tool_doswin.c tool_doswin.h tool_easysrc.c tool_easysrc.h tool_filetime.c tool_filetime.h tool_findfile.c tool_findfile.h tool_formparse.c tool_formparse.h tool_getparam.c tool_getparam.h tool_getpass.c tool_getpass.h tool_help.c tool_help.h tool_helpers.c tool_helpers.h tool_hugehelp.h tool_ipfs.c tool_ipfs.h tool_libinfo.c tool_libinfo.h tool_listhelp.c tool_main.c tool_main.h tool_msgs.c tool_msgs.h tool_operate.c tool_operate.h tool_operhlp.c tool_operhlp.h tool_paramhlp.c tool_paramhlp.h tool_parsecfg.c tool_parsecfg.h tool_progress.c tool_progress.h tool_sdecls.h tool_setopt.c tool_setopt.h tool_setup.h tool_ssls.c tool_ssls.h tool_stderr.c tool_stderr.h tool_urlglob.c tool_urlglob.h tool_util.c tool_util.h tool_version.h tool_vms.c tool_vms.h tool_writeout.c tool_writeout.h tool_writeout_json.c tool_writeout_json.h tool_xattr.c tool_xattr.h var.c var.h
tests
certs .gitignore CMakeLists.txt Makefile.am Makefile.inc genserv.pl srp-verifier-conf srp-verifier-db test-ca.cnf test-ca.prm test-client-cert.prm test-client-eku-only.prm test-localhost-san-first.prm test-localhost-san-last.prm test-localhost.nn.prm test-localhost.prm test-localhost0h.prm
cmake CMakeLists.txt test.c test.cpp test.sh
data .gitignore DISABLED Makefile.am data-xml1 data1400.c data1401.c data1402.c data1403.c data1404.c data1405.c data1406.c data1407.c data1420.c data1461.txt data1463.txt data1465.c data1481.c data1705-1.md data1705-2.md data1705-3.md data1705-4.md data1705-stdout.1 data1706-1.md data1706-2.md data1706-3.md data1706-4.md data1706-stdout.txt data320.html test1 test10 test100 test1000 test1001 test1002 test1003 test1004 test1005 test1006 test1007 test1008 test1009 test101 test1010 test1011 test1012 test1013 test1014 test1015 test1016 test1017 test1018 test1019 test102 test1020 test1021 test1022 test1023 test1024 test1025 test1026 test1027 test1028 test1029 test103 test1030 test1031 test1032 test1033 test1034 test1035 test1036 test1037 test1038 test1039 test104 test1040 test1041 test1042 test1043 test1044 test1045 test1046 test1047 test1048 test1049 test105 test1050 test1051 test1052 test1053 test1054 test1055 test1056 test1057 test1058 test1059 test106 test1060 test1061 test1062 test1063 test1064 test1065 test1066 test1067 test1068 test1069 test107 test1070 test1071 test1072 test1073 test1074 test1075 test1076 test1077 test1078 test1079 test108 test1080 test1081 test1082 test1083 test1084 test1085 test1086 test1087 test1088 test1089 test109 test1090 test1091 test1092 test1093 test1094 test1095 test1096 test1097 test1098 test1099 test11 test110 test1100 test1101 test1102 test1103 test1104 test1105 test1106 test1107 test1108 test1109 test111 test1110 test1111 test1112 test1113 test1114 test1115 test1116 test1117 test1118 test1119 test112 test1120 test1121 test1122 test1123 test1124 test1125 test1126 test1127 test1128 test1129 test113 test1130 test1131 test1132 test1133 test1134 test1135 test1136 test1137 test1138 test1139 test114 test1140 test1141 test1142 test1143 test1144 test1145 test1146 test1147 test1148 test1149 test115 test1150 test1151 test1152 test1153 test1154 test1155 test1156 test1157 test1158 test1159 test116 test1160 test1161 test1162 test1163 test1164 test1165 test1166 test1167 test1168 test1169 test117 test1170 test1171 test1172 test1173 test1174 test1175 test1176 test1177 test1178 test1179 test118 test1180 test1181 test1182 test1183 test1184 test1185 test1186 test1187 test1188 test1189 test119 test1190 test1191 test1192 test1193 test1194 test1195 test1196 test1197 test1198 test1199 test12 test120 test1200 test1201 test1202 test1203 test1204 test1205 test1206 test1207 test1208 test1209 test121 test1210 test1211 test1212 test1213 test1214 test1215 test1216 test1217 test1218 test1219 test122 test1220 test1221 test1222 test1223 test1224 test1225 test1226 test1227 test1228 test1229 test123 test1230 test1231 test1232 test1233 test1234 test1235 test1236 test1237 test1238 test1239 test124 test1240 test1241 test1242 test1243 test1244 test1245 test1246 test1247 test1248 test1249 test125 test1250 test1251 test1252 test1253 test1254 test1255 test1256 test1257 test1258 test1259 test126 test1260 test1261 test1262 test1263 test1264 test1265 test1266 test1267 test1268 test1269 test127 test1270 test1271 test1272 test1273 test1274 test1275 test1276 test1277 test1278 test1279 test128 test1280 test1281 test1282 test1283 test1284 test1285 test1286 test1287 test1288 test1289 test129 test1290 test1291 test1292 test1293 test1294 test1295 test1296 test1297 test1298 test1299 test13 test130 test1300 test1301 test1302 test1303 test1304 test1305 test1306 test1307 test1308 test1309 test131 test1310 test1311 test1312 test1313 test1314 test1315 test1316 test1317 test1318 test1319 test132 test1320 test1321 test1322 test1323 test1324 test1325 test1326 test1327 test1328 test1329 test133 test1330 test1331 test1332 test1333 test1334 test1335 test1336 test1337 test1338 test1339 test134 test1340 test1341 test1342 test1343 test1344 test1345 test1346 test1347 test1348 test1349 test135 test1350 test1351 test1352 test1353 test1354 test1355 test1356 test1357 test1358 test1359 test136 test1360 test1361 test1362 test1363 test1364 test1365 test1366 test1367 test1368 test1369 test137 test1370 test1371 test1372 test1373 test1374 test1375 test1376 test1377 test1378 test1379 test138 test1380 test1381 test1382 test1383 test1384 test1385 test1386 test1387 test1388 test1389 test139 test1390 test1391 test1392 test1393 test1394 test1395 test1396 test1397 test1398 test1399 test14 test140 test1400 test1401 test1402 test1403 test1404 test1405 test1406 test1407 test1408 test1409 test141 test1410 test1411 test1412 test1413 test1414 test1415 test1416 test1417 test1418 test1419 test142 test1420 test1421 test1422 test1423 test1424 test1425 test1426 test1427 test1428 test1429 test143 test1430 test1431 test1432 test1433 test1434 test1435 test1436 test1437 test1438 test1439 test144 test1440 test1441 test1442 test1443 test1444 test1445 test1446 test1447 test1448 test1449 test145 test1450 test1451 test1452 test1453 test1454 test1455 test1456 test1457 test1458 test1459 test146 test1460 test1461 test1462 test1463 test1464 test1465 test1466 test1467 test1468 test1469 test147 test1470 test1471 test1472 test1473 test1474 test1475 test1476 test1477 test1478 test1479 test148 test1480 test1481 test1482 test1483 test1484 test1485 test1486 test1487 test1488 test1489 test149 test1490 test1491 test1492 test1493 test1494 test1495 test1496 test1497 test1498 test1499 test15 test150 test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 test1508 test1509 test151 test1510 test1511 test1512 test1513 test1514 test1515 test1516 test1517 test1518 test1519 test152 test1520 test1521 test1522 test1523 test1524 test1525 test1526 test1527 test1528 test1529 test153 test1530 test1531 test1532 test1533 test1534 test1535 test1536 test1537 test1538 test1539 test154 test1540 test1541 test1542 test1543 test1544 test1545 test1546 test1547 test1548 test1549 test155 test1550 test1551 test1552 test1553 test1554 test1555 test1556 test1557 test1558 test1559 test156 test1560 test1561 test1562 test1563 test1564 test1565 test1566 test1567 test1568 test1569 test157 test1570 test1571 test1572 test1573 test1574 test1575 test1576 test1577 test1578 test1579 test158 test1580 test1581 test1582 test1583 test1584 test1585 test1586 test1587 test1588 test1589 test159 test1590 test1591 test1592 test1593 test1594 test1595 test1596 test1597 test1598 test1599 test16 test160 test1600 test1601 test1602 test1603 test1604 test1605 test1606 test1607 test1608 test1609 test161 test1610 test1611 test1612 test1613 test1614 test1615 test1616 test1617 test1618 test1619 test162 test1620 test1621 test1622 test1623 test1624 test1625 test1626 test1627 test1628 test1629 test163 test1630 test1631 test1632 test1633 test1634 test1635 test1636 test1637 test1638 test1639 test164 test1640 test1641 test1642 test1643 test1644 test1645 test165 test1650 test1651 test1652 test1653 test1654 test1655 test1656 test1657 test1658 test1659 test166 test1660 test1661 test1662 test1663 test1664 test1665 test1666 test1667 test1668 test1669 test167 test1670 test1671 test1672 test1673 test1674 test1675 test1676 test168 test1680 test1681 test1682 test1683 test1684 test1685 test169 test17 test170 test1700 test1701 test1702 test1703 test1704 test1705 test1706 test1707 test1708 test1709 test171 test1710 test1711 test1712 test1713 test1714 test1715 test172 test1720 test1721 test173 test174 test175 test176 test177 test178 test179 test18 test180 test1800 test1801 test1802 test181 test182 test183 test184 test1847 test1848 test1849 test185 test1850 test1851 test186 test187 test188 test189 test19 test190 test1900 test1901 test1902 test1903 test1904 test1905 test1906 test1907 test1908 test1909 test191 test1910 test1911 test1912 test1913 test1914 test1915 test1916 test1917 test1918 test1919 test192 test1920 test1921 test193 test1933 test1934 test1935 test1936 test1937 test1938 test1939 test194 test1940 test1941 test1942 test1943 test1944 test1945 test1946 test1947 test1948 test195 test1955 test1956 test1957 test1958 test1959 test196 test1960 test1964 test1965 test1966 test197 test1970 test1971 test1972 test1973 test1974 test1975 test1976 test1977 test1978 test1979 test198 test1980 test1981 test1982 test1983 test1984 test199 test2 test20 test200 test2000 test2001 test2002 test2003 test2004 test2005 test2006 test2007 test2008 test2009 test201 test2010 test2011 test2012 test2013 test2014 test202 test2023 test2024 test2025 test2026 test2027 test2028 test2029 test203 test2030 test2031 test2032 test2033 test2034 test2035 test2037 test2038 test2039 test204 test2040 test2041 test2042 test2043 test2044 test2045 test2046 test2047 test2048 test2049 test205 test2050 test2051 test2052 test2053 test2054 test2055 test2056 test2057 test2058 test2059 test206 test2060 test2061 test2062 test2063 test2064 test2065 test2066 test2067 test2068 test2069 test207 test2070 test2071 test2072 test2073 test2074 test2075 test2076 test2077 test2078 test2079 test208 test2080 test2081 test2082 test2083 test2084 test2085 test2086 test2087 test2088 test2089 test209 test2090 test2091 test2092 test21 test210 test2100 test2101 test2102 test2103 test2104 test211 test212 test213 test214 test215 test216 test217 test218 test219 test22 test220 test2200 test2201 test2202 test2203 test2204 test2205 test2206 test2207 test221 test222 test223 test224 test225 test226 test227 test228 test229 test23 test230 test2300 test2301 test2302 test2303 test2304 test2306 test2307 test2308 test2309 test231 test232 test233 test234 test235 test236 test237 test238 test239 test24 test240 test2400 test2401 test2402 test2403 test2404 test2405 test2406 test2407 test2408 test2409 test241 test2410 test2411 test242 test243 test244 test245 test246 test247 test248 test249 test25 test250 test2500 test2501 test2502 test2503 test2504 test2505 test2506 test251 test252 test253 test254 test255 test256 test257 test258 test259 test26 test260 test2600 test2601 test2602 test2603 test2604 test2605 test261 test262 test263 test264 test265 test266 test267 test268 test269 test27 test270 test2700 test2701 test2702 test2703 test2704 test2705 test2706 test2707 test2708 test2709 test271 test2710 test2711 test2712 test2713 test2714 test2715 test2716 test2717 test2718 test2719 test272 test2720 test2721 test2722 test2723 test273 test274 test275 test276 test277 test278 test279 test28 test280 test281 test282 test283 test284 test285 test286 test287 test288 test289 test29 test290 test291 test292 test293 test294 test295 test296 test297 test298 test299 test3 test30 test300 test3000 test3001 test3002 test3003 test3004 test3005 test3006 test3007 test3008 test3009 test301 test3010 test3011 test3012 test3013 test3014 test3015 test3016 test3017 test3018 test3019 test302 test3020 test3021 test3022 test3023 test3024 test3025 test3026 test3027 test3028 test3029 test303 test3030 test3031 test3032 test3033 test3034 test3035 test3036 test304 test305 test306 test307 test308 test309 test31 test310 test3100 test3101 test3102 test3103 test3104 test3105 test3106 test311 test312 test313 test314 test315 test316 test317 test318 test319 test32 test320 test3200 test3201 test3202 test3203 test3204 test3205 test3206 test3207 test3208 test3209 test321 test3210 test3211 test3212 test3213 test3214 test3215 test3216 test3217 test3218 test3219 test322 test3220 test323 test324 test325 test326 test327 test328 test329 test33 test330 test3300 test3301 test3302 test331 test332 test333 test334 test335 test336 test337 test338 test339 test34 test340 test341 test342 test343 test344 test345 test346 test347 test348 test349 test35 test350 test351 test352 test353 test354 test355 test356 test357 test358 test359 test36 test360 test361 test362 test363 test364 test365 test366 test367 test368 test369 test37 test370 test371 test372 test373 test374 test375 test376 test378 test379 test38 test380 test381 test383 test384 test385 test386 test387 test388 test389 test39 test390 test391 test392 test393 test394 test395 test396 test397 test398 test399 test4 test40 test400 test4000 test4001 test401 test402 test403 test404 test405 test406 test407 test408 test409 test41 test410 test411 test412 test413 test414 test415 test416 test417 test418 test419 test42 test420 test421 test422 test423 test424 test425 test426 test427 test428 test429 test43 test430 test431 test432 test433 test434 test435 test436 test437 test438 test439 test44 test440 test441 test442 test443 test444 test445 test446 test447 test448 test449 test45 test450 test451 test452 test453 test454 test455 test456 test457 test458 test459 test46 test460 test461 test462 test463 test467 test468 test469 test47 test470 test471 test472 test473 test474 test475 test476 test477 test478 test479 test48 test480 test481 test482 test483 test484 test485 test486 test487 test488 test489 test49 test490 test491 test492 test493 test494 test495 test496 test497 test498 test499 test5 test50 test500 test501 test502 test503 test504 test505 test506 test507 test508 test509 test51 test510 test511 test512 test513 test514 test515 test516 test517 test518 test519 test52 test520 test521 test522 test523 test524 test525 test526 test527 test528 test529 test53 test530 test531 test532 test533 test534 test535 test536 test537 test538 test539 test54 test540 test541 test542 test543 test544 test545 test546 test547 test548 test549 test55 test550 test551 test552 test553 test554 test555 test556 test557 test558 test559 test56 test560 test561 test562 test563 test564 test565 test566 test567 test568 test569 test57 test570 test571 test572 test573 test574 test575 test576 test577 test578 test579 test58 test580 test581 test582 test583 test584 test585 test586 test587 test588 test589 test59 test590 test591 test592 test593 test594 test595 test596 test597 test598 test599 test6 test60 test600 test601 test602 test603 test604 test605 test606 test607 test608 test609 test61 test610 test611 test612 test613 test614 test615 test616 test617 test618 test619 test62 test620 test621 test622 test623 test624 test625 test626 test627 test628 test629 test63 test630 test631 test632 test633 test634 test635 test636 test637 test638 test639 test64 test640 test641 test642 test643 test644 test645 test646 test647 test648 test649 test65 test650 test651 test652 test653 test654 test655 test656 test658 test659 test66 test660 test661 test662 test663 test664 test665 test666 test667 test668 test669 test67 test670 test671 test672 test673 test674 test675 test676 test677 test678 test679 test68 test680 test681 test682 test683 test684 test685 test686 test687 test688 test689 test69 test690 test691 test692 test693 test694 test695 test696 test697 test698 test699 test7 test70 test700 test701 test702 test703 test704 test705 test706 test707 test708 test709 test71 test710 test711 test712 test713 test714 test715 test716 test717 test718 test719 test72 test720 test721 test722 test723 test724 test725 test726 test727 test728 test729 test73 test730 test731 test732 test733 test734 test735 test736 test737 test738 test739 test74 test740 test741 test742 test743 test744 test745 test746 test747 test748 test749 test75 test750 test751 test752 test753 test754 test755 test756 test757 test758 test759 test76 test760 test761 test762 test763 test764 test765 test766 test767 test768 test769 test77 test770 test771 test772 test773 test774 test775 test776 test777 test778 test779 test78 test780 test781 test782 test783 test784 test785 test786 test787 test788 test789 test79 test790 test791 test792 test793 test794 test795 test796 test797 test798 test799 test8 test80 test800 test801 test802 test803 test804 test805 test806 test807 test808 test809 test81 test810 test811 test812 test813 test814 test815 test816 test817 test818 test819 test82 test820 test821 test822 test823 test824 test825 test826 test827 test828 test829 test83 test830 test831 test832 test833 test834 test835 test836 test837 test838 test839 test84 test840 test841 test842 test843 test844 test845 test846 test847 test848 test849 test85 test850 test851 test852 test853 test854 test855 test856 test857 test858 test859 test86 test860 test861 test862 test863 test864 test865 test866 test867 test868 test869 test87 test870 test871 test872 test873 test874 test875 test876 test877 test878 test879 test88 test880 test881 test882 test883 test884 test885 test886 test887 test888 test889 test89 test890 test891 test892 test893 test894 test895 test896 test897 test898 test899 test9 test90 test900 test901 test902 test903 test904 test905 test906 test907 test908 test909 test91 test910 test911 test912 test913 test914 test915 test916 test917 test918 test919 test92 test920 test921 test922 test923 test924 test925 test926 test927 test928 test929 test93 test930 test931 test932 test933 test934 test935 test936 test937 test938 test939 test94 test940 test941 test942 test943 test944 test945 test946 test947 test948 test949 test95 test950 test951 test952 test953 test954 test955 test956 test957 test958 test959 test96 test960 test961 test962 test963 test964 test965 test966 test967 test968 test969 test97 test970 test971 test972 test973 test974 test975 test976 test977 test978 test979 test98 test980 test981 test982 test983 test984 test985 test986 test987 test988 test989 test99 test990 test991 test992 test993 test994 test995 test996 test997 test998 test999
http
testenv
mod_curltest .gitignore mod_curltest.c
__init__.py caddy.py certs.py client.py curl.py dante.py dnsd.py env.py httpd.py nghttpx.py ports.py sshd.py vsftpd.py ws_echo_server.py
.gitignore CMakeLists.txt Makefile.am config.ini.in conftest.py requirements.txt scorecard.py test_01_basic.py test_02_download.py test_03_goaway.py test_04_stuttered.py test_05_errors.py test_06_eyeballs.py test_07_upload.py test_08_caddy.py test_09_push.py test_10_proxy.py test_11_unix.py test_12_reuse.py test_13_proxy_auth.py test_14_auth.py test_15_tracing.py test_16_info.py test_17_ssl_use.py test_18_methods.py test_19_shutdown.py test_20_websockets.py test_21_resolve.py test_22_httpsrr.py test_30_vsftpd.py test_31_vsftpds.py test_32_ftps_vsftpd.py test_40_socks.py test_50_scp.py test_51_sftp.py
libtest .gitignore CMakeLists.txt Makefile.am Makefile.inc cli_ftp_upload.c cli_h2_pausing.c cli_h2_serverpush.c cli_h2_upgrade_extreme.c cli_hx_download.c cli_hx_upload.c cli_tls_session_reuse.c cli_upload_pausing.c cli_ws_data.c cli_ws_pingpong.c first.c first.h lib1156.c lib1301.c lib1308.c lib1485.c lib1500.c lib1501.c lib1502.c lib1506.c lib1507.c lib1508.c lib1509.c lib1510.c lib1511.c lib1512.c lib1513.c lib1514.c lib1515.c lib1517.c lib1518.c lib1520.c lib1522.c lib1523.c lib1525.c lib1526.c lib1527.c lib1528.c lib1529.c lib1530.c lib1531.c lib1532.c lib1533.c lib1534.c lib1535.c lib1536.c lib1537.c lib1538.c lib1540.c lib1541.c lib1542.c lib1545.c lib1549.c lib1550.c lib1551.c lib1552.c lib1553.c lib1554.c lib1555.c lib1556.c lib1557.c lib1558.c lib1559.c lib1560.c lib1564.c lib1565.c lib1567.c lib1568.c lib1569.c lib1571.c lib1576.c lib1582.c lib1587.c lib1588.c lib1589.c lib1591.c lib1592.c lib1593.c lib1594.c lib1597.c lib1598.c lib1599.c lib1662.c lib1900.c lib1901.c lib1902.c lib1903.c lib1905.c lib1906.c lib1907.c lib1908.c lib1910.c lib1911.c lib1912.c lib1913.c lib1915.c lib1916.c lib1918.c lib1919.c lib1920.c lib1921.c lib1933.c lib1934.c lib1935.c lib1936.c lib1937.c lib1938.c lib1939.c lib1940.c lib1945.c lib1947.c lib1948.c lib1955.c lib1956.c lib1957.c lib1958.c lib1959.c lib1960.c lib1964.c lib1965.c lib1970.c lib1971.c lib1972.c lib1973.c lib1974.c lib1975.c lib1977.c lib1978.c lib2023.c lib2032.c lib2082.c lib2301.c lib2302.c lib2304.c lib2306.c lib2308.c lib2309.c lib2402.c lib2404.c lib2405.c lib2502.c lib2504.c lib2505.c lib2506.c lib2700.c lib3010.c lib3025.c lib3026.c lib3027.c lib3033.c lib3034.c lib3100.c lib3101.c lib3102.c lib3103.c lib3104.c lib3105.c lib3207.c lib3208.c lib500.c lib501.c lib502.c lib503.c lib504.c lib505.c lib506.c lib507.c lib508.c lib509.c lib510.c lib511.c lib512.c lib513.c lib514.c lib515.c lib516.c lib517.c lib518.c lib519.c lib520.c lib521.c lib523.c lib524.c lib525.c lib526.c lib530.c lib533.c lib536.c lib537.c lib539.c lib540.c lib541.c lib542.c lib543.c lib544.c lib547.c lib549.c lib552.c lib553.c lib554.c lib555.c lib556.c lib557.c lib558.c lib559.c lib560.c lib562.c lib564.c lib566.c lib567.c lib568.c lib569.c lib570.c lib571.c lib572.c lib573.c lib574.c lib575.c lib576.c lib578.c lib579.c lib582.c lib583.c lib586.c lib589.c lib590.c lib591.c lib597.c lib598.c lib599.c lib643.c lib650.c lib651.c lib652.c lib653.c lib654.c lib655.c lib658.c lib659.c lib661.c lib666.c lib667.c lib668.c lib670.c lib674.c lib676.c lib677.c lib678.c lib694.c lib695.c lib751.c lib753.c lib757.c lib758.c lib766.c memptr.c mk-lib1521.pl test1013.pl test1022.pl test307.pl test610.pl test613.pl testtrace.c testtrace.h testutil.c testutil.h unitcheck.h
server .checksrc .gitignore CMakeLists.txt Makefile.am Makefile.inc dnsd.c first.c first.h getpart.c mqttd.c resolve.c rtspd.c sockfilt.c socksd.c sws.c tftpd.c util.c
tunit .gitignore CMakeLists.txt Makefile.am Makefile.inc README.md tool1394.c tool1604.c tool1621.c tool1622.c tool1623.c tool1720.c
unit .gitignore CMakeLists.txt Makefile.am Makefile.inc README.md unit1300.c unit1302.c unit1303.c unit1304.c unit1305.c unit1307.c unit1309.c unit1323.c unit1330.c unit1395.c unit1396.c unit1397.c unit1398.c unit1399.c unit1600.c unit1601.c unit1602.c unit1603.c unit1605.c unit1606.c unit1607.c unit1608.c unit1609.c unit1610.c unit1611.c unit1612.c unit1614.c unit1615.c unit1616.c unit1620.c unit1625.c unit1626.c unit1627.c unit1636.c unit1650.c unit1651.c unit1652.c unit1653.c unit1654.c unit1655.c unit1656.c unit1657.c unit1658.c unit1660.c unit1661.c unit1663.c unit1664.c unit1666.c unit1667.c unit1668.c unit1669.c unit1674.c unit1675.c unit1676.c unit1979.c unit1980.c unit2600.c unit2601.c unit2602.c unit2603.c unit2604.c unit2605.c unit3200.c unit3205.c unit3211.c unit3212.c unit3213.c unit3214.c unit3216.c unit3219.c unit3300.c unit3301.c unit3302.c
.gitignore CMakeLists.txt Makefile.am allversions.pm appveyor.pm azure.pm config.in configurehelp.pm.in devtest.pl dictserver.py directories.pm ech_combos.py ech_tests.sh ftpserver.pl getpart.pm globalconfig.pm http-server.pl http2-server.pl http3-server.pl memanalyze.pl memanalyzer.pm negtelnetserver.py nghttpx.conf pathhelp.pm processhelp.pm requirements.txt rtspserver.pl runner.pm runtests.pl secureserver.pl serverhelp.pm servers.pm smbserver.py sshhelp.pm sshserver.pl test1119.pl test1135.pl test1139.pl test1140.pl test1165.pl test1167.pl test1173.pl test1175.pl test1177.pl test1222.pl test1275.pl test1276.pl test1477.pl test1486.pl test1488.pl test1544.pl test1707.pl test745.pl test971.pl testcurl.pl testutil.pm tftpserver.pl util.py valgrind.pm valgrind.supp
.clang-tidy.yml .dir-locals.el .editorconfig .git-blame-ignore-revs .gitattributes .gitignore .mailmap CHANGES.md CMakeLists.txt COPYING Dockerfile GIT-INFO.md Makefile.am README README.md RELEASE-NOTES REUSE.toml SECURITY.md acinclude.m4 appveyor.sh appveyor.yml configure.ac curl-config.in libcurl.pc.in renovate.json
examples .env config.ini crypto_test.lua env_test.lua fs_example.lua http_server.lua https_test.lua ini_example.lua json.lua log.lua path_fs_example.lua process_example.lua request_download.lua request_test.lua run_all.lua sqlite_example.lua sqlite_http_template.lua stash_test.lua template_test.lua timer.lua websocket.lua
iniparser
.github
ISSUE_TEMPLATE config.yml
workflows disable-pull-requests.yml trigger-gitlab-ci.yml
cmake JoinPaths.cmake config.cmake.in pc.in
example iniexample.c iniwrite.c parse.c twisted-errors.ini twisted-genhuge.py twisted-ofkey.ini twisted-ofval.ini twisted.ini
src dictionary.c dictionary.h iniparser.c iniparser.h
test
ressources
bad_ini ends_well.ini twisted-errors.ini twisted-ofkey.ini twisted-ofval.ini
good_ini empty.ini spaced.ini spaced2.ini twisted.ini
gruezi.ini old.ini quotes.ini utf8.ini
CMakeLists.txt test_dictionary.c test_iniparser.c unity-config.yml unity_config.h
.cmake-format.py .gitignore .gitlab-ci.yml .gitmessage .travis.yml AUTHORS CMakeLists.txt FAQ-en.md FAQ-zhcn.md INSTALL LICENSE README.md compile_commands.json
jinjac
example CMakeLists.txt example.c
jinjac_test_app CMakeLists.txt jinjac_test_app.c
libjinjac
include jinjac.h
src CMakeLists.txt ast.c ast.h block_statement.c block_statement.h buffer.c buffer.h buildin.c buildin.h common.h convert.c convert.h flex_decl.h jfunction.c jfunction.h jinja_expression.l jinja_expression.y jinjac_parse.c jinjac_parse.h jinjac_stream.c jinjac_stream.h jlist.c jlist.h jobject.c jobject.h parameter.c parameter.h str_obj.c str_obj.h trace.c trace.h
CMakeLists.txt
test .gitignore CMakeLists.txt autotest.rb test_01.expected test_01.jinja test_01b.expected test_01b.jinja test_01c.expected test_01c.jinja test_01d.expected test_01d.jinja test_02.expected test_02.jinja test_03.expected test_03.jinja test_04.expected test_04.jinja test_05.expected test_05.jinja test_06.expected test_06.jinja test_07.expected test_07.jinja test_08.expected test_08.jinja test_08b.expected test_08b.jinja test_09.expected test_09.jinja test_10.expected test_10.jinja test_11.expected test_11.jinja test_12.expected test_12.jinja test_13.expected test_13.jinja test_14.expected test_14.jinja test_15.expected test_15.jinja test_16.expected test_16.jinja test_17.expected test_17.jinja test_18.expected test_18.jinja test_18b.expected test_18b.jinja test_18c.expected test_18c.jinja test_19.expected test_19.jinja test_19b.expected test_19b.jinja test_19c.expected test_19c.jinja test_19d.expected test_19d.jinja test_19e.expected test_19e.jinja test_19f.expected test_19f.jinja test_20.expected test_20.jinja test_21.expected test_21.jinja test_22.expected test_22.jinja test_22a.expected test_22a.jinja test_22b.expected test_22b.jinja test_23.expected test_23.jinja test_24.expected test_24.jinja
.gitignore CMakeLists.txt LICENSE.txt README.md build_coverage.sh build_debug.sh build_release.sh cppcheck_analysis.sh
libev Changes LICENSE Makefile Makefile.am Makefile.in README Symbols.ev Symbols.event aclocal.m4 autogen.sh compile config.guess config.h config.h.in config.status config.sub configure configure.ac depcomp ev++.h ev.3 ev.c ev.h ev.pod ev_epoll.c ev_kqueue.c ev_poll.c ev_port.c ev_select.c ev_vars.h ev_win32.c ev_wrap.h event.c event.h install-sh libev.m4 libtool ltmain.sh missing mkinstalldirs stamp-h1
luajit
doc
img contact.png
bluequad-print.css bluequad.css contact.html ext_buffer.html ext_c_api.html ext_ffi.html ext_ffi_api.html ext_ffi_semantics.html ext_ffi_tutorial.html ext_jit.html ext_profiler.html extensions.html install.html luajit.html running.html
dynasm dasm_arm.h dasm_arm.lua dasm_arm64.h dasm_arm64.lua dasm_mips.h dasm_mips.lua dasm_mips64.lua dasm_ppc.h dasm_ppc.lua dasm_proto.h dasm_x64.lua dasm_x86.h dasm_x86.lua dynasm.lua
etc luajit.1 luajit.pc
src
host .gitignore README buildvm.c buildvm.h buildvm_asm.c buildvm_fold.c buildvm_lib.c buildvm_libbc.h buildvm_peobj.c genlibbc.lua genminilua.lua genversion.lua minilua.c
jit .gitignore bc.lua bcsave.lua dis_arm.lua dis_arm64.lua dis_arm64be.lua dis_mips.lua dis_mips64.lua dis_mips64el.lua dis_mips64r6.lua dis_mips64r6el.lua dis_mipsel.lua dis_ppc.lua dis_x64.lua dis_x86.lua dump.lua p.lua v.lua zone.lua
.gitignore Makefile Makefile.dep lauxlib.h lib_aux.c lib_base.c lib_bit.c lib_buffer.c lib_debug.c lib_ffi.c lib_init.c lib_io.c lib_jit.c lib_math.c lib_os.c lib_package.c lib_string.c lib_table.c lj_alloc.c lj_alloc.h lj_api.c lj_arch.h lj_asm.c lj_asm.h lj_asm_arm.h lj_asm_arm64.h lj_asm_mips.h lj_asm_ppc.h lj_asm_x86.h lj_assert.c lj_bc.c lj_bc.h lj_bcdump.h lj_bcread.c lj_bcwrite.c lj_buf.c lj_buf.h lj_carith.c lj_carith.h lj_ccall.c lj_ccall.h lj_ccallback.c lj_ccallback.h lj_cconv.c lj_cconv.h lj_cdata.c lj_cdata.h lj_char.c lj_char.h lj_clib.c lj_clib.h lj_cparse.c lj_cparse.h lj_crecord.c lj_crecord.h lj_ctype.c lj_ctype.h lj_debug.c lj_debug.h lj_def.h lj_dispatch.c lj_dispatch.h lj_emit_arm.h lj_emit_arm64.h lj_emit_mips.h lj_emit_ppc.h lj_emit_x86.h lj_err.c lj_err.h lj_errmsg.h lj_ff.h lj_ffrecord.c lj_ffrecord.h lj_frame.h lj_func.c lj_func.h lj_gc.c lj_gc.h lj_gdbjit.c lj_gdbjit.h lj_ir.c lj_ir.h lj_ircall.h lj_iropt.h lj_jit.h lj_lex.c lj_lex.h lj_lib.c lj_lib.h lj_load.c lj_mcode.c lj_mcode.h lj_meta.c lj_meta.h lj_obj.c lj_obj.h lj_opt_dce.c lj_opt_fold.c lj_opt_loop.c lj_opt_mem.c lj_opt_narrow.c lj_opt_sink.c lj_opt_split.c lj_parse.c lj_parse.h lj_prng.c lj_prng.h lj_profile.c lj_profile.h lj_record.c lj_record.h lj_serialize.c lj_serialize.h lj_snap.c lj_snap.h lj_state.c lj_state.h lj_str.c lj_str.h lj_strfmt.c lj_strfmt.h lj_strfmt_num.c lj_strscan.c lj_strscan.h lj_tab.c lj_tab.h lj_target.h lj_target_arm.h lj_target_arm64.h lj_target_mips.h lj_target_ppc.h lj_target_x86.h lj_trace.c lj_trace.h lj_traceerr.h lj_udata.c lj_udata.h lj_vm.h lj_vmevent.c lj_vmevent.h lj_vmmath.c ljamalg.c lua.h lua.hpp luaconf.h luajit.c luajit_rolling.h lualib.h msvcbuild.bat nxbuild.bat ps4build.bat ps5build.bat psvitabuild.bat vm_arm.dasc vm_arm64.dasc vm_mips.dasc vm_mips64.dasc vm_ppc.dasc vm_x64.dasc vm_x86.dasc xb1build.bat xedkbuild.bat
.gitattributes .gitignore .relver COPYRIGHT Makefile README
sqlite shell.c sqlite3.c sqlite3.h sqlite3ext.h
wolfssl
.github
ISSUE_TEMPLATE bug_report.yaml other.yaml
actions
install-apt-deps action.yml
scripts
zephyr-4.x external_libc.conf zephyr-test.sh
openssl-ech.sh tls-anvil-test.sh
workflows
disabled haproxy.yml hitch.yml hostap.yml
hostap-files
configs
07c9f183ea744ac04585fb6dd10220c75a5e2e74 hostapd.config tests wpa_supplicant.config
b607d2723e927a3446d89aed813f1aa6068186bb hostapd.config tests wpa_supplicant.config
hostap_2_10 extra.patch hostapd.config tests wpa_supplicant.config
Makefile README dbus-wpa_supplicant.conf
ada.yml arduino.yml async-examples.yml async.yml atecc608-sim.yml bind.yml cmake-autoconf.yml cmake.yml codespell.yml coverity-scan-fixes.yml cryptocb-only.yml curl.yml cyrus-sasl.yml disable-pk-algs.yml docker-Espressif.yml docker-OpenWrt.yml emnet-nonblock.yml fil-c.yml freertos-mem-track.yml gencertbuf.yml grpc.yml haproxy.yml hostap-vm.yml intelasm-c-fallback.yml ipmitool.yml jwt-cpp.yml krb5.yml libspdm.yml libssh2.yml libvncserver.yml linuxkm.yml macos-apple-native-cert-validation.yml mbedtls.sh mbedtls.yml membrowse-comment.yml membrowse-onboard.yml membrowse-report.yml memcached.sh memcached.yml mono.yml mosquitto.yml msmtp.yml msys2.yml multi-arch.yml multi-compiler.yml net-snmp.yml nginx.yml no-malloc.yml no-tls.yml nss.sh nss.yml ntp.yml ocsp.yml openldap.yml openssh.yml openssl-ech.yml opensslcoexist.yml openvpn.yml os-check.yml packaging.yml pam-ipmi.yml pq-all.yml pr-commit-check.yml psk.yml puf.yml python.yml rng-tools.yml rust-wrapper.yml se050-sim.yml smallStackSize.yml socat.yml softhsm.yml sssd.yml stm32-sim.yml stsafe-a120-sim.yml stunnel.yml symbol-prefixes.yml threadx.yml tls-anvil.yml trackmemory.yml watcomc.yml win-csharp-test.yml wolfCrypt-Wconversion.yml wolfboot-integration.yml wolfsm.yml xcode.yml zephyr-4.x.yml zephyr.yml
PULL_REQUEST_TEMPLATE.md SECURITY.md membrowse-targets.json
Docker
OpenWrt Dockerfile README.md runTests.sh
packaging
debian Dockerfile
fedora Dockerfile
wolfCLU Dockerfile README.md
yocto Dockerfile buildAndPush.sh
Dockerfile Dockerfile.cross-compiler README.md buildAndPush.sh include.am run.sh
IDE
ARDUINO
sketches
wolfssl_client README.md
wolfssl_server README.md
wolfssl_version README.md
README.md
Arduino_README_prepend.md README.md include.am keywords.txt library.properties.template wolfssl-arduino.cpp wolfssl-arduino.sh wolfssl.h
AURIX Cpu0_Main.c README.md include.am user_settings.h wolf_main.c
Android Android.bp README.md include.am user_settings.h
CRYPTOCELL README.md include.am main.c user_settings.h
CSBENCH include.am user_settings.h
ECLIPSE
DEOS
deos_wolfssl .options
README.md deos_malloc.c include.am tls_wolfssl.c tls_wolfssl.h user_settings.h
MICRIUM README.md client_wolfssl.c client_wolfssl.h include.am server_wolfssl.c server_wolfssl.h user_settings.h wolfsslRunTests.c
RTTHREAD README.md include.am user_settings.h wolfssl_test.c
SIFIVE README.md include.am
Espressif
ESP-IDF
examples
template
VisualGDB wolfssl_template_IDF_v5.1_ESP32.vgdbproj
components
wolfssl
include user_settings.h
CMakeLists.txt Kconfig README.md component.mk
main
include main.h
CMakeLists.txt Kconfig.projbuild component.mk main.c
CMakeLists.txt Makefile README.md partitions_singleapp_large.csv sdkconfig.defaults sdkconfig.defaults.esp8266
wolfssl_benchmark
VisualGDB wolfssl_benchmark_IDF_v4.4_ESP32.sln wolfssl_benchmark_IDF_v4.4_ESP32.vgdbproj wolfssl_benchmark_IDF_v5_ESP32.sln wolfssl_benchmark_IDF_v5_ESP32.vgdbproj wolfssl_benchmark_IDF_v5_ESP32C3.sln wolfssl_benchmark_IDF_v5_ESP32C3.vgdbproj wolfssl_benchmark_IDF_v5_ESP32S3.sln wolfssl_benchmark_IDF_v5_ESP32S3.vgdbproj
components
wolfssl
include user_settings.h
CMakeLists.txt Kconfig README.md component.mk
main
include main.h
CMakeLists.txt Kconfig.projbuild component.mk main.c
CMakeLists.txt Makefile README.md partitions_singleapp_large.csv sdkconfig.defaults sdkconfig.defaults.esp8266
wolfssl_client
VisualGDB README.md wolfssl_client_IDF_v5_ESP32.sln wolfssl_client_IDF_v5_ESP32.vgdbproj
components
wolfssl
include user_settings.h
CMakeLists.txt Kconfig README.md component.mk
main
include client-tls.h main.h time_helper.h wifi_connect.h
CMakeLists.txt Kconfig.projbuild client-tls.c component.mk main.c time_helper.c wifi_connect.c
CMakeLists.txt Makefile README.md README_server_sm.md partitions_singleapp_large.csv sdkconfig.defaults sdkconfig.defaults.esp32c2 sdkconfig.defaults.esp8266 wolfssl_client_ESP8266.vgdbproj
wolfssl_server
VisualGDB README.md wolfssl_server_IDF_v5_ESP32.sln wolfssl_server_IDF_v5_ESP32.vgdbproj
components
wolfssl
include user_settings.h
CMakeLists.txt Kconfig README.md component.mk
main
include main.h server-tls.h time_helper.h wifi_connect.h
CMakeLists.txt Kconfig.projbuild component.mk main.c server-tls.c time_helper.c wifi_connect.c
CMakeLists.txt Makefile README.md README_server_sm.md partitions_singleapp_large.csv sdkconfig.defaults sdkconfig.defaults.esp32c2 sdkconfig.defaults.esp8266 wolfssl_server_ESP8266.vgdbproj
wolfssl_test
VisualGDB wolfssl_test-IDF_v5_ESP32.sln wolfssl_test-IDF_v5_ESP32.vgdbproj wolfssl_test-IDF_v5_ESP32C3.sln wolfssl_test-IDF_v5_ESP32C3.vgdbproj wolfssl_test-IDF_v5_ESP32C6.sln wolfssl_test-IDF_v5_ESP32C6.vgdbproj wolfssl_test_IDF_v5_ESP32S3.sln wolfssl_test_IDF_v5_ESP32S3.vgdbproj
components
wolfssl
include user_settings.h
CMakeLists.txt Kconfig README.md component.mk
main
include main.h
CMakeLists.txt Kconfig.projbuild component.mk main.c
CMakeLists.txt Makefile README.md partitions_singleapp_large.csv sdkconfig.defaults sdkconfig.defaults.esp32 sdkconfig.defaults.esp32c3 sdkconfig.defaults.esp32c6 sdkconfig.defaults.esp32h2 sdkconfig.defaults.esp32s2 sdkconfig.defaults.esp32s3 sdkconfig.defaults.esp8266 testAll.sh testMonitor.sh wolfssl_test_ESP8266.sln wolfssl_test_ESP8266.vgdbproj
wolfssl_test_idf
VisualGDB VisualGDB_wolfssl_test_idf.sln VisualGDB_wolfssl_test_idf.vgdbproj
main CMakeLists.txt Kconfig.projbuild component.mk main.c main_wip.c.ex time_helper.c time_helper.h
CMakeLists.txt Kconfig.projbuild README.md component.mk sdkconfig.defaults
README.md
libs CMakeLists.txt README.md component.mk tigard.cfg
test CMakeLists.txt README.md component.mk test_wolfssl.c
README.md README_32se.md UPDATE.md compileAllExamples.sh dummy_config_h dummy_test_paths.h setup.sh setup_win.bat user_settings.h
README.md include.am
GCC-ARM
Header user_settings.h
Source armtarget.c benchmark_main.c test_main.c tls_client.c tls_server.c wolf_main.c
Makefile Makefile.bench Makefile.client Makefile.common Makefile.server Makefile.static Makefile.test README.md include.am linker.ld linker_fips.ld
Gaisler-BCC README.md include.am
HEXAGON
DSP Makefile wolfssl_dsp.idl
Makefile README.md build.sh ecc-verify-benchmark.c ecc-verify.c include.am user_settings.h
HEXIWEAR
wolfSSL_HW .cwGeneratedFileSetLog user_settings.h
IAR-EWARM
Projects
benchmark benchmark-main.c current_time.c wolfCrypt-benchmark.ewd wolfCrypt-benchmark.ewp
common minimum-startup.c wolfssl.icf
lib wolfSSL-Lib.ewd wolfSSL-Lib.ewp
test test-main.c wolfCrypt-test.ewd wolfCrypt-test.ewp
user_settings.h wolfssl.eww
embOS
SAMV71_XULT
embOS_SAMV71_XULT_Linker_Script samv71q21_wolfssl.icf
embOS_SAMV71_XULT_user_settings user_settings.h user_settings_simple_example.h user_settings_verbose_example.h
embOS_wolfcrypt_benchmark_SAMV71_XULT
Application runBenchmarks.c
README_wolfcrypt_benchmark wolfcrypt_benchmark.ewd wolfcrypt_benchmark.ewp
embOS_wolfcrypt_lib_SAMV71_XULT README_wolfcrypt_lib wolfcrypt_lib.ewd wolfcrypt_lib.ewp
embOS_wolfcrypt_test_SAMV71_XULT
Application runWolfcryptTests.c
README_wolfcrypt_test wolfcrypt_test.ewd wolfcrypt_test.ewp
README_SAMV71
custom_port
custom_port_Linker_Script samv71q21_wolfssl.icf
custom_port_user_settings user_settings.h
wolfcrypt_benchmark_custom_port
Application runBenchmarks.c
wolfcrypt_test_custom_port
Application runWolfcryptTests.c
README_custom_port
extract_trial_here README_extract_trial_here
README
.gitignore README
IAR-MSP430 Makefile README.md include.am main.c user_settings.h
INTIME-RTOS Makefile README.md include.am libwolfssl.c libwolfssl.vcxproj user_settings.h wolfExamples.c wolfExamples.h wolfExamples.sln wolfExamples.vcxproj wolfssl-lib.sln wolfssl-lib.vcxproj
Infineon README.md include.am user_settings.h
KDS
config user_settings.h
include.am
LINUX-SGX README.md build.sh clean.sh include.am sgx_t_static.mk
LPCXPRESSO
lib_wolfssl lpc_18xx_port.c user_settings.h
wolf_example
src lpc_18xx_startup.c wolfssl_example.c
readme.txt
README.md
M68K
benchmark Makefile main.cpp
testwolfcrypt Makefile main.cpp
Makefile README.md include.am user_settings.h
MCUEXPRESSO
RT1170 fsl_caam_c.patch fsl_caam_h.patch user_settings.h
benchmark
source run_benchmark.c
wolfssl liblinks.xml
README.md include.am user_settings.h wolfcrypt_test.c
MDK-ARM
LPC43xx time-LCP43xx.c
MDK-ARM
wolfSSL Retarget.c cert_data.c cert_data.h config-BARE-METAL.h config-FS.h config-RTX-TCP-FS.h config-WOLFLIB.h main.c shell.c time-CortexM3-4.c time-dummy.c wolfssl_MDK_ARM.c wolfssl_MDK_ARM.h
STM32F2xx_StdPeriph_Lib time-STM32F2xx.c
MDK5-ARM
Conf user_settings.h
Inc wolfssl_MDK_ARM.h
Projects
CryptBenchmark Abstract.txt CryptBenchmark.sct CryptBenchmark.uvoptx CryptBenchmark.uvprojx main.c
CryptTest Abstract.txt CryptTest.sct CryptTest.uvoptx CryptTest.uvprojx main.c
EchoClient Abstract.txt EchoClient.uvoptx EchoClient.uvprojx main.c wolfssl-link.sct
EchoServer Abstract.txt EchoServer.uvoptx EchoServer.uvprojx main.c wolfssl-link.sct
SimpleClient Abstract.txt SimpleClient.uvoptx SimpleClient.uvprojx main.c wolfssl-link.sct
SimpleServer Abstract.txt SimpleServer.uvoptx SimpleServer.uvprojx main.c wolfssl-link.sct
wolfSSL-Full Abstract.txt main.c shell.c time-CortexM3-4.c wolfsslFull.uvoptx wolfsslFull.uvprojx
wolfSSL-Lib Abstract.txt wolfSSL-Lib.uvoptx wolfSSL-Lib.uvprojx
Src ssl-dummy.c
README.md include.am
MPLABX16
wolfcrypt_test.X
nbproject
private configurations.xml private.xml
configurations.xml include.am project.xml
Makefile
wolfssl.X
nbproject configurations.xml include.am project.xml
Makefile
README.md include.am main.c user_settings.h
MQX Makefile README-jp.md README.md client-tls.c include.am server-tls.c user_config.h user_settings.h
MSVS-2019-AZSPHERE
client client.c client.h
server server.c server.h
shared util.h
wolfssl_new_azsphere
HardwareDefinitions
avnet_mt3620_sk
inc
hw template_appliance.h
template_appliance.json
mt3620_rdb
inc
hw template_appliance.h
template_appliance.json
seeed_mt3620_mdb
inc
hw template_appliance.h
template_appliance.json
.gitignore CMakeLists.txt CMakeSettings.json app_manifest.json applibs_versions.h launch.vs.json main.c
README.md include.am user_settings.h
MYSQL CMakeLists_wolfCrypt.txt CMakeLists_wolfSSL.txt do.sh
NDS README.md
NETOS Makefile.wolfcrypt.inc README.md include.am user_settings.h user_settings.h-cert2425 user_settings.h-cert3389 wolfssl_netos_custom.c
OPENSTM32 README.md
PlatformIO
examples
wolfssl_benchmark
include README main.h
lib README
src CMakeLists.txt main.c
test README
CMakeLists.txt README.md platformio.ini sdkconfig.defaults wolfssl_benchmark.code-workspace
wolfssl_test
include README main.h
lib README
src CMakeLists.txt main.c
test README
CMakeLists.txt README.md platformio.ini sdkconfig.defaults wolfssl_test.code-workspace
README.md wolfssl_platformio.code-workspace
README.md include.am
QNX
CAAM-DRIVER Makefile
example-client Makefile client-tls.c
example-cmac Makefile cmac-test.c
example-server Makefile server-tls.c
testwolfcrypt Makefile
wolfssl Makefile user_settings.h
README.md include.am
RISCV
SIFIVE-HIFIVE1 Makefile README.md include.am main.c user_settings.h
SIFIVE-UNLEASHED README.md include.am
include.am
ROWLEY-CROSSWORKS-ARM Kinetis_FlashPlacement.xml README.md arm_startup.c benchmark_main.c hw.h include.am kinetis_hw.c retarget.c test_main.c user_settings.h wolfssl.hzp wolfssl_ltc.hzp
Renesas
cs+
Projects
common strings.h unistd.h user_settings.h wolfssl_dummy.c
t4_demo README_en.txt README_jp.txt t4_demo.mtpj wolf_client.c wolf_demo.h wolf_main.c wolf_server.c
test test.mtpj test_main.c
wolfssl_lib wolfssl_lib.mtpj
README include.am
e2studio
DK-S7G2
benchmark-template
src app_entry.c
example_server-template
src app_entry.c
wolfcrypttest-template
src app_entry.c
wolfssl-template-project configuration.xml
README.md include.am user_settings.h
Projects
common strings.h unistd.h user_settings.h wolfssl_dummy.c
test
src key_data.c key_data.h test_main.c wolf_client.c wolf_server.c wolfssl_demo.h
tools generate_rsa_keypair.sh genhexbuf.pl rsa_pss_sign.sh
wolfssl
src .gitkeep
wolfcrypt
src .gitkeep
README include.am
RA6M3
benchmark-wolfcrypt
common .gitkeep
script .gitkeep
src wolfssl_thread_entry.c
client-wolfssl
common
src .gitkeep
script .gitkeep
src wolfssl_thread_entry.c
wolfssl_thread_entry.h
common
ra6m3g README.md
src freertos_tcp_port.c
user_settings.h util.h
server-wolfssl
common
src .gitkeep
script .gitkeep
src wolfssl_thread_entry.c
wolfssl_thread_entry.h
test-wolfcrypt
common .gitkeep
script .gitkeep
src wolfssl_thread_entry.c
wolfssl
src .gitkeep
wolfcrypt .gitkeep
README.md README_APRA6M_en.md README_APRA6M_jp.md include.am
RA6M3G README.md
RA6M4
common user_settings.h wolfssl_demo.h
test
key_data key_data.h key_data_sce.c
src
SEGGER_RTT myprint.c
common .gitignore
test_main.c wolf_client.c wolfssl_sce_unit_test.c
test_RA6M4Debug.launch
tools
example_keys generate_SignedCA.sh rsa_private.pem rsa_public.pem
README.md
README.md include.am
RX65N
GR-ROSE
common strings.h unistd.h user_settings.h wolfssl_dummy.c
smc smc.scfg
test
src key_data.c key_data.h test_main.c wolf_client.c wolf_server.c wolfssl_demo.h
test.rcpc test_HardwareDebug.launch
tools
example_keys generate_SignedCA.sh rsa_private.pem rsa_public.pem
README.md
wolfssl wolfssl.rcpc
README_EN.md README_JP.md include.am
RSK
resource section.esi
wolfssl wolfssl.rcpc
wolfssl_demo key_data.c key_data.h user_settings.h wolfssl_demo.c wolfssl_demo.h
InstructionManualForExample_RSK+RX65N-2MB_EN.pdf InstructionManualForExample_RSK+RX65N-2MB_JP.pdf README_EN.md README_JP.md include.am
RX72N
EnvisionKit
Simple
common sectioninfo.esi wolfssl_dummy.c
test
src
client simple_tcp_client.c simple_tls_tsip_client.c
server simple_tcp_server.c simple_tls_server.c
test_main.c wolfssl_simple_demo.h
test.rcpc test.scfg test_HardwareDebug.launch
wolfssl wolfssl.rcpc
README_EN.md README_JP.md
resource section.esi
tools
example_keys generate_SignedCA.sh rsa_private.pem rsa_public.pem
README.md
wolfssl wolfssl.rcpc
wolfssl_demo key_data.c key_data.h user_settings.h wolfssl_demo.c wolfssl_demo.h wolfssl_tsip_unit_test.c
InstructionManualForExample_RX72N_EnvisonKit_EN.pdf InstructionManualForExample_RX72N_EnvisonKit_JP.pdf README_EN.md README_JP.md include.am
RZN2L
common user_settings.h wolfssl_demo.h
test
src
serial_io app_print.c
test wolf_client.c wolf_server.c wolfssl_rsip_unit_test.c
wolfCrypt .gitignore
wolfSSL .gitignore
local_system_init.c rzn2l_tst_thread_entry.c wolfssl_dummy.c
README.md include.am
SK-S7G2
common user_settings.h
wolfssl_lib configuration.xml
.gitignore README.md include.am
STARCORE README.txt include.am starcore_test.c user_settings.h
STM32Cube README.md STM32_Benchmarks.md default_conf.ftl include.am main.c wolfssl_example.c wolfssl_example.h
SimplicityStudio README.md include.am test_wolf.c user_settings.h
TRUESTUDIO
wolfssl user_settings.h
README include.am
VS-ARM README.md include.am user_settings.h wolfssl.sln wolfssl.vcxproj
VS-AZURE-SPHERE
client app_manifest.json client.c client.h client.vcxproj
server app_manifest.json server.c server.h server.vcxproj
shared util.h
wolfcrypt_test app_manifest.json wolfcrypt_test.vcxproj
README.md include.am user_settings.h wolfssl.sln wolfssl.vcxproj
VisualDSP include.am user_settings.h wolf_tasks.c
WICED-STUDIO README include.am user_settings.h
WIN README.txt include.am test.vcxproj user_settings.h user_settings_dtls.h wolfssl-fips.sln wolfssl-fips.vcxproj
WIN-SGX ReadMe.txt include.am wolfSSL_SGX.edl wolfSSL_SGX.sln wolfSSL_SGX.vcxproj
WIN-SRTP-KDF-140-3 README.txt include.am resource.h test.vcxproj user_settings.h wolfssl-fips.rc wolfssl-fips.sln wolfssl-fips.vcxproj
WIN10 README.txt include.am resource.h test.vcxproj user_settings.h wolfssl-fips.rc wolfssl-fips.sln wolfssl-fips.vcxproj
WINCE README.md include.am user_settings.h user_settings.h.140-2-deprecated
WORKBENCH README.md include.am
XCODE
Benchmark
wolfBench
Assets.xcassets
AppIcon.appiconset Contents.json
Base.lproj LaunchScreen.storyboard Main.storyboard
AppDelegate.h AppDelegate.m Info.plist ViewController.h ViewController.m main.m
wolfBench.xcodeproj project.pbxproj
include.am
wolfssl-FIPS.xcodeproj project.pbxproj
wolfssl.xcodeproj project.pbxproj
wolfssl_testsuite.xcodeproj project.pbxproj
README.md build-for-i386.sh include.am user_settings.h
XCODE-FIPSv2
macOS-C++
Intel user_settings.h
M1 user_settings.h
include.am user_settings.h
XCODE-FIPSv5 README include.am user_settings.h
XCODE-FIPSv6 README include.am user_settings.h
XilinxSDK
2018_2 lscript.ld
2019_2
wolfCrypt_example
src lscript.ld
wolfCrypt_example_system wolfCrypt_example_system.sprj
2022_1
wolfCrypt_FreeRTOS_example wolfCrypt_FreeRTOS_example.prj
wolfCrypt_FreeRTOS_example_system wolfCrypt_FreeRTOS_example_system.sprj
wolfCrypt_example wolfCrypt_example.prj
wolfCrypt_example_system wolfCrypt_example_system.sprj
.gitignore
README.md bench.sh combine.sh eclipse_formatter_profile.xml graph.sh include.am user_settings.h wolfssl_example.c
apple-universal
wolfssl-multiplatform
wolfssl-multiplatform
Assets.xcassets
AccentColor.colorset Contents.json
AppIcon.appiconset Contents.json
Contents.json
ContentView.swift simple_client_example.c simple_client_example.h wolfssl-multiplatform-Bridging-Header.h wolfssl_multiplatform.entitlements wolfssl_multiplatformApp.swift wolfssl_test_driver.c wolfssl_test_driver.h
wolfssl-multiplatform.xcodeproj project.pbxproj
.gitignore README.md build-wolfssl-framework.sh include.am
iotsafe Makefile README.md ca-cert.c devices.c devices.h include.am main.c memory-tls.c startup.c target.ld user_settings.h
iotsafe-raspberrypi Makefile README.md client-tls13.c include.am main.c
mynewt README.md apps.wolfcrypttest.pkg.yml crypto.wolfssl.pkg.yml crypto.wolfssl.syscfg.yml include.am setup.sh
zephyr README.md include.am
include.am
RTOS
nuttx
wolfssl .gitignore Kconfig Make.defs Makefile README.md setup-wolfssl.sh user_settings.h
include.am
bsdkm Makefile README.md bsdkm_wc_port.h include.am wolfkmod.c wolfkmod_aes.c x86_vecreg.c
certs
1024 ca-cert.der ca-cert.pem ca-key.der ca-key.pem client-cert.der client-cert.pem client-key.der client-key.pem client-keyPub.der dh1024.der dh1024.pem dsa-pub-1024.pem dsa1024.der dsa1024.pem include.am rsa1024.der server-cert.der server-cert.pem server-key.der server-key.pem
3072 client-cert.der client-cert.pem client-key.der client-key.pem client-keyPub.der include.am
4096 client-cert.der client-cert.pem client-key.der client-key.pem client-keyPub.der include.am
acert
rsa_pss acert.pem acert_ietf.pem acert_ietf_pubkey.pem acert_pubkey.pem
acert.pem acert_ietf.pem acert_ietf_pubkey.pem acert_pubkey.pem include.am
aia ca-issuers-cert.pem multi-aia-cert.pem overflow-aia-cert.pem
crl
extra-crls ca-int-cert-revoked.pem claim-root.pem crl_critical_entry.pem crlnum_57oct.pem crlnum_64oct.pem general-server-crl.pem large_crlnum.pem large_crlnum2.pem
hash_der 0fdb2da4.r0
hash_pem 0fdb2da4.r0
bad_time_fmt.pem ca-int-ecc.pem ca-int.pem ca-int2-ecc.pem ca-int2.pem caEcc384Crl.pem caEccCrl.der caEccCrl.pem cliCrl.pem client-int-ecc.pem client-int.pem crl.der crl.pem crl.revoked crl2.der crl2.pem crl_reason.pem crl_rsapss.pem eccCliCRL.pem eccSrvCRL.pem gencrls.sh include.am server-goodaltCrl.pem server-goodaltwildCrl.pem server-goodcnCrl.pem server-goodcnwildCrl.pem server-int-ecc.pem server-int.pem wolfssl.cnf
dilithium bench_dilithium_level2_key.der bench_dilithium_level3_key.der bench_dilithium_level5_key.der include.am
ecc bp256r1-key.der bp256r1-key.pem ca-secp256k1-cert.pem ca-secp256k1-key.pem client-bp256r1-cert.der client-bp256r1-cert.pem client-secp256k1-cert.der client-secp256k1-cert.pem genecc.sh include.am secp256k1-key.der secp256k1-key.pem secp256k1-param.pem secp256k1-privkey.der secp256k1-privkey.pem server-bp256r1-cert.der server-bp256r1-cert.pem server-secp256k1-cert.der server-secp256k1-cert.pem server2-secp256k1-cert.der server2-secp256k1-cert.pem wolfssl.cnf wolfssl_384.cnf
ed25519 ca-ed25519-key.der ca-ed25519-key.pem ca-ed25519-priv.der ca-ed25519-priv.pem ca-ed25519.der ca-ed25519.pem client-ed25519-key.der client-ed25519-key.pem client-ed25519-priv.der client-ed25519-priv.pem client-ed25519.der client-ed25519.pem eddsa-ed25519.der eddsa-ed25519.pem gen-ed25519-certs.sh gen-ed25519-keys.sh gen-ed25519.sh include.am root-ed25519-key.der root-ed25519-key.pem root-ed25519-priv.der root-ed25519-priv.pem root-ed25519.der root-ed25519.pem server-ed25519-cert.pem server-ed25519-key.der server-ed25519-key.pem server-ed25519-priv.der server-ed25519-priv.pem server-ed25519.der server-ed25519.pem
ed448 ca-ed448-key.der ca-ed448-key.pem ca-ed448-priv.der ca-ed448-priv.pem ca-ed448.der ca-ed448.pem client-ed448-key.der client-ed448-key.pem client-ed448-priv.der client-ed448-priv.pem client-ed448.der client-ed448.pem gen-ed448-certs.sh gen-ed448-keys.sh include.am root-ed448-key.der root-ed448-key.pem root-ed448-priv.der root-ed448-priv.pem root-ed448.der root-ed448.pem server-ed448-cert.pem server-ed448-key.der server-ed448-key.pem server-ed448-priv.der server-ed448-priv.pem server-ed448.der server-ed448.pem
external DigiCertGlobalRootCA.pem README.txt ca-digicert-ev.pem ca-globalsign-root.pem ca-google-root.pem ca_collection.pem include.am
falcon bench_falcon_level1_key.der bench_falcon_level5_key.der include.am
intermediate
ca_false_intermediate gentestcert.sh int_ca.key server.key test_ca.key test_ca.pem test_int_not_cacert.pem test_sign_bynoca_srv.pem wolfssl_base.conf wolfssl_srv.conf
ca-ecc-bad-aki.der ca-ecc-bad-aki.pem ca-int-cert.der ca-int-cert.pem ca-int-ecc-cert.der ca-int-ecc-cert.pem ca-int-ecc-key.der ca-int-ecc-key.pem ca-int-key.der ca-int-key.pem ca-int2-cert.der ca-int2-cert.pem ca-int2-ecc-cert.der ca-int2-ecc-cert.pem ca-int2-ecc-key.der ca-int2-ecc-key.pem ca-int2-key.der ca-int2-key.pem client-chain-alt-ecc.pem client-chain-alt.pem client-chain-ecc.der client-chain-ecc.pem client-chain.der client-chain.pem client-int-cert.der client-int-cert.pem client-int-ecc-cert.der client-int-ecc-cert.pem genintcerts.sh include.am server-chain-alt-ecc.pem server-chain-alt.pem server-chain-ecc.der server-chain-ecc.pem server-chain-short.pem server-chain.der server-chain.pem server-int-cert.der server-int-cert.pem server-int-ecc-cert.der server-int-ecc-cert.pem
lms bc_hss_L2_H5_W8_root.der bc_hss_L3_H5_W4_root.der bc_lms_chain_ca.der bc_lms_chain_leaf.der bc_lms_native_bc_root.der bc_lms_sha256_h10_w8_root.der bc_lms_sha256_h5_w4_root.der include.am
mldsa README.txt include.am mldsa44-cert.der mldsa44-cert.pem mldsa44-key.pem mldsa44_bare-priv.der mldsa44_bare-seed.der mldsa44_oqskeypair.der mldsa44_priv-only.der mldsa44_pub-spki.der mldsa44_seed-only.der mldsa44_seed-priv.der mldsa65-cert.der mldsa65-cert.pem mldsa65-key.pem mldsa65_bare-priv.der mldsa65_bare-seed.der mldsa65_oqskeypair.der mldsa65_priv-only.der mldsa65_pub-spki.der mldsa65_seed-only.der mldsa65_seed-priv.der mldsa87-cert.der mldsa87-cert.pem mldsa87-key.pem mldsa87_bare-priv.der mldsa87_bare-seed.der mldsa87_oqskeypair.der mldsa87_priv-only.der mldsa87_pub-spki.der mldsa87_seed-only.der mldsa87_seed-priv.der
ocsp imposter-root-ca-cert.der imposter-root-ca-cert.pem imposter-root-ca-key.der imposter-root-ca-key.pem include.am index-ca-and-intermediate-cas.txt index-ca-and-intermediate-cas.txt.attr index-intermediate1-ca-issued-certs.txt index-intermediate1-ca-issued-certs.txt.attr index-intermediate2-ca-issued-certs.txt index-intermediate2-ca-issued-certs.txt.attr index-intermediate3-ca-issued-certs.txt index-intermediate3-ca-issued-certs.txt.attr intermediate1-ca-cert.der intermediate1-ca-cert.pem intermediate1-ca-key.der intermediate1-ca-key.pem intermediate2-ca-cert.der intermediate2-ca-cert.pem intermediate2-ca-key.der intermediate2-ca-key.pem intermediate3-ca-cert.der intermediate3-ca-cert.pem intermediate3-ca-key.der intermediate3-ca-key.pem ocsp-responder-cert.der ocsp-responder-cert.pem ocsp-responder-key.der ocsp-responder-key.pem openssl.cnf renewcerts-for-test.sh renewcerts.sh root-ca-cert.der root-ca-cert.pem root-ca-crl.pem root-ca-key.der root-ca-key.pem server1-cert.der server1-cert.pem server1-chain-noroot.pem server1-key.der server1-key.pem server2-cert.der server2-cert.pem server2-key.der server2-key.pem server3-cert.der server3-cert.pem server3-key.der server3-key.pem server4-cert.der server4-cert.pem server4-key.der server4-key.pem server5-cert.der server5-cert.pem server5-key.der server5-key.pem test-leaf-response.der test-multi-response.der test-response-nointern.der test-response-rsapss.der test-response.der
p521 ca-p521-key.der ca-p521-key.pem ca-p521-priv.der ca-p521-priv.pem ca-p521.der ca-p521.pem client-p521-key.der client-p521-key.pem client-p521-priv.der client-p521-priv.pem client-p521.der client-p521.pem gen-p521-certs.sh gen-p521-keys.sh include.am root-p521-key.der root-p521-key.pem root-p521-priv.der root-p521-priv.pem root-p521.der root-p521.pem server-p521-cert.pem server-p521-key.der server-p521-key.pem server-p521-priv.der server-p521-priv.pem server-p521.der server-p521.pem
renewcerts wolfssl.cnf
rpk client-cert-rpk.der client-ecc-cert-rpk.der include.am server-cert-rpk.der server-ecc-cert-rpk.der
rsapss ca-3072-rsapss-key.der ca-3072-rsapss-key.pem ca-3072-rsapss-priv.der ca-3072-rsapss-priv.pem ca-3072-rsapss.der ca-3072-rsapss.pem ca-rsapss-key.der ca-rsapss-key.pem ca-rsapss-priv.der ca-rsapss-priv.pem ca-rsapss.der ca-rsapss.pem client-3072-rsapss-key.der client-3072-rsapss-key.pem client-3072-rsapss-priv.der client-3072-rsapss-priv.pem client-3072-rsapss.der client-3072-rsapss.pem client-rsapss-key.der client-rsapss-key.pem client-rsapss-priv.der client-rsapss-priv.pem client-rsapss.der client-rsapss.pem gen-rsapss-keys.sh include.am renew-rsapss-certs.sh root-3072-rsapss-key.der root-3072-rsapss-key.pem root-3072-rsapss-priv.der root-3072-rsapss-priv.pem root-3072-rsapss.der root-3072-rsapss.pem root-rsapss-key.der root-rsapss-key.pem root-rsapss-priv.der root-rsapss-priv.pem root-rsapss.der root-rsapss.pem server-3072-rsapss-cert.pem server-3072-rsapss-key.der server-3072-rsapss-key.pem server-3072-rsapss-priv.der server-3072-rsapss-priv.pem server-3072-rsapss.der server-3072-rsapss.pem server-mix-rsapss-cert.pem server-rsapss-cert.pem server-rsapss-key.der server-rsapss-key.pem server-rsapss-priv.der server-rsapss-priv.pem server-rsapss.der server-rsapss.pem
sia timestamping-sia-cert.pem
slhdsa bench_slhdsa_sha2_128f_key.der bench_slhdsa_sha2_128s_key.der bench_slhdsa_sha2_192f_key.der bench_slhdsa_sha2_192s_key.der bench_slhdsa_sha2_256f_key.der bench_slhdsa_sha2_256s_key.der bench_slhdsa_shake128f_key.der bench_slhdsa_shake128s_key.der bench_slhdsa_shake192f_key.der bench_slhdsa_shake192s_key.der bench_slhdsa_shake256f_key.der bench_slhdsa_shake256s_key.der client-mldsa44-priv.pem client-mldsa44-sha2.der client-mldsa44-sha2.pem client-mldsa44-shake.der client-mldsa44-shake.pem gen-slhdsa-mldsa-certs.sh include.am root-slhdsa-sha2-128s-priv.der root-slhdsa-sha2-128s-priv.pem root-slhdsa-sha2-128s.der root-slhdsa-sha2-128s.pem root-slhdsa-shake-128s-priv.der root-slhdsa-shake-128s-priv.pem root-slhdsa-shake-128s.der root-slhdsa-shake-128s.pem server-mldsa44-priv.pem server-mldsa44-sha2.der server-mldsa44-sha2.pem server-mldsa44-shake.der server-mldsa44-shake.pem
sm2 ca-sm2-key.der ca-sm2-key.pem ca-sm2-priv.der ca-sm2-priv.pem ca-sm2.der ca-sm2.pem client-sm2-key.der client-sm2-key.pem client-sm2-priv.der client-sm2-priv.pem client-sm2.der client-sm2.pem fix_sm2_spki.py gen-sm2-certs.sh gen-sm2-keys.sh include.am root-sm2-key.der root-sm2-key.pem root-sm2-priv.der root-sm2-priv.pem root-sm2.der root-sm2.pem self-sm2-cert.pem self-sm2-key.pem self-sm2-priv.pem server-sm2-cert.der server-sm2-cert.pem server-sm2-key.der server-sm2-key.pem server-sm2-priv.der server-sm2-priv.pem server-sm2.der server-sm2.pem
statickeys dh-ffdhe2048-params.pem dh-ffdhe2048-pub.der dh-ffdhe2048-pub.pem dh-ffdhe2048.der dh-ffdhe2048.pem ecc-secp256r1.der ecc-secp256r1.pem gen-static.sh include.am x25519-pub.der x25519-pub.pem x25519.der x25519.pem
test
expired expired-ca.der expired-ca.pem expired-cert.der expired-cert.pem
catalog.txt cert-bad-neg-int.der cert-bad-oid.der cert-bad-utf8.der cert-ext-ia.cfg cert-ext-ia.der cert-ext-ia.pem cert-ext-joi.cfg cert-ext-joi.der cert-ext-joi.pem cert-ext-mnc.der cert-ext-multiple.cfg cert-ext-multiple.der cert-ext-multiple.pem cert-ext-nc-combined.der cert-ext-nc-combined.pem cert-ext-nc.cfg cert-ext-nc.der cert-ext-nc.pem cert-ext-ncdns.der cert-ext-ncdns.pem cert-ext-ncip.der cert-ext-ncip.pem cert-ext-ncmixed.der cert-ext-ncmulti.der cert-ext-ncmulti.pem cert-ext-ncrid.der cert-ext-ncrid.pem cert-ext-nct.cfg cert-ext-nct.der cert-ext-nct.pem cert-ext-ndir-exc.cfg cert-ext-ndir-exc.der cert-ext-ndir-exc.pem cert-ext-ndir.cfg cert-ext-ndir.der cert-ext-ndir.pem cert-ext-ns.der cert-over-max-altnames.cfg cert-over-max-altnames.der cert-over-max-altnames.pem cert-over-max-nc.cfg cert-over-max-nc.der cert-over-max-nc.pem client-ecc-cert-ski.hex cn-ip-literal.der cn-ip-wildcard.der crit-cert.pem crit-key.pem dh1024.der dh1024.pem dh512.der dh512.pem digsigku.pem encrypteddata.msg gen-badsig.sh gen-ext-certs.sh gen-testcerts.sh include.am kari-keyid-cms.msg ktri-keyid-cms.msg ossl-trusted-cert.pem server-badaltname.der server-badaltname.pem server-badaltnull.der server-badaltnull.pem server-badcn.der server-badcn.pem server-badcnnull.der server-badcnnull.pem server-cert-ecc-badsig.der server-cert-ecc-badsig.pem server-cert-rsa-badsig.der server-cert-rsa-badsig.pem server-duplicate-policy.pem server-garbage.der server-garbage.pem server-goodalt.der server-goodalt.pem server-goodaltwild.der server-goodaltwild.pem server-goodcn.der server-goodcn.pem server-goodcnwild.der server-goodcnwild.pem server-localhost.der server-localhost.pem smime-test-canon.p7s smime-test-multipart-badsig.p7s smime-test-multipart.p7s smime-test.p7s
test-pathlen assemble-chains.sh chainA-ICA1-key.pem chainA-ICA1-pathlen0.pem chainA-assembled.pem chainA-entity-key.pem chainA-entity.pem chainB-ICA1-key.pem chainB-ICA1-pathlen0.pem chainB-ICA2-key.pem chainB-ICA2-pathlen1.pem chainB-assembled.pem chainB-entity-key.pem chainB-entity.pem chainC-ICA1-key.pem chainC-ICA1-pathlen1.pem chainC-assembled.pem chainC-entity-key.pem chainC-entity.pem chainD-ICA1-key.pem chainD-ICA1-pathlen127.pem chainD-assembled.pem chainD-entity-key.pem chainD-entity.pem chainE-ICA1-key.pem chainE-ICA1-pathlen128.pem chainE-assembled.pem chainE-entity-key.pem chainE-entity.pem chainF-ICA1-key.pem chainF-ICA1-pathlen1.pem chainF-ICA2-key.pem chainF-ICA2-pathlen0.pem chainF-assembled.pem chainF-entity-key.pem chainF-entity.pem chainG-ICA1-key.pem chainG-ICA1-pathlen0.pem chainG-ICA2-key.pem chainG-ICA2-pathlen1.pem chainG-ICA3-key.pem chainG-ICA3-pathlen99.pem chainG-ICA4-key.pem chainG-ICA4-pathlen5.pem chainG-ICA5-key.pem chainG-ICA5-pathlen20.pem chainG-ICA6-key.pem chainG-ICA6-pathlen10.pem chainG-ICA7-key.pem chainG-ICA7-pathlen100.pem chainG-assembled.pem chainG-entity-key.pem chainG-entity.pem chainH-ICA1-key.pem chainH-ICA1-pathlen0.pem chainH-ICA2-key.pem chainH-ICA2-pathlen2.pem chainH-ICA3-key.pem chainH-ICA3-pathlen2.pem chainH-ICA4-key.pem chainH-ICA4-pathlen2.pem chainH-assembled.pem chainH-entity-key.pem chainH-entity.pem chainI-ICA1-key.pem chainI-ICA1-no_pathlen.pem chainI-ICA2-key.pem chainI-ICA2-no_pathlen.pem chainI-ICA3-key.pem chainI-ICA3-pathlen2.pem chainI-assembled.pem chainI-entity-key.pem chainI-entity.pem chainJ-ICA1-key.pem chainJ-ICA1-no_pathlen.pem chainJ-ICA2-key.pem chainJ-ICA2-no_pathlen.pem chainJ-ICA3-key.pem chainJ-ICA3-no_pathlen.pem chainJ-ICA4-key.pem chainJ-ICA4-pathlen2.pem chainJ-assembled.pem chainJ-entity-key.pem chainJ-entity.pem include.am refreshkeys.sh
test-serial0 ee_normal.pem ee_serial0.pem generate_certs.sh include.am intermediate_serial0.pem root_serial0.pem root_serial0_key.pem selfsigned_nonca_serial0.pem
xmss bc_xmss_chain_ca.der bc_xmss_chain_leaf.der bc_xmss_sha2_10_256_root.der bc_xmss_sha2_16_256_root.der bc_xmssmt_sha2_20_2_256_root.der bc_xmssmt_sha2_20_4_256_root.der bc_xmssmt_sha2_40_8_256_root.der include.am
ca-cert-chain.der ca-cert.der ca-cert.pem ca-ecc-cert.der ca-ecc-cert.pem ca-ecc-key.der ca-ecc-key.pem ca-ecc384-cert.der ca-ecc384-cert.pem ca-ecc384-key.der ca-ecc384-key.pem ca-key-pkcs8-attribute.der ca-key.der ca-key.pem check_dates.sh client-absolute-urn.pem client-ca-cert.der client-ca-cert.pem client-ca.pem client-cert-ext.der client-cert-ext.pem client-cert.der client-cert.pem client-crl-dist.der client-crl-dist.pem client-ecc-ca-cert.der client-ecc-ca-cert.pem client-ecc-cert.der client-ecc-cert.pem client-ecc384-cert.der client-ecc384-cert.pem client-ecc384-key.der client-ecc384-key.pem client-key.der client-key.pem client-keyEnc.pem client-keyPub.der client-keyPub.pem client-relative-uri.pem client-uri-cert.pem csr.attr.der csr.dsa.der csr.dsa.pem csr.ext.der csr.signed.der dh-priv-2048.der dh-priv-2048.pem dh-pub-2048.der dh-pub-2048.pem dh-pubkey-2048.der dh2048.der dh2048.pem dh3072.der dh3072.pem dh4096.der dh4096.pem dsa-pubkey-2048.der dsa2048.der dsa2048.pem dsa3072.der dsaparams.der dsaparams.pem ecc-client-key.der ecc-client-key.pem ecc-client-keyPub.der ecc-client-keyPub.pem ecc-key-comp.pem ecc-keyPkcs8.der ecc-keyPkcs8.pem ecc-keyPkcs8Enc.der ecc-keyPkcs8Enc.pem ecc-keyPub.der ecc-keyPub.pem ecc-params.der ecc-params.pem ecc-privOnlyCert.pem ecc-privOnlyKey.pem ecc-privkey.der ecc-privkey.pem ecc-privkeyPkcs8.der ecc-privkeyPkcs8.pem ecc-rsa-server.p12 empty-issuer-cert.pem entity-no-ca-bool-cert.pem entity-no-ca-bool-key.pem fpki-cert.der fpki-certpol-cert.der gen_revoked.sh include.am renewcerts.sh rid-cert.der rsa-pub-2048.pem rsa2048.der rsa3072.der server-cert-chain.der server-cert.der server-cert.pem server-ecc-comp.der server-ecc-comp.pem server-ecc-rsa.der server-ecc-rsa.pem server-ecc-self.der server-ecc-self.pem server-ecc.der server-ecc.pem server-ecc384-cert.der server-ecc384-cert.pem server-ecc384-key.der server-ecc384-key.pem server-key.der server-key.pem server-keyEnc.pem server-keyPkcs8.der server-keyPkcs8.pem server-keyPkcs8Enc.der server-keyPkcs8Enc.pem server-keyPkcs8Enc12.pem server-keyPkcs8Enc2.pem server-keyPub.der server-keyPub.pem server-revoked-cert.pem server-revoked-key.pem taoCert.txt test-ber-exp02-05-2022.p7b test-degenerate.p7b test-multiple-recipients.p7b test-servercert-rc2.p12 test-servercert.p12 test-stream-dec.p7b test-stream-sign.p7b wolfssl-website-ca.pem x942dh2048.der x942dh2048.pem
cmake
consumer CMakeLists.txt README.md main.c
modules FindARIA.cmake FindOQS.cmake
Config.cmake.in README.md config.in functions.cmake include.am options.h.in wolfssl-config-version.cmake.in wolfssl-targets.cmake.in
debian
source format
changelog.in control.in copyright include.am libwolfssl-dev.install libwolfssl.install rules.in
doc
dox_comments
header_files aes.h arc4.h ascon.h asn.h asn_public.h blake2.h bn.h camellia.h chacha.h chacha20_poly1305.h cmac.h coding.h compress.h cryptocb.h curve25519.h curve448.h des3.h dh.h doxygen_groups.h doxygen_pages.h dsa.h ecc.h eccsi.h ed25519.h ed448.h error-crypt.h evp.h hash.h hmac.h iotsafe.h kdf.h logging.h md2.h md4.h md5.h memory.h ocsp.h pem.h pkcs11.h pkcs7.h poly1305.h psa.h puf.h pwdbased.h quic.h random.h ripemd.h rsa.h sakke.h sha.h sha256.h sha3.h sha512.h signature.h siphash.h srp.h ssl.h tfm.h types.h wc_encrypt.h wc_port.h wc_she.h wc_slhdsa.h wolfio.h
header_files-ja aes.h arc4.h ascon.h asn.h asn_public.h blake2.h bn.h camellia.h chacha.h chacha20_poly1305.h cmac.h coding.h compress.h cryptocb.h curve25519.h curve448.h des3.h dh.h doxygen_groups.h doxygen_pages.h dsa.h ecc.h eccsi.h ed25519.h ed448.h error-crypt.h evp.h hash.h hmac.h iotsafe.h kdf.h logging.h md2.h md4.h md5.h memory.h ocsp.h pem.h pkcs11.h pkcs7.h poly1305.h psa.h pwdbased.h quic.h random.h ripemd.h rsa.h sakke.h sha.h sha256.h sha3.h sha512.h signature.h siphash.h srp.h ssl.h tfm.h types.h wc_encrypt.h wc_port.h wolfio.h
formats
html
html_changes
search search.css search.js
customdoxygen.css doxygen.css menu.js menudata.js tabs.css
Doxyfile footer.html header.html mainpage.dox
pdf Doxyfile header.tex
images wolfssl_logo.png
QUIC.md README.txt README_DOXYGEN check_api.sh generate_documentation.sh include.am
examples
asn1 asn1.c dumpasn1.cfg gen_oid_names.rb include.am oid_names.h
async Makefile README.md async_client.c async_server.c async_tls.c async_tls.h include.am user_settings.h
benchmark include.am tls_bench.c tls_bench.h
client client.c client.h client.sln client.vcproj client.vcxproj include.am
configs README.md include.am user_settings_EBSnet.h user_settings_all.h user_settings_arduino.h user_settings_baremetal.h user_settings_ca.h user_settings_curve25519nonblock.h user_settings_dtls13.h user_settings_eccnonblock.h user_settings_espressif.h user_settings_fipsv2.h user_settings_fipsv5.h user_settings_min_ecc.h user_settings_openssl_compat.h user_settings_pkcs7.h user_settings_platformio.h user_settings_pq.h user_settings_rsa_only.h user_settings_stm32.h user_settings_template.h user_settings_tls12.h user_settings_tls13.h user_settings_wolfboot_keytools.h user_settings_wolfssh.h user_settings_wolftpm.h
crypto_policies
default wolfssl.txt
future wolfssl.txt
legacy wolfssl.txt
echoclient echoclient.c echoclient.h echoclient.sln echoclient.vcproj echoclient.vcxproj include.am quit
echoserver echoserver.c echoserver.h echoserver.sln echoserver.vcproj echoserver.vcxproj include.am
ocsp_responder include.am ocsp_responder.c ocsp_responder.h
pem include.am pem.c
sctp include.am sctp-client-dtls.c sctp-client.c sctp-server-dtls.c sctp-server.c
server include.am server.c server.h server.sln server.vcproj server.vcxproj
README.md include.am
linuxkm
patches
5.10.17 WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-5v10v17.patch
5.10.236 WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-5v10v236.patch
5.14.0-570.58.1.el9_6 WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-5v14-570v58v1-el9_6.patch
5.15 WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-5v15.patch
5.17 WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-5v17.patch
5.17-ubuntu-jammy-tegra WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-5v17-ubuntu-jammy-tegra.patch
6.1.73 WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-6v1v73.patch
6.12 WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-6v12.patch
6.15 WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-6v15.patch
7.0 WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-7v0.patch
regen-patches.sh
Kbuild Makefile README.md get_thread_size.c include.am linuxkm-fips-hash-wrapper.sh linuxkm-fips-hash.c linuxkm_memory.c linuxkm_memory.h linuxkm_wc_port.h lkcapi_aes_glue.c lkcapi_dh_glue.c lkcapi_ecdh_glue.c lkcapi_ecdsa_glue.c lkcapi_glue.c lkcapi_rsa_glue.c lkcapi_sha_glue.c module_exports.c.template module_hooks.c pie_redirect_table.c wolfcrypt.lds x86_vector_register_glue.c
m4 ax_add_am_macro.m4 ax_am_jobserver.m4 ax_am_macros.m4 ax_append_compile_flags.m4 ax_append_flag.m4 ax_append_link_flags.m4 ax_append_to_file.m4 ax_atomic.m4 ax_bsdkm.m4 ax_check_compile_flag.m4 ax_check_link_flag.m4 ax_compiler_version.m4 ax_count_cpus.m4 ax_create_generic_config.m4 ax_debug.m4 ax_file_escapes.m4 ax_harden_compiler_flags.m4 ax_linuxkm.m4 ax_print_to_file.m4 ax_pthread.m4 ax_require_defined.m4 ax_tls.m4 ax_vcs_checkout.m4 hexversion.m4 lib_socket_nsl.m4 visibility.m4
mcapi
wolfcrypt_mcapi.X
nbproject configurations.xml include.am project.xml
Makefile
wolfcrypt_test.X
nbproject configurations.xml include.am project.xml
Makefile
wolfssl.X
nbproject configurations.xml include.am project.xml
Makefile
zlib.X
nbproject configurations.xml include.am project.xml
Makefile
PIC32MZ-serial.h README crypto.c crypto.h include.am mcapi_test.c user_settings.h
mplabx
wolfcrypt_benchmark.X
nbproject configurations.xml include.am project.xml
Makefile
wolfcrypt_test.X
nbproject configurations.xml include.am project.xml
Makefile
wolfssl.X
nbproject configurations.xml include.am project.xml
Makefile
PIC32MZ-serial.h README benchmark_main.c include.am test_main.c user_settings.h
mqx
util_lib
Sources include.am util.c util.h
wolfcrypt_benchmark
Debugger K70FN1M0.mem init_kinetis.tcl mass_erase_kinetis.tcl
Sources include.am main.c main.h
ReferencedRSESystems.xml wolfcrypt_benchmark_twrk70f120m_Int_Flash_DDRData_Debug_PnE_U-MultiLink.launch wolfcrypt_benchmark_twrk70f120m_Int_Flash_DDRData_Release_PnE_U-MultiLink.launch wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Debug_JTrace.jlink wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Debug_JTrace.launch wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Debug_PnE_U-MultiLink.launch wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Release_PnE_U-MultiLink.launch
wolfcrypt_test
Debugger K70FN1M0.mem init_kinetis.tcl mass_erase_kinetis.tcl
Sources include.am main.c main.h
ReferencedRSESystems.xml wolfcrypt_test_twrk70f120m_Int_Flash_DDRData_Debug_PnE_U-MultiLink.launch wolfcrypt_test_twrk70f120m_Int_Flash_DDRData_Release_PnE_U-MultiLink.launch wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Debug_JTrace.jlink wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Debug_JTrace.launch wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Debug_PnE_U-MultiLink.launch wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Release_PnE_U-MultiLink.launch
wolfssl include.am
wolfssl_client
Debugger K70FN1M0.mem init_kinetis.tcl mass_erase_kinetis.tcl
Sources include.am main.c main.h
ReferencedRSESystems.xml wolfssl_client_twrk70f120m_Int_Flash_DDRData_Debug_PnE_U-MultiLink.launch wolfssl_client_twrk70f120m_Int_Flash_DDRData_Release_PnE_U-MultiLink.launch wolfssl_client_twrk70f120m_Int_Flash_SramData_Debug_JTrace.jlink wolfssl_client_twrk70f120m_Int_Flash_SramData_Debug_JTrace.launch wolfssl_client_twrk70f120m_Int_Flash_SramData_Debug_PnE_U-MultiLink.launch wolfssl_client_twrk70f120m_Int_Flash_SramData_Release_PnE_U-MultiLink.launch
README
rpm include.am spec.in
scripts
bench bench_functions.sh
aria-cmake-build-test.sh asn1_oid_sum.pl benchmark.test benchmark_compare.sh cleanup_testfiles.sh crl-gen-openssl.test crl-revoked.test dertoc.pl dtls.test dtlscid.test external.test google.test include.am makedistsmall.sh memtest.sh ocsp-responder-openssl-interop.test ocsp-stapling-with-ca-as-responder.test ocsp-stapling-with-wolfssl-responder.test ocsp-stapling.test ocsp-stapling2.test ocsp-stapling_tls13multi.test ocsp.test openssl.test openssl_srtp.test pem.test ping.test pkcallbacks.test psk.test resume.test rsapss.test sniffer-gen.sh sniffer-ipv6.pcap sniffer-static-rsa.pcap sniffer-testsuite.test sniffer-tls12-keylog.out sniffer-tls12-keylog.pcap sniffer-tls12-keylog.sslkeylog sniffer-tls13-dh-resume.pcap sniffer-tls13-dh.pcap sniffer-tls13-ecc-resume.pcap sniffer-tls13-ecc.pcap sniffer-tls13-hrr.pcap sniffer-tls13-keylog.out sniffer-tls13-keylog.pcap sniffer-tls13-keylog.sslkeylog sniffer-tls13-x25519-resume.pcap sniffer-tls13-x25519.pcap stm32l4-v4_0_1_build.sh tls13.test trusted_peer.test unit.test.in user_settings_asm.sh
src bio.c conf.c crl.c dtls.c dtls13.c include.am internal.c keys.c ocsp.c pk.c pk_ec.c pk_rsa.c quic.c sniffer.c ssl.c ssl_api_cert.c ssl_api_crl_ocsp.c ssl_api_pk.c ssl_asn1.c ssl_bn.c ssl_certman.c ssl_crypto.c ssl_ech.c ssl_load.c ssl_misc.c ssl_p7p12.c ssl_sess.c ssl_sk.c tls.c tls13.c wolfio.c x509.c x509_str.c
sslSniffer
sslSnifferTest README_WIN.md include.am snifftest.c sslSniffTest.vcproj sslSniffTest.vcxproj
README.md sslSniffer.vcproj sslSniffer.vcxproj
support gen-debug-trace-error-codes.sh include.am wolfssl.pc.in
tests
api api.h api_decl.h create_ocsp_test_blobs.py include.am test_aes.c test_aes.h test_arc4.c test_arc4.h test_ascon.c test_ascon.h test_ascon_kats.h test_asn.c test_asn.h test_blake2.c test_blake2.h test_camellia.c test_camellia.h test_certman.c test_certman.h test_chacha.c test_chacha.h test_chacha20_poly1305.c test_chacha20_poly1305.h test_cmac.c test_cmac.h test_curve25519.c test_curve25519.h test_curve448.c test_curve448.h test_des3.c test_des3.h test_dh.c test_dh.h test_digest.h test_dsa.c test_dsa.h test_dtls.c test_dtls.h test_ecc.c test_ecc.h test_ed25519.c test_ed25519.h test_ed448.c test_ed448.h test_evp.c test_evp.h test_evp_cipher.c test_evp_cipher.h test_evp_digest.c test_evp_digest.h test_evp_pkey.c test_evp_pkey.h test_hash.c test_hash.h test_hmac.c test_hmac.h test_md2.c test_md2.h test_md4.c test_md4.h test_md5.c test_md5.h test_mldsa.c test_mldsa.h test_mlkem.c test_mlkem.h test_ocsp.c test_ocsp.h test_ocsp_test_blobs.h test_ossl_asn1.c test_ossl_asn1.h test_ossl_bio.c test_ossl_bio.h test_ossl_bn.c test_ossl_bn.h test_ossl_cipher.c test_ossl_cipher.h test_ossl_dgst.c test_ossl_dgst.h test_ossl_dh.c test_ossl_dh.h test_ossl_dsa.c test_ossl_dsa.h test_ossl_ec.c test_ossl_ec.h test_ossl_ecx.c test_ossl_ecx.h test_ossl_mac.c test_ossl_mac.h test_ossl_obj.c test_ossl_obj.h test_ossl_p7p12.c test_ossl_p7p12.h test_ossl_pem.c test_ossl_pem.h test_ossl_rand.c test_ossl_rand.h test_ossl_rsa.c test_ossl_rsa.h test_ossl_sk.c test_ossl_sk.h test_ossl_x509.c test_ossl_x509.h test_ossl_x509_acert.c test_ossl_x509_acert.h test_ossl_x509_crypto.c test_ossl_x509_crypto.h test_ossl_x509_ext.c test_ossl_x509_ext.h test_ossl_x509_info.c test_ossl_x509_info.h test_ossl_x509_io.c test_ossl_x509_io.h test_ossl_x509_lu.c test_ossl_x509_lu.h test_ossl_x509_name.c test_ossl_x509_name.h test_ossl_x509_pk.c test_ossl_x509_pk.h test_ossl_x509_str.c test_ossl_x509_str.h test_ossl_x509_vp.c test_ossl_x509_vp.h test_pkcs12.c test_pkcs12.h test_pkcs7.c test_pkcs7.h test_poly1305.c test_poly1305.h test_random.c test_random.h test_rc2.c test_rc2.h test_ripemd.c test_ripemd.h test_rsa.c test_rsa.h test_sha.c test_sha.h test_sha256.c test_sha256.h test_sha3.c test_sha3.h test_sha512.c test_sha512.h test_she.c test_she.h test_signature.c test_signature.h test_slhdsa.c test_slhdsa.h test_sm2.c test_sm2.h test_sm3.c test_sm3.h test_sm4.c test_sm4.h test_tls.c test_tls.h test_tls13.c test_tls13.h test_tls_ext.c test_tls_ext.h test_wc_encrypt.c test_wc_encrypt.h test_wolfmath.c test_wolfmath.h test_x509.c test_x509.h
emnet
IP IP.h
Makefile emnet_nonblock_test.c emnet_shim.c
freertos-mem-track-repro FreeRTOS.h repro.c run.sh semphr.h task.h user_settings.h
swdev .gitignore Makefile README.md swdev.c swdev.h swdev_loader.c swdev_loader.h user_settings.h
CONF_FILES_README.md NCONF_test.cnf README TXT_DB.txt api.c include.am quic.c srp.c suites.c test-altchains.conf test-chains.conf test-dhprime.conf test-dtls-downgrade.conf test-dtls-fails-cipher.conf test-dtls-fails.conf test-dtls-group.conf test-dtls-mtu.conf test-dtls-reneg-client.conf test-dtls-reneg-server.conf test-dtls-resume.conf test-dtls-sha2.conf test-dtls-srtp-fails.conf test-dtls-srtp.conf test-dtls.conf test-dtls13-cid.conf test-dtls13-downgrade-fails.conf test-dtls13-downgrade.conf test-dtls13-pq-hybrid-extra-frag.conf test-dtls13-pq-hybrid-extra.conf test-dtls13-pq-hybrid-frag.conf test-dtls13-pq-standalone-frag.conf test-dtls13-pq-standalone.conf test-dtls13-psk.conf test-dtls13.conf test-ecc-cust-curves.conf test-ed25519.conf test-ed448.conf test-enckeys.conf test-fails.conf test-maxfrag-dtls.conf test-maxfrag.conf test-p521.conf test-psk-no-id-sha2.conf test-psk-no-id.conf test-psk.conf test-rsapss.conf test-sctp-sha2.conf test-sctp.conf test-sha2.conf test-sig.conf test-sm2.conf test-tls-downgrade.conf test-tls13-down.conf test-tls13-ecc.conf test-tls13-pq-hybrid-extra.conf test-tls13-pq-hybrid.conf test-tls13-pq-standalone.conf test-tls13-psk-certs.conf test-tls13-psk.conf test-tls13-slhdsa-fail.conf test-tls13-slhdsa-sha2.conf test-tls13-slhdsa-shake.conf test-tls13.conf test-trustpeer.conf test.conf unit.c unit.h utils.c utils.h w64wrapper.c
testsuite include.am testsuite.c testsuite.sln testsuite.vcproj testsuite.vcxproj utils.c utils.h
tirtos
packages
ti
net
wolfssl
tests
EK_TM4C1294XL
wolfcrypt
benchmark TM4C1294NC.icf benchmark.cfg main.c package.bld.hide package.xdc
test TM4C1294NC.icf main.c package.bld.hide package.xdc test.cfg
package.bld package.xdc package.xs
.gitignore README include.am products.mak wolfssl.bld wolfssl.mak
wolfcrypt
benchmark README.md benchmark-VS2022.sln benchmark-VS2022.vcxproj benchmark-VS2022.vcxproj.user benchmark.c benchmark.h benchmark.sln benchmark.vcproj benchmark.vcxproj include.am
src
port
Espressif
esp_crt_bundle README.md cacrt_all.pem cacrt_deprecated.pem cacrt_local.pem esp_crt_bundle.c gen_crt_bundle.py pio_install_cryptography.py
README.md esp32_aes.c esp32_mp.c esp32_sha.c esp32_util.c esp_sdk_mem_lib.c esp_sdk_time_lib.c esp_sdk_wifi_lib.c
Renesas README.md renesas_common.c renesas_fspsm_aes.c renesas_fspsm_rsa.c renesas_fspsm_sha.c renesas_fspsm_util.c renesas_rx64_hw_sha.c renesas_rx64_hw_util.c renesas_tsip_aes.c renesas_tsip_rsa.c renesas_tsip_sha.c renesas_tsip_util.c
af_alg afalg_aes.c afalg_hash.c wc_afalg.c
aria aria-crypt.c aria-cryptocb.c
arm armv8-32-aes-asm.S armv8-32-aes-asm_c.c armv8-32-chacha-asm.S armv8-32-chacha-asm_c.c armv8-32-curve25519.S armv8-32-curve25519_c.c armv8-32-mlkem-asm.S armv8-32-mlkem-asm_c.c armv8-32-poly1305-asm.S armv8-32-poly1305-asm_c.c armv8-32-sha256-asm.S armv8-32-sha256-asm_c.c armv8-32-sha3-asm.S armv8-32-sha3-asm_c.c armv8-32-sha512-asm.S armv8-32-sha512-asm_c.c armv8-aes-asm.S armv8-aes-asm_c.c armv8-aes.c armv8-chacha-asm.S armv8-chacha-asm_c.c armv8-curve25519.S armv8-curve25519_c.c armv8-mlkem-asm.S armv8-mlkem-asm_c.c armv8-poly1305-asm.S armv8-poly1305-asm_c.c armv8-sha256-asm.S armv8-sha256-asm_c.c armv8-sha256.c armv8-sha3-asm.S armv8-sha3-asm_c.c armv8-sha512-asm.S armv8-sha512-asm_c.c armv8-sha512.c cryptoCell.c cryptoCellHash.c thumb2-aes-asm.S thumb2-aes-asm_c.c thumb2-chacha-asm.S thumb2-chacha-asm_c.c thumb2-curve25519.S thumb2-curve25519_c.c thumb2-mlkem-asm.S thumb2-mlkem-asm_c.c thumb2-poly1305-asm.S thumb2-poly1305-asm_c.c thumb2-sha256-asm.S thumb2-sha256-asm_c.c thumb2-sha3-asm.S thumb2-sha3-asm_c.c thumb2-sha512-asm.S thumb2-sha512-asm_c.c
atmel README.md atmel.c
autosar README.md cryif.c crypto.c csm.c include.am test.c
caam README.md caam_aes.c caam_doc.pdf caam_driver.c caam_error.c caam_integrity.c caam_qnx.c caam_sha.c wolfcaam_aes.c wolfcaam_cmac.c wolfcaam_ecdsa.c wolfcaam_fsl_nxp.c wolfcaam_hash.c wolfcaam_hmac.c wolfcaam_init.c wolfcaam_qnx.c wolfcaam_rsa.c wolfcaam_seco.c wolfcaam_x25519.c
cavium README.md README_Octeon.md cavium_nitrox.c cavium_octeon_sync.c
cuda README.md aes-cuda.cu
cypress README.md psoc6_crypto.c
devcrypto README.md devcrypto_aes.c devcrypto_ecdsa.c devcrypto_hash.c devcrypto_hmac.c devcrypto_rsa.c devcrypto_x25519.c wc_devcrypto.c
intel README.md quickassist.c quickassist_mem.c quickassist_sync.c
iotsafe iotsafe.c
kcapi README.md kcapi_aes.c kcapi_dh.c kcapi_ecc.c kcapi_hash.c kcapi_hmac.c kcapi_rsa.c
liboqs liboqs.c
maxim README.md max3266x.c maxq10xx.c
mynewt mynewt_port.c
nxp README.md README_SE050.md casper_port.c dcp_port.c hashcrypt_port.c ksdk_port.c se050_port.c
pic32 pic32mz-crypt.c
ppc32 ppc32-sha256-asm.S ppc32-sha256-asm_c.c ppc32-sha256-asm_cr.c
psa README.md psa.c psa_aes.c psa_hash.c psa_pkcbs.c
riscv riscv-64-aes.c riscv-64-chacha.c riscv-64-poly1305.c riscv-64-sha256.c riscv-64-sha3.c riscv-64-sha512.c
rpi_pico README.md pico.c
silabs README.md silabs_aes.c silabs_ecc.c silabs_hash.c silabs_random.c
st README.md STM32MP13.md STM32MP25.md stm32.c stsafe.c
ti ti-aes.c ti-ccm.c ti-des3.c ti-hash.c
tropicsquare README.md tropic01.c
xilinx xil-aesgcm.c xil-sha3.c xil-versal-glue.c xil-versal-trng.c
nrf51.c
ASN_TEMPLATE.md aes.c aes_asm.S aes_asm.asm aes_gcm_asm.S aes_gcm_asm.asm aes_gcm_x86_asm.S aes_xts_asm.S aes_xts_asm.asm arc4.c ascon.c asm.c asn.c asn_orig.c async.c blake2b.c blake2s.c camellia.c chacha.c chacha20_poly1305.c chacha_asm.S chacha_asm.asm cmac.c coding.c compress.c cpuid.c cryptocb.c curve25519.c curve448.c des3.c dh.c dilithium.c dsa.c ecc.c ecc_fp.c eccsi.c ed25519.c ed448.c error.c evp.c evp_pk.c falcon.c fe_448.c fe_low_mem.c fe_operations.c fe_x25519_128.h fe_x25519_asm.S fp_mont_small.i fp_mul_comba_12.i fp_mul_comba_17.i fp_mul_comba_20.i fp_mul_comba_24.i fp_mul_comba_28.i fp_mul_comba_3.i fp_mul_comba_32.i fp_mul_comba_4.i fp_mul_comba_48.i fp_mul_comba_6.i fp_mul_comba_64.i fp_mul_comba_7.i fp_mul_comba_8.i fp_mul_comba_9.i fp_mul_comba_small_set.i fp_sqr_comba_12.i fp_sqr_comba_17.i fp_sqr_comba_20.i fp_sqr_comba_24.i fp_sqr_comba_28.i fp_sqr_comba_3.i fp_sqr_comba_32.i fp_sqr_comba_4.i fp_sqr_comba_48.i fp_sqr_comba_6.i fp_sqr_comba_64.i fp_sqr_comba_7.i fp_sqr_comba_8.i fp_sqr_comba_9.i fp_sqr_comba_small_set.i ge_448.c ge_low_mem.c ge_operations.c hash.c hmac.c hpke.c include.am integer.c kdf.c logging.c md2.c md4.c md5.c memory.c misc.c pkcs12.c pkcs7.c poly1305.c poly1305_asm.S poly1305_asm.asm puf.c pwdbased.c random.c rc2.c ripemd.c rng_bank.c rsa.c sakke.c sha.c sha256.c sha256_asm.S sha3.c sha3_asm.S sha512.c sha512_asm.S signature.c siphash.c sm2.c sm3.c sm3_asm.S sm4.c sp_arm32.c sp_arm64.c sp_armthumb.c sp_c32.c sp_c64.c sp_cortexm.c sp_dsp32.c sp_int.c sp_sm2_arm32.c sp_sm2_arm64.c sp_sm2_armthumb.c sp_sm2_c32.c sp_sm2_c64.c sp_sm2_cortexm.c sp_sm2_x86_64.c sp_sm2_x86_64_asm.S sp_x86_64.c sp_x86_64_asm.S sp_x86_64_asm.asm srp.c tfm.c wc_dsp.c wc_encrypt.c wc_lms.c wc_lms_impl.c wc_mldsa_asm.S wc_mlkem.c wc_mlkem_asm.S wc_mlkem_poly.c wc_pkcs11.c wc_port.c wc_she.c wc_slhdsa.c wc_xmss.c wc_xmss_impl.c wolfentropy.c wolfevent.c wolfmath.c
test README.md include.am test-VS2022.sln test-VS2022.vcxproj test-VS2022.vcxproj.user test.c test.h test.sln test.vcproj test_paths.h.in
wolfssl
openssl aes.h asn1.h asn1t.h bio.h bn.h buffer.h camellia.h cmac.h cms.h compat_types.h conf.h crypto.h des.h dh.h dsa.h ec.h ec25519.h ec448.h ecdh.h ecdsa.h ed25519.h ed448.h engine.h err.h evp.h fips_rand.h hmac.h include.am kdf.h lhash.h md4.h md5.h modes.h obj_mac.h objects.h ocsp.h opensslconf.h opensslv.h ossl_typ.h pem.h pkcs12.h pkcs7.h rand.h rc4.h ripemd.h rsa.h safestack.h sha.h sha3.h srp.h ssl.h ssl23.h stack.h tls1.h txt_db.h ui.h x509.h x509_vfy.h x509v3.h
wolfcrypt
port
Espressif esp-sdk-lib.h esp32-crypt.h esp_crt_bundle.h
Renesas renesas-fspsm-crypt.h renesas-fspsm-types.h renesas-rx64-hw-crypt.h renesas-tsip-crypt.h renesas_cmn.h renesas_fspsm_internal.h renesas_sync.h renesas_tsip_internal.h renesas_tsip_types.h
af_alg afalg_hash.h wc_afalg.h
aria aria-crypt.h aria-cryptocb.h
arm cryptoCell.h
atmel atmel.h
autosar CryIf.h Crypto.h Csm.h StandardTypes.h
caam caam_driver.h caam_error.h caam_qnx.h wolfcaam.h wolfcaam_aes.h wolfcaam_cmac.h wolfcaam_ecdsa.h wolfcaam_fsl_nxp.h wolfcaam_hash.h wolfcaam_qnx.h wolfcaam_rsa.h wolfcaam_seco.h wolfcaam_sha.h wolfcaam_x25519.h
cavium cavium_nitrox.h cavium_octeon_sync.h
cypress psoc6_crypto.h
devcrypto wc_devcrypto.h
intel quickassist.h quickassist_mem.h quickassist_sync.h
iotsafe iotsafe.h
kcapi kcapi_dh.h kcapi_ecc.h kcapi_hash.h kcapi_hmac.h kcapi_rsa.h wc_kcapi.h
liboqs liboqs.h
maxim max3266x-cryptocb.h max3266x.h maxq10xx.h
nxp casper_port.h dcp_port.h hashcrypt_port.h ksdk_port.h se050_port.h
pic32 pic32mz-crypt.h
psa psa.h
riscv riscv-64-asm.h
rpi_pico pico.h
silabs silabs_aes.h silabs_ecc.h silabs_hash.h silabs_random.h
st stm32.h stsafe.h
ti ti-ccm.h ti-hash.h
tropicsquare tropic01.h
xilinx xil-sha3.h xil-versal-glue.h xil-versal-trng.h
nrf51.h
aes.h arc4.h ascon.h asn.h asn_public.h async.h blake2-impl.h blake2-int.h blake2.h camellia.h chacha.h chacha20_poly1305.h cmac.h coding.h compress.h cpuid.h cryptocb.h curve25519.h curve448.h des3.h dh.h dilithium.h dsa.h ecc.h eccsi.h ed25519.h ed448.h error-crypt.h falcon.h fe_448.h fe_operations.h fips_test.h ge_448.h ge_operations.h hash.h hmac.h hpke.h include.am integer.h kdf.h libwolfssl_sources.h libwolfssl_sources_asm.h logging.h md2.h md4.h md5.h mem_track.h memory.h misc.h mpi_class.h mpi_superclass.h oid_sum.h pkcs11.h pkcs12.h pkcs7.h poly1305.h puf.h pwdbased.h random.h rc2.h ripemd.h rng_bank.h rsa.h sakke.h selftest.h settings.h sha.h sha256.h sha3.h sha512.h signature.h siphash.h sm2.h sm3.h sm4.h sp.h sp_int.h srp.h tfm.h types.h visibility.h wc_encrypt.h wc_lms.h wc_mlkem.h wc_pkcs11.h wc_port.h wc_she.h wc_slhdsa.h wc_xmss.h wolfentropy.h wolfevent.h wolfmath.h
callbacks.h certs_test.h certs_test_sm.h crl.h error-ssl.h include.am internal.h ocsp.h options.h.in quic.h sniffer.h sniffer_error.h sniffer_error.rc ssl.h test.h version.h version.h.in wolfio.h
wrapper
Ada
examples
src aes_verify_main.adb rsa_verify_main.adb sha256_main.adb spark_sockets.adb spark_sockets.ads spark_terminal.adb spark_terminal.ads tls_client.adb tls_client.ads tls_client_main.adb tls_server.adb tls_server.ads tls_server_main.adb
.gitignore alire.toml examples.gpr
tests
src
support test_support.adb test_support.ads tests_root_suite.adb tests_root_suite.ads
aes_bindings_tests.adb aes_bindings_tests.ads rsa_verify_bindings_tests.adb rsa_verify_bindings_tests.ads sha256_bindings_tests.adb sha256_bindings_tests.ads tests.adb
.gitignore README.md alire.toml tests.gpr valgrind.supp
.gitignore README.md ada_binding.c alire.toml default.gpr include.am restricted.adc user_settings.h wolfssl-full_runtime.adb wolfssl-full_runtime.ads wolfssl.adb wolfssl.ads wolfssl.gpr
CSharp
wolfCrypt-Test
Properties AssemblyInfo.cs
App.config wolfCrypt-Test.cs wolfCrypt-Test.csproj
wolfSSL-DTLS-PSK-Server
Properties AssemblyInfo.cs
App.config wolfSSL-DTLS-PSK-Server.cs wolfSSL-DTLS-PSK-Server.csproj
wolfSSL-DTLS-Server
Properties AssemblyInfo.cs
App.config wolfSSL-DTLS-Server.cs wolfSSL-DTLS-Server.csproj
wolfSSL-Example-IOCallbacks
Properties AssemblyInfo.cs
App.config wolfSSL-Example-IOCallbacks.cs wolfSSL-Example-IOCallbacks.csproj
wolfSSL-TLS-Client
Properties AssemblyInfo.cs
App.config wolfSSL-TLS-Client.cs wolfSSL-TLS-Client.csproj
wolfSSL-TLS-PSK-Client
Properties AssemblyInfo.cs
App.config wolfSSL-TLS-PSK-Client.cs wolfSSL-TLS-PSK-Client.csproj
wolfSSL-TLS-PSK-Server
Properties AssemblyInfo.cs
App.config wolfSSL-TLS-PSK-Server.cs wolfSSL-TLS-PSK-Server.csproj
wolfSSL-TLS-Server
Properties AssemblyInfo.cs
App.config wolfSSL-TLS-Server.cs wolfSSL-TLS-Server.csproj
wolfSSL-TLS-ServerThreaded
Properties AssemblyInfo.cs
App.config wolfSSL-TLS-ServerThreaded.cs wolfSSL-TLS-ServerThreaded.csproj
wolfSSL_CSharp
Properties AssemblyInfo.cs Resources.Designer.cs Resources.resx
X509.cs wolfCrypt.cs wolfSSL.cs wolfSSL_CSharp.csproj
README.md include.am user_settings.h wolfSSL_CSharp.sln wolfssl.vcxproj
python README.md
rust
wolfssl-wolfcrypt
src aes.rs blake2.rs chacha20_poly1305.rs cmac.rs cmac_mac.rs curve25519.rs dh.rs dilithium.rs ecc.rs ecdsa.rs ed25519.rs ed448.rs fips.rs hkdf.rs hmac.rs hmac_mac.rs kdf.rs lib.rs lms.rs mlkem.rs mlkem_kem.rs pbkdf2_password_hash.rs prf.rs random.rs rsa.rs rsa_pkcs1v15.rs sha.rs sha_digest.rs sys.rs
tests
common mod.rs
test_aes.rs test_blake2.rs test_chacha20_poly1305.rs test_cmac.rs test_cmac_mac.rs test_curve25519.rs test_dh.rs test_dilithium.rs test_ecc.rs test_ecdsa.rs test_ed25519.rs test_ed448.rs test_hkdf.rs test_hmac.rs test_hmac_mac.rs test_kdf.rs test_lms.rs test_mlkem.rs test_mlkem_kem.rs test_pbkdf2_password_hash.rs test_prf.rs test_random.rs test_rsa.rs test_rsa_pkcs1v15.rs test_sha.rs test_sha_digest.rs test_wolfcrypt.rs
CHANGELOG.md Cargo.lock Cargo.toml Makefile README.md build.rs headers.h
Makefile README.md include.am
include.am
zephyr
samples
wolfssl_benchmark
boards native_sim.conf nrf5340dk_nrf5340_cpuapp.conf nrf5340dk_nrf5340_cpuapp_ns.conf
CMakeLists.txt README install_test.sh prj.conf sample.yaml zephyr_legacy.conf zephyr_v4.1.conf
wolfssl_test
boards native_sim.conf nrf5340dk_nrf5340_cpuapp.conf nrf5340dk_nrf5340_cpuapp_ns.conf
CMakeLists.txt README install_test.sh prj-no-malloc.conf prj.conf sample.yaml zephyr_legacy.conf zephyr_v4.1.conf
wolfssl_tls_sock
boards native_sim.conf
src tls_sock.c
CMakeLists.txt README install_sample.sh prj-no-malloc.conf prj.conf sample.yaml zephyr_legacy.conf zephyr_v4.1.conf
wolfssl_tls_thread
boards native_sim.conf nrf5340dk_nrf5340_cpuapp.conf nrf5340dk_nrf5340_cpuapp_ns.conf
src tls_threaded.c
CMakeLists.txt README install_sample.sh prj.conf sample.yaml zephyr_legacy.conf zephyr_v4.1.conf
wolfssl options.h
CMakeLists.txt Kconfig Kconfig.tls-generic README.md include.am module.yml user_settings-no-malloc.h user_settings.h zephyr_init.c
.codespellexcludelines .cyignore .editorconfig .gitignore .wolfssl_known_macro_extras AUTHORS CMakeLists.txt CMakePresets.json CMakeSettings.json COPYING ChangeLog.md INSTALL LICENSING LPCExpresso.cproject LPCExpresso.project Makefile.am README README-async.md README.md SCRIPTS-LIST SECURITY-POLICY.md SECURITY-REPORT-TEMPLATE.md Vagrantfile autogen.sh commit-tests.sh configure.ac fips-check.sh fips-hash.sh gencertbuf.pl input pull_to_vagrant.sh quit resource.h stamp-h.in valgrind-bash.supp valgrind-error.sh wnr-example.conf wolfssl-VS2022.vcxproj wolfssl.rc wolfssl.vcproj wolfssl.vcxproj wolfssl64.sln
.clangd .gitignore DOCS.md Makefile README.md assert.c core.c crypto.c env.c fs.c http.c ini.c json.c log.c luna.h main.c makext.mk path.c process.c request.c sqlite.c stash.c template.c util.c
wolfssl/src/tls.c raw
    1/* tls.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/*
   23 * TLS Build Options:
   24 * (See tls13.c for TLS 1.3-specific options)
   25 *
   26 * Protocol Control:
   27 * NO_OLD_TLS:               Disable TLS 1.0 and 1.1              default: off
   28 * WOLFSSL_ALLOW_TLSV10:     Allow TLS 1.0 connections             default: off
   29 * WOLFSSL_NO_TLS12:         Disable TLS 1.2                       default: off
   30 * NO_TLS:                   Disable TLS entirely (SSL only)       default: off
   31 * WOLFSSL_DTLS:             Enable DTLS support                   default: off
   32 * WOLFSSL_DTLS13:           Enable DTLS 1.3 support               default: off
   33 * WOLFSSL_DTLS_CID:         Enable DTLS Connection ID             default: off
   34 * WOLFSSL_AEAD_ONLY:        Only allow AEAD cipher suites         default: off
   35 * NO_WOLFSSL_CLIENT:        Disable TLS client functionality      default: off
   36 * NO_WOLFSSL_SERVER:        Disable TLS server functionality      default: off
   37 * WOLFSSL_EITHER_SIDE:      Allow same context for client/server  default: off
   38 * HAVE_TLS_EXTENSIONS:      Enable TLS extension support          default: on
   39 * HAVE_SNI:                 Server Name Indication extension      default: off
   40 * WOLFSSL_ALWAYS_KEEP_SNI:  Keep SNI after handshake              default: off
   41 * HAVE_MAX_FRAGMENT:        Max Fragment Length extension          default: off
   42 * HAVE_TRUNCATED_HMAC:      Truncated HMAC extension              default: off
   43 * HAVE_SUPPORTED_CURVES:    Supported Curves extension            default: on
   44 * HAVE_EXTENDED_MASTER:     Extended Master Secret (RFC 7627)     default: on
   45 * HAVE_ENCRYPT_THEN_MAC:    Encrypt-Then-MAC extension            default: on
   46 * HAVE_ALPN:                Application-Layer Protocol Negotiation default: off
   47 * HAVE_CERTIFICATE_STATUS_REQUEST: OCSP stapling                  default: off
   48 * HAVE_CERTIFICATE_STATUS_REQUEST_V2: OCSP stapling v2            default: off
   49 * HAVE_SECURE_RENEGOTIATION: Secure renegotiation support         default: off
   50 * HAVE_SERVER_RENEGOTIATION_INFO: Server renegotiation info       default: off
   51 * HAVE_SESSION_TICKET:      Session ticket support                default: off
   52 * HAVE_TRUSTED_CA:          Trusted CA Indication extension       default: off
   53 * HAVE_RPK:                 Raw Public Key support (RFC 7250)     default: off
   54 * HAVE_ECH:                 Encrypted Client Hello support        default: off
   55 * WOLFSSL_NO_SIGALG:        Disable signature algorithms ext      default: off
   56 * WOLFSSL_NO_CA_NAMES:      Disable CA Names in CertificateReq   default: off
   57 * WOLFSSL_NO_SERVER_GROUPS_EXT: Don't send server groups ext      default: off
   58 * NO_TLSX_PSKKEM_PLAIN_ANNOUNCE: Disable plain PSK announce      default: off
   59 * WOLFSSL_OLD_UNSUPPORTED_EXTENSION: Old unsupported ext handling default: off
   60 * WOLFSSL_ALLOW_SERVER_SC_EXT: Allow server supported curves ext  default: off
   61 *
   62 * Pre-Shared Keys:
   63 * NO_PSK:                   Disable PSK cipher suites             default: off
   64 *
   65 * Key Exchange:
   66 * HAVE_FFDHE:               Enable Finite Field DH ephemeral      default: off
   67 * HAVE_FFDHE_2048:          Enable FFDHE 2048-bit group           default: off
   68 * HAVE_FFDHE_3072:          Enable FFDHE 3072-bit group           default: off
   69 * HAVE_FFDHE_4096:          Enable FFDHE 4096-bit group           default: off
   70 * HAVE_FFDHE_6144:          Enable FFDHE 6144-bit group           default: off
   71 * HAVE_FFDHE_8192:          Enable FFDHE 8192-bit group           default: off
   72 * HAVE_PUBLIC_FFDHE:        Use public FFDHE parameters only      default: off
   73 * WOLFSSL_OLD_PRIME_CHECK:  Use old DH prime checking method      default: off
   74 * WOLFSSL_STATIC_DH:        Enable static DH cipher suites       default: off
   75 * WOLFSSL_STATIC_EPHEMERAL: Enable static ephemeral key loading   default: off
   76 *
   77 * Post-Quantum:
   78 * WOLFSSL_HAVE_MLKEM:       Enable ML-KEM (Kyber) support         default: off
   79 * WOLFSSL_MLKEM_KYBER:      Use Kyber round 3 parameters          default: off
   80 * WOLFSSL_KYBER512:         Enable Kyber/ML-KEM-512               default: off
   81 * WOLFSSL_KYBER768:         Enable Kyber/ML-KEM-768               default: off
   82 * WOLFSSL_KYBER1024:        Enable Kyber/ML-KEM-1024              default: off
   83 * WOLFSSL_NO_ML_KEM:        Disable all ML-KEM support            default: off
   84 * WOLFSSL_NO_ML_KEM_512:    Disable ML-KEM-512                    default: off
   85 * WOLFSSL_NO_ML_KEM_768:    Disable ML-KEM-768                    default: off
   86 * WOLFSSL_NO_ML_KEM_1024:   Disable ML-KEM-1024                  default: off
   87 * WOLFSSL_ML_KEM_USE_OLD_IDS: Use old IANA IDs for ML-KEM        default: off
   88 * WOLFSSL_TLSX_PQC_MLKEM_STORE_OBJ: Store ML-KEM object in ext   default: off
   89 * WOLFSSL_TLSX_PQC_MLKEM_STORE_PRIV_KEY: Store ML-KEM priv key   default: off
   90 * WOLFSSL_MLKEM_CACHE_A:    Cache ML-KEM A matrix                 default: off
   91 * WOLFSSL_MLKEM_NO_MAKE_KEY: Disable ML-KEM key generation       default: off
   92 * WOLFSSL_MLKEM_NO_ENCAPSULATE: Disable ML-KEM encapsulation     default: off
   93 * WOLFSSL_MLKEM_NO_DECAPSULATE: Disable ML-KEM decapsulation     default: off
   94 * HAVE_LIBOQS:              Use liboqs for PQ algorithms          default: off
   95 *
   96 * Curves:
   97 * HAVE_SECRET_CALLBACK:     Enable TLS secret callback            default: off
   98 * HAVE_PK_CALLBACKS:        Enable public key callbacks           default: off
   99 * HAVE_FUZZER:              Enable fuzzing callback support        default: off
  100 *
  101 * Features:
  102 * WOLFSSL_SNIFFER:          Enable TLS packet sniffing support    default: off
  103 * WOLFSSL_SNIFFER_KEYLOGFILE: Sniffer keylog file support         default: off
  104 * WOLFSSL_SSLKEYLOGFILE:    Enable SSL key log file output        default: off
  105 * WOLFSSL_SRTP:             Enable SRTP extension support         default: off
  106 * WOLFSSL_DUAL_ALG_CERTS:   Enable dual algorithm certificates   default: off
  107 * WOLFSSL_HAVE_PRF:         Enable TLS PRF function access        default: off
  108 * WOLFSSL_DEBUG_TLS:        Debug TLS protocol messages            default: off
  109 * WOLFSSL_32BIT_MILLI_TIME: 32-bit millisecond time function      default: off
  110 * WOLFSSL_REQUIRE_TCA:      Require Trusted CA extension          default: off
  111 * WOLFSSL_DH_EXTRA:         Extra DH key info in SSL object       default: off
  112 * WOLFSSL_CURVE25519_BLINDING: Curve25519 blinding in TLS         default: off
  113 * HAVE_NULL_CIPHER:         Allow NULL cipher suites               default: off
  114 * HAVE_WEBSERVER:           Enable web server features             default: off
  115 * NO_CERTS:                 Disable certificate processing        default: off
  116 */
  117
  118#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
  119
  120#ifndef WOLFCRYPT_ONLY
  121
  122#include <wolfssl/ssl.h>
  123#include <wolfssl/internal.h>
  124#include <wolfssl/error-ssl.h>
  125#include <wolfssl/wolfcrypt/hash.h>
  126#include <wolfssl/wolfcrypt/hmac.h>
  127#include <wolfssl/wolfcrypt/kdf.h>
  128#ifdef NO_INLINE
  129    #include <wolfssl/wolfcrypt/misc.h>
  130#else
  131    #define WOLFSSL_MISC_INCLUDED
  132    #include <wolfcrypt/src/misc.c>
  133#endif
  134
  135#ifdef HAVE_CURVE25519
  136    #include <wolfssl/wolfcrypt/curve25519.h>
  137#endif
  138#ifdef HAVE_CURVE448
  139    #include <wolfssl/wolfcrypt/curve448.h>
  140#endif
  141#ifdef WOLFSSL_HAVE_MLKEM
  142    #include <wolfssl/wolfcrypt/wc_mlkem.h>
  143#endif
  144
  145#if defined(WOLFSSL_RENESAS_TSIP_TLS)
  146    #include <wolfssl/wolfcrypt/port/Renesas/renesas_tsip_internal.h>
  147#endif
  148
  149#include <wolfssl/wolfcrypt/hpke.h>
  150
  151#ifndef NO_TLS
  152
  153#if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES)
  154static void TLSX_KeyShare_FreeAll(KeyShareEntry* list, void* heap);
  155#endif
  156
  157#ifdef HAVE_SUPPORTED_CURVES
  158static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions);
  159#endif
  160
  161/* Digest enable checks */
  162#ifdef NO_OLD_TLS /* TLS 1.2 only */
  163    #if defined(NO_SHA256) && !defined(WOLFSSL_SHA384) && \
  164            !defined(WOLFSSL_SHA512)
  165        #error Must have SHA256, SHA384 or SHA512 enabled for TLS 1.2
  166    #endif
  167#else  /* TLS 1.1 or older */
  168    #if defined(NO_MD5) && defined(NO_SHA)
  169        #error Must have SHA1 and MD5 enabled for old TLS
  170    #endif
  171#endif
  172
  173#ifdef WOLFSSL_TLS13
  174    #if !defined(NO_DH) && \
  175        !defined(HAVE_FFDHE_2048) && !defined(HAVE_FFDHE_3072) && \
  176        !defined(HAVE_FFDHE_4096) && !defined(HAVE_FFDHE_6144) && \
  177        !defined(HAVE_FFDHE_8192)
  178        #error Please configure your TLS 1.3 DH key size using either: HAVE_FFDHE_2048, HAVE_FFDHE_3072, HAVE_FFDHE_4096, HAVE_FFDHE_6144 or HAVE_FFDHE_8192
  179    #endif
  180    #if !defined(NO_RSA) && !defined(WC_RSA_PSS)
  181        #error The build option WC_RSA_PSS is required for TLS 1.3 with RSA
  182    #endif
  183    #ifndef HAVE_TLS_EXTENSIONS
  184        #if !defined(_MSC_VER) && !defined(__TASKING__)
  185            #error "The build option HAVE_TLS_EXTENSIONS is required for TLS 1.3"
  186        #else
  187            #pragma message("Error: The build option HAVE_TLS_EXTENSIONS is required for TLS 1.3")
  188        #endif
  189    #endif
  190#endif
  191
  192/* Warn if secrets logging is enabled */
  193#if (defined(SHOW_SECRETS) || defined(WOLFSSL_SSLKEYLOGFILE)) && \
  194    !defined(WOLFSSL_KEYLOG_EXPORT_WARNED)
  195    #if !defined(_MSC_VER) && !defined(__TASKING__)
  196        #warning The SHOW_SECRETS and WOLFSSL_SSLKEYLOGFILE options should only be used for debugging and never in a production environment
  197    #else
  198        #pragma message("Warning: The SHOW_SECRETS and WOLFSSL_SSLKEYLOGFILE options should only be used for debugging and never in a production environment")
  199    #endif
  200#endif
  201
  202#ifndef WOLFSSL_NO_TLS12
  203
  204#ifdef WOLFSSL_SHA384
  205    #define HSHASH_SZ WC_SHA384_DIGEST_SIZE
  206#else
  207    #define HSHASH_SZ FINISHED_SZ
  208#endif
  209
  210int BuildTlsHandshakeHash(WOLFSSL* ssl, byte* hash, word32* hashLen)
  211{
  212    int ret = 0;
  213    word32 hashSz = FINISHED_SZ;
  214
  215    if (ssl == NULL || hash == NULL || hashLen == NULL || *hashLen < HSHASH_SZ)
  216        return BAD_FUNC_ARG;
  217
  218    /* for constant timing perform these even if error */
  219#ifndef NO_OLD_TLS
  220    ret |= wc_Md5GetHash(&ssl->hsHashes->hashMd5, hash);
  221    ret |= wc_ShaGetHash(&ssl->hsHashes->hashSha, &hash[WC_MD5_DIGEST_SIZE]);
  222#endif
  223
  224    if (IsAtLeastTLSv1_2(ssl)) {
  225#ifndef NO_SHA256
  226        if (ssl->specs.mac_algorithm <= sha256_mac ||
  227            ssl->specs.mac_algorithm == blake2b_mac) {
  228            ret |= wc_Sha256GetHash(&ssl->hsHashes->hashSha256, hash);
  229            hashSz = WC_SHA256_DIGEST_SIZE;
  230        }
  231#endif
  232#ifdef WOLFSSL_SHA384
  233        if (ssl->specs.mac_algorithm == sha384_mac) {
  234            ret |= wc_Sha384GetHash(&ssl->hsHashes->hashSha384, hash);
  235            hashSz = WC_SHA384_DIGEST_SIZE;
  236        }
  237#endif
  238#ifdef WOLFSSL_SM3
  239        if (ssl->specs.mac_algorithm == sm3_mac) {
  240            ret |= wc_Sm3GetHash(&ssl->hsHashes->hashSm3, hash);
  241            hashSz = WC_SM3_DIGEST_SIZE;
  242        }
  243#endif
  244    }
  245
  246    *hashLen = hashSz;
  247#ifdef WOLFSSL_CHECK_MEM_ZERO
  248     wc_MemZero_Add("TLS handshake hash", hash, hashSz);
  249#endif
  250
  251    if (ret != 0) {
  252        ret = BUILD_MSG_ERROR;
  253        WOLFSSL_ERROR_VERBOSE(ret);
  254    }
  255
  256    return ret;
  257}
  258
  259
  260int BuildTlsFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
  261{
  262    int ret;
  263    const byte* side = NULL;
  264    word32 hashSz = HSHASH_SZ;
  265#if !defined(WOLFSSL_ASYNC_CRYPT) || defined(WC_ASYNC_NO_HASH)
  266    byte handshake_hash[HSHASH_SZ];
  267#else
  268    byte* handshake_hash = NULL;
  269    handshake_hash = (byte*)XMALLOC(HSHASH_SZ, ssl->heap, DYNAMIC_TYPE_DIGEST);
  270    if (handshake_hash == NULL)
  271        return MEMORY_E;
  272#endif
  273
  274    XMEMSET(handshake_hash, 0, HSHASH_SZ);
  275    ret = BuildTlsHandshakeHash(ssl, handshake_hash, &hashSz);
  276    if (ret == 0) {
  277        if (XSTRNCMP((const char*)sender, (const char*)kTlsClientStr,
  278                                                          SIZEOF_SENDER) == 0) {
  279            side = kTlsClientFinStr;
  280        }
  281        else if (XSTRNCMP((const char*)sender, (const char*)kTlsServerStr,
  282                                                          SIZEOF_SENDER) == 0) {
  283            side = kTlsServerFinStr;
  284        }
  285        else {
  286            ret = BAD_FUNC_ARG;
  287            WOLFSSL_MSG("Unexpected sender value");
  288        }
  289    }
  290
  291    if (ret == 0) {
  292#ifdef WOLFSSL_HAVE_PRF
  293#if !defined(NO_CERTS) && defined(HAVE_PK_CALLBACKS)
  294        if (ssl->ctx->TlsFinishedCb) {
  295            void* ctx = wolfSSL_GetTlsFinishedCtx(ssl);
  296            ret = ssl->ctx->TlsFinishedCb(ssl, side, handshake_hash, hashSz,
  297                                          (byte*)hashes, ctx);
  298        }
  299        if (!ssl->ctx->TlsFinishedCb ||
  300            ret == WC_NO_ERR_TRACE(PROTOCOLCB_UNAVAILABLE))
  301#endif
  302        {
  303            PRIVATE_KEY_UNLOCK();
  304            ret = wc_PRF_TLS((byte*)hashes, TLS_FINISHED_SZ,
  305                      ssl->arrays->masterSecret, SECRET_LEN, side,
  306                      FINISHED_LABEL_SZ, handshake_hash, hashSz,
  307                      IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm,
  308                      ssl->heap, ssl->devId);
  309            PRIVATE_KEY_LOCK();
  310        }
  311        ForceZero(handshake_hash, hashSz);
  312#else
  313        /* Pseudo random function must be enabled in the configuration. */
  314        ret = PRF_MISSING;
  315        WOLFSSL_ERROR_VERBOSE(ret);
  316        WOLFSSL_MSG("Pseudo-random function is not enabled");
  317
  318        (void)side;
  319        (void)hashes;
  320#endif
  321    }
  322
  323#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
  324    XFREE(handshake_hash, ssl->heap, DYNAMIC_TYPE_DIGEST);
  325#elif defined(WOLFSSL_CHECK_MEM_ZERO)
  326    wc_MemZero_Check(handshake_hash, HSHASH_SZ);
  327#endif
  328
  329    return ret;
  330}
  331
  332#endif /* !WOLFSSL_NO_TLS12 */
  333
  334#ifndef NO_OLD_TLS
  335
  336#ifdef WOLFSSL_ALLOW_TLSV10
  337ProtocolVersion MakeTLSv1(void)
  338{
  339    ProtocolVersion pv;
  340    pv.major = SSLv3_MAJOR;
  341    pv.minor = TLSv1_MINOR;
  342
  343    return pv;
  344}
  345#endif /* WOLFSSL_ALLOW_TLSV10 */
  346
  347
  348ProtocolVersion MakeTLSv1_1(void)
  349{
  350    ProtocolVersion pv;
  351    pv.major = SSLv3_MAJOR;
  352    pv.minor = TLSv1_1_MINOR;
  353
  354    return pv;
  355}
  356
  357#endif /* !NO_OLD_TLS */
  358
  359
  360#ifndef WOLFSSL_NO_TLS12
  361
  362ProtocolVersion MakeTLSv1_2(void)
  363{
  364    ProtocolVersion pv;
  365    pv.major = SSLv3_MAJOR;
  366    pv.minor = TLSv1_2_MINOR;
  367
  368    return pv;
  369}
  370
  371#endif /* !WOLFSSL_NO_TLS12 */
  372
  373#ifdef WOLFSSL_TLS13
  374/* The TLS v1.3 protocol version.
  375 *
  376 * returns the protocol version data for TLS v1.3.
  377 */
  378ProtocolVersion MakeTLSv1_3(void)
  379{
  380    ProtocolVersion pv;
  381    pv.major = SSLv3_MAJOR;
  382    pv.minor = TLSv1_3_MINOR;
  383
  384    return pv;
  385}
  386#endif
  387
  388#if defined(HAVE_SUPPORTED_CURVES)
  389/* Sets the key exchange groups in rank order on a context.
  390 *
  391 * ctx     SSL/TLS context object.
  392 * groups  Array of groups.
  393 * count   Number of groups in array.
  394 * returns BAD_FUNC_ARG when ctx or groups is NULL, not using TLS v1.3 or
  395 * count is greater than WOLFSSL_MAX_GROUP_COUNT and WOLFSSL_SUCCESS on success.
  396 */
  397int wolfSSL_CTX_set_groups(WOLFSSL_CTX* ctx, int* groups, int count)
  398{
  399    int ret, i;
  400
  401    WOLFSSL_ENTER("wolfSSL_CTX_set_groups");
  402    if (ctx == NULL || groups == NULL || count > WOLFSSL_MAX_GROUP_COUNT)
  403        return BAD_FUNC_ARG;
  404    if (!IsTLS_ex(ctx->method->version))
  405        return BAD_FUNC_ARG;
  406
  407    #ifdef WOLFSSL_TLS13
  408    ctx->numGroups = 0;
  409    #endif
  410    #if !defined(NO_TLS)
  411    TLSX_Remove(&ctx->extensions, TLSX_SUPPORTED_GROUPS, ctx->heap);
  412    #endif /* !NO_TLS */
  413    for (i = 0; i < count; i++) {
  414        /* Call to wolfSSL_CTX_UseSupportedCurve also checks if input groups
  415         * are valid */
  416        if ((ret = wolfSSL_CTX_UseSupportedCurve(ctx, (word16)groups[i]))
  417                != WOLFSSL_SUCCESS) {
  418    #if !defined(NO_TLS)
  419            TLSX_Remove(&ctx->extensions, TLSX_SUPPORTED_GROUPS, ctx->heap);
  420    #endif /* !NO_TLS */
  421            return ret;
  422        }
  423        #ifdef WOLFSSL_TLS13
  424        ctx->group[i] = (word16)groups[i];
  425        #endif
  426    }
  427    #ifdef WOLFSSL_TLS13
  428    ctx->numGroups = (byte)count;
  429    #endif
  430
  431    return WOLFSSL_SUCCESS;
  432}
  433
  434/* Sets the key exchange groups in rank order.
  435 *
  436 * ssl     SSL/TLS object.
  437 * groups  Array of groups.
  438 * count   Number of groups in array.
  439 * returns BAD_FUNC_ARG when ssl or groups is NULL, not using TLS v1.3 or
  440 * count is greater than WOLFSSL_MAX_GROUP_COUNT and WOLFSSL_SUCCESS on success.
  441 */
  442int wolfSSL_set_groups(WOLFSSL* ssl, int* groups, int count)
  443{
  444    int ret, i;
  445
  446    WOLFSSL_ENTER("wolfSSL_set_groups");
  447    if (ssl == NULL || groups == NULL || count > WOLFSSL_MAX_GROUP_COUNT)
  448        return BAD_FUNC_ARG;
  449    if (!IsTLS_ex(ssl->version))
  450        return BAD_FUNC_ARG;
  451
  452    #ifdef WOLFSSL_TLS13
  453    ssl->numGroups = 0;
  454    #endif
  455    #if !defined(NO_TLS)
  456    TLSX_Remove(&ssl->extensions, TLSX_SUPPORTED_GROUPS, ssl->heap);
  457    #endif /* !NO_TLS */
  458    for (i = 0; i < count; i++) {
  459        /* Call to wolfSSL_UseSupportedCurve also checks if input groups
  460                 * are valid */
  461        if ((ret = wolfSSL_UseSupportedCurve(ssl, (word16)groups[i]))
  462                != WOLFSSL_SUCCESS) {
  463    #if !defined(NO_TLS)
  464            TLSX_Remove(&ssl->extensions, TLSX_SUPPORTED_GROUPS, ssl->heap);
  465    #endif /* !NO_TLS */
  466            return ret;
  467        }
  468        #ifdef WOLFSSL_TLS13
  469        ssl->group[i] = (word16)groups[i];
  470        #endif
  471    }
  472    #ifdef WOLFSSL_TLS13
  473    ssl->numGroups = (byte)count;
  474    #endif
  475
  476    return WOLFSSL_SUCCESS;
  477}
  478#endif /* HAVE_SUPPORTED_CURVES */
  479
  480#ifndef WOLFSSL_NO_TLS12
  481
  482#ifdef HAVE_EXTENDED_MASTER
  483static const byte ext_master_label[EXT_MASTER_LABEL_SZ + 1] =
  484                                                      "extended master secret";
  485#endif
  486static const byte master_label[MASTER_LABEL_SZ + 1] = "master secret";
  487static const byte key_label   [KEY_LABEL_SZ + 1]    = "key expansion";
  488
  489static int _DeriveTlsKeys(byte* key_dig, word32 key_dig_len,
  490                         const byte* ms, word32 msLen,
  491                         const byte* sr, const byte* cr,
  492                         int tls1_2, int hash_type,
  493                         void* heap, int devId)
  494{
  495    int ret;
  496#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
  497    byte* seed = NULL;
  498    seed = (byte*)XMALLOC(SEED_LEN, heap, DYNAMIC_TYPE_SEED);
  499    if (seed == NULL)
  500        return MEMORY_E;
  501#else
  502    byte seed[SEED_LEN];
  503#endif
  504
  505    XMEMCPY(seed,           sr, RAN_LEN);
  506    XMEMCPY(seed + RAN_LEN, cr, RAN_LEN);
  507
  508#ifdef WOLFSSL_HAVE_PRF
  509    PRIVATE_KEY_UNLOCK();
  510    ret = wc_PRF_TLS(key_dig, key_dig_len, ms, msLen, key_label, KEY_LABEL_SZ,
  511               seed, SEED_LEN, tls1_2, hash_type, heap, devId);
  512    PRIVATE_KEY_LOCK();
  513#else
  514    /* Pseudo random function must be enabled in the configuration. */
  515    ret = PRF_MISSING;
  516    WOLFSSL_ERROR_VERBOSE(ret);
  517    WOLFSSL_MSG("Pseudo-random function is not enabled");
  518
  519    (void)key_dig;
  520    (void)key_dig_len;
  521    (void)ms;
  522    (void)msLen;
  523    (void)tls1_2;
  524    (void)hash_type;
  525    (void)heap;
  526    (void)devId;
  527    (void)key_label;
  528    (void)master_label;
  529#ifdef HAVE_EXTENDED_MASTER
  530    (void)ext_master_label;
  531#endif
  532#endif
  533
  534#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
  535    XFREE(seed, heap, DYNAMIC_TYPE_SEED);
  536#endif
  537
  538    return ret;
  539}
  540
  541/* External facing wrapper so user can call as well, 0 on success */
  542int wolfSSL_DeriveTlsKeys(byte* key_data, word32 keyLen,
  543                         const byte* ms, word32 msLen,
  544                         const byte* sr, const byte* cr,
  545                         int tls1_2, int hash_type)
  546{
  547    return _DeriveTlsKeys(key_data, keyLen, ms, msLen, sr, cr, tls1_2,
  548        hash_type, NULL, INVALID_DEVID);
  549}
  550
  551
  552int DeriveTlsKeys(WOLFSSL* ssl)
  553{
  554    int   ret;
  555    int   key_dig_len = 2 * ssl->specs.hash_size +
  556                        2 * ssl->specs.key_size  +
  557                        2 * ssl->specs.iv_size;
  558    WC_DECLARE_VAR(key_dig, byte, MAX_PRF_DIG, 0);
  559
  560    WC_ALLOC_VAR_EX(key_dig, byte, MAX_PRF_DIG, ssl->heap,
  561        DYNAMIC_TYPE_DIGEST, return MEMORY_E);
  562
  563    XMEMSET(key_dig, 0, MAX_PRF_DIG);
  564
  565#if !defined(NO_CERTS) && defined(HAVE_PK_CALLBACKS)
  566    ret = PROTOCOLCB_UNAVAILABLE;
  567    if (ssl->ctx->GenSessionKeyCb) {
  568        void* ctx = wolfSSL_GetGenSessionKeyCtx(ssl);
  569        ret = ssl->ctx->GenSessionKeyCb(ssl, ctx);
  570    }
  571    if (!ssl->ctx->GenSessionKeyCb ||
  572        ret == WC_NO_ERR_TRACE(PROTOCOLCB_UNAVAILABLE))
  573#endif
  574    ret = _DeriveTlsKeys(key_dig, (word32)key_dig_len,
  575                     ssl->arrays->masterSecret, SECRET_LEN,
  576                     ssl->arrays->serverRandom, ssl->arrays->clientRandom,
  577                     IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm,
  578                     ssl->heap, ssl->devId);
  579    if (ret == 0)
  580        ret = StoreKeys(ssl, key_dig, PROVISION_CLIENT_SERVER);
  581
  582#ifdef WOLFSSL_CHECK_MEM_ZERO
  583    wc_MemZero_Add("DeriveTlsKeys key_dig", key_dig, MAX_PRF_DIG);
  584#endif
  585    ForceZero(key_dig, MAX_PRF_DIG);
  586#ifdef WOLFSSL_CHECK_MEM_ZERO
  587    wc_MemZero_Check(key_dig, MAX_PRF_DIG);
  588#endif
  589
  590    WC_FREE_VAR_EX(key_dig, ssl->heap, DYNAMIC_TYPE_DIGEST);
  591
  592    return ret;
  593}
  594
  595static int _MakeTlsMasterSecret(byte* ms, word32 msLen,
  596                               const byte* pms, word32 pmsLen,
  597                               const byte* cr, const byte* sr,
  598                               int tls1_2, int hash_type,
  599                               void* heap, int devId)
  600{
  601    int ret;
  602#if !defined(WOLFSSL_ASYNC_CRYPT) || defined(WC_ASYNC_NO_HASH)
  603    byte seed[SEED_LEN];
  604#else
  605    byte* seed = NULL;
  606    seed = (byte*)XMALLOC(SEED_LEN, heap, DYNAMIC_TYPE_SEED);
  607    if (seed == NULL)
  608        return MEMORY_E;
  609#endif
  610
  611    XMEMCPY(seed,           cr, RAN_LEN);
  612    XMEMCPY(seed + RAN_LEN, sr, RAN_LEN);
  613
  614#ifdef WOLFSSL_HAVE_PRF
  615    PRIVATE_KEY_UNLOCK();
  616    ret = wc_PRF_TLS(ms, msLen, pms, pmsLen, master_label, MASTER_LABEL_SZ,
  617               seed, SEED_LEN, tls1_2, hash_type, heap, devId);
  618    PRIVATE_KEY_LOCK();
  619#else
  620    /* Pseudo random function must be enabled in the configuration. */
  621    ret = PRF_MISSING;
  622    WOLFSSL_MSG("Pseudo-random function is not enabled");
  623
  624    (void)ms;
  625    (void)msLen;
  626    (void)pms;
  627    (void)pmsLen;
  628    (void)tls1_2;
  629    (void)hash_type;
  630    (void)heap;
  631    (void)devId;
  632#endif
  633
  634#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH)
  635    XFREE(seed, heap, DYNAMIC_TYPE_SEED);
  636#endif
  637
  638    return ret;
  639}
  640
  641/* External facing wrapper so user can call as well, 0 on success */
  642int wolfSSL_MakeTlsMasterSecret(byte* ms, word32 msLen,
  643                               const byte* pms, word32 pmsLen,
  644                               const byte* cr, const byte* sr,
  645                               int tls1_2, int hash_type)
  646{
  647    return _MakeTlsMasterSecret(ms, msLen, pms, pmsLen, cr, sr, tls1_2,
  648        hash_type, NULL, INVALID_DEVID);
  649}
  650
  651
  652#ifdef HAVE_EXTENDED_MASTER
  653
  654static int _MakeTlsExtendedMasterSecret(byte* ms, word32 msLen,
  655                                        const byte* pms, word32 pmsLen,
  656                                        const byte* sHash, word32 sHashLen,
  657                                        int tls1_2, int hash_type,
  658                                        void* heap, int devId)
  659{
  660    int ret;
  661
  662#ifdef WOLFSSL_HAVE_PRF
  663    PRIVATE_KEY_UNLOCK();
  664    ret = wc_PRF_TLS(ms, msLen, pms, pmsLen, ext_master_label, EXT_MASTER_LABEL_SZ,
  665               sHash, sHashLen, tls1_2, hash_type, heap, devId);
  666    PRIVATE_KEY_LOCK();
  667#else
  668    /* Pseudo random function must be enabled in the configuration. */
  669    ret = PRF_MISSING;
  670    WOLFSSL_MSG("Pseudo-random function is not enabled");
  671
  672    (void)ms;
  673    (void)msLen;
  674    (void)pms;
  675    (void)pmsLen;
  676    (void)sHash;
  677    (void)sHashLen;
  678    (void)tls1_2;
  679    (void)hash_type;
  680    (void)heap;
  681    (void)devId;
  682#endif
  683    return ret;
  684}
  685
  686/* External facing wrapper so user can call as well, 0 on success */
  687int wolfSSL_MakeTlsExtendedMasterSecret(byte* ms, word32 msLen,
  688                                        const byte* pms, word32 pmsLen,
  689                                        const byte* sHash, word32 sHashLen,
  690                                        int tls1_2, int hash_type)
  691{
  692    return _MakeTlsExtendedMasterSecret(ms, msLen, pms, pmsLen, sHash, sHashLen,
  693        tls1_2, hash_type, NULL, INVALID_DEVID);
  694}
  695
  696#endif /* HAVE_EXTENDED_MASTER */
  697
  698
  699int MakeTlsMasterSecret(WOLFSSL* ssl)
  700{
  701    int ret;
  702
  703#if defined(WOLFSSL_SNIFFER) && defined(WOLFSSL_SNIFFER_KEYLOGFILE)
  704    /* If this is called from a sniffer session with keylog file support, obtain
  705     * the master secret from the callback */
  706    if (ssl->snifferSecretCb != NULL) {
  707        ret = ssl->snifferSecretCb(ssl->arrays->clientRandom,
  708                                   SNIFFER_SECRET_TLS12_MASTER_SECRET,
  709                                   ssl->arrays->masterSecret);
  710        if (ret != 0) {
  711            return ret;
  712        }
  713        ret = DeriveTlsKeys(ssl);
  714        return ret;
  715    }
  716#endif /* WOLFSSL_SNIFFER && WOLFSSL_SNIFFER_KEYLOGFILE */
  717
  718#ifdef HAVE_EXTENDED_MASTER
  719    if (ssl->options.haveEMS) {
  720        word32 hashSz = HSHASH_SZ;
  721    #ifdef WOLFSSL_SMALL_STACK
  722        byte* handshake_hash = (byte*)XMALLOC(HSHASH_SZ, ssl->heap,
  723                                              DYNAMIC_TYPE_DIGEST);
  724        if (handshake_hash == NULL)
  725            return MEMORY_E;
  726    #else
  727        byte handshake_hash[HSHASH_SZ];
  728    #endif
  729
  730        XMEMSET(handshake_hash, 0, HSHASH_SZ);
  731        ret = BuildTlsHandshakeHash(ssl, handshake_hash, &hashSz);
  732        if (ret == 0) {
  733        #if !defined(NO_CERTS) && defined(HAVE_PK_CALLBACKS)
  734            ret = PROTOCOLCB_UNAVAILABLE;
  735            if (ssl->ctx->GenExtMasterCb) {
  736                void* ctx = wolfSSL_GetGenExtMasterSecretCtx(ssl);
  737                ret = ssl->ctx->GenExtMasterCb(ssl, handshake_hash, hashSz,
  738                                                ctx);
  739            }
  740            if (!ssl->ctx->GenExtMasterCb ||
  741                ret == WC_NO_ERR_TRACE(PROTOCOLCB_UNAVAILABLE))
  742        #endif /* (HAVE_SECRET_CALLBACK) && (HAVE_EXT_SECRET_CALLBACK) */
  743            {
  744                ret = _MakeTlsExtendedMasterSecret(
  745                    ssl->arrays->masterSecret, SECRET_LEN,
  746                    ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz,
  747                    handshake_hash, hashSz,
  748                    IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm,
  749                    ssl->heap, ssl->devId);
  750            }
  751            ForceZero(handshake_hash, hashSz);
  752        }
  753
  754    #ifdef WOLFSSL_SMALL_STACK
  755        XFREE(handshake_hash, ssl->heap, DYNAMIC_TYPE_DIGEST);
  756    #elif defined(WOLFSSL_CHECK_MEM_ZERO)
  757        wc_MemZero_Check(handshake_hash, HSHASH_SZ);
  758    #endif
  759    }
  760    else
  761#endif /* HAVE_EXTENDED_MASTER */
  762    {
  763
  764#if !defined(NO_CERTS) && defined(HAVE_PK_CALLBACKS)
  765        ret = PROTOCOLCB_UNAVAILABLE;
  766        if (ssl->ctx->GenMasterCb) {
  767            void* ctx = wolfSSL_GetGenMasterSecretCtx(ssl);
  768            ret = ssl->ctx->GenMasterCb(ssl, ctx);
  769        }
  770        if (!ssl->ctx->GenMasterCb ||
  771            ret == WC_NO_ERR_TRACE(PROTOCOLCB_UNAVAILABLE))
  772#endif
  773        {
  774            ret = _MakeTlsMasterSecret(ssl->arrays->masterSecret,
  775                      SECRET_LEN, ssl->arrays->preMasterSecret,
  776                      ssl->arrays->preMasterSz, ssl->arrays->clientRandom,
  777                      ssl->arrays->serverRandom, IsAtLeastTLSv1_2(ssl),
  778                      ssl->specs.mac_algorithm, ssl->heap, ssl->devId);
  779        }
  780    }
  781#ifdef HAVE_SECRET_CALLBACK
  782    if (ret == 0 && ssl->tlsSecretCb != NULL) {
  783        ret = ssl->tlsSecretCb(ssl, ssl->arrays->masterSecret,
  784                SECRET_LEN, ssl->tlsSecretCtx);
  785    }
  786#endif /* HAVE_SECRET_CALLBACK */
  787    if (ret == 0) {
  788        ret = DeriveTlsKeys(ssl);
  789    }
  790
  791    return ret;
  792}
  793
  794
  795/* Used by EAP-TLS and EAP-TTLS to derive keying material from
  796 * the master_secret. */
  797int wolfSSL_make_eap_keys(WOLFSSL* ssl, void* key, unsigned int len,
  798                                                              const char* label)
  799{
  800    int   ret;
  801    WC_DECLARE_VAR(seed, byte, SEED_LEN, 0);
  802
  803    WC_ALLOC_VAR_EX(seed, byte, SEED_LEN, ssl->heap, DYNAMIC_TYPE_SEED,
  804        return MEMORY_E);
  805
  806    /*
  807     * As per RFC-5281, the order of the client and server randoms is reversed
  808     * from that used by the TLS protocol to derive keys.
  809     */
  810    XMEMCPY(seed,           ssl->arrays->clientRandom, RAN_LEN);
  811    XMEMCPY(seed + RAN_LEN, ssl->arrays->serverRandom, RAN_LEN);
  812
  813#ifdef WOLFSSL_HAVE_PRF
  814    PRIVATE_KEY_UNLOCK();
  815    ret = wc_PRF_TLS((byte*)key, len, ssl->arrays->masterSecret, SECRET_LEN,
  816              (const byte *)label, (word32)XSTRLEN(label), seed, SEED_LEN,
  817              IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm,
  818              ssl->heap, ssl->devId);
  819    PRIVATE_KEY_LOCK();
  820#else
  821    /* Pseudo random function must be enabled in the configuration. */
  822    ret = PRF_MISSING;
  823    WOLFSSL_MSG("Pseudo-random function is not enabled");
  824
  825    (void)key;
  826    (void)len;
  827    (void)label;
  828#endif
  829
  830    WC_FREE_VAR_EX(seed, ssl->heap, DYNAMIC_TYPE_SEED);
  831
  832    return ret;
  833}
  834
  835/* return HMAC digest type in wolfSSL format */
  836int wolfSSL_GetHmacType(WOLFSSL* ssl)
  837{
  838    if (ssl == NULL)
  839        return BAD_FUNC_ARG;
  840
  841    return wolfSSL_GetHmacType_ex(&ssl->specs);
  842}
  843
  844
  845int wolfSSL_SetTlsHmacInner(WOLFSSL* ssl, byte* inner, word32 sz, int content,
  846                           int verify)
  847{
  848    if (ssl == NULL || inner == NULL)
  849        return BAD_FUNC_ARG;
  850
  851    if (content == dtls12_cid
  852#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_DTLS_CID)
  853       || (ssl->options.dtls && DtlsGetCidTxSize(ssl) > 0)
  854#endif
  855    ) {
  856        WOLFSSL_MSG("wolfSSL_SetTlsHmacInner doesn't support CID");
  857        return BAD_FUNC_ARG;
  858    }
  859
  860    XMEMSET(inner, 0, WOLFSSL_TLS_HMAC_INNER_SZ);
  861
  862    WriteSEQ(ssl, verify, inner);
  863    inner[SEQ_SZ] = (byte)content;
  864    inner[SEQ_SZ + ENUM_LEN]            = ssl->version.major;
  865    inner[SEQ_SZ + ENUM_LEN + ENUM_LEN] = ssl->version.minor;
  866    c16toa((word16)sz, inner + SEQ_SZ + ENUM_LEN + VERSION_SZ);
  867
  868    return 0;
  869}
  870
  871
  872#ifndef WOLFSSL_AEAD_ONLY
  873#if !defined(WOLFSSL_NO_HASH_RAW) && !defined(HAVE_FIPS) && \
  874    !defined(HAVE_SELFTEST)
  875
  876/* Update the hash in the HMAC.
  877 *
  878 * hmac  HMAC object.
  879 * data  Data to be hashed.
  880 * sz    Size of data to hash.
  881 * returns 0 on success, otherwise failure.
  882 */
  883static int Hmac_HashUpdate(Hmac* hmac, const byte* data, word32 sz)
  884{
  885    int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG);
  886
  887    switch (hmac->macType) {
  888    #ifndef NO_SHA
  889        case WC_SHA:
  890            ret = wc_ShaUpdate(&hmac->hash.sha, data, sz);
  891            break;
  892    #endif /* !NO_SHA */
  893
  894    #ifndef NO_SHA256
  895        case WC_SHA256:
  896            ret = wc_Sha256Update(&hmac->hash.sha256, data, sz);
  897            break;
  898    #endif /* !NO_SHA256 */
  899
  900    #ifdef WOLFSSL_SHA384
  901        case WC_SHA384:
  902            ret = wc_Sha384Update(&hmac->hash.sha384, data, sz);
  903            break;
  904    #endif /* WOLFSSL_SHA384 */
  905
  906    #ifdef WOLFSSL_SHA512
  907        case WC_SHA512:
  908            ret = wc_Sha512Update(&hmac->hash.sha512, data, sz);
  909            break;
  910    #endif /* WOLFSSL_SHA512 */
  911
  912    #ifdef WOLFSSL_SM3
  913        case WC_SM3:
  914            ret = wc_Sm3Update(&hmac->hash.sm3, data, sz);
  915            break;
  916    #endif /* WOLFSSL_SM3 */
  917
  918        default:
  919            ret = BAD_FUNC_ARG;
  920            break;
  921    }
  922
  923    return ret;
  924}
  925
  926/* Finalize the hash but don't put the EOC, padding or length in.
  927 *
  928 * hmac  HMAC object.
  929 * hash  Hash result.
  930 * returns 0 on success, otherwise failure.
  931 */
  932static int Hmac_HashFinalRaw(Hmac* hmac, unsigned char* hash)
  933{
  934    int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG);
  935
  936    switch (hmac->macType) {
  937    #ifndef NO_SHA
  938        case WC_SHA:
  939            ret = wc_ShaFinalRaw(&hmac->hash.sha, hash);
  940            break;
  941    #endif /* !NO_SHA */
  942
  943    #ifndef NO_SHA256
  944        case WC_SHA256:
  945            ret = wc_Sha256FinalRaw(&hmac->hash.sha256, hash);
  946            break;
  947    #endif /* !NO_SHA256 */
  948
  949    #ifdef WOLFSSL_SHA384
  950        case WC_SHA384:
  951            ret = wc_Sha384FinalRaw(&hmac->hash.sha384, hash);
  952            break;
  953    #endif /* WOLFSSL_SHA384 */
  954
  955    #ifdef WOLFSSL_SHA512
  956        case WC_SHA512:
  957            ret = wc_Sha512FinalRaw(&hmac->hash.sha512, hash);
  958            break;
  959    #endif /* WOLFSSL_SHA512 */
  960
  961    #ifdef WOLFSSL_SM3
  962        case WC_SM3:
  963            ret = wc_Sm3FinalRaw(&hmac->hash.sm3, hash);
  964            break;
  965    #endif /* WOLFSSL_SM3 */
  966
  967        default:
  968            ret = BAD_FUNC_ARG;
  969            break;
  970    }
  971
  972    return ret;
  973}
  974
  975/* Finalize the HMAC by performing outer hash.
  976 *
  977 * hmac  HMAC object.
  978 * mac   MAC result.
  979 * returns 0 on success, otherwise failure.
  980 */
  981static int Hmac_OuterHash(Hmac* hmac, unsigned char* mac)
  982{
  983    int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG);
  984    WC_DECLARE_VAR(hash, wc_HashAlg, 1, hmac ? hmac->heap : NULL);
  985    enum wc_HashType hashType = (enum wc_HashType)hmac->macType;
  986    int digestSz = wc_HashGetDigestSize(hashType);
  987    int blockSz = wc_HashGetBlockSize(hashType);
  988
  989    WC_ALLOC_VAR_EX(hash, wc_HashAlg, 1, hmac->heap, DYNAMIC_TYPE_HASHES,
  990                    return MEMORY_E);
  991
  992    if ((digestSz >= 0) && (blockSz >= 0)) {
  993        ret = wc_HashInit(hash, hashType);
  994    }
  995    else {
  996        ret = BAD_FUNC_ARG;
  997    }
  998
  999    if (ret == 0) {
 1000        ret = wc_HashUpdate(hash, hashType, (byte*)hmac->opad,
 1001            (word32)blockSz);
 1002        if (ret == 0)
 1003            ret = wc_HashUpdate(hash, hashType, (byte*)hmac->innerHash,
 1004                (word32)digestSz);
 1005        if (ret == 0)
 1006            ret = wc_HashFinal(hash, hashType, mac);
 1007        wc_HashFree(hash, hashType);
 1008    }
 1009
 1010    WC_FREE_VAR_EX(hash, hmac->heap, DYNAMIC_TYPE_HASHES);
 1011    return ret;
 1012}
 1013
 1014/* Calculate the HMAC of the header + message data.
 1015 * Constant time implementation using wc_Sha*FinalRaw().
 1016 *
 1017 * hmac    HMAC object.
 1018 * digest  MAC result.
 1019 * in      Message data.
 1020 * sz      Size of the message data.
 1021 * header  Constructed record header with length of handshake data.
 1022 * headerSz Length of header
 1023 * returns 0 on success, otherwise failure.
 1024 */
 1025static int Hmac_UpdateFinal_CT(Hmac* hmac, byte* digest, const byte* in,
 1026                           word32 sz, int macLen, byte* header, word32 headerSz)
 1027{
 1028    byte         lenBytes[8];
 1029    int          i, j;
 1030    unsigned int k;
 1031    int          blockBits, blockMask;
 1032    int          lastBlockLen, extraLen, eocIndex;
 1033    int          blocks;
 1034    int          safeBlocks;
 1035    int          lenBlock;
 1036    int          eocBlock;
 1037    word32       maxLen;
 1038    int          blockSz, padSz;
 1039    int          ret;
 1040    word32       realLen;
 1041    byte         extraBlock;
 1042
 1043    if (macLen <= 0 || macLen > (int)sizeof(hmac->innerHash))
 1044        return BAD_FUNC_ARG;
 1045
 1046    switch (hmac->macType) {
 1047    #ifndef NO_SHA
 1048        case WC_SHA:
 1049            blockSz = WC_SHA_BLOCK_SIZE;
 1050            blockBits = 6;
 1051            padSz = WC_SHA_BLOCK_SIZE - WC_SHA_PAD_SIZE + 1;
 1052            break;
 1053    #endif /* !NO_SHA */
 1054
 1055    #ifndef NO_SHA256
 1056        case WC_SHA256:
 1057            blockSz = WC_SHA256_BLOCK_SIZE;
 1058            blockBits = 6;
 1059            padSz = WC_SHA256_BLOCK_SIZE - WC_SHA256_PAD_SIZE + 1;
 1060            break;
 1061    #endif /* !NO_SHA256 */
 1062
 1063    #ifdef WOLFSSL_SHA384
 1064        case WC_SHA384:
 1065            blockSz = WC_SHA384_BLOCK_SIZE;
 1066            blockBits = 7;
 1067            padSz = WC_SHA384_BLOCK_SIZE - WC_SHA384_PAD_SIZE + 1;
 1068            break;
 1069    #endif /* WOLFSSL_SHA384 */
 1070
 1071    #ifdef WOLFSSL_SHA512
 1072        case WC_SHA512:
 1073            blockSz = WC_SHA512_BLOCK_SIZE;
 1074            blockBits = 7;
 1075            padSz = WC_SHA512_BLOCK_SIZE - WC_SHA512_PAD_SIZE + 1;
 1076            break;
 1077    #endif /* WOLFSSL_SHA512 */
 1078
 1079    #ifdef WOLFSSL_SM3
 1080        case WC_SM3:
 1081            blockSz = WC_SM3_BLOCK_SIZE;
 1082            blockBits = 6;
 1083            padSz = WC_SM3_BLOCK_SIZE - WC_SM3_PAD_SIZE + 1;
 1084            break;
 1085    #endif /* WOLFSSL_SM3 */
 1086
 1087        default:
 1088            return BAD_FUNC_ARG;
 1089    }
 1090    blockMask = blockSz - 1;
 1091
 1092    /* Size of data to HMAC if padding length byte is zero. */
 1093    maxLen = WOLFSSL_TLS_HMAC_INNER_SZ + sz - 1 - (word32)macLen;
 1094
 1095    /* Complete data (including padding) has block for EOC and/or length. */
 1096    extraBlock = ctSetLTE(((int)maxLen + padSz) & blockMask, padSz);
 1097    /* Total number of blocks for data including padding. */
 1098    blocks = ((int)(maxLen + (word32)blockSz - 1) >> blockBits) + extraBlock;
 1099    /* Up to last 6 blocks can be hashed safely. */
 1100    safeBlocks = blocks - 6;
 1101
 1102    /* Length of message data. */
 1103    realLen = maxLen - in[sz - 1];
 1104    /* Number of message bytes in last block. */
 1105    lastBlockLen = (int)realLen & blockMask;
 1106    /* Number of padding bytes in last block. */
 1107    extraLen = ((blockSz * 2 - padSz - lastBlockLen) & blockMask) + 1;
 1108    /* Number of blocks to create for hash. */
 1109    lenBlock = ((int)realLen + extraLen) >> blockBits;
 1110    /* Block containing EOC byte. */
 1111    eocBlock = (int)(realLen >> (word32)blockBits);
 1112    /* Index of EOC byte in block. */
 1113    eocIndex = (int)(realLen & (word32)blockMask);
 1114
 1115    /* Add length of hmac's ipad to total length. */
 1116    realLen += (word32)blockSz;
 1117    /* Length as bits - 8 bytes bigendian. */
 1118    c32toa(realLen >> ((sizeof(word32) * 8) - 3), lenBytes);
 1119    c32toa(realLen << 3, lenBytes + sizeof(word32));
 1120
 1121    ret = Hmac_HashUpdate(hmac, (unsigned char*)hmac->ipad, (word32)blockSz);
 1122    if (ret != 0)
 1123        return ret;
 1124
 1125    XMEMSET(hmac->innerHash, 0, (size_t)macLen);
 1126
 1127    if (safeBlocks > 0) {
 1128        ret = Hmac_HashUpdate(hmac, header, headerSz);
 1129        if (ret != 0)
 1130            return ret;
 1131        ret = Hmac_HashUpdate(hmac, in, (word32)(safeBlocks * blockSz -
 1132                                WOLFSSL_TLS_HMAC_INNER_SZ));
 1133
 1134        if (ret != 0)
 1135            return ret;
 1136    }
 1137    else
 1138        safeBlocks = 0;
 1139
 1140    XMEMSET(digest, 0, (size_t)macLen);
 1141    k = (unsigned int)(safeBlocks * blockSz);
 1142    for (i = safeBlocks; i < blocks; i++) {
 1143        unsigned char hashBlock[WC_MAX_BLOCK_SIZE];
 1144        unsigned char isEocBlock = ctMaskEq(i, eocBlock);
 1145        unsigned char isOutBlock = ctMaskEq(i, lenBlock);
 1146
 1147        for (j = 0; j < blockSz; j++) {
 1148            unsigned char atEoc = ctMaskEq(j, eocIndex) & isEocBlock;
 1149            volatile unsigned char maskPastEoc = ctMaskGT(j, eocIndex);
 1150            volatile unsigned char pastEoc = maskPastEoc & isEocBlock;
 1151            unsigned char b = 0;
 1152
 1153            if (k < headerSz)
 1154                b = header[k];
 1155            else if (k < maxLen)
 1156                b = in[k - headerSz];
 1157            k++;
 1158
 1159            b = ctMaskSel(atEoc, 0x80, b);
 1160            b &= (unsigned char)~(word32)pastEoc;
 1161            b &= ((unsigned char)~(word32)isOutBlock) | isEocBlock;
 1162
 1163            if (j >= blockSz - 8) {
 1164                b = ctMaskSel(isOutBlock, lenBytes[j - (blockSz - 8)], b);
 1165            }
 1166
 1167            hashBlock[j] = b;
 1168        }
 1169
 1170        /* cppcheck-suppress uninitvar */
 1171        ret = Hmac_HashUpdate(hmac, hashBlock, (word32)blockSz);
 1172        if (ret != 0)
 1173            return ret;
 1174        ret = Hmac_HashFinalRaw(hmac, hashBlock);
 1175        if (ret != 0)
 1176            return ret;
 1177        for (j = 0; j < macLen; j++)
 1178            ((unsigned char*)hmac->innerHash)[j] |= hashBlock[j] & isOutBlock;
 1179    }
 1180
 1181    ret = Hmac_OuterHash(hmac, digest);
 1182
 1183    return ret;
 1184}
 1185
 1186#endif
 1187
 1188#if defined(WOLFSSL_NO_HASH_RAW) || defined(HAVE_FIPS) || \
 1189    defined(HAVE_SELFTEST) || defined(HAVE_BLAKE2B)
 1190
 1191/* Calculate the HMAC of the header + message data.
 1192 * Constant time implementation using normal hashing operations.
 1193 * Update-Final need to be constant time.
 1194 *
 1195 * hmac    HMAC object.
 1196 * digest  MAC result.
 1197 * in      Message data.
 1198 * sz      Size of the message data.
 1199 * header  Constructed record header with length of handshake data.
 1200 * headerSz Length of header
 1201 * returns 0 on success, otherwise failure.
 1202 */
 1203static int Hmac_UpdateFinal(Hmac* hmac, byte* digest, const byte* in,
 1204                            word32 sz, byte* header, word32 headerSz)
 1205{
 1206    byte       dummy[WC_MAX_BLOCK_SIZE] = {0};
 1207    int        ret = 0;
 1208    word32     msgSz, blockSz, macSz, padSz, maxSz, realSz;
 1209    word32     offset = 0;
 1210    int        msgBlocks, blocks, blockBits;
 1211    int        i;
 1212
 1213    switch (hmac->macType) {
 1214    #ifndef NO_SHA
 1215        case WC_SHA:
 1216            blockSz = WC_SHA_BLOCK_SIZE;
 1217            blockBits = 6;
 1218            macSz = WC_SHA_DIGEST_SIZE;
 1219            padSz = WC_SHA_BLOCK_SIZE - WC_SHA_PAD_SIZE + 1;
 1220            break;
 1221    #endif /* !NO_SHA */
 1222
 1223    #ifndef NO_SHA256
 1224        case WC_SHA256:
 1225            blockSz = WC_SHA256_BLOCK_SIZE;
 1226            blockBits = 6;
 1227            macSz = WC_SHA256_DIGEST_SIZE;
 1228            padSz = WC_SHA256_BLOCK_SIZE - WC_SHA256_PAD_SIZE + 1;
 1229            break;
 1230    #endif /* !NO_SHA256 */
 1231
 1232    #ifdef WOLFSSL_SHA384
 1233        case WC_SHA384:
 1234            blockSz = WC_SHA384_BLOCK_SIZE;
 1235            blockBits = 7;
 1236            macSz = WC_SHA384_DIGEST_SIZE;
 1237            padSz = WC_SHA384_BLOCK_SIZE - WC_SHA384_PAD_SIZE + 1;
 1238            break;
 1239    #endif /* WOLFSSL_SHA384 */
 1240
 1241    #ifdef WOLFSSL_SHA512
 1242        case WC_SHA512:
 1243            blockSz = WC_SHA512_BLOCK_SIZE;
 1244            blockBits = 7;
 1245            macSz = WC_SHA512_DIGEST_SIZE;
 1246            padSz = WC_SHA512_BLOCK_SIZE - WC_SHA512_PAD_SIZE + 1;
 1247            break;
 1248    #endif /* WOLFSSL_SHA512 */
 1249
 1250    #ifdef HAVE_BLAKE2B
 1251        case WC_HASH_TYPE_BLAKE2B:
 1252            blockSz = BLAKE2B_BLOCKBYTES;
 1253            blockBits = 7;
 1254            macSz = BLAKE2B_256;
 1255            padSz = 0;
 1256            break;
 1257    #endif /* HAVE_BLAKE2B */
 1258
 1259    #ifdef WOLFSSL_SM3
 1260        case WC_SM3:
 1261            blockSz = WC_SM3_BLOCK_SIZE;
 1262            blockBits = 6;
 1263            macSz = WC_SM3_DIGEST_SIZE;
 1264            padSz = WC_SM3_BLOCK_SIZE - WC_SM3_PAD_SIZE + 1;
 1265            break;
 1266    #endif
 1267
 1268        default:
 1269            WOLFSSL_MSG("ERROR: Hmac_UpdateFinal failed, no hmac->macType");
 1270            return BAD_FUNC_ARG;
 1271    }
 1272
 1273    msgSz = sz - (1 + in[sz - 1] + macSz);
 1274    /* Make negative result 0 */
 1275    msgSz &= ~(0 - (msgSz >> 31));
 1276    realSz = WOLFSSL_TLS_HMAC_INNER_SZ + msgSz;
 1277    maxSz = WOLFSSL_TLS_HMAC_INNER_SZ + (sz - 1) - macSz;
 1278    /* Make negative result 0 */
 1279    maxSz &= ~(0 - (maxSz >> 31));
 1280
 1281    /* Calculate #blocks processed in HMAC for max and real data. */
 1282    blocks      = (int)(maxSz >> blockBits);
 1283    blocks     += ((maxSz + padSz) % blockSz) < padSz;
 1284    msgBlocks   = (int)(realSz >> blockBits);
 1285    /* #Extra blocks to process. */
 1286    blocks -= msgBlocks + ((((realSz + padSz) % blockSz) < padSz) ? 1 : 0);
 1287    /* Calculate whole blocks. */
 1288    msgBlocks--;
 1289
 1290    ret = wc_HmacUpdate(hmac, header, headerSz);
 1291    if (ret == 0) {
 1292        /* Fill the rest of the block with any available data. */
 1293        word32 currSz = ctMaskLT((int)msgSz, (int)blockSz) & msgSz;
 1294        currSz |= ctMaskGTE((int)msgSz, (int)blockSz) & blockSz;
 1295        currSz -= WOLFSSL_TLS_HMAC_INNER_SZ;
 1296        currSz &= ~(0 - (currSz >> 31));
 1297        ret = wc_HmacUpdate(hmac, in, currSz);
 1298        offset = currSz;
 1299    }
 1300    if (ret == 0) {
 1301        /* Do the hash operations on a block basis. */
 1302        for (i = 0; i < msgBlocks; i++, offset += blockSz) {
 1303            ret = wc_HmacUpdate(hmac, in + offset, blockSz);
 1304            if (ret != 0)
 1305                break;
 1306        }
 1307    }
 1308    if (ret == 0)
 1309        ret = wc_HmacUpdate(hmac, in + offset, msgSz - offset);
 1310    if (ret == 0)
 1311        ret = wc_HmacFinal(hmac, digest);
 1312    if (ret == 0) {
 1313        /* Do the dummy hash operations. Do at least one. */
 1314        for (i = 0; i < blocks + 1; i++) {
 1315            ret = wc_HmacUpdate(hmac, dummy, blockSz);
 1316            if (ret != 0)
 1317                break;
 1318        }
 1319    }
 1320
 1321    return ret;
 1322}
 1323
 1324#endif
 1325
 1326#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_DTLS_CID)
 1327#define TLS_HMAC_CID_SZ(s, v) \
 1328                ((v) ? DtlsGetCidRxSize((s)) \
 1329                     : DtlsGetCidTxSize((s)))
 1330#define TLS_HMAC_CID(s, v, b, c) \
 1331                ((v) ? wolfSSL_dtls_cid_get_rx((s), (b), (c)) \
 1332                     : wolfSSL_dtls_cid_get_tx((s), (b), (c)))
 1333#endif
 1334
 1335static int TLS_hmac_SetInner(WOLFSSL* ssl, byte* inner, word32* innerSz,
 1336        word32 sz, int content, int verify, int epochOrder)
 1337{
 1338#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_DTLS_CID)
 1339    unsigned int cidSz = 0;
 1340    if (ssl->options.dtls && (cidSz = TLS_HMAC_CID_SZ(ssl, verify)) > 0) {
 1341        word32 idx = 0;
 1342        if (cidSz > DTLS_CID_MAX_SIZE) {
 1343            WOLFSSL_MSG("DTLS CID too large");
 1344            return DTLS_CID_ERROR;
 1345        }
 1346
 1347        XMEMSET(inner + idx, 0xFF, SEQ_SZ);
 1348        idx += SEQ_SZ;
 1349        inner[idx++] = dtls12_cid;
 1350        inner[idx++] = (byte)cidSz;
 1351        inner[idx++] = dtls12_cid;
 1352        inner[idx++] = ssl->version.major;
 1353        inner[idx++] = ssl->version.minor;
 1354        WriteSEQ(ssl, epochOrder, inner + idx);
 1355        idx += SEQ_SZ;
 1356        if (TLS_HMAC_CID(ssl, verify, inner + idx, cidSz) ==
 1357                WC_NO_ERR_TRACE(WOLFSSL_FAILURE)) {
 1358            WOLFSSL_MSG("DTLS CID write failed");
 1359            return DTLS_CID_ERROR;
 1360        }
 1361        idx += cidSz;
 1362        c16toa((word16)sz, inner + idx);
 1363        idx += LENGTH_SZ;
 1364
 1365        *innerSz = idx;
 1366        return 0;
 1367    }
 1368#endif
 1369    *innerSz = WOLFSSL_TLS_HMAC_INNER_SZ;
 1370    return wolfSSL_SetTlsHmacInner(ssl, inner, sz, content,
 1371            !ssl->options.dtls ? verify : epochOrder);
 1372}
 1373
 1374#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_DTLS_CID)
 1375#define TLS_HMAC_INNER_SZ WOLFSSL_TLS_HMAC_CID_INNER_SZ
 1376#else
 1377#define TLS_HMAC_INNER_SZ WOLFSSL_TLS_HMAC_INNER_SZ
 1378#endif
 1379
 1380int TLS_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, int padSz,
 1381             int content, int verify, int epochOrder)
 1382{
 1383    WC_DECLARE_VAR(hmac, Hmac, 1, ssl ? ssl->heap : NULL);
 1384    byte   myInner[TLS_HMAC_INNER_SZ];
 1385    word32 innerSz = TLS_HMAC_INNER_SZ;
 1386    int    ret = 0;
 1387    const byte* macSecret = NULL;
 1388    word32 hashSz = 0;
 1389    word32 totalSz = 0;
 1390
 1391    if (ssl == NULL)
 1392        return BAD_FUNC_ARG;
 1393
 1394    WC_ALLOC_VAR_EX(hmac, Hmac, 1, ssl->heap, DYNAMIC_TYPE_HMAC,
 1395                    return MEMORY_E);
 1396
 1397#ifdef HAVE_TRUNCATED_HMAC
 1398    hashSz = ssl->truncated_hmac ? (byte)TRUNCATED_HMAC_SZ
 1399                                        : ssl->specs.hash_size;
 1400#else
 1401    hashSz = ssl->specs.hash_size;
 1402#endif
 1403
 1404    /* Pre-compute sz + hashSz + padSz + 1 with overflow checking.
 1405     * Used by fuzzer callback and Hmac_UpdateFinal* in the verify path. */
 1406    if (verify && padSz >= 0) {
 1407        word32 hmacSz = 0;
 1408        if (!WC_SAFE_SUM_WORD32(sz, hashSz, hmacSz) ||
 1409            !WC_SAFE_SUM_WORD32(hmacSz, (word32)padSz, hmacSz) ||
 1410            !WC_SAFE_SUM_WORD32(hmacSz, 1, hmacSz)) {
 1411            WC_FREE_VAR_EX(hmac, ssl->heap, DYNAMIC_TYPE_HMAC);
 1412            return BUFFER_E;
 1413        }
 1414        totalSz = hmacSz;
 1415    }
 1416
 1417#ifdef HAVE_FUZZER
 1418    /* Fuzz "in" buffer with sz to be used in HMAC algorithm */
 1419    if (ssl->fuzzerCb) {
 1420        if (verify && padSz >= 0) {
 1421            ssl->fuzzerCb(ssl, in, totalSz, FUZZ_HMAC,
 1422                          ssl->fuzzerCtx);
 1423        }
 1424        else {
 1425            ssl->fuzzerCb(ssl, in, sz, FUZZ_HMAC, ssl->fuzzerCtx);
 1426        }
 1427    }
 1428#endif
 1429
 1430    ret = TLS_hmac_SetInner(ssl, myInner, &innerSz, sz, content, verify,
 1431                            epochOrder);
 1432    if (ret != 0) {
 1433        WC_FREE_VAR_EX(hmac, ssl->heap, DYNAMIC_TYPE_HMAC);
 1434        return ret;
 1435    }
 1436
 1437    ret = wc_HmacInit(hmac, ssl->heap, ssl->devId);
 1438    if (ret != 0) {
 1439        WC_FREE_VAR_EX(hmac, ssl->heap, DYNAMIC_TYPE_HMAC);
 1440        return ret;
 1441    }
 1442
 1443
 1444#ifdef WOLFSSL_DTLS
 1445    if (ssl->options.dtls)
 1446        macSecret = wolfSSL_GetDtlsMacSecret(ssl, verify, epochOrder);
 1447    else
 1448#endif
 1449        macSecret = wolfSSL_GetMacSecret(ssl, verify);
 1450    ret = wc_HmacSetKey(hmac, wolfSSL_GetHmacType(ssl),
 1451                                              macSecret,
 1452                                              ssl->specs.hash_size);
 1453
 1454    if (ret == 0) {
 1455        /* Constant time verification required. */
 1456        if (verify && padSz >= 0) {
 1457#if !defined(WOLFSSL_NO_HASH_RAW) && !defined(HAVE_FIPS) && \
 1458    !defined(HAVE_SELFTEST)
 1459    #ifdef HAVE_BLAKE2B
 1460            if (wolfSSL_GetHmacType(ssl) == WC_HASH_TYPE_BLAKE2B) {
 1461                ret = Hmac_UpdateFinal(hmac, digest, in,
 1462                        totalSz, myInner, innerSz);
 1463            }
 1464            else
 1465    #endif
 1466            {
 1467                ret = Hmac_UpdateFinal_CT(hmac, digest, in,
 1468                                      totalSz,
 1469                                      (int)hashSz, myInner, innerSz);
 1470
 1471            }
 1472#else
 1473            ret = Hmac_UpdateFinal(hmac, digest, in, totalSz,
 1474                                        myInner, innerSz);
 1475#endif
 1476        }
 1477        else {
 1478            ret = wc_HmacUpdate(hmac, myInner, innerSz);
 1479            if (ret == 0)
 1480                ret = wc_HmacUpdate(hmac, in, sz);                /* content */
 1481            if (ret == 0)
 1482                ret = wc_HmacFinal(hmac, digest);
 1483        }
 1484    }
 1485
 1486    wc_HmacFree(hmac);
 1487    WC_FREE_VAR_EX(hmac, ssl->heap, DYNAMIC_TYPE_HMAC);
 1488
 1489    return ret;
 1490}
 1491#endif /* WOLFSSL_AEAD_ONLY */
 1492
 1493#endif /* !WOLFSSL_NO_TLS12 */
 1494
 1495int wolfSSL_GetHmacType_ex(CipherSpecs* specs)
 1496{
 1497    if (specs == NULL)
 1498        return BAD_FUNC_ARG;
 1499
 1500    switch (specs->mac_algorithm) {
 1501        #ifndef NO_MD5
 1502        case md5_mac:
 1503        {
 1504            return WC_MD5;
 1505        }
 1506        #endif
 1507        #ifndef NO_SHA256
 1508        case sha256_mac:
 1509        {
 1510            return WC_SHA256;
 1511        }
 1512        #endif
 1513        #ifdef WOLFSSL_SHA384
 1514        case sha384_mac:
 1515        {
 1516            return WC_SHA384;
 1517        }
 1518        #endif
 1519        #ifdef WOLFSSL_SM3
 1520        case sm3_mac:
 1521        {
 1522            return WC_SM3;
 1523        }
 1524        #endif
 1525        #ifndef NO_SHA
 1526        case sha_mac:
 1527        {
 1528            return WC_SHA;
 1529        }
 1530        #endif
 1531        #ifdef HAVE_BLAKE2B
 1532        case blake2b_mac:
 1533        {
 1534            return BLAKE2B_ID;
 1535        }
 1536        #endif
 1537        default:
 1538        {
 1539            return WOLFSSL_FATAL_ERROR;
 1540        }
 1541    }
 1542}
 1543
 1544#ifdef HAVE_TLS_EXTENSIONS
 1545
 1546/**
 1547 * The TLSX semaphore is used to calculate the size of the extensions to be sent
 1548 * from one peer to another.
 1549 */
 1550
 1551/** Supports up to 72 flags. Increase as needed. */
 1552#define SEMAPHORE_SIZE 9
 1553
 1554/**
 1555 * Converts the extension type (id) to an index in the semaphore.
 1556 *
 1557 * Official reference for TLS extension types:
 1558 *   http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xml
 1559 *
 1560 * Motivation:
 1561 *   Previously, we used the extension type itself as the index of that
 1562 *   extension in the semaphore as the extension types were declared
 1563 *   sequentially, but maintain a semaphore as big as the number of available
 1564 *   extensions is no longer an option since the release of renegotiation_info.
 1565 *
 1566 * How to update:
 1567 *   Assign extension types that extrapolate the number of available semaphores
 1568 *   to the first available index going backwards in the semaphore array.
 1569 *   When adding a new extension type that don't extrapolate the number of
 1570 *   available semaphores, check for a possible collision with with a
 1571 *   'remapped' extension type.
 1572 *
 1573 * Update TLSX_Parse for duplicate detection if more added above 62.
 1574 */
 1575static WC_INLINE word16 TLSX_ToSemaphore(word16 type)
 1576{
 1577    switch (type) {
 1578
 1579        case TLSX_RENEGOTIATION_INFO: /* 0xFF01 */
 1580            return 63;
 1581#ifdef WOLFSSL_QUIC
 1582        case TLSX_KEY_QUIC_TP_PARAMS_DRAFT: /* 0xffa5 */
 1583            return 64;
 1584#endif
 1585#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
 1586        case TLSX_ECH: /* 0xfe0d */
 1587            return 65;
 1588#endif
 1589#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_DUAL_ALG_CERTS)
 1590        case TLSX_CKS:
 1591            return 66;
 1592#endif
 1593        default:
 1594            if (type > 62) {
 1595                /* This message SHOULD only happens during the adding of
 1596                   new TLS extensions in which its IANA number overflows
 1597                   the current semaphore's range, or if its number already
 1598                   is assigned to be used by another extension.
 1599                   Use this check value for the new extension and decrement
 1600                   the check value by one. */
 1601                WOLFSSL_MSG("### TLSX semaphore collision or overflow detected!");
 1602            }
 1603    }
 1604
 1605    return type;
 1606}
 1607
 1608/** Checks if a specific light (tls extension) is not set in the semaphore. */
 1609#define IS_OFF(semaphore, light) \
 1610    (!(((semaphore)[(light) / 8] &  (byte) (0x01 << ((light) % 8)))))
 1611
 1612/** Turn on a specific light (tls extension) in the semaphore. */
 1613/* the semaphore marks the extensions already written to the message */
 1614#define TURN_ON(semaphore, light) \
 1615    ((semaphore)[(light) / 8] |= (byte) (0x01 << ((light) % 8)))
 1616
 1617/** Turn off a specific light (tls extension) in the semaphore. */
 1618#define TURN_OFF(semaphore, light) \
 1619    ((semaphore)[(light) / 8] &= (byte) ~(0x01 << ((light) % 8)))
 1620
 1621/** Creates a new extension. */
 1622static TLSX* TLSX_New(TLSX_Type type, const void* data, void* heap)
 1623{
 1624    TLSX* extension = (TLSX*)XMALLOC(sizeof(TLSX), heap, DYNAMIC_TYPE_TLSX);
 1625
 1626    (void)heap;
 1627
 1628    if (extension) {
 1629        extension->type = type;
 1630        extension->data = (void*)data;
 1631        extension->resp = 0;
 1632        extension->next = NULL;
 1633    }
 1634
 1635    return extension;
 1636}
 1637
 1638/**
 1639 * Creates a new extension and appends it to the provided list.
 1640 * Checks for duplicate extensions, keeps the newest.
 1641 */
 1642int TLSX_Append(TLSX** list, TLSX_Type type, const void* data, void* heap)
 1643{
 1644    TLSX* extension = TLSX_New(type, data, heap);
 1645    TLSX* cur;
 1646    TLSX** prevNext = list;
 1647
 1648    if (extension == NULL)
 1649        return MEMORY_E;
 1650
 1651    for (cur = *list; cur != NULL;) {
 1652        if (cur->type == type) {
 1653            *prevNext = cur->next;
 1654            cur->next = NULL;
 1655            TLSX_FreeAll(cur, heap);
 1656            cur = *prevNext;
 1657        }
 1658        else {
 1659            prevNext = &cur->next;
 1660            cur = cur->next;
 1661        }
 1662    }
 1663
 1664    /* Append the extension to the list */
 1665    *prevNext = extension;
 1666
 1667    return 0;
 1668}
 1669
 1670/**
 1671 * Creates a new extension and pushes it to the provided list.
 1672 * Checks for duplicate extensions, keeps the newest.
 1673 */
 1674int TLSX_Push(TLSX** list, TLSX_Type type, const void* data, void* heap)
 1675{
 1676    TLSX* extension = TLSX_New(type, data, heap);
 1677
 1678    if (extension == NULL)
 1679        return MEMORY_E;
 1680
 1681    /* pushes the new extension on the list. */
 1682    extension->next = *list;
 1683    *list = extension;
 1684
 1685    /* remove duplicate extensions, there should be only one of each type. */
 1686    do {
 1687        if (extension->next && extension->next->type == type) {
 1688            TLSX *next = extension->next;
 1689
 1690            extension->next = next->next;
 1691            next->next = NULL;
 1692
 1693            TLSX_FreeAll(next, heap);
 1694
 1695            /* there is no way to occur more than
 1696             * two extensions of the same type.
 1697             */
 1698            break;
 1699        }
 1700    } while ((extension = extension->next));
 1701
 1702    return 0;
 1703}
 1704
 1705#ifndef NO_WOLFSSL_CLIENT
 1706
 1707int TLSX_CheckUnsupportedExtension(WOLFSSL* ssl, TLSX_Type type);
 1708
 1709int TLSX_CheckUnsupportedExtension(WOLFSSL* ssl, TLSX_Type type)
 1710{
 1711    TLSX *extension = TLSX_Find(ssl->extensions, type);
 1712
 1713    if (!extension)
 1714        extension = TLSX_Find(ssl->ctx->extensions, type);
 1715
 1716    return extension == NULL;
 1717}
 1718
 1719int TLSX_HandleUnsupportedExtension(WOLFSSL* ssl);
 1720
 1721int TLSX_HandleUnsupportedExtension(WOLFSSL* ssl)
 1722{
 1723    SendAlert(ssl, alert_fatal, unsupported_extension);
 1724    WOLFSSL_ERROR_VERBOSE(UNSUPPORTED_EXTENSION);
 1725    return UNSUPPORTED_EXTENSION;
 1726}
 1727
 1728#else
 1729
 1730#define TLSX_CheckUnsupportedExtension(ssl, type) 0
 1731#define TLSX_HandleUnsupportedExtension(ssl) 0
 1732
 1733#endif
 1734
 1735#if !defined(NO_WOLFSSL_SERVER) || defined(WOLFSSL_TLS13)
 1736void TLSX_SetResponse(WOLFSSL* ssl, TLSX_Type type);
 1737/** Mark an extension to be sent back to the client. */
 1738void TLSX_SetResponse(WOLFSSL* ssl, TLSX_Type type)
 1739{
 1740    TLSX *extension = TLSX_Find(ssl->extensions, type);
 1741
 1742    if (extension)
 1743        extension->resp = 1;
 1744}
 1745#endif
 1746
 1747/******************************************************************************/
 1748/* Application-Layer Protocol Negotiation                                     */
 1749/******************************************************************************/
 1750
 1751#ifdef HAVE_ALPN
 1752/** Creates a new ALPN object, providing protocol name to use. */
 1753static ALPN* TLSX_ALPN_New(char *protocol_name, word16 protocol_nameSz,
 1754                                                                     void* heap)
 1755{
 1756    ALPN *alpn;
 1757
 1758    WOLFSSL_ENTER("TLSX_ALPN_New");
 1759
 1760    if (protocol_name == NULL ||
 1761        protocol_nameSz > WOLFSSL_MAX_ALPN_PROTO_NAME_LEN) {
 1762        WOLFSSL_MSG("Invalid arguments");
 1763        return NULL;
 1764    }
 1765
 1766    alpn = (ALPN*)XMALLOC(sizeof(ALPN), heap, DYNAMIC_TYPE_TLSX);
 1767    if (alpn == NULL) {
 1768        WOLFSSL_MSG("Memory failure");
 1769        return NULL;
 1770    }
 1771
 1772    alpn->next = NULL;
 1773    alpn->negotiated = 0;
 1774    alpn->options = 0;
 1775
 1776    alpn->protocol_name = (char*)XMALLOC(protocol_nameSz + 1,
 1777                                         heap, DYNAMIC_TYPE_TLSX);
 1778    if (alpn->protocol_name == NULL) {
 1779        WOLFSSL_MSG("Memory failure");
 1780        XFREE(alpn, heap, DYNAMIC_TYPE_TLSX);
 1781        return NULL;
 1782    }
 1783
 1784    XMEMCPY(alpn->protocol_name, protocol_name, protocol_nameSz);
 1785    alpn->protocol_name[protocol_nameSz] = 0;
 1786
 1787    (void)heap;
 1788
 1789    return alpn;
 1790}
 1791
 1792/** Releases an ALPN object. */
 1793static void TLSX_ALPN_Free(ALPN *alpn, void* heap)
 1794{
 1795    (void)heap;
 1796
 1797    if (alpn == NULL)
 1798        return;
 1799
 1800    XFREE(alpn->protocol_name, heap, DYNAMIC_TYPE_TLSX);
 1801    XFREE(alpn, heap, DYNAMIC_TYPE_TLSX);
 1802}
 1803
 1804/** Releases all ALPN objects in the provided list. */
 1805static void TLSX_ALPN_FreeAll(ALPN *list, void* heap)
 1806{
 1807    ALPN* alpn;
 1808
 1809    while ((alpn = list)) {
 1810        list = alpn->next;
 1811        TLSX_ALPN_Free(alpn, heap);
 1812    }
 1813}
 1814
 1815/** Tells the buffered size of the ALPN objects in a list. */
 1816static word16 TLSX_ALPN_GetSize(ALPN *list)
 1817{
 1818    ALPN* alpn;
 1819    word32 length = OPAQUE16_LEN; /* list length */
 1820
 1821    while ((alpn = list)) {
 1822        list = alpn->next;
 1823
 1824        length++; /* protocol name length is on one byte */
 1825        length += (word32)XSTRLEN(alpn->protocol_name);
 1826
 1827        if (length > WOLFSSL_MAX_16BIT) {
 1828            return 0;
 1829        }
 1830    }
 1831
 1832    return (word16)length;
 1833}
 1834
 1835/** Writes the ALPN objects of a list in a buffer. */
 1836static word16 TLSX_ALPN_Write(ALPN *list, byte *output)
 1837{
 1838    ALPN* alpn;
 1839    word16 length = 0;
 1840    word16 offset = OPAQUE16_LEN; /* list length offset */
 1841
 1842    while ((alpn = list)) {
 1843        list = alpn->next;
 1844
 1845        length = (word16)XSTRLEN(alpn->protocol_name);
 1846
 1847        /* protocol name length */
 1848        output[offset++] = (byte)length;
 1849
 1850        /* protocol name value */
 1851        XMEMCPY(output + offset, alpn->protocol_name, length);
 1852
 1853        offset += length;
 1854    }
 1855
 1856    /* writing list length */
 1857    c16toa(offset - OPAQUE16_LEN, output);
 1858
 1859    return offset;
 1860}
 1861
 1862/** Finds a protocol name in the provided ALPN list */
 1863static ALPN* TLSX_ALPN_Find(ALPN *list, char *protocol_name, word16 size)
 1864{
 1865    ALPN *alpn;
 1866
 1867    if (list == NULL || protocol_name == NULL)
 1868        return NULL;
 1869
 1870    alpn = list;
 1871    while (alpn != NULL && (
 1872           (word16)XSTRLEN(alpn->protocol_name) != size ||
 1873           XSTRNCMP(alpn->protocol_name, protocol_name, size)))
 1874        alpn = alpn->next;
 1875
 1876    return alpn;
 1877}
 1878
 1879/** Set the ALPN matching client and server requirements */
 1880static int TLSX_SetALPN(TLSX** extensions, const void* data, word16 size,
 1881                                                                     void* heap)
 1882{
 1883    ALPN *alpn;
 1884    int  ret;
 1885
 1886    if (extensions == NULL || data == NULL)
 1887        return BAD_FUNC_ARG;
 1888
 1889    alpn = TLSX_ALPN_New((char *)data, size, heap);
 1890    if (alpn == NULL) {
 1891        WOLFSSL_MSG("Memory failure");
 1892        return MEMORY_E;
 1893    }
 1894
 1895    alpn->negotiated = 1;
 1896
 1897    ret = TLSX_Push(extensions, TLSX_APPLICATION_LAYER_PROTOCOL, (void*)alpn,
 1898                                                                          heap);
 1899    if (ret != 0) {
 1900        TLSX_ALPN_Free(alpn, heap);
 1901        return ret;
 1902    }
 1903
 1904    return WOLFSSL_SUCCESS;
 1905}
 1906
 1907static int ALPN_find_match(WOLFSSL *ssl, TLSX **pextension,
 1908                           const byte **psel, byte *psel_len,
 1909                           const byte *alpn_val, word16 alpn_val_len)
 1910{
 1911    TLSX    *extension;
 1912    ALPN    *alpn, *list;
 1913    const byte *sel = NULL, *s;
 1914    byte sel_len = 0, wlen;
 1915
 1916    extension = TLSX_Find(ssl->extensions, TLSX_APPLICATION_LAYER_PROTOCOL);
 1917    if (extension == NULL)
 1918        extension = TLSX_Find(ssl->ctx->extensions,
 1919                              TLSX_APPLICATION_LAYER_PROTOCOL);
 1920
 1921    /* No ALPN configured here */
 1922    if (extension == NULL || extension->data == NULL) {
 1923        *pextension = NULL;
 1924        *psel = NULL;
 1925        *psel_len = 0;
 1926        return 0;
 1927    }
 1928
 1929    list = (ALPN*)extension->data;
 1930    for (s = alpn_val;
 1931         (s - alpn_val) < alpn_val_len;
 1932         s += wlen) {
 1933        wlen = *s++; /* bounds already checked on save */
 1934        alpn = TLSX_ALPN_Find(list, (char*)s, wlen);
 1935        if (alpn != NULL) {
 1936            WOLFSSL_MSG("ALPN protocol match");
 1937            sel = s,
 1938            sel_len = wlen;
 1939            break;
 1940        }
 1941    }
 1942
 1943    if (sel == NULL) {
 1944        WOLFSSL_MSG("No ALPN protocol match");
 1945
 1946        /* do nothing if no protocol match between client and server and option
 1947         is set to continue (like OpenSSL) */
 1948        if (list->options & WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) {
 1949            WOLFSSL_MSG("Continue on mismatch");
 1950        }
 1951        else {
 1952            SendAlert(ssl, alert_fatal, no_application_protocol);
 1953            WOLFSSL_ERROR_VERBOSE(UNKNOWN_ALPN_PROTOCOL_NAME_E);
 1954            return UNKNOWN_ALPN_PROTOCOL_NAME_E;
 1955        }
 1956    }
 1957
 1958    *pextension = extension;
 1959    *psel = sel;
 1960    *psel_len = sel_len;
 1961    return 0;
 1962}
 1963
 1964int ALPN_Select(WOLFSSL *ssl)
 1965{
 1966    TLSX *extension;
 1967    const byte *sel = NULL;
 1968    byte sel_len = 0;
 1969    int r = 0;
 1970
 1971    WOLFSSL_ENTER("ALPN_Select");
 1972    if (ssl->alpn_peer_requested == NULL)
 1973        return 0;
 1974
 1975#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
 1976    if (ssl->alpnSelect != NULL && ssl->options.side == WOLFSSL_SERVER_END) {
 1977        r = ssl->alpnSelect(ssl, &sel, &sel_len, ssl->alpn_peer_requested,
 1978                ssl->alpn_peer_requested_length, ssl->alpnSelectArg);
 1979        switch (r) {
 1980            case SSL_TLSEXT_ERR_OK:
 1981                WOLFSSL_MSG("ALPN protocol match");
 1982                break;
 1983            case SSL_TLSEXT_ERR_NOACK:
 1984                WOLFSSL_MSG("ALPN cb no match but not fatal");
 1985                sel = NULL;
 1986                sel_len = 0;
 1987                break;
 1988            case SSL_TLSEXT_ERR_ALERT_FATAL:
 1989            default:
 1990                WOLFSSL_MSG("ALPN cb no match and fatal");
 1991                SendAlert(ssl, alert_fatal, no_application_protocol);
 1992                WOLFSSL_ERROR_VERBOSE(UNKNOWN_ALPN_PROTOCOL_NAME_E);
 1993                return UNKNOWN_ALPN_PROTOCOL_NAME_E;
 1994        }
 1995    }
 1996    else
 1997#endif
 1998    {
 1999        r = ALPN_find_match(ssl, &extension, &sel, &sel_len,
 2000                            ssl->alpn_peer_requested,
 2001                            ssl->alpn_peer_requested_length);
 2002        if (r != 0)
 2003            return r;
 2004    }
 2005
 2006    if (sel != NULL) {
 2007        /* set the matching negotiated protocol */
 2008        r = TLSX_SetALPN(&ssl->extensions, sel, sel_len, ssl->heap);
 2009        if (r != WOLFSSL_SUCCESS) {
 2010            WOLFSSL_MSG("TLSX_SetALPN failed");
 2011            return BUFFER_ERROR;
 2012        }
 2013        /* reply to ALPN extension sent from peer */
 2014#ifndef NO_WOLFSSL_SERVER
 2015        TLSX_SetResponse(ssl, TLSX_APPLICATION_LAYER_PROTOCOL);
 2016#endif
 2017    }
 2018    return 0;
 2019}
 2020
 2021/** Parses a buffer of ALPN extensions and set the first one matching
 2022 * client and server requirements */
 2023static int TLSX_ALPN_ParseAndSet(WOLFSSL *ssl, const byte *input, word16 length,
 2024                                 byte isRequest)
 2025{
 2026    word16  size = 0, offset = 0, wlen;
 2027    int     r = WC_NO_ERR_TRACE(BUFFER_ERROR);
 2028    const byte *s;
 2029
 2030    if (OPAQUE16_LEN > length)
 2031        return BUFFER_ERROR;
 2032
 2033    ato16(input, &size);
 2034    offset += OPAQUE16_LEN;
 2035
 2036    /* validating alpn list length */
 2037    if (size == 0 || length != OPAQUE16_LEN + size)
 2038        return BUFFER_ERROR;
 2039
 2040    /* validating length of entries before accepting */
 2041    for (s = input + offset; (s - input) < length; s += wlen) {
 2042        wlen = *s++;
 2043        if (wlen == 0 || (s + wlen - input) > length)
 2044            return BUFFER_ERROR;
 2045    }
 2046
 2047    if (isRequest) {
 2048        /* keep the list sent by peer, if this is from a request. We
 2049         * use it later in ALPN_Select() for evaluation. */
 2050        if (ssl->alpn_peer_requested != NULL) {
 2051            XFREE(ssl->alpn_peer_requested, ssl->heap, DYNAMIC_TYPE_ALPN);
 2052            ssl->alpn_peer_requested_length = 0;
 2053        }
 2054        ssl->alpn_peer_requested = (byte *)XMALLOC(size, ssl->heap,
 2055                                                   DYNAMIC_TYPE_ALPN);
 2056        if (ssl->alpn_peer_requested == NULL) {
 2057            return MEMORY_ERROR;
 2058        }
 2059        ssl->alpn_peer_requested_length = size;
 2060        XMEMCPY(ssl->alpn_peer_requested, (char*)input + offset, size);
 2061    }
 2062    else {
 2063        /* a response, we should find the value in our config */
 2064        const byte *sel = NULL;
 2065        byte sel_len = 0;
 2066        TLSX *extension = NULL;
 2067
 2068        r = ALPN_find_match(ssl, &extension, &sel, &sel_len, input + offset, size);
 2069        if (r != 0)
 2070            return r;
 2071
 2072        if (sel != NULL) {
 2073            /* set the matching negotiated protocol */
 2074            r = TLSX_SetALPN(&ssl->extensions, sel, sel_len, ssl->heap);
 2075            if (r != WOLFSSL_SUCCESS) {
 2076                WOLFSSL_MSG("TLSX_SetALPN failed");
 2077                return BUFFER_ERROR;
 2078            }
 2079        }
 2080        /* If we had nothing configured, the response is unexpected */
 2081        else if (extension == NULL) {
 2082            r = TLSX_HandleUnsupportedExtension(ssl);
 2083            if (r != 0)
 2084                return r;
 2085        }
 2086    }
 2087    return 0;
 2088}
 2089
 2090/** Add a protocol name to the list of accepted usable ones */
 2091int TLSX_UseALPN(TLSX** extensions, const void* data, word16 size, byte options,
 2092                                                                     void* heap)
 2093{
 2094    ALPN *alpn;
 2095    TLSX *extension;
 2096    int  ret;
 2097
 2098    if (extensions == NULL || data == NULL)
 2099        return BAD_FUNC_ARG;
 2100
 2101    alpn = TLSX_ALPN_New((char *)data, size, heap);
 2102    if (alpn == NULL) {
 2103        WOLFSSL_MSG("Memory failure");
 2104        return MEMORY_E;
 2105    }
 2106
 2107    /* Set Options of ALPN */
 2108    alpn->options = options;
 2109
 2110    extension = TLSX_Find(*extensions, TLSX_APPLICATION_LAYER_PROTOCOL);
 2111    if (extension == NULL) {
 2112        ret = TLSX_Push(extensions, TLSX_APPLICATION_LAYER_PROTOCOL,
 2113                                                             (void*)alpn, heap);
 2114        if (ret != 0) {
 2115            TLSX_ALPN_Free(alpn, heap);
 2116            return ret;
 2117        }
 2118    }
 2119    else {
 2120        /* push new ALPN object to extension data. */
 2121        alpn->next = (ALPN*)extension->data;
 2122        extension->data = (void*)alpn;
 2123    }
 2124
 2125    return WOLFSSL_SUCCESS;
 2126}
 2127
 2128/** Get the protocol name set by the server */
 2129int TLSX_ALPN_GetRequest(TLSX* extensions, void** data, word16 *dataSz)
 2130{
 2131    TLSX *extension;
 2132    ALPN *alpn;
 2133
 2134    if (extensions == NULL || data == NULL || dataSz == NULL)
 2135        return BAD_FUNC_ARG;
 2136
 2137    *data = NULL;
 2138    *dataSz = 0;
 2139
 2140    extension = TLSX_Find(extensions, TLSX_APPLICATION_LAYER_PROTOCOL);
 2141    if (extension == NULL) {
 2142        WOLFSSL_MSG("TLS extension not found");
 2143        WOLFSSL_ERROR_VERBOSE(WOLFSSL_ALPN_NOT_FOUND);
 2144        return WOLFSSL_ALPN_NOT_FOUND;
 2145    }
 2146
 2147    alpn = (ALPN *)extension->data;
 2148    if (alpn == NULL) {
 2149        WOLFSSL_MSG("ALPN extension not found");
 2150        WOLFSSL_ERROR_VERBOSE(WOLFSSL_FATAL_ERROR);
 2151        return WOLFSSL_FATAL_ERROR;
 2152    }
 2153
 2154    if (alpn->negotiated != 1) {
 2155
 2156        /* consider as an error */
 2157        if (alpn->options & WOLFSSL_ALPN_FAILED_ON_MISMATCH) {
 2158            WOLFSSL_MSG("No protocol match with peer -> Failed");
 2159            WOLFSSL_ERROR_VERBOSE(WOLFSSL_FATAL_ERROR);
 2160            return WOLFSSL_FATAL_ERROR;
 2161        }
 2162
 2163        /* continue without negotiated protocol */
 2164        WOLFSSL_MSG("No protocol match with peer -> Continue");
 2165        WOLFSSL_ERROR_VERBOSE(WOLFSSL_ALPN_NOT_FOUND);
 2166        return WOLFSSL_ALPN_NOT_FOUND;
 2167    }
 2168
 2169    if (alpn->next != NULL) {
 2170        WOLFSSL_MSG("Only one protocol name must be accepted");
 2171        WOLFSSL_ERROR_VERBOSE(WOLFSSL_FATAL_ERROR);
 2172        return WOLFSSL_FATAL_ERROR;
 2173    }
 2174
 2175    *data = alpn->protocol_name;
 2176    *dataSz = (word16)XSTRLEN((char*)*data);
 2177
 2178    return WOLFSSL_SUCCESS;
 2179}
 2180
 2181#define ALPN_FREE_ALL     TLSX_ALPN_FreeAll
 2182#define ALPN_GET_SIZE     TLSX_ALPN_GetSize
 2183#define ALPN_WRITE        TLSX_ALPN_Write
 2184#define ALPN_PARSE        TLSX_ALPN_ParseAndSet
 2185
 2186#else /* HAVE_ALPN */
 2187
 2188#define ALPN_FREE_ALL(list, heap) WC_DO_NOTHING
 2189#define ALPN_GET_SIZE(list)     0
 2190#define ALPN_WRITE(a, b)        0
 2191#define ALPN_PARSE(a, b, c, d)  0
 2192
 2193#endif /* HAVE_ALPN */
 2194
 2195/******************************************************************************/
 2196/* Server Name Indication                                                     */
 2197/******************************************************************************/
 2198
 2199#ifdef HAVE_SNI
 2200
 2201/** Creates a new SNI object. */
 2202static SNI* TLSX_SNI_New(byte type, const void* data, word16 size, void* heap)
 2203{
 2204    SNI* sni = (SNI*)XMALLOC(sizeof(SNI), heap, DYNAMIC_TYPE_TLSX);
 2205
 2206    (void)heap;
 2207
 2208    if (sni) {
 2209        sni->type = type;
 2210        sni->next = NULL;
 2211
 2212    #ifndef NO_WOLFSSL_SERVER
 2213        sni->options = 0;
 2214        sni->status  = WOLFSSL_SNI_NO_MATCH;
 2215    #endif
 2216
 2217        switch (sni->type) {
 2218            case WOLFSSL_SNI_HOST_NAME:
 2219                sni->data.host_name = (char*)XMALLOC(size + 1, heap,
 2220                                                     DYNAMIC_TYPE_TLSX);
 2221                if (sni->data.host_name) {
 2222                    XSTRNCPY(sni->data.host_name, (const char*)data, size);
 2223                    sni->data.host_name[size] = '\0';
 2224                } else {
 2225                    XFREE(sni, heap, DYNAMIC_TYPE_TLSX);
 2226                    sni = NULL;
 2227                }
 2228            break;
 2229
 2230            default: /* invalid type */
 2231                XFREE(sni, heap, DYNAMIC_TYPE_TLSX);
 2232                sni = NULL;
 2233        }
 2234    }
 2235
 2236    return sni;
 2237}
 2238
 2239/** Releases a SNI object. */
 2240static void TLSX_SNI_Free(SNI* sni, void* heap)
 2241{
 2242    if (sni) {
 2243        switch (sni->type) {
 2244            case WOLFSSL_SNI_HOST_NAME:
 2245                XFREE(sni->data.host_name, heap, DYNAMIC_TYPE_TLSX);
 2246            break;
 2247        }
 2248
 2249        XFREE(sni, heap, DYNAMIC_TYPE_TLSX);
 2250    }
 2251    (void)heap;
 2252}
 2253
 2254/** Releases all SNI objects in the provided list. */
 2255static void TLSX_SNI_FreeAll(SNI* list, void* heap)
 2256{
 2257    SNI* sni;
 2258
 2259    while ((sni = list)) {
 2260        list = sni->next;
 2261        TLSX_SNI_Free(sni, heap);
 2262    }
 2263}
 2264
 2265/** Tells the buffered size of the SNI objects in a list. */
 2266WOLFSSL_TEST_VIS word16 TLSX_SNI_GetSize(SNI* list)
 2267{
 2268    SNI* sni;
 2269    word32 length = OPAQUE16_LEN; /* list length */
 2270
 2271    while ((sni = list)) {
 2272        list = sni->next;
 2273
 2274        length += ENUM_LEN + OPAQUE16_LEN; /* sni type + sni length */
 2275
 2276        switch (sni->type) {
 2277            case WOLFSSL_SNI_HOST_NAME:
 2278                length += (word32)XSTRLEN((char*)sni->data.host_name);
 2279            break;
 2280        }
 2281
 2282        if (length > WOLFSSL_MAX_16BIT) {
 2283            return 0;
 2284        }
 2285    }
 2286
 2287    return (word16)length;
 2288}
 2289
 2290/** Writes the SNI objects of a list in a buffer. */
 2291static word16 TLSX_SNI_Write(SNI* list, byte* output)
 2292{
 2293    SNI* sni;
 2294    word16 length = 0;
 2295    word16 offset = OPAQUE16_LEN; /* list length offset */
 2296
 2297    while ((sni = list)) {
 2298        list = sni->next;
 2299
 2300        output[offset++] = sni->type; /* sni type */
 2301
 2302        switch (sni->type) {
 2303            case WOLFSSL_SNI_HOST_NAME:
 2304                length = (word16)XSTRLEN((char*)sni->data.host_name);
 2305
 2306                c16toa(length, output + offset); /* sni length */
 2307                offset += OPAQUE16_LEN;
 2308
 2309                XMEMCPY(output + offset, sni->data.host_name, length);
 2310
 2311                offset += length;
 2312            break;
 2313        }
 2314    }
 2315
 2316    c16toa(offset - OPAQUE16_LEN, output); /* writing list length */
 2317
 2318    return offset;
 2319}
 2320
 2321/** Finds a SNI object in the provided list. */
 2322static SNI* TLSX_SNI_Find(SNI *list, byte type)
 2323{
 2324    SNI* sni = list;
 2325
 2326    while (sni && sni->type != type)
 2327        sni = sni->next;
 2328
 2329    return sni;
 2330}
 2331
 2332#if (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER))
 2333/** Sets the status of a SNI object. */
 2334static void TLSX_SNI_SetStatus(TLSX* extensions, byte type, byte status)
 2335{
 2336    TLSX* extension = TLSX_Find(extensions, TLSX_SERVER_NAME);
 2337    SNI* sni = TLSX_SNI_Find(extension ? (SNI*)extension->data : NULL, type);
 2338
 2339    if (sni)
 2340        sni->status = status;
 2341}
 2342#endif
 2343
 2344/** Gets the status of a SNI object. */
 2345byte TLSX_SNI_Status(TLSX* extensions, byte type)
 2346{
 2347    TLSX* extension = TLSX_Find(extensions, TLSX_SERVER_NAME);
 2348    SNI* sni = TLSX_SNI_Find(extension ? (SNI*)extension->data : NULL, type);
 2349
 2350    if (sni)
 2351        return sni->status;
 2352
 2353    return 0;
 2354}
 2355
 2356/** Parses a buffer of SNI extensions. */
 2357static int TLSX_SNI_Parse(WOLFSSL* ssl, const byte* input, word16 length,
 2358                          byte isRequest)
 2359{
 2360#ifndef NO_WOLFSSL_SERVER
 2361    word16 size = 0;
 2362    word16 offset = 0;
 2363    int cacheOnly = 0;
 2364    SNI *sni = NULL;
 2365    byte type;
 2366    byte matched;
 2367#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
 2368    TLSX* echX = NULL;
 2369    WOLFSSL_ECH* ech = NULL;
 2370    WOLFSSL_EchConfig* workingConfig;
 2371    word16 privateNameLen;
 2372#endif
 2373#endif /* !NO_WOLFSSL_SERVER */
 2374    TLSX *extension = TLSX_Find(ssl->extensions, TLSX_SERVER_NAME);
 2375
 2376    if (!extension)
 2377        extension = TLSX_Find(ssl->ctx->extensions, TLSX_SERVER_NAME);
 2378
 2379    if (!isRequest) {
 2380        #ifndef NO_WOLFSSL_CLIENT
 2381            if (!extension || !extension->data)
 2382                return TLSX_HandleUnsupportedExtension(ssl);
 2383
 2384            if (length > 0)
 2385                return BUFFER_ERROR; /* SNI response MUST be empty. */
 2386
 2387            /* This call enables wolfSSL_SNI_GetRequest() to be called in the
 2388             * client side to fetch the used SNI. It will only work if the SNI
 2389             * was set at the SSL object level. Right now we only support one
 2390             * name type, WOLFSSL_SNI_HOST_NAME, but in the future, the
 2391             * inclusion of other name types will turn this method inaccurate,
 2392             * as the extension response doesn't contains information of which
 2393             * name was accepted.
 2394             */
 2395            TLSX_SNI_SetStatus(ssl->extensions, WOLFSSL_SNI_HOST_NAME,
 2396                                                        WOLFSSL_SNI_REAL_MATCH);
 2397
 2398            return 0;
 2399        #endif
 2400    }
 2401
 2402#ifndef NO_WOLFSSL_SERVER
 2403#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
 2404    if (!ssl->options.disableECH) {
 2405        echX = TLSX_Find(ssl->extensions, TLSX_ECH);
 2406        if (echX != NULL) {
 2407            ech = (WOLFSSL_ECH*)(echX->data);
 2408        }
 2409    }
 2410#endif
 2411
 2412#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
 2413    if ((!extension || !extension->data) ||
 2414            (ech != NULL && ech->sniState == ECH_INNER_SNI &&
 2415             ech->privateName == NULL)) {
 2416#else
 2417    if (!extension || !extension->data) {
 2418#endif
 2419        /* This will keep SNI even though TLSX_UseSNI has not been called.
 2420         * Enable it so that the received sni is available to functions
 2421         * that use a custom callback when SNI is received.
 2422         */
 2423    #ifdef WOLFSSL_ALWAYS_KEEP_SNI
 2424        cacheOnly = 1;
 2425    #endif
 2426        if (ssl->ctx->sniRecvCb) {
 2427            cacheOnly = 1;
 2428        }
 2429
 2430        if (cacheOnly) {
 2431            WOLFSSL_MSG("Forcing SSL object to store SNI parameter");
 2432        }
 2433        else {
 2434            /* Skipping, SNI not enabled at server side. */
 2435            return 0;
 2436        }
 2437    }
 2438
 2439    if (OPAQUE16_LEN > length)
 2440        return BUFFER_ERROR;
 2441
 2442    ato16(input, &size);
 2443    offset += OPAQUE16_LEN;
 2444
 2445    /* validating sni list length */
 2446    if (length != OPAQUE16_LEN + size || size == 0)
 2447        return BUFFER_ERROR;
 2448
 2449    /* SNI was badly specified and only one type is now recognized and allowed.
 2450     * Only one SNI value per type (RFC6066), so, no loop. */
 2451    type = input[offset++];
 2452    if (type != WOLFSSL_SNI_HOST_NAME)
 2453        return BUFFER_ERROR;
 2454
 2455    if (offset + OPAQUE16_LEN > length)
 2456        return BUFFER_ERROR;
 2457    ato16(input + offset, &size);
 2458    offset += OPAQUE16_LEN;
 2459
 2460    if (offset + size != length || size == 0)
 2461        return BUFFER_ERROR;
 2462
 2463    if (!cacheOnly && !(sni = TLSX_SNI_Find((SNI*)extension->data, type)))
 2464        return 0; /* not using this type of SNI. */
 2465
 2466#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
 2467    if (ech != NULL && ech->sniState == ECH_INNER_SNI){
 2468        /* SNI status is carried over from processing the outer hello so it is
 2469         * necessary to clear it before processing the inner hello */
 2470        ech->sniState = ECH_INNER_SNI_ATTEMPT;
 2471        if (sni != NULL){
 2472            sni->status = WOLFSSL_SNI_NO_MATCH;
 2473        }
 2474    }
 2475    else if (ech != NULL && ech->sniState == ECH_OUTER_SNI &&
 2476            ech->privateName == NULL && sni != NULL){
 2477        /* save the private SNI before it is overwritten by the public SNI */
 2478        privateNameLen = (word16)XSTRLEN(sni->data.host_name) + 1;
 2479        ech->privateName = (char*)XMALLOC(privateNameLen, ssl->heap,
 2480            DYNAMIC_TYPE_TMP_BUFFER);
 2481        if (ech->privateName == NULL)
 2482            return MEMORY_E;
 2483        XMEMCPY((char*)ech->privateName, sni->data.host_name,
 2484            privateNameLen);
 2485    }
 2486#endif
 2487
 2488#if defined(WOLFSSL_TLS13)
 2489    /* Don't process the second ClientHello SNI extension if there
 2490     * was problems with the first.
 2491     */
 2492    if (!cacheOnly && sni != NULL && sni->status != WOLFSSL_SNI_NO_MATCH)
 2493        return 0;
 2494#endif
 2495
 2496#if defined(HAVE_ECH)
 2497    if (ech != NULL && ech->sniState == ECH_INNER_SNI_ATTEMPT &&
 2498            ech->privateName != NULL) {
 2499        matched = cacheOnly || (XSTRLEN(ech->privateName) == size &&
 2500            XSTRNCMP(ech->privateName, (const char*)input + offset, size) == 0);
 2501    }
 2502    else
 2503#endif
 2504    {
 2505        const char* hostName = (sni != NULL) ? sni->data.host_name : NULL;
 2506        matched = cacheOnly || (hostName != NULL &&
 2507            XSTRLEN(hostName) == size &&
 2508            XSTRNCMP(hostName, (const char*)input + offset, size) == 0);
 2509    }
 2510
 2511#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
 2512    if (!matched && ech != NULL && ech->sniState == ECH_OUTER_SNI) {
 2513        workingConfig = ech->echConfig;
 2514        while (workingConfig != NULL) {
 2515            matched = XSTRLEN(workingConfig->publicName) == size &&
 2516                XSTRNCMP(workingConfig->publicName,
 2517                (const char*)input + offset, size) == 0;
 2518
 2519            if (matched)
 2520                break;
 2521
 2522            workingConfig = workingConfig->next;
 2523        }
 2524    }
 2525#endif
 2526
 2527    if (matched ||
 2528            (sni != NULL && (sni->options & WOLFSSL_SNI_ANSWER_ON_MISMATCH))) {
 2529        int matchStat;
 2530        int r = TLSX_UseSNI(&ssl->extensions, type, input + offset, size,
 2531                                                                     ssl->heap);
 2532
 2533        if (r != WOLFSSL_SUCCESS)
 2534            return r; /* throws error. */
 2535
 2536        if (cacheOnly) {
 2537            WOLFSSL_MSG("Forcing storage of SNI, Fake match");
 2538            matchStat = WOLFSSL_SNI_FORCE_KEEP;
 2539        }
 2540        else if (matched) {
 2541            WOLFSSL_MSG("SNI did match!");
 2542            matchStat = WOLFSSL_SNI_REAL_MATCH;
 2543        }
 2544        else {
 2545            WOLFSSL_MSG("fake SNI match from ANSWER_ON_MISMATCH");
 2546            matchStat = WOLFSSL_SNI_FAKE_MATCH;
 2547        }
 2548
 2549        TLSX_SNI_SetStatus(ssl->extensions, type, (byte)matchStat);
 2550
 2551        if (!cacheOnly)
 2552            TLSX_SetResponse(ssl, TLSX_SERVER_NAME);
 2553    }
 2554    else if ((sni == NULL) ||
 2555            !(sni->options & WOLFSSL_SNI_CONTINUE_ON_MISMATCH)) {
 2556        SendAlert(ssl, alert_fatal, unrecognized_name);
 2557        WOLFSSL_ERROR_VERBOSE(UNKNOWN_SNI_HOST_NAME_E);
 2558        return UNKNOWN_SNI_HOST_NAME_E;
 2559    }
 2560#else
 2561    (void)input;
 2562#endif /* !NO_WOLFSSL_SERVER */
 2563
 2564#if defined(NO_WOLFSSL_CLIENT) && defined(NO_WOLFSSL_SERVER)
 2565    (void)length;
 2566#endif
 2567
 2568    return 0;
 2569}
 2570
 2571static int TLSX_SNI_VerifyParse(WOLFSSL* ssl,  byte isRequest)
 2572{
 2573    (void)ssl;
 2574
 2575    if (isRequest) {
 2576    #ifndef NO_WOLFSSL_SERVER
 2577        TLSX* ctx_ext = TLSX_Find(ssl->ctx->extensions, TLSX_SERVER_NAME);
 2578        TLSX* ssl_ext = TLSX_Find(ssl->extensions,      TLSX_SERVER_NAME);
 2579        SNI* ctx_sni = ctx_ext ? (SNI*)ctx_ext->data : NULL;
 2580        SNI* ssl_sni = ssl_ext ? (SNI*)ssl_ext->data : NULL;
 2581        SNI* sni = NULL;
 2582
 2583        for (; ctx_sni; ctx_sni = ctx_sni->next) {
 2584            if (ctx_sni->options & WOLFSSL_SNI_ABORT_ON_ABSENCE) {
 2585                sni = TLSX_SNI_Find(ssl_sni, ctx_sni->type);
 2586
 2587                if (sni) {
 2588                    if (sni->status != WOLFSSL_SNI_NO_MATCH)
 2589                        continue;
 2590
 2591                    /* if ssl level overrides ctx level, it is ok. */
 2592                    if ((sni->options & WOLFSSL_SNI_ABORT_ON_ABSENCE) == 0)
 2593                        continue;
 2594                }
 2595
 2596                SendAlert(ssl, alert_fatal, handshake_failure);
 2597                WOLFSSL_ERROR_VERBOSE(SNI_ABSENT_ERROR);
 2598                return SNI_ABSENT_ERROR;
 2599            }
 2600        }
 2601
 2602        for (; ssl_sni; ssl_sni = ssl_sni->next) {
 2603            if (ssl_sni->options & WOLFSSL_SNI_ABORT_ON_ABSENCE) {
 2604                if (ssl_sni->status != WOLFSSL_SNI_NO_MATCH)
 2605                    continue;
 2606
 2607                SendAlert(ssl, alert_fatal, handshake_failure);
 2608                WOLFSSL_ERROR_VERBOSE(SNI_ABSENT_ERROR);
 2609                return SNI_ABSENT_ERROR;
 2610            }
 2611        }
 2612    #endif /* NO_WOLFSSL_SERVER */
 2613    }
 2614
 2615    return 0;
 2616}
 2617
 2618int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, word16 size,
 2619                                                                     void* heap)
 2620{
 2621    TLSX* extension;
 2622    SNI* sni = NULL;
 2623
 2624    if (extensions == NULL || data == NULL)
 2625        return BAD_FUNC_ARG;
 2626
 2627    if ((type == WOLFSSL_SNI_HOST_NAME) && (size >= WOLFSSL_HOST_NAME_MAX))
 2628        return BAD_LENGTH_E;
 2629
 2630    if ((sni = TLSX_SNI_New(type, data, size, heap)) == NULL)
 2631        return MEMORY_E;
 2632
 2633    extension = TLSX_Find(*extensions, TLSX_SERVER_NAME);
 2634    if (!extension) {
 2635        int ret = TLSX_Push(extensions, TLSX_SERVER_NAME, (void*)sni, heap);
 2636
 2637        if (ret != 0) {
 2638            TLSX_SNI_Free(sni, heap);
 2639            return ret;
 2640        }
 2641    }
 2642    else {
 2643        /* push new SNI object to extension data. */
 2644        sni->next = (SNI*)extension->data;
 2645        extension->data = (void*)sni;
 2646
 2647        /* remove duplicate SNI, there should be only one of each type. */
 2648        do {
 2649            if (sni->next && sni->next->type == type) {
 2650                SNI* next = sni->next;
 2651
 2652                sni->next = next->next;
 2653                TLSX_SNI_Free(next, heap);
 2654
 2655                /* there is no way to occur more than
 2656                 * two SNIs of the same type.
 2657                 */
 2658                break;
 2659            }
 2660        } while ((sni = sni->next));
 2661    }
 2662
 2663    return WOLFSSL_SUCCESS;
 2664}
 2665
 2666#ifndef NO_WOLFSSL_SERVER
 2667
 2668/** Tells the SNI requested by the client. */
 2669word16 TLSX_SNI_GetRequest(TLSX* extensions, byte type, void** data,
 2670        byte ignoreStatus)
 2671{
 2672    TLSX* extension = TLSX_Find(extensions, TLSX_SERVER_NAME);
 2673    SNI* sni = TLSX_SNI_Find(extension ? (SNI*)extension->data : NULL, type);
 2674
 2675    if (sni && (ignoreStatus || sni->status != WOLFSSL_SNI_NO_MATCH)) {
 2676        switch (sni->type) {
 2677            case WOLFSSL_SNI_HOST_NAME:
 2678                if (data) {
 2679                    *data = sni->data.host_name;
 2680                    return (word16)XSTRLEN((char*)*data);
 2681                }
 2682        }
 2683    }
 2684
 2685    return 0;
 2686}
 2687
 2688/** Sets the options for a SNI object. */
 2689void TLSX_SNI_SetOptions(TLSX* extensions, byte type, byte options)
 2690{
 2691    TLSX* extension = TLSX_Find(extensions, TLSX_SERVER_NAME);
 2692    SNI* sni = TLSX_SNI_Find(extension ? (SNI*)extension->data : NULL, type);
 2693
 2694    if (sni)
 2695        sni->options = options;
 2696}
 2697
 2698/** Retrieves a SNI request from a client hello buffer. */
 2699int TLSX_SNI_GetFromBuffer(const byte* clientHello, word32 helloSz,
 2700                           byte type, byte* sni, word32* inOutSz)
 2701{
 2702    word32 offset = 0;
 2703    word32 len32 = 0;
 2704    word16 len16 = 0;
 2705
 2706    if (helloSz < RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + CLIENT_HELLO_FIRST)
 2707        return INCOMPLETE_DATA;
 2708
 2709    /* TLS record header */
 2710    if ((enum ContentType) clientHello[offset++] != handshake) {
 2711
 2712        /* checking for SSLv2.0 client hello according to: */
 2713        /* http://tools.ietf.org/html/rfc4346#appendix-E.1 */
 2714        if ((enum HandShakeType) clientHello[++offset] == client_hello) {
 2715            offset += ENUM_LEN + VERSION_SZ; /* skip version */
 2716
 2717            ato16(clientHello + offset, &len16);
 2718            offset += OPAQUE16_LEN;
 2719
 2720            if (len16 % 3) /* cipher_spec_length must be multiple of 3 */
 2721                return BUFFER_ERROR;
 2722
 2723            ato16(clientHello + offset, &len16);
 2724            /* Returning SNI_UNSUPPORTED do not increment offset here */
 2725
 2726            if (len16 != 0) /* session_id_length must be 0 */
 2727                return BUFFER_ERROR;
 2728
 2729            WOLFSSL_ERROR_VERBOSE(SNI_UNSUPPORTED);
 2730            return SNI_UNSUPPORTED;
 2731        }
 2732
 2733        return BUFFER_ERROR;
 2734    }
 2735
 2736    if (clientHello[offset++] != SSLv3_MAJOR)
 2737        return BUFFER_ERROR;
 2738
 2739    if (clientHello[offset++] < TLSv1_MINOR) {
 2740        WOLFSSL_ERROR_VERBOSE(SNI_UNSUPPORTED);
 2741        return SNI_UNSUPPORTED;
 2742    }
 2743
 2744    ato16(clientHello + offset, &len16);
 2745    offset += OPAQUE16_LEN;
 2746
 2747    if (offset + len16 > helloSz)
 2748        return INCOMPLETE_DATA;
 2749
 2750    /* Handshake header */
 2751    if ((enum HandShakeType) clientHello[offset] != client_hello)
 2752        return BUFFER_ERROR;
 2753
 2754    c24to32(clientHello + offset + 1, &len32);
 2755    offset += HANDSHAKE_HEADER_SZ;
 2756
 2757    if (offset + len32 > helloSz)
 2758        return BUFFER_ERROR;
 2759
 2760    /* client hello */
 2761    offset += VERSION_SZ + RAN_LEN; /* version, random */
 2762
 2763    if (helloSz < offset + clientHello[offset])
 2764        return BUFFER_ERROR;
 2765
 2766    offset += ENUM_LEN + clientHello[offset]; /* skip session id */
 2767
 2768    /* cypher suites */
 2769    if (helloSz < offset + OPAQUE16_LEN)
 2770        return BUFFER_ERROR;
 2771
 2772    ato16(clientHello + offset, &len16);
 2773    offset += OPAQUE16_LEN;
 2774
 2775    if (helloSz < offset + len16)
 2776        return BUFFER_ERROR;
 2777
 2778    offset += len16; /* skip cypher suites */
 2779
 2780    /* compression methods */
 2781    if (helloSz < offset + 1)
 2782        return BUFFER_ERROR;
 2783
 2784    if (helloSz < offset + clientHello[offset])
 2785        return BUFFER_ERROR;
 2786
 2787    offset += ENUM_LEN + clientHello[offset]; /* skip compression methods */
 2788
 2789    /* extensions */
 2790    if (helloSz < offset + OPAQUE16_LEN)
 2791        return 0; /* no extensions in client hello. */
 2792
 2793    ato16(clientHello + offset, &len16);
 2794    offset += OPAQUE16_LEN;
 2795
 2796    if (helloSz < offset + len16)
 2797        return BUFFER_ERROR;
 2798
 2799    while (len16 >= OPAQUE16_LEN + OPAQUE16_LEN) {
 2800        word16 extType;
 2801        word16 extLen;
 2802
 2803        ato16(clientHello + offset, &extType);
 2804        offset += OPAQUE16_LEN;
 2805
 2806        ato16(clientHello + offset, &extLen);
 2807        offset += OPAQUE16_LEN;
 2808
 2809        if (helloSz < offset + extLen)
 2810            return BUFFER_ERROR;
 2811
 2812        if (extType != TLSX_SERVER_NAME) {
 2813            offset += extLen; /* skip extension */
 2814        } else {
 2815            word16 listLen;
 2816
 2817            if (extLen < OPAQUE16_LEN)
 2818                return BUFFER_ERROR;
 2819
 2820            ato16(clientHello + offset, &listLen);
 2821            offset += OPAQUE16_LEN;
 2822
 2823            if (helloSz < offset + listLen)
 2824                return BUFFER_ERROR;
 2825
 2826            while (listLen > ENUM_LEN + OPAQUE16_LEN) {
 2827                byte   sniType = clientHello[offset++];
 2828                word16 sniLen;
 2829
 2830                ato16(clientHello + offset, &sniLen);
 2831                offset += OPAQUE16_LEN;
 2832
 2833                if (helloSz < offset + sniLen)
 2834                    return BUFFER_ERROR;
 2835
 2836                if (sniType != type) {
 2837                    offset  += sniLen;
 2838                    listLen -= min(ENUM_LEN + OPAQUE16_LEN + sniLen, listLen);
 2839                    continue;
 2840                }
 2841
 2842                *inOutSz = min(sniLen, *inOutSz);
 2843                XMEMCPY(sni, clientHello + offset, *inOutSz);
 2844
 2845                return WOLFSSL_SUCCESS;
 2846            }
 2847        }
 2848
 2849        len16 -= min(2 * OPAQUE16_LEN + extLen, len16);
 2850    }
 2851
 2852    return len16 ? BUFFER_ERROR : 0;
 2853}
 2854
 2855#endif
 2856
 2857#define SNI_FREE_ALL     TLSX_SNI_FreeAll
 2858#define SNI_GET_SIZE     TLSX_SNI_GetSize
 2859#define SNI_WRITE        TLSX_SNI_Write
 2860#define SNI_PARSE        TLSX_SNI_Parse
 2861#define SNI_VERIFY_PARSE TLSX_SNI_VerifyParse
 2862
 2863#else
 2864
 2865#define SNI_FREE_ALL(list, heap) WC_DO_NOTHING
 2866#define SNI_GET_SIZE(list)     0
 2867#define SNI_WRITE(a, b)        0
 2868#define SNI_PARSE(a, b, c, d)  0
 2869#define SNI_VERIFY_PARSE(a, b) 0
 2870
 2871#endif /* HAVE_SNI */
 2872
 2873/******************************************************************************/
 2874/* Trusted CA Key Indication                                                  */
 2875/******************************************************************************/
 2876
 2877#ifdef HAVE_TRUSTED_CA
 2878
 2879/** Creates a new TCA object. */
 2880static TCA* TLSX_TCA_New(byte type, const byte* id, word16 idSz, void* heap)
 2881{
 2882    TCA* tca = (TCA*)XMALLOC(sizeof(TCA), heap, DYNAMIC_TYPE_TLSX);
 2883
 2884    if (tca) {
 2885        XMEMSET(tca, 0, sizeof(TCA));
 2886        tca->type = type;
 2887
 2888        switch (type) {
 2889            case WOLFSSL_TRUSTED_CA_PRE_AGREED:
 2890                break;
 2891
 2892            #ifndef NO_SHA
 2893            case WOLFSSL_TRUSTED_CA_KEY_SHA1:
 2894            case WOLFSSL_TRUSTED_CA_CERT_SHA1:
 2895                if (idSz == WC_SHA_DIGEST_SIZE &&
 2896                        (tca->id =
 2897                            (byte*)XMALLOC(idSz, heap, DYNAMIC_TYPE_TLSX))) {
 2898                    XMEMCPY(tca->id, id, idSz);
 2899                    tca->idSz = idSz;
 2900                }
 2901                else {
 2902                    XFREE(tca, heap, DYNAMIC_TYPE_TLSX);
 2903                    tca = NULL;
 2904                }
 2905                break;
 2906            #endif
 2907
 2908            case WOLFSSL_TRUSTED_CA_X509_NAME:
 2909                if (idSz > 0 &&
 2910                        (tca->id =
 2911                            (byte*)XMALLOC(idSz, heap, DYNAMIC_TYPE_TLSX))) {
 2912                    XMEMCPY(tca->id, id, idSz);
 2913                    tca->idSz = idSz;
 2914                }
 2915                else {
 2916                    XFREE(tca, heap, DYNAMIC_TYPE_TLSX);
 2917                    tca = NULL;
 2918                }
 2919                break;
 2920
 2921            default: /* invalid type */
 2922                XFREE(tca, heap, DYNAMIC_TYPE_TLSX);
 2923                tca = NULL;
 2924        }
 2925    }
 2926
 2927    (void)heap;
 2928
 2929    return tca;
 2930}
 2931
 2932/** Releases a TCA object. */
 2933static void TLSX_TCA_Free(TCA* tca, void* heap)
 2934{
 2935    (void)heap;
 2936
 2937    if (tca) {
 2938        XFREE(tca->id, heap, DYNAMIC_TYPE_TLSX);
 2939        XFREE(tca, heap, DYNAMIC_TYPE_TLSX);
 2940    }
 2941}
 2942
 2943/** Releases all TCA objects in the provided list. */
 2944static void TLSX_TCA_FreeAll(TCA* list, void* heap)
 2945{
 2946    TCA* tca;
 2947
 2948    while ((tca = list)) {
 2949        list = tca->next;
 2950        TLSX_TCA_Free(tca, heap);
 2951    }
 2952}
 2953
 2954/** Tells the buffered size of the TCA objects in a list. */
 2955static word16 TLSX_TCA_GetSize(TCA* list)
 2956{
 2957    TCA* tca;
 2958    word32 length = OPAQUE16_LEN; /* list length */
 2959
 2960    while ((tca = list)) {
 2961        list = tca->next;
 2962
 2963        length += ENUM_LEN; /* tca type */
 2964
 2965        switch (tca->type) {
 2966            case WOLFSSL_TRUSTED_CA_PRE_AGREED:
 2967                break;
 2968            case WOLFSSL_TRUSTED_CA_KEY_SHA1:
 2969            case WOLFSSL_TRUSTED_CA_CERT_SHA1:
 2970                length += tca->idSz;
 2971                break;
 2972            case WOLFSSL_TRUSTED_CA_X509_NAME:
 2973                length += OPAQUE16_LEN + tca->idSz;
 2974                break;
 2975        }
 2976
 2977        if (length > WOLFSSL_MAX_16BIT) {
 2978            return 0;
 2979        }
 2980    }
 2981
 2982    return (word16)length;
 2983}
 2984
 2985/** Writes the TCA objects of a list in a buffer. */
 2986static word16 TLSX_TCA_Write(TCA* list, byte* output)
 2987{
 2988    TCA* tca;
 2989    word16 offset = OPAQUE16_LEN; /* list length offset */
 2990
 2991    while ((tca = list)) {
 2992        list = tca->next;
 2993
 2994        output[offset++] = tca->type; /* tca type */
 2995
 2996        switch (tca->type) {
 2997            case WOLFSSL_TRUSTED_CA_PRE_AGREED:
 2998                break;
 2999            #ifndef NO_SHA
 3000            case WOLFSSL_TRUSTED_CA_KEY_SHA1:
 3001            case WOLFSSL_TRUSTED_CA_CERT_SHA1:
 3002                if (tca->id != NULL) {
 3003                    XMEMCPY(output + offset, tca->id, tca->idSz);
 3004                    offset += tca->idSz;
 3005                }
 3006                else {
 3007                    /* ID missing. Set to an empty string. */
 3008                    c16toa(0, output + offset);
 3009                    offset += OPAQUE16_LEN;
 3010                }
 3011                break;
 3012            #endif
 3013            case WOLFSSL_TRUSTED_CA_X509_NAME:
 3014                if (tca->id != NULL) {
 3015                    c16toa(tca->idSz, output + offset); /* tca length */
 3016                    offset += OPAQUE16_LEN;
 3017                    XMEMCPY(output + offset, tca->id, tca->idSz);
 3018                    offset += tca->idSz;
 3019                }
 3020                else {
 3021                    /* ID missing. Set to an empty string. */
 3022                    c16toa(0, output + offset);
 3023                    offset += OPAQUE16_LEN;
 3024                }
 3025                break;
 3026            default:
 3027                /* ID unknown. Set to an empty string. */
 3028                c16toa(0, output + offset);
 3029                offset += OPAQUE16_LEN;
 3030        }
 3031    }
 3032
 3033    c16toa(offset - OPAQUE16_LEN, output); /* writing list length */
 3034
 3035    return offset;
 3036}
 3037
 3038#ifndef NO_WOLFSSL_SERVER
 3039static TCA* TLSX_TCA_Find(TCA *list, byte type, const byte* id, word16 idSz)
 3040{
 3041    TCA* tca = list;
 3042
 3043    while (tca) {
 3044        if (type == WOLFSSL_TRUSTED_CA_PRE_AGREED)
 3045            break;
 3046        if (tca->type == type && idSz == tca->idSz &&
 3047                XMEMCMP(id, tca->id, idSz) == 0)
 3048            break;
 3049        tca = tca->next;
 3050    }
 3051
 3052    return tca;
 3053}
 3054#endif /* NO_WOLFSSL_SERVER */
 3055
 3056/** Parses a buffer of TCA extensions. */
 3057static int TLSX_TCA_Parse(WOLFSSL* ssl, const byte* input, word16 length,
 3058                          byte isRequest)
 3059{
 3060#ifndef NO_WOLFSSL_SERVER
 3061    word16 size = 0;
 3062    word16 offset = 0;
 3063#endif
 3064
 3065    TLSX *extension = TLSX_Find(ssl->extensions, TLSX_TRUSTED_CA_KEYS);
 3066
 3067    if (!extension)
 3068        extension = TLSX_Find(ssl->ctx->extensions, TLSX_TRUSTED_CA_KEYS);
 3069
 3070    if (!isRequest) {
 3071        #ifndef NO_WOLFSSL_CLIENT
 3072            if (!extension || !extension->data)
 3073                return TLSX_HandleUnsupportedExtension(ssl);
 3074
 3075            if (length > 0)
 3076                return BUFFER_ERROR; /* TCA response MUST be empty. */
 3077
 3078            /* Set the flag that we're good for keys */
 3079            TLSX_SetResponse(ssl, TLSX_TRUSTED_CA_KEYS);
 3080
 3081            return 0;
 3082        #endif
 3083    }
 3084
 3085#ifndef NO_WOLFSSL_SERVER
 3086    if (!extension || !extension->data) {
 3087        /* Skipping, TCA not enabled at server side. */
 3088        return 0;
 3089    }
 3090
 3091    if (OPAQUE16_LEN > length)
 3092        return BUFFER_ERROR;
 3093
 3094    ato16(input, &size);
 3095    offset += OPAQUE16_LEN;
 3096
 3097    /* validating tca list length */
 3098    if (length != OPAQUE16_LEN + size)
 3099        return BUFFER_ERROR;
 3100
 3101    for (size = 0; offset < length; offset += size) {
 3102        TCA *tca = NULL;
 3103        byte type;
 3104        const byte* id = NULL;
 3105        word16 idSz = 0;
 3106
 3107        if (offset + ENUM_LEN > length)
 3108            return BUFFER_ERROR;
 3109
 3110        type = input[offset++];
 3111
 3112        switch (type) {
 3113            case WOLFSSL_TRUSTED_CA_PRE_AGREED:
 3114                break;
 3115            #ifndef NO_SHA
 3116            case WOLFSSL_TRUSTED_CA_KEY_SHA1:
 3117            case WOLFSSL_TRUSTED_CA_CERT_SHA1:
 3118                if (offset + WC_SHA_DIGEST_SIZE > length)
 3119                    return BUFFER_ERROR;
 3120                idSz = WC_SHA_DIGEST_SIZE;
 3121                id = input + offset;
 3122                offset += idSz;
 3123                break;
 3124            #endif
 3125            case WOLFSSL_TRUSTED_CA_X509_NAME:
 3126                if (offset + OPAQUE16_LEN > length)
 3127                    return BUFFER_ERROR;
 3128                ato16(input + offset, &idSz);
 3129                offset += OPAQUE16_LEN;
 3130                if ((offset > length) || (idSz > length - offset))
 3131                    return BUFFER_ERROR;
 3132                id = input + offset;
 3133                offset += idSz;
 3134                break;
 3135            default:
 3136                WOLFSSL_ERROR_VERBOSE(TCA_INVALID_ID_TYPE);
 3137                return TCA_INVALID_ID_TYPE;
 3138        }
 3139
 3140        /* Find the type/ID in the TCA list. */
 3141        tca = TLSX_TCA_Find((TCA*)extension->data, type, id, idSz);
 3142        if (tca != NULL) {
 3143            /* Found it. Set the response flag and break out of the loop. */
 3144            TLSX_SetResponse(ssl, TLSX_TRUSTED_CA_KEYS);
 3145            break;
 3146        }
 3147    }
 3148#else
 3149    (void)input;
 3150#endif
 3151
 3152    return 0;
 3153}
 3154
 3155/* Checks to see if the server sent a response for the TCA. */
 3156static int TLSX_TCA_VerifyParse(WOLFSSL* ssl, byte isRequest)
 3157{
 3158    (void)ssl;
 3159
 3160    if (!isRequest) {
 3161        /* RFC 6066 section 6 states that the server responding
 3162         * to trusted_ca_keys is optional.  Do not error out unless
 3163         * opted into with the define WOLFSSL_REQUIRE_TCA. */
 3164    #if !defined(NO_WOLFSSL_CLIENT) && defined(WOLFSSL_REQUIRE_TCA)
 3165        TLSX* extension = TLSX_Find(ssl->extensions, TLSX_TRUSTED_CA_KEYS);
 3166
 3167        if (extension && !extension->resp) {
 3168            SendAlert(ssl, alert_fatal, handshake_failure);
 3169            WOLFSSL_ERROR_VERBOSE(TCA_ABSENT_ERROR);
 3170            return TCA_ABSENT_ERROR;
 3171        }
 3172    #else
 3173        WOLFSSL_MSG("No response received for trusted_ca_keys.  Continuing.");
 3174    #endif /* !NO_WOLFSSL_CLIENT && WOLFSSL_REQUIRE_TCA */
 3175    }
 3176
 3177    return 0;
 3178}
 3179
 3180int TLSX_UseTrustedCA(TLSX** extensions, byte type,
 3181                    const byte* id, word16 idSz, void* heap)
 3182{
 3183    TLSX* extension;
 3184    TCA* tca = NULL;
 3185
 3186    if (extensions == NULL)
 3187        return BAD_FUNC_ARG;
 3188
 3189    if ((tca = TLSX_TCA_New(type, id, idSz, heap)) == NULL)
 3190        return MEMORY_E;
 3191
 3192    extension = TLSX_Find(*extensions, TLSX_TRUSTED_CA_KEYS);
 3193    if (!extension) {
 3194        int ret = TLSX_Push(extensions, TLSX_TRUSTED_CA_KEYS, (void*)tca, heap);
 3195
 3196        if (ret != 0) {
 3197            TLSX_TCA_Free(tca, heap);
 3198            return ret;
 3199        }
 3200    }
 3201    else {
 3202        /* push new TCA object to extension data. */
 3203        tca->next = (TCA*)extension->data;
 3204        extension->data = (void*)tca;
 3205    }
 3206
 3207    return WOLFSSL_SUCCESS;
 3208}
 3209
 3210#define TCA_FREE_ALL     TLSX_TCA_FreeAll
 3211#define TCA_GET_SIZE     TLSX_TCA_GetSize
 3212#define TCA_WRITE        TLSX_TCA_Write
 3213#define TCA_PARSE        TLSX_TCA_Parse
 3214#define TCA_VERIFY_PARSE TLSX_TCA_VerifyParse
 3215
 3216#else /* HAVE_TRUSTED_CA */
 3217
 3218#define TCA_FREE_ALL(list, heap) WC_DO_NOTHING
 3219#define TCA_GET_SIZE(list)     0
 3220#define TCA_WRITE(a, b)        0
 3221#define TCA_PARSE(a, b, c, d)  0
 3222#define TCA_VERIFY_PARSE(a, b) 0
 3223
 3224#endif /* HAVE_TRUSTED_CA */
 3225
 3226/******************************************************************************/
 3227/* Max Fragment Length Negotiation                                            */
 3228/******************************************************************************/
 3229
 3230#ifdef HAVE_MAX_FRAGMENT
 3231
 3232static word16 TLSX_MFL_Write(byte* data, byte* output)
 3233{
 3234    output[0] = data[0];
 3235
 3236    return ENUM_LEN;
 3237}
 3238
 3239static int TLSX_MFL_Parse(WOLFSSL* ssl, const byte* input, word16 length,
 3240                          byte isRequest)
 3241{
 3242    if (length != ENUM_LEN)
 3243        return BUFFER_ERROR;
 3244
 3245#ifdef WOLFSSL_OLD_UNSUPPORTED_EXTENSION
 3246    (void) isRequest;
 3247#else
 3248    if (!isRequest)
 3249        if (TLSX_CheckUnsupportedExtension(ssl, TLSX_MAX_FRAGMENT_LENGTH))
 3250            return TLSX_HandleUnsupportedExtension(ssl);
 3251#endif
 3252
 3253    switch (*input) {
 3254        case WOLFSSL_MFL_2_8 : ssl->max_fragment =  256; break;
 3255        case WOLFSSL_MFL_2_9 : ssl->max_fragment =  512; break;
 3256        case WOLFSSL_MFL_2_10: ssl->max_fragment = 1024; break;
 3257        case WOLFSSL_MFL_2_11: ssl->max_fragment = 2048; break;
 3258        case WOLFSSL_MFL_2_12: ssl->max_fragment = 4096; break;
 3259        case WOLFSSL_MFL_2_13: ssl->max_fragment = 8192; break;
 3260
 3261        default:
 3262            SendAlert(ssl, alert_fatal, illegal_parameter);
 3263            WOLFSSL_ERROR_VERBOSE(UNKNOWN_MAX_FRAG_LEN_E);
 3264            return UNKNOWN_MAX_FRAG_LEN_E;
 3265    }
 3266    if (ssl->session != NULL) {
 3267        ssl->session->mfl = *input;
 3268    }
 3269
 3270#ifndef NO_WOLFSSL_SERVER
 3271    if (isRequest) {
 3272        int ret = TLSX_UseMaxFragment(&ssl->extensions, *input, ssl->heap);
 3273
 3274        if (ret != WOLFSSL_SUCCESS)
 3275            return ret; /* throw error */
 3276
 3277        TLSX_SetResponse(ssl, TLSX_MAX_FRAGMENT_LENGTH);
 3278    }
 3279#endif
 3280
 3281    return 0;
 3282}
 3283
 3284int TLSX_UseMaxFragment(TLSX** extensions, byte mfl, void* heap)
 3285{
 3286    byte* data = NULL;
 3287    int ret = 0;
 3288
 3289    if (extensions == NULL || mfl < WOLFSSL_MFL_MIN || mfl > WOLFSSL_MFL_MAX)
 3290        return BAD_FUNC_ARG;
 3291
 3292    data = (byte*)XMALLOC(ENUM_LEN, heap, DYNAMIC_TYPE_TLSX);
 3293    if (data == NULL)
 3294        return MEMORY_E;
 3295
 3296    data[0] = mfl;
 3297
 3298    ret = TLSX_Push(extensions, TLSX_MAX_FRAGMENT_LENGTH, data, heap);
 3299    if (ret != 0) {
 3300        XFREE(data, heap, DYNAMIC_TYPE_TLSX);
 3301        return ret;
 3302    }
 3303
 3304    return WOLFSSL_SUCCESS;
 3305}
 3306
 3307
 3308#define MFL_FREE_ALL(data, heap) XFREE(data, (heap), DYNAMIC_TYPE_TLSX)
 3309#define MFL_GET_SIZE(data) ENUM_LEN
 3310#define MFL_WRITE          TLSX_MFL_Write
 3311#define MFL_PARSE          TLSX_MFL_Parse
 3312
 3313#else
 3314
 3315#define MFL_FREE_ALL(a, b) WC_DO_NOTHING
 3316#define MFL_GET_SIZE(a)       0
 3317#define MFL_WRITE(a, b)       0
 3318#define MFL_PARSE(a, b, c, d) 0
 3319
 3320#endif /* HAVE_MAX_FRAGMENT */
 3321
 3322/******************************************************************************/
 3323/* Truncated HMAC                                                             */
 3324/******************************************************************************/
 3325
 3326#ifdef HAVE_TRUNCATED_HMAC
 3327
 3328static int TLSX_THM_Parse(WOLFSSL* ssl, const byte* input, word16 length,
 3329                          byte isRequest)
 3330{
 3331    if (length != 0 || input == NULL)
 3332        return BUFFER_ERROR;
 3333
 3334    if (!isRequest) {
 3335    #ifndef WOLFSSL_OLD_UNSUPPORTED_EXTENSION
 3336        if (TLSX_CheckUnsupportedExtension(ssl, TLSX_TRUNCATED_HMAC))
 3337            return TLSX_HandleUnsupportedExtension(ssl);
 3338    #endif
 3339    }
 3340    else {
 3341        #ifndef NO_WOLFSSL_SERVER
 3342            int ret = TLSX_UseTruncatedHMAC(&ssl->extensions, ssl->heap);
 3343
 3344            if (ret != WOLFSSL_SUCCESS)
 3345                return ret; /* throw error */
 3346
 3347            TLSX_SetResponse(ssl, TLSX_TRUNCATED_HMAC);
 3348        #endif
 3349    }
 3350
 3351    ssl->truncated_hmac = 1;
 3352
 3353    return 0;
 3354}
 3355
 3356int TLSX_UseTruncatedHMAC(TLSX** extensions, void* heap)
 3357{
 3358    int ret = 0;
 3359
 3360    if (extensions == NULL)
 3361        return BAD_FUNC_ARG;
 3362
 3363    ret = TLSX_Push(extensions, TLSX_TRUNCATED_HMAC, NULL, heap);
 3364    if (ret != 0)
 3365        return ret;
 3366
 3367    return WOLFSSL_SUCCESS;
 3368}
 3369
 3370#define THM_PARSE TLSX_THM_Parse
 3371
 3372#else
 3373
 3374#define THM_PARSE(a, b, c, d) 0
 3375
 3376#endif /* HAVE_TRUNCATED_HMAC */
 3377
 3378/******************************************************************************/
 3379/* Certificate Status Request                                                 */
 3380/******************************************************************************/
 3381
 3382#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
 3383
 3384static void TLSX_CSR_Free(CertificateStatusRequest* csr, void* heap)
 3385{
 3386    int i;
 3387
 3388    switch (csr->status_type) {
 3389        case WOLFSSL_CSR_OCSP:
 3390            for (i = 0; i <= csr->requests; i++) {
 3391                FreeOcspRequest(&csr->request.ocsp[i]);
 3392            }
 3393        break;
 3394    }
 3395#ifdef WOLFSSL_TLS13
 3396    for (i = 0; i < MAX_CERT_EXTENSIONS; i++) {
 3397        if (csr->responses[i].buffer != NULL) {
 3398            XFREE(csr->responses[i].buffer, heap,
 3399                DYNAMIC_TYPE_TMP_BUFFER);
 3400        }
 3401    }
 3402#endif
 3403    XFREE(csr, heap, DYNAMIC_TYPE_TLSX);
 3404    (void)heap;
 3405}
 3406
 3407word16 TLSX_CSR_GetSize_ex(CertificateStatusRequest* csr, byte isRequest,
 3408                                                             int idx)
 3409{
 3410    word32 size = 0;
 3411
 3412    /* shut up compiler warnings */
 3413    (void) csr; (void) isRequest;
 3414#ifndef NO_WOLFSSL_CLIENT
 3415    if (isRequest) {
 3416        switch (csr->status_type) {
 3417            case WOLFSSL_CSR_OCSP:
 3418                size += ENUM_LEN + 2 * OPAQUE16_LEN;
 3419
 3420                if (csr->request.ocsp[0].nonceSz)
 3421                    size += OCSP_NONCE_EXT_SZ;
 3422            break;
 3423        }
 3424    }
 3425#endif
 3426#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER)
 3427    if (!isRequest && IsAtLeastTLSv1_3(csr->ssl->version)) {
 3428        if (csr->ssl != NULL && SSL_CM(csr->ssl) != NULL &&
 3429                SSL_CM(csr->ssl)->ocsp_stapling != NULL &&
 3430                SSL_CM(csr->ssl)->ocsp_stapling->statusCb != NULL) {
 3431            if (WOLFSSL_MAX_16BIT - OPAQUE8_LEN - OPAQUE24_LEN <
 3432                    csr->ssl->ocspCsrResp[idx].length) {
 3433                return 0;
 3434            }
 3435            size = OPAQUE8_LEN + OPAQUE24_LEN +
 3436                    csr->ssl->ocspCsrResp[idx].length;
 3437            return (word16)size;
 3438        }
 3439        if (WOLFSSL_MAX_16BIT - OPAQUE8_LEN - OPAQUE24_LEN <
 3440                csr->responses[idx].length) {
 3441            return 0;
 3442        }
 3443        size = OPAQUE8_LEN + OPAQUE24_LEN + csr->responses[idx].length;
 3444        return (word16)size;
 3445    }
 3446#else
 3447    (void)idx;
 3448#endif
 3449    return (word16)size;
 3450}
 3451
 3452#if (defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER))
 3453int TLSX_CSR_SetResponseWithStatusCB(WOLFSSL *ssl)
 3454{
 3455    WOLFSSL_OCSP *ocsp;
 3456    int ret;
 3457
 3458    if (ssl == NULL || SSL_CM(ssl) == NULL)
 3459        return BAD_FUNC_ARG;
 3460    ocsp = SSL_CM(ssl)->ocsp_stapling;
 3461    if (ocsp == NULL || ocsp->statusCb == NULL)
 3462        return BAD_FUNC_ARG;
 3463    ret = ocsp->statusCb(ssl, ocsp->statusCbArg);
 3464    switch (ret) {
 3465        case WOLFSSL_OCSP_STATUS_CB_OK: {
 3466            size_t i;
 3467            for (i = 0; i < XELEM_CNT(ssl->ocspCsrResp); i++) {
 3468                if (ssl->ocspCsrResp[i].length > 0) {
 3469                    /* ack the extension, status cb provided the response in
 3470                     * ssl->ocspCsrResp */
 3471                    TLSX_SetResponse(ssl, TLSX_STATUS_REQUEST);
 3472                    ssl->status_request = WOLFSSL_CSR_OCSP;
 3473                    break;
 3474                }
 3475            }
 3476            ret = 0;
 3477            break;
 3478        }
 3479        case WOLFSSL_OCSP_STATUS_CB_NOACK:
 3480            /* suppressing as not critical */
 3481            ret = 0;
 3482            break;
 3483        case WOLFSSL_OCSP_STATUS_CB_ALERT_FATAL:
 3484        default:
 3485            ret = WOLFSSL_FATAL_ERROR;
 3486            break;
 3487    }
 3488    return ret;
 3489}
 3490
 3491static int TLSX_CSR_WriteWithStatusCB(CertificateStatusRequest* csr,
 3492    byte* output, int idx)
 3493{
 3494    WOLFSSL *ssl = csr->ssl;
 3495    WOLFSSL_OCSP *ocsp;
 3496    word16 offset = 0;
 3497    byte *response;
 3498    int respSz;
 3499
 3500    if (ssl == NULL || SSL_CM(ssl) == NULL)
 3501        return BAD_FUNC_ARG;
 3502    ocsp = SSL_CM(ssl)->ocsp_stapling;
 3503    if (ocsp == NULL || ocsp->statusCb == NULL)
 3504        return BAD_FUNC_ARG;
 3505    response = ssl->ocspCsrResp[idx].buffer;
 3506    respSz = ssl->ocspCsrResp[idx].length;
 3507    if (response == NULL || respSz == 0)
 3508        return BAD_FUNC_ARG;
 3509    output[offset++] = WOLFSSL_CSR_OCSP;
 3510    c32to24(respSz, output + offset);
 3511    offset += OPAQUE24_LEN;
 3512    XMEMCPY(output + offset, response, respSz);
 3513    return offset + respSz;
 3514}
 3515#endif /* (TLS13 && !NO_WOLFSLL_SERVER) */
 3516
 3517static word16 TLSX_CSR_GetSize(CertificateStatusRequest* csr, byte isRequest)
 3518{
 3519    return TLSX_CSR_GetSize_ex(csr, isRequest, 0);
 3520}
 3521
 3522int TLSX_CSR_Write_ex(CertificateStatusRequest* csr, byte* output,
 3523                          byte isRequest, int idx)
 3524{
 3525    /* shut up compiler warnings */
 3526    (void) csr; (void) output; (void) isRequest;
 3527
 3528#ifndef NO_WOLFSSL_CLIENT
 3529    if (isRequest) {
 3530        int ret = 0;
 3531        word16 offset = 0;
 3532        word16 length = 0;
 3533
 3534        /* type */
 3535        output[offset++] = csr->status_type;
 3536
 3537        switch (csr->status_type) {
 3538            case WOLFSSL_CSR_OCSP:
 3539                /* responder id list */
 3540                c16toa(0, output + offset);
 3541                offset += OPAQUE16_LEN;
 3542
 3543                /* request extensions */
 3544                if (csr->request.ocsp[0].nonceSz) {
 3545                    ret = (int)EncodeOcspRequestExtensions(&csr->request.ocsp[0],
 3546                                                 output + offset + OPAQUE16_LEN,
 3547                                                 OCSP_NONCE_EXT_SZ);
 3548
 3549                    if (ret > 0) {
 3550                        length = (word16)ret;
 3551                    }
 3552                    else {
 3553                        return ret;
 3554                    }
 3555                }
 3556
 3557                c16toa(length, output + offset);
 3558                offset += OPAQUE16_LEN + length;
 3559
 3560            break;
 3561        }
 3562
 3563        return (int)offset;
 3564    }
 3565#endif
 3566#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER)
 3567    if (!isRequest && IsAtLeastTLSv1_3(csr->ssl->version)) {
 3568        word16 offset = 0;
 3569        if (csr->ssl != NULL && SSL_CM(csr->ssl) != NULL &&
 3570                SSL_CM(csr->ssl)->ocsp_stapling != NULL &&
 3571                SSL_CM(csr->ssl)->ocsp_stapling->statusCb != NULL) {
 3572            return TLSX_CSR_WriteWithStatusCB(csr, output, idx);
 3573        }
 3574        output[offset++] = csr->status_type;
 3575        c32to24(csr->responses[idx].length, output + offset);
 3576        offset += OPAQUE24_LEN;
 3577        XMEMCPY(output + offset, csr->responses[idx].buffer,
 3578                                        csr->responses[idx].length);
 3579        offset += (word16)csr->responses[idx].length;
 3580        return offset;
 3581    }
 3582#else
 3583    (void)idx;
 3584#endif
 3585
 3586    return 0;
 3587}
 3588
 3589static int TLSX_CSR_Write(CertificateStatusRequest* csr, byte* output,
 3590                          byte isRequest)
 3591{
 3592    return TLSX_CSR_Write_ex(csr, output, isRequest, 0);
 3593}
 3594
 3595#if !defined(NO_WOLFSSL_SERVER) && defined(WOLFSSL_TLS13) && \
 3596    defined(WOLFSSL_TLS_OCSP_MULTI)
 3597/* Process OCSP request certificate chain
 3598 *
 3599 * ssl       SSL/TLS object.
 3600 * returns 0 on success, otherwise failure.
 3601 */
 3602int ProcessChainOCSPRequest(WOLFSSL* ssl)
 3603{
 3604    DecodedCert* cert;
 3605    OcspRequest* request;
 3606    TLSX* extension;
 3607    CertificateStatusRequest* csr;
 3608    DerBuffer* chain;
 3609    word32 pos = 0;
 3610    buffer der;
 3611    int i = 1;
 3612    int ret = 0;
 3613    byte ctxOwnsRequest = 0;
 3614
 3615    /* use certChain if available, otherwise use peer certificate */
 3616    chain = ssl->buffers.certChain;
 3617    if (chain == NULL) {
 3618        chain = ssl->buffers.certificate;
 3619    }
 3620
 3621    extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST);
 3622    csr = extension ?
 3623                (CertificateStatusRequest*)extension->data : NULL;
 3624    if (csr == NULL)
 3625        return MEMORY_ERROR;
 3626
 3627    cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap,
 3628                                         DYNAMIC_TYPE_DCERT);
 3629    if (cert == NULL) {
 3630        return MEMORY_E;
 3631    }
 3632
 3633    if (chain && chain->buffer) {
 3634        while (ret == 0 && pos + OPAQUE24_LEN < chain->length) {
 3635            if (i >= MAX_CERT_EXTENSIONS) {
 3636                WOLFSSL_MSG_EX(
 3637                    "OCSP request cert chain exceeds maximum length: "
 3638                    "i=%d, MAX_CERT_EXTENSIONS=%d", i, MAX_CERT_EXTENSIONS);
 3639                ret = MAX_CERT_EXTENSIONS_ERR;
 3640                break;
 3641            }
 3642
 3643            c24to32(chain->buffer + pos, &der.length);
 3644            pos += OPAQUE24_LEN;
 3645            der.buffer = chain->buffer + pos;
 3646            pos += der.length;
 3647
 3648            if (pos > chain->length)
 3649                break;
 3650            request = &csr->request.ocsp[i];
 3651            if (ret == 0) {
 3652                ret = CreateOcspRequest(ssl, request, cert,
 3653                        der.buffer, der.length, &ctxOwnsRequest);
 3654                if (ctxOwnsRequest) {
 3655                    wolfSSL_Mutex* ocspLock =
 3656                        &SSL_CM(ssl)->ocsp_stapling->ocspLock;
 3657                    if (wc_LockMutex(ocspLock) == 0) {
 3658                        /* the request is ours */
 3659                        ssl->ctx->certOcspRequest = NULL;
 3660                    }
 3661                    wc_UnLockMutex(ocspLock);
 3662                }
 3663            }
 3664
 3665            if (ret == 0) {
 3666                request->ssl = ssl;
 3667                ret = CheckOcspRequest(SSL_CM(ssl)->ocsp_stapling,
 3668                                 request, &csr->responses[i], ssl->heap);
 3669                /* Suppressing, not critical */
 3670                if (ret == WC_NO_ERR_TRACE(OCSP_CERT_REVOKED) ||
 3671                    ret == WC_NO_ERR_TRACE(OCSP_CERT_UNKNOWN) ||
 3672                    ret == WC_NO_ERR_TRACE(OCSP_LOOKUP_FAIL)) {
 3673                    ret = 0;
 3674                }
 3675                i++;
 3676                csr->requests++;
 3677            }
 3678        }
 3679    }
 3680    XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
 3681
 3682    return ret;
 3683}
 3684#endif
 3685
 3686static int TLSX_CSR_Parse(WOLFSSL* ssl, const byte* input, word16 length,
 3687                          byte isRequest)
 3688{
 3689    int ret;
 3690#if !defined(NO_WOLFSSL_SERVER)
 3691    byte status_type;
 3692    word16 size = 0;
 3693#endif
 3694
 3695#if !defined(NO_WOLFSSL_CLIENT)
 3696    OcspRequest* request;
 3697    TLSX* extension;
 3698    CertificateStatusRequest* csr;
 3699#endif
 3700
 3701#if !defined(NO_WOLFSSL_CLIENT) && defined(WOLFSSL_TLS13) \
 3702 || !defined(NO_WOLFSSL_SERVER)
 3703    word32 offset = 0;
 3704#endif
 3705
 3706#if !defined(NO_WOLFSSL_CLIENT) && defined(WOLFSSL_TLS13)
 3707    word32 resp_length = 0;
 3708#endif
 3709
 3710    /* shut up compiler warnings */
 3711    (void) ssl; (void) input;
 3712
 3713    if (!isRequest) {
 3714#ifndef NO_WOLFSSL_CLIENT
 3715        extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST);
 3716        csr = extension ? (CertificateStatusRequest*)extension->data : NULL;
 3717
 3718        if (!csr) {
 3719            /* look at context level */
 3720            extension = TLSX_Find(ssl->ctx->extensions, TLSX_STATUS_REQUEST);
 3721            csr = extension ? (CertificateStatusRequest*)extension->data : NULL;
 3722
 3723            if (!csr) /* unexpected extension */
 3724                return TLSX_HandleUnsupportedExtension(ssl);
 3725
 3726            /* enable extension at ssl level */
 3727            ret = TLSX_UseCertificateStatusRequest(&ssl->extensions,
 3728                                     csr->status_type, csr->options, ssl,
 3729                                     ssl->heap, ssl->devId);
 3730            if (ret != WOLFSSL_SUCCESS)
 3731                return ret == 0 ? -1 : ret;
 3732
 3733            switch (csr->status_type) {
 3734                case WOLFSSL_CSR_OCSP:
 3735                    /* propagate nonce */
 3736                    if (csr->request.ocsp[0].nonceSz) {
 3737                        request =
 3738                            (OcspRequest*)TLSX_CSR_GetRequest(ssl->extensions);
 3739
 3740                        if (request) {
 3741                            XMEMCPY(request->nonce, csr->request.ocsp[0].nonce,
 3742                                        (size_t)csr->request.ocsp[0].nonceSz);
 3743                            request->nonceSz = csr->request.ocsp[0].nonceSz;
 3744                        }
 3745                    }
 3746                break;
 3747            }
 3748        }
 3749
 3750        ssl->status_request = 1;
 3751
 3752    #ifdef WOLFSSL_TLS13
 3753        if (ssl->options.tls1_3) {
 3754            /* Get the new extension potentially created above. */
 3755            extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST);
 3756            csr = extension ? (CertificateStatusRequest*)extension->data : NULL;
 3757            if (csr == NULL)
 3758                return MEMORY_ERROR;
 3759
 3760            ret = 0;
 3761            if (OPAQUE8_LEN + OPAQUE24_LEN > length)
 3762                ret = BUFFER_ERROR;
 3763            if (ret == 0 && input[offset++] != WOLFSSL_CSR_OCSP) {
 3764                ret = BAD_CERTIFICATE_STATUS_ERROR;
 3765                WOLFSSL_ERROR_VERBOSE(ret);
 3766            }
 3767            if (ret == 0) {
 3768                c24to32(input + offset, &resp_length);
 3769                offset += OPAQUE24_LEN;
 3770                if (offset + resp_length != length)
 3771                    ret = BUFFER_ERROR;
 3772            }
 3773            if (ret == 0) {
 3774                if (ssl->response_idx < (1 + MAX_CHAIN_DEPTH))
 3775                    csr->responses[ssl->response_idx].buffer =
 3776                    (byte*)XMALLOC(resp_length, ssl->heap,
 3777                        DYNAMIC_TYPE_TMP_BUFFER);
 3778                else
 3779                    ret = BAD_FUNC_ARG;
 3780
 3781                if (ret == 0 &&
 3782                        csr->responses[ssl->response_idx].buffer == NULL)
 3783                    ret = MEMORY_ERROR;
 3784            }
 3785            if (ret == 0) {
 3786                XMEMCPY(csr->responses[ssl->response_idx].buffer,
 3787                                            input + offset, resp_length);
 3788                csr->responses[ssl->response_idx].length = resp_length;
 3789            }
 3790
 3791            return ret;
 3792        }
 3793        else
 3794    #endif
 3795        {
 3796            /* extension_data MUST be empty. */
 3797            return length ? BUFFER_ERROR : 0;
 3798        }
 3799#endif
 3800    }
 3801    else {
 3802#ifndef NO_WOLFSSL_SERVER
 3803        if (length == 0)
 3804            return 0;
 3805
 3806        status_type = input[offset++];
 3807
 3808        switch (status_type) {
 3809            case WOLFSSL_CSR_OCSP: {
 3810
 3811                /* skip responder_id_list */
 3812                if ((int)(length - offset) < OPAQUE16_LEN)
 3813                    return BUFFER_ERROR;
 3814
 3815                ato16(input + offset, &size);
 3816                offset += OPAQUE16_LEN + size;
 3817
 3818                /* skip request_extensions */
 3819                if ((int)(length - offset) < OPAQUE16_LEN)
 3820                    return BUFFER_ERROR;
 3821
 3822                ato16(input + offset, &size);
 3823                offset += OPAQUE16_LEN + size;
 3824
 3825                if (offset > length)
 3826                    return BUFFER_ERROR;
 3827
 3828                /* is able to send OCSP response? */
 3829                if (SSL_CM(ssl) == NULL || !SSL_CM(ssl)->ocspStaplingEnabled)
 3830                    return 0;
 3831            }
 3832            break;
 3833
 3834            /* unknown status type */
 3835            default:
 3836                return 0;
 3837        }
 3838
 3839        /* if using status_request and already sending it, skip this one */
 3840        #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
 3841        if (ssl->status_request_v2)
 3842            return 0;
 3843        #endif
 3844
 3845        /* accept the first good status_type and return */
 3846        ret = TLSX_UseCertificateStatusRequest(&ssl->extensions, status_type,
 3847                                                 0, ssl, ssl->heap, ssl->devId);
 3848        if (ret != WOLFSSL_SUCCESS)
 3849            return ret == 0 ? -1 : ret; /* throw error */
 3850
 3851        TLSX_SetResponse(ssl, TLSX_STATUS_REQUEST);
 3852        ssl->status_request = status_type;
 3853#endif
 3854    }
 3855
 3856    return 0;
 3857}
 3858
 3859int TLSX_CSR_InitRequest_ex(TLSX* extensions, DecodedCert* cert,
 3860                                                            void* heap, int idx)
 3861{
 3862     TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST);
 3863    CertificateStatusRequest* csr = extension ?
 3864        (CertificateStatusRequest*)extension->data : NULL;
 3865    int ret = 0;
 3866
 3867    if (csr) {
 3868        switch (csr->status_type) {
 3869            case WOLFSSL_CSR_OCSP: {
 3870                byte nonce[MAX_OCSP_NONCE_SZ];
 3871                int  req_cnt = idx == -1 ? csr->requests : idx;
 3872                int  nonceSz = csr->request.ocsp[0].nonceSz;
 3873                OcspRequest* request;
 3874
 3875                request = &csr->request.ocsp[req_cnt];
 3876                if (request->serial != NULL) {
 3877                    /* clear request contents before reuse */
 3878                    FreeOcspRequest(request);
 3879                    if (csr->requests > 0)
 3880                        csr->requests--;
 3881                }
 3882                /* preserve nonce */
 3883                XMEMCPY(nonce, csr->request.ocsp->nonce, (size_t)nonceSz);
 3884
 3885                if (req_cnt < MAX_CERT_EXTENSIONS) {
 3886                    if ((ret = InitOcspRequest(request, cert, 0, heap)) != 0)
 3887                        return ret;
 3888
 3889                    /* restore nonce */
 3890                    XMEMCPY(csr->request.ocsp->nonce, nonce, (size_t)nonceSz);
 3891                    request->nonceSz = nonceSz;
 3892                    csr->requests++;
 3893                }
 3894                else {
 3895                    WOLFSSL_ERROR_VERBOSE(MAX_CERT_EXTENSIONS_ERR);
 3896                    return MAX_CERT_EXTENSIONS_ERR;
 3897                }
 3898            }
 3899            break;
 3900        }
 3901    }
 3902
 3903    return ret;
 3904}
 3905
 3906int TLSX_CSR_InitRequest(TLSX* extensions, DecodedCert* cert, void* heap)
 3907{
 3908    return TLSX_CSR_InitRequest_ex(extensions, cert, heap, -1);
 3909}
 3910
 3911void* TLSX_CSR_GetRequest_ex(TLSX* extensions, int idx)
 3912{
 3913    TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST);
 3914    CertificateStatusRequest* csr = extension ?
 3915                              (CertificateStatusRequest*)extension->data : NULL;
 3916
 3917    if (csr && csr->ssl) {
 3918        switch (csr->status_type) {
 3919            case WOLFSSL_CSR_OCSP:
 3920                if (IsAtLeastTLSv1_3(csr->ssl->version)) {
 3921                    return idx < csr->requests ? &csr->request.ocsp[idx] : NULL;
 3922                }
 3923                else {
 3924                    return idx == 0 ? &csr->request.ocsp[0] : NULL;
 3925                }
 3926        }
 3927    }
 3928
 3929    return NULL;
 3930}
 3931
 3932void* TLSX_CSR_GetRequest(TLSX* extensions)
 3933{
 3934    return TLSX_CSR_GetRequest_ex(extensions, 0);
 3935}
 3936
 3937int TLSX_CSR_ForceRequest(WOLFSSL* ssl)
 3938{
 3939    TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST);
 3940    CertificateStatusRequest* csr = extension ?
 3941                              (CertificateStatusRequest*)extension->data : NULL;
 3942
 3943    if (csr) {
 3944        switch (csr->status_type) {
 3945            case WOLFSSL_CSR_OCSP:
 3946                if (SSL_CM(ssl)->ocspEnabled) {
 3947                    csr->request.ocsp[0].ssl = ssl;
 3948                    return CheckOcspRequest(SSL_CM(ssl)->ocsp,
 3949                                              &csr->request.ocsp[0], NULL, NULL);
 3950                }
 3951                else {
 3952                    WOLFSSL_ERROR_VERBOSE(OCSP_LOOKUP_FAIL);
 3953                    return OCSP_LOOKUP_FAIL;
 3954                }
 3955        }
 3956    }
 3957
 3958    return 0;
 3959}
 3960
 3961int TLSX_UseCertificateStatusRequest(TLSX** extensions, byte status_type,
 3962                                         byte options, WOLFSSL* ssl, void* heap,
 3963                                                                      int devId)
 3964{
 3965    CertificateStatusRequest* csr = NULL;
 3966    int ret = 0;
 3967
 3968    if (!extensions || status_type != WOLFSSL_CSR_OCSP)
 3969        return BAD_FUNC_ARG;
 3970
 3971    csr = (CertificateStatusRequest*)
 3972             XMALLOC(sizeof(CertificateStatusRequest), heap, DYNAMIC_TYPE_TLSX);
 3973    if (!csr)
 3974        return MEMORY_E;
 3975
 3976    ForceZero(csr, sizeof(CertificateStatusRequest));
 3977#if defined(WOLFSSL_TLS13)
 3978    XMEMSET(csr->responses, 0, sizeof(csr->responses));
 3979#endif
 3980    csr->status_type = status_type;
 3981    csr->options     = options;
 3982    csr->ssl         = ssl;
 3983
 3984    switch (csr->status_type) {
 3985        case WOLFSSL_CSR_OCSP:
 3986            if (options & WOLFSSL_CSR_OCSP_USE_NONCE) {
 3987                WC_RNG rng;
 3988
 3989            #ifndef HAVE_FIPS
 3990                ret = wc_InitRng_ex(&rng, heap, devId);
 3991            #else
 3992                ret = wc_InitRng(&rng);
 3993                (void)devId;
 3994            #endif
 3995                if (ret == 0) {
 3996                    if (wc_RNG_GenerateBlock(&rng, csr->request.ocsp[0].nonce,
 3997                                                        MAX_OCSP_NONCE_SZ) == 0)
 3998                        csr->request.ocsp[0].nonceSz = MAX_OCSP_NONCE_SZ;
 3999
 4000                    wc_FreeRng(&rng);
 4001                }
 4002            }
 4003        break;
 4004    }
 4005
 4006    if ((ret = TLSX_Push(extensions, TLSX_STATUS_REQUEST, csr, heap)) != 0) {
 4007        XFREE(csr, heap, DYNAMIC_TYPE_TLSX);
 4008        return ret;
 4009    }
 4010
 4011    return WOLFSSL_SUCCESS;
 4012}
 4013
 4014#define CSR_FREE_ALL TLSX_CSR_Free
 4015#define CSR_GET_SIZE TLSX_CSR_GetSize
 4016#define CSR_WRITE    TLSX_CSR_Write
 4017#define CSR_PARSE    TLSX_CSR_Parse
 4018
 4019#else
 4020
 4021#define CSR_FREE_ALL(data, heap) WC_DO_NOTHING
 4022#define CSR_GET_SIZE(a, b)    0
 4023#define CSR_WRITE(a, b, c)    0
 4024#define CSR_PARSE(a, b, c, d) 0
 4025
 4026#endif /* HAVE_CERTIFICATE_STATUS_REQUEST */
 4027
 4028/******************************************************************************/
 4029/* Certificate Status Request v2                                              */
 4030/******************************************************************************/
 4031
 4032#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
 4033
 4034static void TLSX_CSR2_FreePendingSigners(Signer *s, void* heap)
 4035{
 4036    Signer* next;
 4037    while(s) {
 4038        next = s->next;
 4039        FreeSigner(s, heap);
 4040        s = next;
 4041    }
 4042}
 4043static void TLSX_CSR2_FreeAll(CertificateStatusRequestItemV2* csr2, void* heap)
 4044{
 4045    CertificateStatusRequestItemV2* next;
 4046
 4047    TLSX_CSR2_FreePendingSigners(csr2->pendingSigners, heap);
 4048    for (; csr2; csr2 = next) {
 4049        next = csr2->next;
 4050
 4051        switch (csr2->status_type) {
 4052            case WOLFSSL_CSR2_OCSP:
 4053            case WOLFSSL_CSR2_OCSP_MULTI:
 4054                while(csr2->requests--)
 4055                    FreeOcspRequest(&csr2->request.ocsp[csr2->requests]);
 4056            break;
 4057        }
 4058
 4059        XFREE(csr2, heap, DYNAMIC_TYPE_TLSX);
 4060    }
 4061    (void)heap;
 4062}
 4063
 4064static word16 TLSX_CSR2_GetSize(CertificateStatusRequestItemV2* csr2,
 4065                                                                 byte isRequest)
 4066{
 4067    word32 size = 0;
 4068
 4069    /* shut up compiler warnings */
 4070    (void) csr2; (void) isRequest;
 4071
 4072#ifndef NO_WOLFSSL_CLIENT
 4073    if (isRequest) {
 4074        CertificateStatusRequestItemV2* next;
 4075
 4076        for (size = OPAQUE16_LEN; csr2; csr2 = next) {
 4077            next = csr2->next;
 4078
 4079            switch (csr2->status_type) {
 4080                case WOLFSSL_CSR2_OCSP:
 4081                case WOLFSSL_CSR2_OCSP_MULTI:
 4082                    size += ENUM_LEN + 3 * OPAQUE16_LEN;
 4083
 4084                    if (csr2->request.ocsp[0].nonceSz)
 4085                        size += OCSP_NONCE_EXT_SZ;
 4086                break;
 4087            }
 4088
 4089            if (size > WOLFSSL_MAX_16BIT) {
 4090                return 0;
 4091            }
 4092        }
 4093    }
 4094#endif
 4095
 4096    return (word16)size;
 4097}
 4098
 4099static int TLSX_CSR2_Write(CertificateStatusRequestItemV2* csr2,
 4100                                                   byte* output, byte isRequest)
 4101{
 4102    /* shut up compiler warnings */
 4103    (void) csr2; (void) output; (void) isRequest;
 4104
 4105#ifndef NO_WOLFSSL_CLIENT
 4106    if (isRequest) {
 4107        int ret = 0;
 4108        word16 offset;
 4109        word16 length;
 4110
 4111        for (offset = OPAQUE16_LEN; csr2 != NULL; csr2 = csr2->next) {
 4112            /* status_type */
 4113            output[offset++] = csr2->status_type;
 4114
 4115            /* request */
 4116            switch (csr2->status_type) {
 4117                case WOLFSSL_CSR2_OCSP:
 4118                case WOLFSSL_CSR2_OCSP_MULTI:
 4119                    /* request_length */
 4120                    length = 2 * OPAQUE16_LEN;
 4121
 4122                    if (csr2->request.ocsp[0].nonceSz)
 4123                        length += OCSP_NONCE_EXT_SZ;
 4124
 4125                    c16toa(length, output + offset);
 4126                    offset += OPAQUE16_LEN;
 4127
 4128                    /* responder id list */
 4129                    c16toa(0, output + offset);
 4130                    offset += OPAQUE16_LEN;
 4131
 4132                    /* request extensions */
 4133                    length = 0;
 4134
 4135                    if (csr2->request.ocsp[0].nonceSz) {
 4136                        ret = (int)EncodeOcspRequestExtensions(
 4137                                                 &csr2->request.ocsp[0],
 4138                                                 output + offset + OPAQUE16_LEN,
 4139                                                 OCSP_NONCE_EXT_SZ);
 4140
 4141                        if (ret > 0) {
 4142                            length = (word16)ret;
 4143                        }
 4144                        else {
 4145                            return ret;
 4146                        }
 4147                    }
 4148
 4149                    c16toa(length, output + offset);
 4150                    offset += OPAQUE16_LEN + length;
 4151                break;
 4152            }
 4153        }
 4154
 4155        /* list size */
 4156        c16toa(offset - OPAQUE16_LEN, output);
 4157
 4158        return (int)offset;
 4159    }
 4160#endif
 4161
 4162    return 0;
 4163}
 4164
 4165static int TLSX_CSR2_Parse(WOLFSSL* ssl, const byte* input, word16 length,
 4166                           byte isRequest)
 4167{
 4168    int ret;
 4169
 4170    /* shut up compiler warnings */
 4171    (void) ssl; (void) input;
 4172
 4173    if (!isRequest) {
 4174#ifndef NO_WOLFSSL_CLIENT
 4175        TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST_V2);
 4176        CertificateStatusRequestItemV2* csr2 = extension ?
 4177                        (CertificateStatusRequestItemV2*)extension->data : NULL;
 4178
 4179        if (!csr2) {
 4180            /* look at context level */
 4181            extension = TLSX_Find(ssl->ctx->extensions, TLSX_STATUS_REQUEST_V2);
 4182            csr2 = extension ?
 4183                        (CertificateStatusRequestItemV2*)extension->data : NULL;
 4184
 4185            if (!csr2) /* unexpected extension */
 4186                return TLSX_HandleUnsupportedExtension(ssl);
 4187
 4188            /* enable extension at ssl level */
 4189            for (; csr2; csr2 = csr2->next) {
 4190                ret = TLSX_UseCertificateStatusRequestV2(&ssl->extensions,
 4191                                    csr2->status_type, csr2->options, ssl->heap,
 4192                                                                    ssl->devId);
 4193                if (ret != WOLFSSL_SUCCESS)
 4194                    return ret;
 4195
 4196                switch (csr2->status_type) {
 4197                    case WOLFSSL_CSR2_OCSP:
 4198                        /* followed by */
 4199                    case WOLFSSL_CSR2_OCSP_MULTI:
 4200                        /* propagate nonce */
 4201                        if (csr2->request.ocsp[0].nonceSz) {
 4202                            OcspRequest* request =
 4203                             (OcspRequest*)TLSX_CSR2_GetRequest(ssl->extensions,
 4204                                                          csr2->status_type, 0);
 4205
 4206                            if (request) {
 4207                                XMEMCPY(request->nonce,
 4208                                        csr2->request.ocsp[0].nonce,
 4209                                        (size_t)csr2->request.ocsp[0].nonceSz);
 4210
 4211                                request->nonceSz =
 4212                                                  csr2->request.ocsp[0].nonceSz;
 4213                            }
 4214                        }
 4215                    break;
 4216                }
 4217            }
 4218        }
 4219
 4220        ssl->status_request_v2 = 1;
 4221
 4222        return length ? BUFFER_ERROR : 0; /* extension_data MUST be empty. */
 4223#endif
 4224    }
 4225    else {
 4226#ifndef NO_WOLFSSL_SERVER
 4227        byte   status_type;
 4228        word16 request_length;
 4229        word16 offset = 0;
 4230        word16 size = 0;
 4231
 4232        /* list size */
 4233        if (offset + OPAQUE16_LEN >= length) {
 4234            return BUFFER_E;
 4235        }
 4236
 4237        ato16(input + offset, &request_length);
 4238        offset += OPAQUE16_LEN;
 4239
 4240        if (length - OPAQUE16_LEN != request_length)
 4241            return BUFFER_ERROR;
 4242
 4243        while (length > offset) {
 4244            if ((int)(length - offset) < ENUM_LEN + OPAQUE16_LEN)
 4245                return BUFFER_ERROR;
 4246
 4247            status_type = input[offset++];
 4248
 4249            ato16(input + offset, &request_length);
 4250            offset += OPAQUE16_LEN;
 4251
 4252            if (length - offset < request_length)
 4253                return BUFFER_ERROR;
 4254
 4255            switch (status_type) {
 4256                case WOLFSSL_CSR2_OCSP:
 4257                case WOLFSSL_CSR2_OCSP_MULTI:
 4258                    /* skip responder_id_list */
 4259                    if ((int)(length - offset) < OPAQUE16_LEN)
 4260                        return BUFFER_ERROR;
 4261
 4262                    ato16(input + offset, &size);
 4263                    if (length - offset - OPAQUE16_LEN < size)
 4264                        return BUFFER_ERROR;
 4265
 4266                    offset += OPAQUE16_LEN + size;
 4267                    /* skip request_extensions */
 4268                    if ((int)(length - offset) < OPAQUE16_LEN)
 4269                        return BUFFER_ERROR;
 4270
 4271                    ato16(input + offset, &size);
 4272                    if (length - offset < size)
 4273                        return BUFFER_ERROR;
 4274
 4275                    offset += OPAQUE16_LEN + size;
 4276                    if (offset > length)
 4277                        return BUFFER_ERROR;
 4278
 4279                    /* is able to send OCSP response? */
 4280                    if (SSL_CM(ssl) == NULL
 4281                    || !SSL_CM(ssl)->ocspStaplingEnabled)
 4282                        continue;
 4283                break;
 4284
 4285                default:
 4286                    /* unknown status type, skipping! */
 4287                    offset += request_length;
 4288                    continue;
 4289            }
 4290
 4291            /* if using status_request and already sending it, remove it
 4292             * and prefer to use the v2 version */
 4293            #ifdef HAVE_CERTIFICATE_STATUS_REQUEST
 4294            if (ssl->status_request) {
 4295                ssl->status_request = 0;
 4296                TLSX_Remove(&ssl->extensions, TLSX_STATUS_REQUEST, ssl->heap);
 4297            }
 4298            #endif
 4299
 4300            /* TLS 1.3 servers MUST NOT act upon presence or information in
 4301             * this extension (RFC 8448 Section 4.4.2.1).
 4302             */
 4303            if (!IsAtLeastTLSv1_3(ssl->version)) {
 4304                /* accept the first good status_type and return */
 4305                ret = TLSX_UseCertificateStatusRequestV2(&ssl->extensions,
 4306                                         status_type, 0, ssl->heap, ssl->devId);
 4307                if (ret != WOLFSSL_SUCCESS)
 4308                    return ret; /* throw error */
 4309
 4310                TLSX_SetResponse(ssl, TLSX_STATUS_REQUEST_V2);
 4311                ssl->status_request_v2 = status_type;
 4312            }
 4313
 4314            return 0;
 4315        }
 4316#endif
 4317    }
 4318
 4319    return 0;
 4320}
 4321
 4322static CertificateStatusRequestItemV2* TLSX_CSR2_GetMulti(TLSX *extensions)
 4323{
 4324    TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST_V2);
 4325    CertificateStatusRequestItemV2* csr2 = extension ?
 4326        (CertificateStatusRequestItemV2*)extension->data : NULL;
 4327
 4328    for (; csr2; csr2 = csr2->next) {
 4329        if (csr2->status_type == WOLFSSL_CSR2_OCSP_MULTI)
 4330            return csr2;
 4331    }
 4332    return NULL;
 4333}
 4334
 4335int TLSX_CSR2_IsMulti(TLSX *extensions)
 4336{
 4337    return TLSX_CSR2_GetMulti(extensions) != NULL;
 4338}
 4339
 4340int TLSX_CSR2_AddPendingSigner(TLSX *extensions, Signer *s)
 4341{
 4342    CertificateStatusRequestItemV2* csr2;
 4343
 4344    csr2 = TLSX_CSR2_GetMulti(extensions);
 4345    if (!csr2)
 4346        return WOLFSSL_FATAL_ERROR;
 4347
 4348    s->next = csr2->pendingSigners;
 4349    csr2->pendingSigners = s;
 4350    return 0;
 4351}
 4352
 4353Signer* TLSX_CSR2_GetPendingSigners(TLSX *extensions)
 4354{
 4355    CertificateStatusRequestItemV2* csr2;
 4356
 4357    csr2 = TLSX_CSR2_GetMulti(extensions);
 4358    if (!csr2)
 4359        return NULL;
 4360
 4361    return csr2->pendingSigners;
 4362}
 4363
 4364int TLSX_CSR2_ClearPendingCA(WOLFSSL *ssl)
 4365{
 4366    CertificateStatusRequestItemV2* csr2;
 4367
 4368    csr2 = TLSX_CSR2_GetMulti(ssl->extensions);
 4369    if (csr2 == NULL)
 4370        return 0;
 4371
 4372    TLSX_CSR2_FreePendingSigners(csr2->pendingSigners, SSL_CM(ssl)->heap);
 4373    csr2->pendingSigners = NULL;
 4374    return 0;
 4375}
 4376
 4377int TLSX_CSR2_MergePendingCA(WOLFSSL* ssl)
 4378{
 4379    CertificateStatusRequestItemV2* csr2;
 4380    Signer *s, *next;
 4381    int r = 0;
 4382
 4383    csr2 = TLSX_CSR2_GetMulti(ssl->extensions);
 4384    if (csr2 == NULL)
 4385        return 0;
 4386
 4387    s = csr2->pendingSigners;
 4388    while (s != NULL) {
 4389        next = s->next;
 4390        r = AddSigner(SSL_CM(ssl), s);
 4391        if (r != 0)
 4392            FreeSigner(s, SSL_CM(ssl)->heap);
 4393        s = next;
 4394    }
 4395    csr2->pendingSigners = NULL;
 4396    return r;
 4397}
 4398
 4399int TLSX_CSR2_InitRequests(TLSX* extensions, DecodedCert* cert, byte isPeer,
 4400                                                                     void* heap)
 4401{
 4402    TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST_V2);
 4403    CertificateStatusRequestItemV2* csr2 = extension ?
 4404        (CertificateStatusRequestItemV2*)extension->data : NULL;
 4405    int ret = 0;
 4406
 4407    for (; csr2; csr2 = csr2->next) {
 4408        switch (csr2->status_type) {
 4409            case WOLFSSL_CSR2_OCSP:
 4410                if (!isPeer || csr2->requests != 0)
 4411                    break;
 4412
 4413                FALL_THROUGH; /* followed by */
 4414
 4415            case WOLFSSL_CSR2_OCSP_MULTI: {
 4416                if (csr2->requests < 1 + MAX_CHAIN_DEPTH) {
 4417                    byte nonce[MAX_OCSP_NONCE_SZ];
 4418                    int  nonceSz = csr2->request.ocsp[0].nonceSz;
 4419
 4420                    /* preserve nonce, replicating nonce of ocsp[0] */
 4421                    XMEMCPY(nonce, csr2->request.ocsp[0].nonce,
 4422                    (size_t)nonceSz);
 4423
 4424                    if ((ret = InitOcspRequest(
 4425                                      &csr2->request.ocsp[csr2->requests], cert,
 4426                                                                 0, heap)) != 0)
 4427                        return ret;
 4428
 4429                    /* restore nonce */
 4430                    XMEMCPY(csr2->request.ocsp[csr2->requests].nonce,
 4431                                                        nonce, (size_t)nonceSz);
 4432                    csr2->request.ocsp[csr2->requests].nonceSz = nonceSz;
 4433                    csr2->requests++;
 4434                }
 4435            }
 4436            break;
 4437        }
 4438    }
 4439
 4440    (void)cert;
 4441    return ret;
 4442}
 4443
 4444void* TLSX_CSR2_GetRequest(TLSX* extensions, byte status_type, byte idx)
 4445{
 4446    TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST_V2);
 4447    CertificateStatusRequestItemV2* csr2 = extension ?
 4448                        (CertificateStatusRequestItemV2*)extension->data : NULL;
 4449
 4450    for (; csr2; csr2 = csr2->next) {
 4451        if (csr2->status_type == status_type) {
 4452            switch (csr2->status_type) {
 4453                case WOLFSSL_CSR2_OCSP:
 4454                    /* followed by */
 4455
 4456                case WOLFSSL_CSR2_OCSP_MULTI:
 4457                    /* requests are initialized in the reverse order */
 4458                    return idx < csr2->requests
 4459                         ? &csr2->request.ocsp[csr2->requests - idx - 1]
 4460                         : NULL;
 4461            }
 4462        }
 4463    }
 4464
 4465    return NULL;
 4466}
 4467
 4468int TLSX_CSR2_ForceRequest(WOLFSSL* ssl)
 4469{
 4470    TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST_V2);
 4471    CertificateStatusRequestItemV2* csr2 = extension ?
 4472                        (CertificateStatusRequestItemV2*)extension->data : NULL;
 4473
 4474    /* forces only the first one */
 4475    if (csr2) {
 4476        switch (csr2->status_type) {
 4477            case WOLFSSL_CSR2_OCSP:
 4478                /* followed by */
 4479
 4480            case WOLFSSL_CSR2_OCSP_MULTI:
 4481                if (SSL_CM(ssl)->ocspEnabled && csr2->requests >= 1) {
 4482                    csr2->request.ocsp[csr2->requests-1].ssl = ssl;
 4483                    return CheckOcspRequest(SSL_CM(ssl)->ocsp,
 4484                                          &csr2->request.ocsp[csr2->requests-1], NULL, NULL);
 4485                }
 4486                else {
 4487                    WOLFSSL_ERROR_VERBOSE(OCSP_LOOKUP_FAIL);
 4488                    return OCSP_LOOKUP_FAIL;
 4489                }
 4490        }
 4491    }
 4492
 4493    return 0;
 4494}
 4495
 4496int TLSX_UseCertificateStatusRequestV2(TLSX** extensions, byte status_type,
 4497                                           byte options, void* heap, int devId)
 4498{
 4499    TLSX* extension = NULL;
 4500    CertificateStatusRequestItemV2* csr2 = NULL;
 4501    int ret = 0;
 4502
 4503    if (!extensions)
 4504        return BAD_FUNC_ARG;
 4505
 4506    if (status_type != WOLFSSL_CSR2_OCSP
 4507    &&  status_type != WOLFSSL_CSR2_OCSP_MULTI)
 4508        return BAD_FUNC_ARG;
 4509
 4510    csr2 = (CertificateStatusRequestItemV2*)
 4511       XMALLOC(sizeof(CertificateStatusRequestItemV2), heap, DYNAMIC_TYPE_TLSX);
 4512    if (!csr2)
 4513        return MEMORY_E;
 4514
 4515    ForceZero(csr2, sizeof(CertificateStatusRequestItemV2));
 4516
 4517    csr2->status_type = status_type;
 4518    csr2->options     = options;
 4519    csr2->next        = NULL;
 4520
 4521    switch (csr2->status_type) {
 4522        case WOLFSSL_CSR2_OCSP:
 4523        case WOLFSSL_CSR2_OCSP_MULTI:
 4524            if (options & WOLFSSL_CSR2_OCSP_USE_NONCE) {
 4525                WC_RNG rng;
 4526
 4527            #ifndef HAVE_FIPS
 4528                ret = wc_InitRng_ex(&rng, heap, devId);
 4529            #else
 4530                ret = wc_InitRng(&rng);
 4531                (void)devId;
 4532            #endif
 4533                if (ret == 0) {
 4534                    if (wc_RNG_GenerateBlock(&rng, csr2->request.ocsp[0].nonce,
 4535                                                        MAX_OCSP_NONCE_SZ) == 0)
 4536                        csr2->request.ocsp[0].nonceSz = MAX_OCSP_NONCE_SZ;
 4537
 4538                    wc_FreeRng(&rng);
 4539                }
 4540            }
 4541        break;
 4542    }
 4543
 4544    /* append new item */
 4545    if ((extension = TLSX_Find(*extensions, TLSX_STATUS_REQUEST_V2))) {
 4546        CertificateStatusRequestItemV2* last =
 4547                               (CertificateStatusRequestItemV2*)extension->data;
 4548
 4549        if (last == NULL) {
 4550            XFREE(csr2, heap, DYNAMIC_TYPE_TLSX);
 4551            return BAD_FUNC_ARG;
 4552        }
 4553
 4554        for (; last->next; last = last->next);
 4555
 4556        last->next = csr2;
 4557    }
 4558    else if ((ret = TLSX_Push(extensions, TLSX_STATUS_REQUEST_V2, csr2,heap))) {
 4559        XFREE(csr2, heap, DYNAMIC_TYPE_TLSX);
 4560        return ret;
 4561    }
 4562
 4563    return WOLFSSL_SUCCESS;
 4564}
 4565
 4566#define CSR2_FREE_ALL TLSX_CSR2_FreeAll
 4567#define CSR2_GET_SIZE TLSX_CSR2_GetSize
 4568#define CSR2_WRITE    TLSX_CSR2_Write
 4569#define CSR2_PARSE    TLSX_CSR2_Parse
 4570
 4571#else
 4572
 4573#define CSR2_FREE_ALL(data, heap) WC_DO_NOTHING
 4574#define CSR2_GET_SIZE(a, b)    0
 4575#define CSR2_WRITE(a, b, c)    0
 4576#define CSR2_PARSE(a, b, c, d) 0
 4577
 4578#endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
 4579
 4580#if defined(HAVE_SUPPORTED_CURVES) || \
 4581    (defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES))
 4582
 4583/* Returns whether this group is supported.
 4584 *
 4585 * namedGroup  The named group to check.
 4586 * returns 1 when supported or 0 otherwise.
 4587 */
 4588int TLSX_IsGroupSupported(int namedGroup)
 4589{
 4590    switch (namedGroup) {
 4591    #ifdef HAVE_FFDHE_2048
 4592        case WOLFSSL_FFDHE_2048:
 4593            break;
 4594    #endif
 4595    #ifdef HAVE_FFDHE_3072
 4596        case WOLFSSL_FFDHE_3072:
 4597            break;
 4598    #endif
 4599    #ifdef HAVE_FFDHE_4096
 4600        case WOLFSSL_FFDHE_4096:
 4601            break;
 4602    #endif
 4603    #ifdef HAVE_FFDHE_6144
 4604        case WOLFSSL_FFDHE_6144:
 4605            break;
 4606    #endif
 4607    #ifdef HAVE_FFDHE_8192
 4608        case WOLFSSL_FFDHE_8192:
 4609            break;
 4610    #endif
 4611    #if (!defined(NO_ECC256)  || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 256
 4612        #ifdef HAVE_ECC_KOBLITZ
 4613        case WOLFSSL_ECC_SECP256K1:
 4614            break;
 4615        #endif
 4616        #ifndef NO_ECC_SECP
 4617        case WOLFSSL_ECC_SECP256R1:
 4618            break;
 4619        #endif /* !NO_ECC_SECP */
 4620        #ifdef HAVE_ECC_BRAINPOOL
 4621        case WOLFSSL_ECC_BRAINPOOLP256R1:
 4622        case WOLFSSL_ECC_BRAINPOOLP256R1TLS13:
 4623            break;
 4624        #endif
 4625        #ifdef WOLFSSL_SM2
 4626        case WOLFSSL_ECC_SM2P256V1:
 4627            break;
 4628        #endif /* WOLFSSL_SM2 */
 4629    #endif
 4630    #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256
 4631        case WOLFSSL_ECC_X25519:
 4632            break;
 4633    #endif
 4634    #if defined(HAVE_CURVE448) && ECC_MIN_KEY_SZ <= 448
 4635        case WOLFSSL_ECC_X448:
 4636            break;
 4637    #endif
 4638    #if (defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 384
 4639        #ifndef NO_ECC_SECP
 4640        case WOLFSSL_ECC_SECP384R1:
 4641            break;
 4642        #endif /* !NO_ECC_SECP */
 4643        #ifdef HAVE_ECC_BRAINPOOL
 4644        case WOLFSSL_ECC_BRAINPOOLP384R1:
 4645        case WOLFSSL_ECC_BRAINPOOLP384R1TLS13:
 4646            break;
 4647        #endif
 4648    #endif
 4649    #if (defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 521
 4650        #ifndef NO_ECC_SECP
 4651        case WOLFSSL_ECC_SECP521R1:
 4652            break;
 4653        #endif /* !NO_ECC_SECP */
 4654    #endif
 4655    #if (defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 160
 4656        #ifdef HAVE_ECC_KOBLITZ
 4657        case WOLFSSL_ECC_SECP160K1:
 4658            break;
 4659        #endif
 4660        #ifndef NO_ECC_SECP
 4661        case WOLFSSL_ECC_SECP160R1:
 4662            break;
 4663        #endif
 4664        #ifdef HAVE_ECC_SECPR2
 4665        case WOLFSSL_ECC_SECP160R2:
 4666            break;
 4667        #endif
 4668    #endif
 4669    #if (defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 192
 4670        #ifdef HAVE_ECC_KOBLITZ
 4671        case WOLFSSL_ECC_SECP192K1:
 4672            break;
 4673        #endif
 4674        #ifndef NO_ECC_SECP
 4675        case WOLFSSL_ECC_SECP192R1:
 4676            break;
 4677        #endif
 4678    #endif
 4679    #if (defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 224
 4680        #ifdef HAVE_ECC_KOBLITZ
 4681        case WOLFSSL_ECC_SECP224K1:
 4682            break;
 4683        #endif
 4684        #ifndef NO_ECC_SECP
 4685        case WOLFSSL_ECC_SECP224R1:
 4686            break;
 4687        #endif
 4688    #endif
 4689    #if (defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 512
 4690        #ifdef HAVE_ECC_BRAINPOOL
 4691        case WOLFSSL_ECC_BRAINPOOLP512R1:
 4692        case WOLFSSL_ECC_BRAINPOOLP512R1TLS13:
 4693            break;
 4694        #endif
 4695    #endif
 4696#ifdef WOLFSSL_HAVE_MLKEM
 4697#ifndef WOLFSSL_NO_ML_KEM
 4698        #ifndef WOLFSSL_NO_ML_KEM_512
 4699            #ifndef WOLFSSL_TLS_NO_MLKEM_STANDALONE
 4700            case WOLFSSL_ML_KEM_512:
 4701                break;
 4702            #endif /* !WOLFSSL_TLS_NO_MLKEM_STANDALONE */
 4703            #ifdef WOLFSSL_EXTRA_PQC_HYBRIDS
 4704            case WOLFSSL_SECP256R1MLKEM512:
 4705            #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256
 4706            case WOLFSSL_X25519MLKEM512:
 4707            #endif /* HAVE_CURVE25519 */
 4708                break;
 4709            #endif /* WOLFSSL_EXTRA_PQC_HYBRIDS */
 4710        #endif /* WOLFSSL_NO_ML_KEM_512 */
 4711        #ifndef WOLFSSL_NO_ML_KEM_768
 4712            #ifndef WOLFSSL_TLS_NO_MLKEM_STANDALONE
 4713            case WOLFSSL_ML_KEM_768:
 4714            #endif /* !WOLFSSL_TLS_NO_MLKEM_STANDALONE */
 4715            #ifdef WOLFSSL_PQC_HYBRIDS
 4716            case WOLFSSL_SECP256R1MLKEM768:
 4717            #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256
 4718            case WOLFSSL_X25519MLKEM768:
 4719            #endif /* HAVE_CURVE25519 */
 4720            #endif /* WOLFSSL_PQC_HYBRIDS */
 4721            #ifdef WOLFSSL_EXTRA_PQC_HYBRIDS
 4722            case WOLFSSL_SECP384R1MLKEM768:
 4723            #if defined(HAVE_CURVE448) && ECC_MIN_KEY_SZ <= 448
 4724            case WOLFSSL_X448MLKEM768:
 4725            #endif /* HAVE_CURVE448 */
 4726            #endif /* WOLFSSL_EXTRA_PQC_HYBRIDS */
 4727                break;
 4728        #endif /* WOLFSSL_NO_ML_KEM_768 */
 4729        #ifndef WOLFSSL_NO_ML_KEM_1024
 4730            #ifndef WOLFSSL_TLS_NO_MLKEM_STANDALONE
 4731            case WOLFSSL_ML_KEM_1024:
 4732            #endif /* !WOLFSSL_TLS_NO_MLKEM_STANDALONE */
 4733            #ifdef WOLFSSL_PQC_HYBRIDS
 4734            case WOLFSSL_SECP384R1MLKEM1024:
 4735            #endif /* WOLFSSL_PQC_HYBRIDS */
 4736            #ifdef WOLFSSL_EXTRA_PQC_HYBRIDS
 4737            case WOLFSSL_SECP521R1MLKEM1024:
 4738            #endif /* WOLFSSL_EXTRA_PQC_HYBRIDS */
 4739                break;
 4740        #endif
 4741        #if defined(WOLFSSL_ML_KEM_USE_OLD_IDS) && \
 4742                                             defined (WOLFSSL_EXTRA_PQC_HYBRIDS)
 4743            case WOLFSSL_P256_ML_KEM_512_OLD:
 4744            case WOLFSSL_P384_ML_KEM_768_OLD:
 4745            case WOLFSSL_P521_ML_KEM_1024_OLD:
 4746                break;
 4747        #endif /* WOLFSSL_ML_KEM_USE_OLD_IDS && WOLFSSL_EXTRA_PQC_HYBRIDS */
 4748#endif /* WOLFSSL_NO_ML_KEM */
 4749#ifdef WOLFSSL_MLKEM_KYBER
 4750        #ifdef WOLFSSL_KYBER512
 4751            case WOLFSSL_KYBER_LEVEL1:
 4752            case WOLFSSL_P256_KYBER_LEVEL1:
 4753        #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256
 4754            case WOLFSSL_X25519_KYBER_LEVEL1:
 4755        #endif
 4756        #endif
 4757        #ifdef WOLFSSL_KYBER768
 4758            case WOLFSSL_KYBER_LEVEL3:
 4759            case WOLFSSL_P384_KYBER_LEVEL3:
 4760            case WOLFSSL_P256_KYBER_LEVEL3:
 4761        #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256
 4762            case WOLFSSL_X25519_KYBER_LEVEL3:
 4763        #endif
 4764        #if defined(HAVE_CURVE448) && ECC_MIN_KEY_SZ <= 448
 4765            case WOLFSSL_X448_KYBER_LEVEL3:
 4766        #endif
 4767        #endif
 4768        #ifdef WOLFSSL_KYBER1024
 4769            case WOLFSSL_KYBER_LEVEL5:
 4770            case WOLFSSL_P521_KYBER_LEVEL5:
 4771        #endif
 4772                break;
 4773#endif
 4774#endif /* WOLFSSL_HAVE_MLKEM */
 4775        default:
 4776            return 0;
 4777    }
 4778
 4779    return 1;
 4780}
 4781#endif
 4782
 4783/******************************************************************************/
 4784/* Supported Elliptic Curves                                                  */
 4785/******************************************************************************/
 4786
 4787#ifdef HAVE_SUPPORTED_CURVES
 4788
 4789#if !defined(HAVE_ECC) && !defined(HAVE_CURVE25519) && !defined(HAVE_CURVE448) \
 4790                       && !defined(HAVE_FFDHE) && !defined(WOLFSSL_HAVE_MLKEM)
 4791#error Elliptic Curves Extension requires Elliptic Curve Cryptography or liboqs groups. \
 4792       Use --enable-ecc and/or --enable-liboqs in the configure script or \
 4793       define HAVE_ECC. Alternatively use FFDHE for DH cipher suites.
 4794#endif
 4795
 4796static int TLSX_SupportedCurve_New(SupportedCurve** curve, word16 name,
 4797                                                                     void* heap)
 4798{
 4799    if (curve == NULL)
 4800        return BAD_FUNC_ARG;
 4801
 4802    (void)heap;
 4803
 4804    *curve = (SupportedCurve*)XMALLOC(sizeof(SupportedCurve), heap,
 4805                                                             DYNAMIC_TYPE_TLSX);
 4806    if (*curve == NULL)
 4807        return MEMORY_E;
 4808
 4809    (*curve)->name = name;
 4810    (*curve)->next = NULL;
 4811
 4812    return 0;
 4813}
 4814
 4815static int TLSX_PointFormat_New(PointFormat** point, byte format, void* heap)
 4816{
 4817    if (point == NULL)
 4818        return BAD_FUNC_ARG;
 4819
 4820    (void)heap;
 4821
 4822    *point = (PointFormat*)XMALLOC(sizeof(PointFormat), heap,
 4823                                                             DYNAMIC_TYPE_TLSX);
 4824    if (*point == NULL)
 4825        return MEMORY_E;
 4826
 4827    (*point)->format = format;
 4828    (*point)->next = NULL;
 4829
 4830    return 0;
 4831}
 4832
 4833static void TLSX_SupportedCurve_FreeAll(SupportedCurve* list, void* heap)
 4834{
 4835    SupportedCurve* curve;
 4836
 4837    while ((curve = list)) {
 4838        list = curve->next;
 4839        XFREE(curve, heap, DYNAMIC_TYPE_TLSX);
 4840    }
 4841    (void)heap;
 4842}
 4843
 4844static void TLSX_PointFormat_FreeAll(PointFormat* list, void* heap)
 4845{
 4846    PointFormat* point;
 4847
 4848    while ((point = list)) {
 4849        list = point->next;
 4850        XFREE(point, heap, DYNAMIC_TYPE_TLSX);
 4851    }
 4852    (void)heap;
 4853}
 4854
 4855static int TLSX_SupportedCurve_Append(SupportedCurve* list, word16 name,
 4856                                                                     void* heap)
 4857{
 4858    int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG);
 4859
 4860    while (list) {
 4861        if (list->name == name) {
 4862            ret = 0; /* curve already in use */
 4863            break;
 4864        }
 4865
 4866        if (list->next == NULL) {
 4867            ret = TLSX_SupportedCurve_New(&list->next, name, heap);
 4868            break;
 4869        }
 4870
 4871        list = list->next;
 4872    }
 4873
 4874    return ret;
 4875}
 4876
 4877static int TLSX_PointFormat_Append(PointFormat* list, byte format, void* heap)
 4878{
 4879    int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG);
 4880
 4881    while (list) {
 4882        if (list->format == format) {
 4883            ret = 0; /* format already in use */
 4884            break;
 4885        }
 4886
 4887        if (list->next == NULL) {
 4888            ret = TLSX_PointFormat_New(&list->next, format, heap);
 4889            break;
 4890        }
 4891
 4892        list = list->next;
 4893    }
 4894
 4895    return ret;
 4896}
 4897
 4898#if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_CLIENT)
 4899
 4900#if defined(HAVE_FFDHE) && (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
 4901                                                         defined(HAVE_CURVE448))
 4902static void TLSX_SupportedCurve_ValidateRequest(const WOLFSSL* ssl,
 4903                                                const byte* semaphore)
 4904{
 4905    /* If all pre-defined parameter types for key exchange are supported then
 4906     * always send SupportedGroups extension.
 4907     */
 4908    (void)ssl;
 4909    (void)semaphore;
 4910}
 4911#else
 4912static void TLSX_SupportedCurve_ValidateRequest(WOLFSSL* ssl, byte* semaphore)
 4913{
 4914    word16 i;
 4915    const Suites* suites = WOLFSSL_SUITES(ssl);
 4916
 4917    for (i = 0; i < suites->suiteSz; i += 2) {
 4918        if (suites->suites[i] == TLS13_BYTE)
 4919            return;
 4920    #ifdef BUILD_TLS_SM4_GCM_SM3
 4921        if ((suites->suites[i] == CIPHER_BYTE) &&
 4922            (suites->suites[i+1] == TLS_SM4_GCM_SM3))
 4923            return;
 4924    #endif
 4925    #ifdef BUILD_TLS_SM4_CCM_SM3
 4926        if ((suites->suites[i] == CIPHER_BYTE) &&
 4927            (suites->suites[i+1] == TLS_SM4_CCM_SM3))
 4928            return;
 4929    #endif
 4930    #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_SM4_CBC_SM3
 4931        if ((suites->suites[i] == SM_BYTE) &&
 4932            (suites->suites[i+1] == TLS_ECDHE_ECDSA_WITH_SM4_CBC_SM3))
 4933            return;
 4934    #endif
 4935        if ((suites->suites[i] == ECC_BYTE) ||
 4936            (suites->suites[i] == ECDHE_PSK_BYTE) ||
 4937            (suites->suites[i] == CHACHA_BYTE)) {
 4938        #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
 4939                                                          defined(HAVE_CURVE448)
 4940            return;
 4941        #endif
 4942        }
 4943        #ifdef HAVE_FFDHE
 4944        else {
 4945            return;
 4946        }
 4947        #endif
 4948    }
 4949
 4950    /* turns semaphore on to avoid sending this extension. */
 4951    TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_GROUPS));
 4952}
 4953#endif
 4954
 4955/* Only send PointFormats if TLSv13, ECC or CHACHA cipher suite present.
 4956 */
 4957static void TLSX_PointFormat_ValidateRequest(WOLFSSL* ssl, byte* semaphore)
 4958{
 4959#ifdef HAVE_FFDHE
 4960    (void)ssl;
 4961    (void)semaphore;
 4962#else
 4963    word16 i;
 4964    const Suites* suites = WOLFSSL_SUITES(ssl);
 4965
 4966    if (suites == NULL)
 4967        return;
 4968
 4969    for (i = 0; i < suites->suiteSz; i += 2) {
 4970        if (suites->suites[i] == TLS13_BYTE)
 4971            return;
 4972    #ifdef BUILD_TLS_SM4_GCM_SM3
 4973        if ((suites->suites[i] == CIPHER_BYTE) &&
 4974            (suites->suites[i+1] == TLS_SM4_GCM_SM3))
 4975            return;
 4976    #endif
 4977    #ifdef BUILD_TLS_SM4_CCM_SM3
 4978        if ((suites->suites[i] == CIPHER_BYTE) &&
 4979            (suites->suites[i+1] == TLS_SM4_CCM_SM3))
 4980            return;
 4981    #endif
 4982    #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_SM4_CBC_SM3
 4983        if ((suites->suites[i] == SM_BYTE) &&
 4984            (suites->suites[i+1] == TLS_ECDHE_ECDSA_WITH_SM4_CBC_SM3))
 4985            return;
 4986    #endif
 4987        if ((suites->suites[i] == ECC_BYTE) ||
 4988            (suites->suites[i] == ECDHE_PSK_BYTE) ||
 4989            (suites->suites[i] == CHACHA_BYTE)) {
 4990        #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
 4991                                                          defined(HAVE_CURVE448)
 4992            return;
 4993        #endif
 4994        }
 4995    }
 4996   /* turns semaphore on to avoid sending this extension. */
 4997   TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EC_POINT_FORMATS));
 4998#endif
 4999}
 5000
 5001#endif /* WOLFSSL_TLS13 || !NO_WOLFSSL_CLIENT */
 5002
 5003#ifndef NO_WOLFSSL_SERVER
 5004
 5005static void TLSX_PointFormat_ValidateResponse(WOLFSSL* ssl, byte* semaphore)
 5006{
 5007#if defined(HAVE_FFDHE) || defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
 5008                                                          defined(HAVE_CURVE448)
 5009    (void)semaphore;
 5010#endif
 5011
 5012    if (ssl->options.cipherSuite0 == TLS13_BYTE)
 5013        return;
 5014#ifdef BUILD_TLS_SM4_GCM_SM3
 5015    if ((ssl->options.cipherSuite0 == CIPHER_BYTE) &&
 5016        (ssl->options.cipherSuite == TLS_SM4_GCM_SM3))
 5017        return;
 5018#endif
 5019#ifdef BUILD_TLS_SM4_CCM_SM3
 5020    if ((ssl->options.cipherSuite0 == CIPHER_BYTE) &&
 5021        (ssl->options.cipherSuite == TLS_SM4_CCM_SM3))
 5022        return;
 5023#endif
 5024#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_SM4_CBC_SM3
 5025    if ((ssl->options.cipherSuite0 == SM_BYTE) &&
 5026        (ssl->options.cipherSuite == TLS_ECDHE_ECDSA_WITH_SM4_CBC_SM3))
 5027        return;
 5028#endif
 5029#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
 5030    if (ssl->options.cipherSuite0 == ECC_BYTE ||
 5031        ssl->options.cipherSuite0 == ECDHE_PSK_BYTE ||
 5032        ssl->options.cipherSuite0 == CHACHA_BYTE) {
 5033        return;
 5034    }
 5035#endif
 5036
 5037    /* turns semaphore on to avoid sending this extension. */
 5038    TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EC_POINT_FORMATS));
 5039}
 5040
 5041#endif /* !NO_WOLFSSL_SERVER */
 5042
 5043#if !defined(NO_WOLFSSL_CLIENT) || defined(WOLFSSL_TLS13)
 5044
 5045static word16 TLSX_SupportedCurve_GetSize(SupportedCurve* list)
 5046{
 5047    SupportedCurve* curve;
 5048    word16 length = OPAQUE16_LEN; /* list length */
 5049
 5050    while ((curve = list)) {
 5051        list = curve->next;
 5052        length += OPAQUE16_LEN; /* curve length */
 5053    }
 5054
 5055    return length;
 5056}
 5057
 5058#endif
 5059
 5060static word16 TLSX_PointFormat_GetSize(PointFormat* list)
 5061{
 5062    PointFormat* point;
 5063    word16 length = ENUM_LEN; /* list length */
 5064
 5065    while ((point = list)) {
 5066        list = point->next;
 5067        length += ENUM_LEN; /* format length */
 5068    }
 5069
 5070    return length;
 5071}
 5072
 5073#if !defined(NO_WOLFSSL_CLIENT) || defined(WOLFSSL_TLS13)
 5074
 5075static word16 TLSX_SupportedCurve_Write(SupportedCurve* list, byte* output)
 5076{
 5077    word16 offset = OPAQUE16_LEN;
 5078
 5079    while (list) {
 5080        c16toa(list->name, output + offset);
 5081        offset += OPAQUE16_LEN;
 5082        list = list->next;
 5083    }
 5084
 5085    c16toa(offset - OPAQUE16_LEN, output); /* writing list length */
 5086
 5087    return offset;
 5088}
 5089
 5090#endif
 5091
 5092static word16 TLSX_PointFormat_Write(PointFormat* list, byte* output)
 5093{
 5094    word16 offset = ENUM_LEN;
 5095
 5096    while (list) {
 5097        output[offset++] = list->format;
 5098        list = list->next;
 5099    }
 5100
 5101    output[0] = (byte)(offset - ENUM_LEN);
 5102
 5103    return offset;
 5104}
 5105
 5106#if !defined(NO_WOLFSSL_SERVER) || (defined(WOLFSSL_TLS13) && \
 5107                                         !defined(WOLFSSL_NO_SERVER_GROUPS_EXT))
 5108
 5109int TLSX_SupportedCurve_Parse(const WOLFSSL* ssl, const byte* input,
 5110                              word16 length, byte isRequest, TLSX** extensions)
 5111{
 5112    word16 offset;
 5113    word16 name;
 5114    int ret = 0;
 5115    TLSX* extension;
 5116
 5117    if(!isRequest && !IsAtLeastTLSv1_3(ssl->version)) {
 5118#ifdef WOLFSSL_ALLOW_SERVER_SC_EXT
 5119        return 0;
 5120#else
 5121        return BUFFER_ERROR; /* servers doesn't send this extension. */
 5122#endif
 5123    }
 5124    if (OPAQUE16_LEN > length || length % OPAQUE16_LEN)
 5125        return BUFFER_ERROR;
 5126    ato16(input, &offset);
 5127    /* validating curve list length */
 5128    if (length != OPAQUE16_LEN + offset)
 5129        return BUFFER_ERROR;
 5130    offset = OPAQUE16_LEN;
 5131    if (offset == length)
 5132        return 0;
 5133
 5134    extension = TLSX_Find(*extensions, TLSX_SUPPORTED_GROUPS);
 5135    if (extension == NULL) {
 5136        /* Just accept what the peer wants to use */
 5137        for (; offset < length; offset += OPAQUE16_LEN) {
 5138            ato16(input + offset, &name);
 5139
 5140            ret = TLSX_UseSupportedCurve(extensions, name, ssl->heap);
 5141            /* If it is BAD_FUNC_ARG then it is a group we do not support, but
 5142             * that is fine. */
 5143            if (ret != WOLFSSL_SUCCESS &&
 5144                    ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
 5145                break;
 5146            ret = 0;
 5147        }
 5148    }
 5149    else {
 5150        /* Find the intersection with what the user has set */
 5151        SupportedCurve* commonCurves = NULL;
 5152        for (; offset < length; offset += OPAQUE16_LEN) {
 5153            SupportedCurve* foundCurve = (SupportedCurve*)extension->data;
 5154            ato16(input + offset, &name);
 5155
 5156            while (foundCurve != NULL && foundCurve->name != name)
 5157                foundCurve = foundCurve->next;
 5158
 5159            if (foundCurve != NULL) {
 5160                ret = commonCurves == NULL ?
 5161                      TLSX_SupportedCurve_New(&commonCurves, name, ssl->heap) :
 5162                      TLSX_SupportedCurve_Append(commonCurves, name, ssl->heap);
 5163                if (ret != 0)
 5164                    break;
 5165            }
 5166        }
 5167        /* If no common curves return error. In TLS 1.3 we can still try to save
 5168         * this by using HRR. */
 5169        if (ret == 0 && commonCurves == NULL &&
 5170                !IsAtLeastTLSv1_3(ssl->version))
 5171            ret = ECC_CURVE_ERROR;
 5172        if (ret == 0) {
 5173            /* Now swap out the curves in the extension */
 5174            TLSX_SupportedCurve_FreeAll((SupportedCurve*)extension->data,
 5175                                        ssl->heap);
 5176            extension->data = commonCurves;
 5177            commonCurves = NULL;
 5178        }
 5179        TLSX_SupportedCurve_FreeAll(commonCurves, ssl->heap);
 5180    }
 5181
 5182    return ret;
 5183}
 5184#endif
 5185
 5186#if !defined(NO_WOLFSSL_SERVER)
 5187
 5188#if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_NO_SERVER_GROUPS_EXT)
 5189
 5190/* Checks the priority of the groups on the server and set the supported groups
 5191 * response if there is a group not advertised by the client that is preferred.
 5192 *
 5193 * ssl  SSL/TLS object.
 5194 * returns 0 on success, otherwise an error.
 5195 */
 5196int TLSX_SupportedCurve_CheckPriority(WOLFSSL* ssl)
 5197{
 5198    int ret;
 5199    TLSX* extension;
 5200    TLSX* priority = NULL;
 5201    TLSX* ext = NULL;
 5202    word16 name;
 5203    SupportedCurve* curve;
 5204
 5205    extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS);
 5206    /* May be doing PSK with no key exchange. */
 5207    if (extension == NULL)
 5208        return 0;
 5209
 5210    ret = TLSX_PopulateSupportedGroups(ssl, &priority);
 5211    if (ret != WOLFSSL_SUCCESS) {
 5212        TLSX_FreeAll(priority, ssl->heap);
 5213        return ret;
 5214    }
 5215
 5216    ext = TLSX_Find(priority, TLSX_SUPPORTED_GROUPS);
 5217    if (ext == NULL) {
 5218        WOLFSSL_MSG("Could not find supported groups extension");
 5219        TLSX_FreeAll(priority, ssl->heap);
 5220        return 0;
 5221    }
 5222
 5223    curve = (SupportedCurve*)ext->data;
 5224    name = curve->name;
 5225
 5226    curve = (SupportedCurve*)extension->data;
 5227    while (curve != NULL) {
 5228        if (curve->name == name)
 5229            break;
 5230        curve = curve->next;
 5231    }
 5232
 5233    if (curve == NULL) {
 5234        /* Couldn't find the preferred group in client list. */
 5235        extension->resp = 1;
 5236
 5237        /* Send server list back and free client list. */
 5238        curve = (SupportedCurve*)extension->data;
 5239        extension->data = ext->data;
 5240        ext->data = curve;
 5241    }
 5242
 5243    TLSX_FreeAll(priority, ssl->heap);
 5244
 5245    return 0;
 5246}
 5247
 5248#endif /* WOLFSSL_TLS13 && !WOLFSSL_NO_SERVER_GROUPS_EXT */
 5249
 5250#if defined(HAVE_FFDHE) && !defined(WOLFSSL_NO_TLS12)
 5251#ifdef HAVE_PUBLIC_FFDHE
 5252static int tlsx_ffdhe_find_group(WOLFSSL* ssl, SupportedCurve* clientGroup,
 5253    SupportedCurve* serverGroup)
 5254{
 5255    int ret = 0;
 5256    SupportedCurve* group;
 5257    const DhParams* params = NULL;
 5258
 5259    for (; serverGroup != NULL; serverGroup = serverGroup->next) {
 5260        if (!WOLFSSL_NAMED_GROUP_IS_FFDHE(serverGroup->name))
 5261            continue;
 5262
 5263        for (group = clientGroup; group != NULL; group = group->next) {
 5264            if (serverGroup->name != group->name)
 5265                continue;
 5266
 5267            switch (serverGroup->name) {
 5268            #ifdef HAVE_FFDHE_2048
 5269                case WOLFSSL_FFDHE_2048:
 5270                    params = wc_Dh_ffdhe2048_Get();
 5271                    break;
 5272            #endif
 5273            #ifdef HAVE_FFDHE_3072
 5274                case WOLFSSL_FFDHE_3072:
 5275                    params = wc_Dh_ffdhe3072_Get();
 5276                    break;
 5277            #endif
 5278            #ifdef HAVE_FFDHE_4096
 5279                case WOLFSSL_FFDHE_4096:
 5280                    params = wc_Dh_ffdhe4096_Get();
 5281                    break;
 5282            #endif
 5283            #ifdef HAVE_FFDHE_6144
 5284                case WOLFSSL_FFDHE_6144:
 5285                    params = wc_Dh_ffdhe6144_Get();
 5286                    break;
 5287            #endif
 5288            #ifdef HAVE_FFDHE_8192
 5289                case WOLFSSL_FFDHE_8192:
 5290                    params = wc_Dh_ffdhe8192_Get();
 5291                    break;
 5292            #endif
 5293                default:
 5294                    break;
 5295            }
 5296            if (params == NULL) {
 5297                ret = BAD_FUNC_ARG;
 5298                break;
 5299            }
 5300            if (params->p_len >= ssl->options.minDhKeySz &&
 5301                                     params->p_len <= ssl->options.maxDhKeySz) {
 5302                break;
 5303            }
 5304        }
 5305
 5306        if (ret != 0)
 5307            break;
 5308        if ((group != NULL) && (serverGroup->name == group->name))
 5309            break;
 5310    }
 5311
 5312    if ((ret == 0) && (serverGroup != NULL) && (params != NULL)) {
 5313        ssl->buffers.serverDH_P.buffer = (unsigned char *)params->p;
 5314        ssl->buffers.serverDH_P.length = params->p_len;
 5315        ssl->buffers.serverDH_G.buffer = (unsigned char *)params->g;
 5316        ssl->buffers.serverDH_G.length = params->g_len;
 5317
 5318        ssl->namedGroup = serverGroup->name;
 5319    #if !defined(WOLFSSL_OLD_PRIME_CHECK) && \
 5320        !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)
 5321        ssl->options.dhDoKeyTest = 0;
 5322    #endif
 5323        ssl->options.haveDH = 1;
 5324    }
 5325
 5326    return ret;
 5327}
 5328#else
 5329static int tlsx_ffdhe_find_group(WOLFSSL* ssl, SupportedCurve* clientGroup,
 5330    SupportedCurve* serverGroup)
 5331{
 5332    int ret = 0;
 5333    SupportedCurve* group;
 5334    word32 p_len;
 5335
 5336    for (; serverGroup != NULL; serverGroup = serverGroup->next) {
 5337        if (!WOLFSSL_NAMED_GROUP_IS_FFDHE(serverGroup->name))
 5338            continue;
 5339
 5340        for (group = clientGroup; group != NULL; group = group->next) {
 5341            if (serverGroup->name != group->name)
 5342                continue;
 5343
 5344            ret = wc_DhGetNamedKeyParamSize(serverGroup->name, &p_len, NULL, NULL);
 5345            if (ret == 0) {
 5346                if (p_len == 0) {
 5347                    ret = BAD_FUNC_ARG;
 5348                    break;
 5349                }
 5350                if (p_len >= ssl->options.minDhKeySz &&
 5351                                                p_len <= ssl->options.maxDhKeySz) {
 5352                    break;
 5353                }
 5354            }
 5355        }
 5356
 5357        if (ret != 0)
 5358            break;
 5359        if ((group != NULL) && (serverGroup->name == group->name))
 5360            break;
 5361    }
 5362
 5363    if ((ret == 0) && (serverGroup != NULL)) {
 5364        word32 pSz, gSz;
 5365
 5366        ssl->buffers.serverDH_P.buffer = NULL;
 5367        ssl->buffers.serverDH_G.buffer = NULL;
 5368        ret = wc_DhGetNamedKeyParamSize(serverGroup->name, &pSz, &gSz, NULL);
 5369        if (ret == 0) {
 5370            ssl->buffers.serverDH_P.buffer =
 5371                (byte*)XMALLOC(pSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
 5372            if (ssl->buffers.serverDH_P.buffer == NULL)
 5373                ret = MEMORY_E;
 5374            else
 5375                ssl->buffers.serverDH_P.length = pSz;
 5376        }
 5377        if (ret == 0) {
 5378            ssl->buffers.serverDH_G.buffer =
 5379                (byte*)XMALLOC(gSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
 5380            if (ssl->buffers.serverDH_G.buffer == NULL) {
 5381                ret = MEMORY_E;
 5382            } else
 5383                ssl->buffers.serverDH_G.length = gSz;
 5384        }
 5385        if (ret == 0) {
 5386            ret = wc_DhCopyNamedKey(serverGroup->name,
 5387                              ssl->buffers.serverDH_P.buffer, &pSz,
 5388                              ssl->buffers.serverDH_G.buffer, &gSz,
 5389                              NULL, NULL);
 5390        }
 5391        if (ret == 0) {
 5392            ssl->buffers.weOwnDH = 1;
 5393
 5394            ssl->namedGroup = serverGroup->name;
 5395        #if !defined(WOLFSSL_OLD_PRIME_CHECK) && \
 5396            !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)
 5397            ssl->options.dhDoKeyTest = 0;
 5398        #endif
 5399            ssl->options.haveDH = 1;
 5400        }
 5401        else {
 5402            if (ssl->buffers.serverDH_P.buffer != NULL) {
 5403                XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap,
 5404                    DYNAMIC_TYPE_PUBLIC_KEY);
 5405                ssl->buffers.serverDH_P.length = 0;
 5406                ssl->buffers.serverDH_P.buffer = NULL;
 5407            }
 5408            if (ssl->buffers.serverDH_G.buffer != NULL) {
 5409                XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap,
 5410                    DYNAMIC_TYPE_PUBLIC_KEY);
 5411                ssl->buffers.serverDH_G.length = 0;
 5412                ssl->buffers.serverDH_G.buffer = NULL;
 5413            }
 5414        }
 5415    }
 5416
 5417    return ret;
 5418}
 5419#endif
 5420
 5421/* Set the highest priority common FFDHE group on the server as compared to
 5422 * client extensions.
 5423 *
 5424 * ssl    SSL/TLS object.
 5425 * returns 0 on success, otherwise an error.
 5426 */
 5427int TLSX_SupportedFFDHE_Set(WOLFSSL* ssl)
 5428{
 5429    int ret;
 5430    TLSX* priority = NULL;
 5431    TLSX* ext = NULL;
 5432    TLSX* extension;
 5433    SupportedCurve* clientGroup;
 5434    SupportedCurve* group;
 5435    int found = 0;
 5436
 5437    extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS);
 5438    /* May be doing PSK with no key exchange. */
 5439    if (extension == NULL)
 5440        return 0;
 5441    clientGroup = (SupportedCurve*)extension->data;
 5442    for (group = clientGroup; group != NULL; group = group->next) {
 5443        if (WOLFSSL_NAMED_GROUP_IS_FFDHE(group->name)) {
 5444            found = 1;
 5445            break;
 5446        }
 5447    }
 5448    if (!found)
 5449        return 0;
 5450
 5451    if (ssl->buffers.serverDH_P.buffer && ssl->buffers.weOwnDH) {
 5452        XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap,
 5453                                                       DYNAMIC_TYPE_PUBLIC_KEY);
 5454    }
 5455    if (ssl->buffers.serverDH_G.buffer && ssl->buffers.weOwnDH) {
 5456        XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap,
 5457                                                       DYNAMIC_TYPE_PUBLIC_KEY);
 5458    }
 5459    ssl->buffers.serverDH_P.buffer = NULL;
 5460    ssl->buffers.serverDH_G.buffer = NULL;
 5461    ssl->buffers.weOwnDH = 0;
 5462    ssl->options.haveDH = 0;
 5463
 5464    ret = TLSX_PopulateSupportedGroups(ssl, &priority);
 5465    if (ret == WOLFSSL_SUCCESS) {
 5466        SupportedCurve* serverGroup;
 5467
 5468        ext = TLSX_Find(priority, TLSX_SUPPORTED_GROUPS);
 5469        if (ext == NULL) {
 5470            WOLFSSL_MSG("Could not find supported groups extension");
 5471            ret = 0;
 5472        }
 5473        else {
 5474            serverGroup = (SupportedCurve*)ext->data;
 5475            ret = tlsx_ffdhe_find_group(ssl, clientGroup, serverGroup);
 5476        }
 5477    }
 5478
 5479    TLSX_FreeAll(priority, ssl->heap);
 5480
 5481    return ret;
 5482}
 5483#endif /* HAVE_FFDHE && !WOLFSSL_NO_TLS12 */
 5484#endif /* !NO_WOLFSSL_SERVER */
 5485
 5486/* Check if the given curve is present in the supported groups extension.
 5487 *
 5488 * ssl             SSL/TLS object.
 5489 * name            The curve name to check.
 5490 * returns 1 if present, 0 otherwise.
 5491 */
 5492int TLSX_SupportedCurve_IsSupported(WOLFSSL* ssl, word16 name)
 5493{
 5494    TLSX* extension;
 5495    SupportedCurve* curve;
 5496
 5497    extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS);
 5498    if (extension == NULL)
 5499        return 0;
 5500
 5501    curve = (SupportedCurve*)extension->data;
 5502    while (curve != NULL) {
 5503        if (curve->name == name)
 5504            return 1;
 5505        curve = curve->next;
 5506    }
 5507
 5508    return 0;
 5509}
 5510
 5511#if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_NO_SERVER_GROUPS_EXT)
 5512/* Return the preferred group.
 5513 *
 5514 * ssl             SSL/TLS object.
 5515 * checkSupported  Whether to check for the first supported group.
 5516 * returns BAD_FUNC_ARG if no group found, otherwise the group.
 5517 */
 5518int TLSX_SupportedCurve_Preferred(WOLFSSL* ssl, int checkSupported)
 5519{
 5520    TLSX* extension;
 5521    SupportedCurve* curve;
 5522
 5523    extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS);
 5524    if (extension == NULL)
 5525        return BAD_FUNC_ARG;
 5526
 5527    curve = (SupportedCurve*)extension->data;
 5528    while (curve != NULL) {
 5529        if (!checkSupported || TLSX_IsGroupSupported(curve->name))
 5530            return curve->name;
 5531        curve = curve->next;
 5532    }
 5533
 5534    return BAD_FUNC_ARG;
 5535}
 5536
 5537#endif /* HAVE_SUPPORTED_CURVES */
 5538
 5539#ifndef NO_WOLFSSL_SERVER
 5540
 5541static int TLSX_PointFormat_Parse(WOLFSSL* ssl, const byte* input,
 5542                                  word16 length, byte isRequest)
 5543{
 5544    int ret;
 5545
 5546    /* validating formats list length */
 5547    if (ENUM_LEN > length || length != (word16)ENUM_LEN + input[0])
 5548        return BUFFER_ERROR;
 5549
 5550    if (isRequest) {
 5551        /* adding uncompressed point format to response */
 5552        ret = TLSX_UsePointFormat(&ssl->extensions, WOLFSSL_EC_PF_UNCOMPRESSED,
 5553                                                                     ssl->heap);
 5554        if (ret != WOLFSSL_SUCCESS)
 5555            return ret; /* throw error */
 5556
 5557        TLSX_SetResponse(ssl, TLSX_EC_POINT_FORMATS);
 5558    }
 5559
 5560    return 0;
 5561}
 5562
 5563#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
 5564int TLSX_ValidateSupportedCurves(const WOLFSSL* ssl, byte first, byte second,
 5565                                 word32* ecdhCurveOID) {
 5566    TLSX*           extension = NULL;
 5567    SupportedCurve* curve     = NULL;
 5568    word32          oid       = 0;
 5569    word32          defOid    = 0;
 5570    word32          defSz     = 80; /* Maximum known curve size is 66. */
 5571    word32          nextOid   = 0;
 5572    word32          nextSz    = 80; /* Maximum known curve size is 66. */
 5573    word32          currOid   = ssl->ecdhCurveOID;
 5574    int             ephmSuite = 0;
 5575    word16          octets    = 0; /* according to 'ecc_set_type ecc_sets[];' */
 5576    int             key       = 0; /* validate key       */
 5577    int             foundCurve = 0; /* Found at least one supported curve */
 5578
 5579    (void)oid;
 5580
 5581    if (first == CHACHA_BYTE) {
 5582        switch (second) {
 5583            case TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
 5584            case TLS_PSK_WITH_CHACHA20_POLY1305_SHA256:
 5585            case TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256:
 5586            case TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256:
 5587                return 1; /* no suite restriction */
 5588            case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
 5589            case TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256:
 5590            case TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256:
 5591                break;
 5592        }
 5593    }
 5594    if (first == ECC_BYTE || first == ECDHE_PSK_BYTE || first == CHACHA_BYTE)
 5595        extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS);
 5596    if (!extension)
 5597        return 1; /* no suite restriction */
 5598
 5599    for (curve = (SupportedCurve*)extension->data;
 5600         curve && !key;
 5601         curve = curve->next) {
 5602
 5603    #ifdef OPENSSL_EXTRA
 5604        /* skip if name is not in supported ECC range
 5605         * or disabled by user */
 5606        if (wolfSSL_curve_is_disabled(ssl, curve->name))
 5607            continue;
 5608    #endif
 5609
 5610        /* find supported curve */
 5611        switch (curve->name) {
 5612#ifdef HAVE_ECC
 5613    #if (defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 160
 5614        #ifndef NO_ECC_SECP
 5615            case WOLFSSL_ECC_SECP160R1:
 5616                oid = ECC_SECP160R1_OID;
 5617                octets = 20;
 5618                break;
 5619        #endif /* !NO_ECC_SECP */
 5620        #ifdef HAVE_ECC_SECPR2
 5621            case WOLFSSL_ECC_SECP160R2:
 5622                oid = ECC_SECP160R2_OID;
 5623                octets = 20;
 5624                break;
 5625        #endif /* HAVE_ECC_SECPR2 */
 5626        #ifdef HAVE_ECC_KOBLITZ
 5627            case WOLFSSL_ECC_SECP160K1:
 5628                oid = ECC_SECP160K1_OID;
 5629                octets = 20;
 5630                break;
 5631        #endif /* HAVE_ECC_KOBLITZ */
 5632        #endif
 5633    #if (defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 192
 5634        #ifndef NO_ECC_SECP
 5635            case WOLFSSL_ECC_SECP192R1:
 5636                oid = ECC_SECP192R1_OID;
 5637                octets = 24;
 5638                break;
 5639        #endif /* !NO_ECC_SECP */
 5640        #ifdef HAVE_ECC_KOBLITZ
 5641            case WOLFSSL_ECC_SECP192K1:
 5642                oid = ECC_SECP192K1_OID;
 5643                octets = 24;
 5644                break;
 5645        #endif /* HAVE_ECC_KOBLITZ */
 5646    #endif
 5647    #if (defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 224
 5648        #ifndef NO_ECC_SECP
 5649            case WOLFSSL_ECC_SECP224R1:
 5650                oid = ECC_SECP224R1_OID;
 5651                octets = 28;
 5652                break;
 5653        #endif /* !NO_ECC_SECP */
 5654        #ifdef HAVE_ECC_KOBLITZ
 5655            case WOLFSSL_ECC_SECP224K1:
 5656                oid = ECC_SECP224K1_OID;
 5657                octets = 28;
 5658                break;
 5659        #endif /* HAVE_ECC_KOBLITZ */
 5660    #endif
 5661    #if (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 256
 5662        #ifndef NO_ECC_SECP
 5663            case WOLFSSL_ECC_SECP256R1:
 5664                oid = ECC_SECP256R1_OID;
 5665                octets = 32;
 5666                break;
 5667        #endif /* !NO_ECC_SECP */
 5668    #endif /* !NO_ECC256 || HAVE_ALL_CURVES */
 5669#endif
 5670        #if (defined(HAVE_CURVE25519) || defined(HAVE_ED25519)) && ECC_MIN_KEY_SZ <= 256
 5671            case WOLFSSL_ECC_X25519:
 5672                oid = ECC_X25519_OID;
 5673                octets = 32;
 5674                break;
 5675        #endif /* HAVE_CURVE25519 */
 5676#ifdef HAVE_ECC
 5677    #if (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 256
 5678        #ifdef HAVE_ECC_KOBLITZ
 5679            case WOLFSSL_ECC_SECP256K1:
 5680                oid = ECC_SECP256K1_OID;
 5681                octets = 32;
 5682                break;
 5683        #endif /* HAVE_ECC_KOBLITZ */
 5684        #ifdef HAVE_ECC_BRAINPOOL
 5685            case WOLFSSL_ECC_BRAINPOOLP256R1:
 5686                oid = ECC_BRAINPOOLP256R1_OID;
 5687                octets = 32;
 5688                break;
 5689        #endif /* HAVE_ECC_BRAINPOOL */
 5690        #ifdef WOLFSSL_SM2
 5691            case WOLFSSL_ECC_SM2P256V1:
 5692                oid = ECC_SM2P256V1_OID;
 5693                octets = 32;
 5694                break;
 5695        #endif /* WOLFSSL_SM2 */
 5696    #endif
 5697    #if (defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 384
 5698        #ifndef NO_ECC_SECP
 5699            case WOLFSSL_ECC_SECP384R1:
 5700                oid = ECC_SECP384R1_OID;
 5701                octets = 48;
 5702                break;
 5703        #endif /* !NO_ECC_SECP */
 5704        #ifdef HAVE_ECC_BRAINPOOL
 5705            case WOLFSSL_ECC_BRAINPOOLP384R1:
 5706                oid = ECC_BRAINPOOLP384R1_OID;
 5707                octets = 48;
 5708                break;
 5709        #endif /* HAVE_ECC_BRAINPOOL */
 5710    #endif
 5711#endif
 5712        #if (defined(HAVE_CURVE448) || defined(HAVE_ED448)) && ECC_MIN_KEY_SZ <= 448
 5713            case WOLFSSL_ECC_X448:
 5714                oid = ECC_X448_OID;
 5715                octets = 57;
 5716                break;
 5717        #endif /* HAVE_CURVE448 */
 5718#ifdef HAVE_ECC
 5719    #if (defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 512
 5720        #ifdef HAVE_ECC_BRAINPOOL
 5721            case WOLFSSL_ECC_BRAINPOOLP512R1:
 5722                oid = ECC_BRAINPOOLP512R1_OID;
 5723                octets = 64;
 5724                break;
 5725        #endif /* HAVE_ECC_BRAINPOOL */
 5726    #endif
 5727    #if (defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 521
 5728        #ifndef NO_ECC_SECP
 5729            case WOLFSSL_ECC_SECP521R1:
 5730                oid = ECC_SECP521R1_OID;
 5731                octets = 66;
 5732                break;
 5733        #endif /* !NO_ECC_SECP */
 5734    #endif
 5735#endif
 5736            default: continue; /* unsupported curve */
 5737        }
 5738
 5739        foundCurve = 1;
 5740
 5741    #ifdef HAVE_ECC
 5742        /* Set default Oid */
 5743        if (defOid == 0 && ssl->eccTempKeySz <= octets && defSz > octets) {
 5744            defOid = oid;
 5745            defSz = octets;
 5746        }
 5747
 5748        /* The eccTempKeySz is the preferred ephemeral key size */
 5749        if (currOid == 0 && ssl->eccTempKeySz == octets)
 5750            currOid = oid;
 5751        if ((nextOid == 0 || nextSz > octets) && ssl->eccTempKeySz <= octets) {
 5752            nextOid = oid;
 5753            nextSz  = octets;
 5754        }
 5755    #else
 5756        if (defOid == 0 && defSz > octets) {
 5757            defOid = oid;
 5758            defSz = octets;
 5759        }
 5760
 5761        if (currOid == 0)
 5762            currOid = oid;
 5763        if (nextOid == 0 || nextSz > octets) {
 5764            nextOid = oid;
 5765            nextSz  = octets;
 5766        }
 5767    #endif
 5768
 5769        if (first == ECC_BYTE) {
 5770            switch (second) {
 5771#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448)
 5772                /* ECDHE_ECDSA */
 5773                case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
 5774                case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
 5775                case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
 5776                case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
 5777                case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
 5778                case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
 5779                case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
 5780                case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
 5781                case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
 5782                case TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8:
 5783                    key |= ssl->ecdhCurveOID == oid;
 5784                    ephmSuite = 1;
 5785                break;
 5786
 5787    #ifdef WOLFSSL_STATIC_DH
 5788                /* ECDH_ECDSA */
 5789                case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
 5790                case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
 5791                case TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
 5792                case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
 5793                case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
 5794                case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
 5795                case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
 5796                case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
 5797                    if (oid == ECC_X25519_OID && defOid == oid) {
 5798                        defOid = 0;
 5799                        defSz = 80;
 5800                    }
 5801                    if (oid == ECC_X448_OID && defOid == oid) {
 5802                        defOid = 0;
 5803                        defSz = 80;
 5804                    }
 5805                    key |= ssl->pkCurveOID == oid;
 5806                break;
 5807    #endif /* WOLFSSL_STATIC_DH */
 5808#endif /* HAVE_ECC || HAVE_ED25519 || HAVE_ED448 */
 5809#ifndef NO_RSA
 5810                /* ECDHE_RSA */
 5811                case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
 5812                case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
 5813                case TLS_ECDHE_RSA_WITH_RC4_128_SHA:
 5814                case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
 5815                case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
 5816                case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
 5817                case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
 5818                case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
 5819                    key |= ssl->ecdhCurveOID == oid;
 5820                    ephmSuite = 1;
 5821                break;
 5822
 5823    #if defined(HAVE_ECC) && defined(WOLFSSL_STATIC_DH)
 5824                /* ECDH_RSA */
 5825                case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
 5826                case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
 5827                case TLS_ECDH_RSA_WITH_RC4_128_SHA:
 5828                case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
 5829                case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
 5830                case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
 5831                case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
 5832                case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
 5833                    if (oid == ECC_X25519_OID && defOid == oid) {
 5834                        defOid = 0;
 5835                        defSz = 80;
 5836                    }
 5837                    if (oid == ECC_X448_OID && defOid == oid) {
 5838                        defOid = 0;
 5839                        defSz = 80;
 5840                    }
 5841                    key |= ssl->pkCurveOID == oid;
 5842                break;
 5843    #endif /* HAVE_ECC && WOLFSSL_STATIC_DH */
 5844#endif
 5845                default:
 5846                    if (oid == ECC_X25519_OID && defOid == oid) {
 5847                        defOid = 0;
 5848                        defSz = 80;
 5849                    }
 5850                    if (oid == ECC_X448_OID && defOid == oid) {
 5851                        defOid = 0;
 5852                        defSz = 80;
 5853                    }
 5854                    key = 1;
 5855                break;
 5856            }
 5857        }
 5858
 5859        /* ChaCha20-Poly1305 ECC cipher suites */
 5860        if (first == CHACHA_BYTE) {
 5861            switch (second) {
 5862#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448)
 5863                /* ECDHE_ECDSA */
 5864                case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 :
 5865                case TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 :
 5866                    key |= ssl->ecdhCurveOID == oid;
 5867                    ephmSuite = 1;
 5868                break;
 5869#endif /* HAVE_ECC || HAVE_ED25519 || HAVE_ED448 */
 5870#ifndef NO_RSA
 5871                /* ECDHE_RSA */
 5872                case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 :
 5873                case TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 :
 5874                    key |= ssl->ecdhCurveOID == oid;
 5875                    ephmSuite = 1;
 5876                break;
 5877#endif
 5878                default:
 5879                    key = 1;
 5880                break;
 5881            }
 5882        }
 5883    }
 5884
 5885    /* Check we found at least one supported curve */
 5886    if (!foundCurve)
 5887        return 0;
 5888
 5889    *ecdhCurveOID = ssl->ecdhCurveOID;
 5890    /* Choose the default if it is at the required strength. */
 5891#ifdef HAVE_ECC
 5892    if (*ecdhCurveOID == 0 && defSz == ssl->eccTempKeySz)
 5893#else
 5894    if (*ecdhCurveOID == 0)
 5895#endif
 5896    {
 5897        key = 1;
 5898        *ecdhCurveOID = defOid;
 5899    }
 5900    /* Choose any curve at the required strength. */
 5901    if (*ecdhCurveOID == 0) {
 5902        key = 1;
 5903        *ecdhCurveOID = currOid;
 5904    }
 5905    /* Choose the default if it is at the next highest strength. */
 5906    if (*ecdhCurveOID == 0 && defSz == nextSz)
 5907        *ecdhCurveOID = defOid;
 5908    /* Choose any curve at the next highest strength. */
 5909    if (*ecdhCurveOID == 0)
 5910        *ecdhCurveOID = nextOid;
 5911    /* No curve and ephemeral ECC suite requires a matching curve. */
 5912    if (*ecdhCurveOID == 0 && ephmSuite)
 5913        key = 0;
 5914
 5915    return key;
 5916}
 5917#endif
 5918
 5919#endif /* NO_WOLFSSL_SERVER */
 5920
 5921
 5922int TLSX_SupportedCurve_Copy(TLSX* src, TLSX** dst, void* heap)
 5923{
 5924    TLSX* extension;
 5925    int ret;
 5926
 5927    extension = TLSX_Find(src, TLSX_SUPPORTED_GROUPS);
 5928    if (extension != NULL) {
 5929        SupportedCurve* curve;
 5930        for (curve = (SupportedCurve*)extension->data; curve != NULL;
 5931                curve = curve->next) {
 5932            ret = TLSX_UseSupportedCurve(dst, curve->name, heap);
 5933            if (ret != WOLFSSL_SUCCESS)
 5934                return MEMORY_E;
 5935        }
 5936    }
 5937
 5938    return 0;
 5939}
 5940
 5941int TLSX_UseSupportedCurve(TLSX** extensions, word16 name, void* heap)
 5942{
 5943    TLSX* extension = NULL;
 5944    SupportedCurve* curve = NULL;
 5945    int ret;
 5946
 5947    if (extensions == NULL) {
 5948        return BAD_FUNC_ARG;
 5949    }
 5950
 5951    if (! TLSX_IsGroupSupported(name)) {
 5952        return BAD_FUNC_ARG;
 5953    }
 5954
 5955    extension = TLSX_Find(*extensions, TLSX_SUPPORTED_GROUPS);
 5956
 5957    if (!extension) {
 5958        ret = TLSX_SupportedCurve_New(&curve, name, heap);
 5959        if (ret != 0)
 5960            return ret;
 5961
 5962        ret = TLSX_Push(extensions, TLSX_SUPPORTED_GROUPS, curve, heap);
 5963        if (ret != 0) {
 5964            XFREE(curve, heap, DYNAMIC_TYPE_TLSX);
 5965            return ret;
 5966        }
 5967    }
 5968    else {
 5969        ret = TLSX_SupportedCurve_Append((SupportedCurve*)extension->data, name,
 5970                                                                          heap);
 5971        if (ret != 0)
 5972            return ret;
 5973    #if defined(WOLFSSL_ML_KEM_USE_OLD_IDS) && \
 5974                                             defined (WOLFSSL_EXTRA_PQC_HYBRIDS)
 5975        if (name == WOLFSSL_SECP256R1MLKEM512) {
 5976            ret = TLSX_SupportedCurve_Append((SupportedCurve*)extension->data,
 5977                WOLFSSL_P256_ML_KEM_512_OLD, heap);
 5978        }
 5979        else if (name == WOLFSSL_SECP384R1MLKEM768) {
 5980            ret = TLSX_SupportedCurve_Append((SupportedCurve*)extension->data,
 5981                WOLFSSL_P384_ML_KEM_768_OLD, heap);
 5982        }
 5983        else if (name == WOLFSSL_SECP521R1MLKEM1024) {
 5984            ret = TLSX_SupportedCurve_Append((SupportedCurve*)extension->data,
 5985                WOLFSSL_P521_ML_KEM_1024_OLD, heap);
 5986        }
 5987        if (ret != 0) {
 5988            return ret;
 5989        }
 5990    #endif /* WOLFSSL_ML_KEM_USE_OLD_IDS && WOLFSSL_EXTRA_PQC_HYBRIDS */
 5991    }
 5992
 5993    return WOLFSSL_SUCCESS;
 5994}
 5995
 5996int TLSX_UsePointFormat(TLSX** extensions, byte format, void* heap)
 5997{
 5998    TLSX* extension = NULL;
 5999    PointFormat* point = NULL;
 6000    int ret = 0;
 6001
 6002    if (extensions == NULL)
 6003        return BAD_FUNC_ARG;
 6004
 6005    extension = TLSX_Find(*extensions, TLSX_EC_POINT_FORMATS);
 6006
 6007    if (!extension) {
 6008        ret = TLSX_PointFormat_New(&point, format, heap);
 6009        if (ret != 0)
 6010            return ret;
 6011
 6012        ret = TLSX_Push(extensions, TLSX_EC_POINT_FORMATS, point, heap);
 6013        if (ret != 0) {
 6014            XFREE(point, heap, DYNAMIC_TYPE_TLSX);
 6015            return ret;
 6016        }
 6017    }
 6018    else {
 6019        ret = TLSX_PointFormat_Append((PointFormat*)extension->data, format,
 6020                                                                          heap);
 6021        if (ret != 0)
 6022            return ret;
 6023    }
 6024
 6025    return WOLFSSL_SUCCESS;
 6026}
 6027
 6028#define EC_FREE_ALL         TLSX_SupportedCurve_FreeAll
 6029#define EC_VALIDATE_REQUEST TLSX_SupportedCurve_ValidateRequest
 6030
 6031/* In TLS 1.2 the server never sends supported curve extension, but in TLS 1.3
 6032 * the server can send supported groups extension to indicate what it will
 6033 * support for later connections. */
 6034#if !defined(NO_WOLFSSL_CLIENT) || defined(WOLFSSL_TLS13)
 6035#define EC_GET_SIZE TLSX_SupportedCurve_GetSize
 6036#define EC_WRITE    TLSX_SupportedCurve_Write
 6037#else
 6038#define EC_GET_SIZE(list)         0
 6039#define EC_WRITE(a, b)            0
 6040#endif
 6041
 6042#if !defined(NO_WOLFSSL_SERVER) || (defined(WOLFSSL_TLS13) && \
 6043                                         !defined(WOLFSSL_NO_SERVER_GROUPS_EXT))
 6044#define EC_PARSE TLSX_SupportedCurve_Parse
 6045#else
 6046#define EC_PARSE(a, b, c, d, e)   0
 6047#endif
 6048
 6049#define PF_FREE_ALL          TLSX_PointFormat_FreeAll
 6050#define PF_VALIDATE_REQUEST  TLSX_PointFormat_ValidateRequest
 6051#define PF_VALIDATE_RESPONSE TLSX_PointFormat_ValidateResponse
 6052
 6053#define PF_GET_SIZE TLSX_PointFormat_GetSize
 6054#define PF_WRITE    TLSX_PointFormat_Write
 6055
 6056#ifndef NO_WOLFSSL_SERVER
 6057#define PF_PARSE TLSX_PointFormat_Parse
 6058#else
 6059#define PF_PARSE(a, b, c, d)      0
 6060#endif
 6061
 6062#else
 6063
 6064#define EC_FREE_ALL(list, heap) WC_DO_NOTHING
 6065#define EC_GET_SIZE(list)         0
 6066#define EC_WRITE(a, b)            0
 6067#define EC_PARSE(a, b, c, d, e)   0
 6068#define EC_VALIDATE_REQUEST(a, b) WC_DO_NOTHING
 6069
 6070#define PF_FREE_ALL(list, heap)   WC_DO_NOTHING
 6071#define PF_GET_SIZE(list)         0
 6072#define PF_WRITE(a, b)            0
 6073#define PF_PARSE(a, b, c, d)      0
 6074#define PF_VALIDATE_REQUEST(a, b) WC_DO_NOTHING
 6075#define PF_VALIDATE_RESPONSE(a, b) WC_DO_NOTHING
 6076
 6077#endif /* HAVE_SUPPORTED_CURVES */
 6078
 6079/******************************************************************************/
 6080/* Renegotiation Indication                                                   */
 6081/******************************************************************************/
 6082
 6083#if defined(HAVE_SECURE_RENEGOTIATION) \
 6084 || defined(HAVE_SERVER_RENEGOTIATION_INFO)
 6085
 6086static byte TLSX_SecureRenegotiation_GetSize(SecureRenegotiation* data,
 6087                                                                  int isRequest)
 6088{
 6089    byte length = OPAQUE8_LEN; /* empty info length */
 6090
 6091    /* data will be NULL for HAVE_SERVER_RENEGOTIATION_INFO only */
 6092    if (data && data->enabled && data->verifySet) {
 6093        /* client sends client_verify_data only */
 6094        length += TLS_FINISHED_SZ;
 6095
 6096        /* server also sends server_verify_data */
 6097        if (!isRequest)
 6098            length += TLS_FINISHED_SZ;
 6099    }
 6100
 6101    return length;
 6102}
 6103
 6104static word16 TLSX_SecureRenegotiation_Write(SecureRenegotiation* data,
 6105                                                    byte* output, int isRequest)
 6106{
 6107    word16 offset = OPAQUE8_LEN; /* RenegotiationInfo length */
 6108    if (data && data->enabled && data->verifySet) {
 6109        /* client sends client_verify_data only */
 6110        XMEMCPY(output + offset, data->client_verify_data, TLS_FINISHED_SZ);
 6111        offset += TLS_FINISHED_SZ;
 6112
 6113        /* server also sends server_verify_data */
 6114        if (!isRequest) {
 6115            XMEMCPY(output + offset, data->server_verify_data, TLS_FINISHED_SZ);
 6116            offset += TLS_FINISHED_SZ;
 6117        }
 6118    }
 6119
 6120    output[0] = (byte)(offset - 1);  /* info length - self */
 6121
 6122    return offset;
 6123}
 6124
 6125static int TLSX_SecureRenegotiation_Parse(WOLFSSL* ssl, const byte* input,
 6126                                          word16 length, byte isRequest)
 6127{
 6128    int ret = WC_NO_ERR_TRACE(SECURE_RENEGOTIATION_E);
 6129
 6130    if (length >= OPAQUE8_LEN) {
 6131        if (isRequest) {
 6132        #ifndef NO_WOLFSSL_SERVER
 6133            if (ssl->secure_renegotiation == NULL) {
 6134                ret = wolfSSL_UseSecureRenegotiation(ssl);
 6135                if (ret == WOLFSSL_SUCCESS)
 6136                    ret = 0;
 6137            }
 6138            if (ret != 0 && ret != WC_NO_ERR_TRACE(SECURE_RENEGOTIATION_E)) {
 6139            }
 6140            else if (ssl->secure_renegotiation == NULL) {
 6141            }
 6142            else if (!ssl->secure_renegotiation->enabled) {
 6143                if (*input == 0) {
 6144                    input++; /* get past size */
 6145
 6146                    ssl->secure_renegotiation->enabled = 1;
 6147                    TLSX_SetResponse(ssl, TLSX_RENEGOTIATION_INFO);
 6148                    ret = 0;
 6149                }
 6150                else {
 6151                    /* already in error state */
 6152                    WOLFSSL_MSG("SCR client verify data present");
 6153                }
 6154            }
 6155            else if (*input == TLS_FINISHED_SZ) {
 6156                if (length < TLS_FINISHED_SZ + 1) {
 6157                    WOLFSSL_MSG("SCR malformed buffer");
 6158                    ret = BUFFER_E;
 6159                }
 6160                else {
 6161                    input++; /* get past size */
 6162
 6163                    /* validate client verify data */
 6164                    if (ConstantCompare(input,
 6165                            ssl->secure_renegotiation->client_verify_data,
 6166                            TLS_FINISHED_SZ) == 0) {
 6167                        WOLFSSL_MSG("SCR client verify data match");
 6168                        TLSX_SetResponse(ssl, TLSX_RENEGOTIATION_INFO);
 6169                        ret = 0;  /* verified */
 6170                    }
 6171                    else {
 6172                        /* already in error state */
 6173                        WOLFSSL_MSG("SCR client verify data Failure");
 6174                    }
 6175                }
 6176            }
 6177        #endif
 6178        }
 6179        else if (ssl->secure_renegotiation != NULL) {
 6180        #ifndef NO_WOLFSSL_CLIENT
 6181            if (!ssl->secure_renegotiation->enabled) {
 6182                if (*input == 0) {
 6183                    ssl->secure_renegotiation->enabled = 1;
 6184                    ret = 0;
 6185                }
 6186            }
 6187            else if (*input == 2 * TLS_FINISHED_SZ &&
 6188                     length == 2 * TLS_FINISHED_SZ + OPAQUE8_LEN) {
 6189                int cmpRes = 0;
 6190                input++;  /* get past size */
 6191                cmpRes |= ConstantCompare(input,
 6192                        ssl->secure_renegotiation->client_verify_data,
 6193                        TLS_FINISHED_SZ);
 6194                cmpRes |= ConstantCompare(input + TLS_FINISHED_SZ,
 6195                        ssl->secure_renegotiation->server_verify_data,
 6196                        TLS_FINISHED_SZ);
 6197                /* validate client and server verify data */
 6198                if (cmpRes == 0) {
 6199                    WOLFSSL_MSG("SCR client and server verify data match");
 6200                    ret = 0;  /* verified */
 6201                }
 6202                else {
 6203                    /* already in error state */
 6204                    WOLFSSL_MSG("SCR client and server verify data Failure");
 6205                }
 6206            }
 6207        #endif
 6208        }
 6209        else {
 6210            ret = SECURE_RENEGOTIATION_E;
 6211        }
 6212    }
 6213    else {
 6214        ret = SECURE_RENEGOTIATION_E;
 6215    }
 6216
 6217    if (ret != 0) {
 6218        WOLFSSL_ERROR_VERBOSE(ret);
 6219        SendAlert(ssl, alert_fatal, handshake_failure);
 6220    }
 6221
 6222    return ret;
 6223}
 6224
 6225int TLSX_UseSecureRenegotiation(TLSX** extensions, void* heap)
 6226{
 6227    int ret = 0;
 6228    SecureRenegotiation* data;
 6229
 6230    data = (SecureRenegotiation*)XMALLOC(sizeof(SecureRenegotiation), heap,
 6231                                                             DYNAMIC_TYPE_TLSX);
 6232    if (data == NULL)
 6233        return MEMORY_E;
 6234
 6235    XMEMSET(data, 0, sizeof(SecureRenegotiation));
 6236
 6237    ret = TLSX_Push(extensions, TLSX_RENEGOTIATION_INFO, data, heap);
 6238    if (ret != 0) {
 6239        XFREE(data, heap, DYNAMIC_TYPE_TLSX);
 6240        return ret;
 6241    }
 6242
 6243    return WOLFSSL_SUCCESS;
 6244}
 6245
 6246#ifdef HAVE_SERVER_RENEGOTIATION_INFO
 6247
 6248int TLSX_AddEmptyRenegotiationInfo(TLSX** extensions, void* heap)
 6249{
 6250    int ret;
 6251
 6252    /* send empty renegotiation_info extension */
 6253    TLSX* ext = TLSX_Find(*extensions, TLSX_RENEGOTIATION_INFO);
 6254    if (ext == NULL) {
 6255        ret = TLSX_UseSecureRenegotiation(extensions, heap);
 6256        if (ret != WOLFSSL_SUCCESS)
 6257            return ret;
 6258
 6259        ext = TLSX_Find(*extensions, TLSX_RENEGOTIATION_INFO);
 6260    }
 6261    if (ext)
 6262        ext->resp = 1;
 6263
 6264    return WOLFSSL_SUCCESS;
 6265}
 6266
 6267#endif /* HAVE_SERVER_RENEGOTIATION_INFO */
 6268
 6269
 6270#define SCR_FREE_ALL(data, heap) XFREE(data, (heap), DYNAMIC_TYPE_TLSX)
 6271#define SCR_GET_SIZE       TLSX_SecureRenegotiation_GetSize
 6272#define SCR_WRITE          TLSX_SecureRenegotiation_Write
 6273#define SCR_PARSE          TLSX_SecureRenegotiation_Parse
 6274
 6275#else
 6276
 6277#define SCR_FREE_ALL(a, heap) WC_DO_NOTHING
 6278#define SCR_GET_SIZE(a, b)    0
 6279#define SCR_WRITE(a, b, c)    0
 6280#define SCR_PARSE(a, b, c, d) 0
 6281
 6282#endif /* HAVE_SECURE_RENEGOTIATION || HAVE_SERVER_RENEGOTIATION_INFO */
 6283
 6284/******************************************************************************/
 6285/* Session Tickets                                                            */
 6286/******************************************************************************/
 6287
 6288#ifdef HAVE_SESSION_TICKET
 6289
 6290static word16 TLSX_SessionTicket_GetSize(SessionTicket* ticket, int isRequest)
 6291{
 6292    (void)isRequest;
 6293    return ticket ? ticket->size : 0;
 6294}
 6295
 6296static word16 TLSX_SessionTicket_Write(SessionTicket* ticket, byte* output,
 6297                                       int isRequest)
 6298{
 6299    word16 offset = 0; /* empty ticket */
 6300
 6301    if (isRequest && ticket) {
 6302        XMEMCPY(output + offset, ticket->data, ticket->size);
 6303        offset += ticket->size;
 6304    }
 6305
 6306    return offset;
 6307}
 6308
 6309
 6310static int TLSX_SessionTicket_Parse(WOLFSSL* ssl, const byte* input,
 6311                                    word16 length, byte isRequest)
 6312{
 6313    int ret = 0;
 6314
 6315    (void) input; /* avoid unused parameter if NO_WOLFSSL_SERVER defined */
 6316
 6317    if (!isRequest) {
 6318        if (TLSX_CheckUnsupportedExtension(ssl, TLSX_SESSION_TICKET))
 6319            return TLSX_HandleUnsupportedExtension(ssl);
 6320
 6321        if (length != 0)
 6322            return BUFFER_ERROR;
 6323
 6324#ifndef NO_WOLFSSL_CLIENT
 6325        ssl->expect_session_ticket = 1;
 6326#endif
 6327    }
 6328#ifndef NO_WOLFSSL_SERVER
 6329    else {
 6330        /* server side */
 6331        if (ssl->ctx->ticketEncCb == NULL) {
 6332            WOLFSSL_MSG("Client sent session ticket, server has no callback");
 6333            return 0;
 6334        }
 6335
 6336#ifdef HAVE_SECURE_RENEGOTIATION
 6337        if (IsSCR(ssl)) {
 6338            WOLFSSL_MSG("Client sent session ticket during SCR. Ignoring.");
 6339            return 0;
 6340        }
 6341#endif
 6342
 6343        if (length > SESSION_TICKET_LEN) {
 6344            ret = BAD_TICKET_MSG_SZ;
 6345            WOLFSSL_ERROR_VERBOSE(ret);
 6346        } else if (IsAtLeastTLSv1_3(ssl->version)) {
 6347            WOLFSSL_MSG("Process client ticket rejected, TLS 1.3 no support");
 6348            ssl->options.rejectTicket = 1;
 6349            ret = 0;  /* not fatal */
 6350        } else if (ssl->options.noTicketTls12) {
 6351            /* ignore ticket request */
 6352        } else if (length == 0) {
 6353            /* blank ticket */
 6354            ret = TLSX_UseSessionTicket(&ssl->extensions, NULL, ssl->heap);
 6355            if (ret == WOLFSSL_SUCCESS) {
 6356                ret = 0;
 6357                /* send blank ticket */
 6358                TLSX_SetResponse(ssl, TLSX_SESSION_TICKET);
 6359                ssl->options.createTicket = 1;  /* will send ticket msg */
 6360                ssl->options.useTicket    = 1;
 6361                ssl->options.resuming     = 0;  /* no standard resumption */
 6362                ssl->arrays->sessionIDSz  = 0;  /* no echo on blank ticket */
 6363            }
 6364        } else {
 6365            /* got actual ticket from client */
 6366            ret = DoClientTicket(ssl, input, length);
 6367            if (ret == WOLFSSL_TICKET_RET_OK) {    /* use ticket to resume */
 6368                WOLFSSL_MSG("Using existing client ticket");
 6369                ssl->options.useTicket    = 1;
 6370                ssl->options.resuming     = 1;
 6371                /* SERVER: ticket is peer auth. */
 6372                ssl->options.peerAuthGood = 1;
 6373            } else if (ret == WOLFSSL_TICKET_RET_CREATE) {
 6374                WOLFSSL_MSG("Using existing client ticket, creating new one");
 6375                ret = TLSX_UseSessionTicket(&ssl->extensions, NULL, ssl->heap);
 6376                if (ret == WOLFSSL_SUCCESS) {
 6377                    ret = 0;
 6378                    TLSX_SetResponse(ssl, TLSX_SESSION_TICKET);
 6379                                                    /* send blank ticket */
 6380                    ssl->options.createTicket = 1;  /* will send ticket msg */
 6381                    ssl->options.useTicket    = 1;
 6382                    ssl->options.resuming     = 1;
 6383                    /* SERVER: ticket is peer auth. */
 6384                    ssl->options.peerAuthGood = 1;
 6385                }
 6386            } else if (ret == WOLFSSL_TICKET_RET_REJECT ||
 6387                    ret == WC_NO_ERR_TRACE(VERSION_ERROR)) {
 6388                WOLFSSL_MSG("Process client ticket rejected, not using");
 6389                if (ret == WC_NO_ERR_TRACE(VERSION_ERROR))
 6390                    WOLFSSL_MSG("\tbad TLS version");
 6391                ret = 0;  /* not fatal */
 6392
 6393                ssl->options.rejectTicket = 1;
 6394                /* If we have session tickets enabled then send a new ticket */
 6395                if (!TLSX_CheckUnsupportedExtension(ssl, TLSX_SESSION_TICKET)) {
 6396                    ret = TLSX_UseSessionTicket(&ssl->extensions, NULL,
 6397                                                ssl->heap);
 6398                    if (ret == WOLFSSL_SUCCESS) {
 6399                        ret = 0;
 6400                        TLSX_SetResponse(ssl, TLSX_SESSION_TICKET);
 6401                        ssl->options.createTicket = 1;
 6402                        ssl->options.useTicket    = 1;
 6403                    }
 6404                }
 6405            } else if (ret == WOLFSSL_TICKET_RET_FATAL) {
 6406                WOLFSSL_MSG("Process client ticket fatal error, not using");
 6407            } else if (ret < 0) {
 6408                WOLFSSL_MSG("Process client ticket unknown error, not using");
 6409            }
 6410        }
 6411    }
 6412#endif /* NO_WOLFSSL_SERVER */
 6413
 6414#if defined(NO_WOLFSSL_CLIENT) && defined(NO_WOLFSSL_SERVER)
 6415    (void)ssl;
 6416#endif
 6417
 6418    return ret;
 6419}
 6420
 6421WOLFSSL_TEST_VIS SessionTicket* TLSX_SessionTicket_Create(word32 lifetime,
 6422                                            byte* data, word16 size, void* heap)
 6423{
 6424    SessionTicket* ticket = (SessionTicket*)XMALLOC(sizeof(SessionTicket),
 6425                                                       heap, DYNAMIC_TYPE_TLSX);
 6426    if (ticket) {
 6427        ticket->data = (byte*)XMALLOC(size, heap, DYNAMIC_TYPE_TLSX);
 6428        if (ticket->data == NULL) {
 6429            XFREE(ticket, heap, DYNAMIC_TYPE_TLSX);
 6430            return NULL;
 6431        }
 6432
 6433        XMEMCPY(ticket->data, data, size);
 6434        ticket->size     = size;
 6435        ticket->lifetime = lifetime;
 6436    }
 6437
 6438    (void)heap;
 6439
 6440    return ticket;
 6441}
 6442WOLFSSL_TEST_VIS void TLSX_SessionTicket_Free(SessionTicket* ticket, void* heap)
 6443{
 6444    if (ticket) {
 6445        XFREE(ticket->data, heap, DYNAMIC_TYPE_TLSX);
 6446        XFREE(ticket,       heap, DYNAMIC_TYPE_TLSX);
 6447    }
 6448
 6449    (void)heap;
 6450}
 6451
 6452int TLSX_UseSessionTicket(TLSX** extensions, SessionTicket* ticket, void* heap)
 6453{
 6454    int ret = 0;
 6455
 6456    if (extensions == NULL)
 6457        return BAD_FUNC_ARG;
 6458
 6459    /* If the ticket is NULL, the client will request a new ticket from the
 6460       server. Otherwise, the client will use it in the next client hello. */
 6461    if ((ret = TLSX_Push(extensions, TLSX_SESSION_TICKET, (void*)ticket, heap))
 6462                                                                           != 0)
 6463        return ret;
 6464
 6465    return WOLFSSL_SUCCESS;
 6466}
 6467
 6468#define WOLF_STK_GET_SIZE         TLSX_SessionTicket_GetSize
 6469#define WOLF_STK_WRITE            TLSX_SessionTicket_Write
 6470#define WOLF_STK_PARSE            TLSX_SessionTicket_Parse
 6471#define WOLF_STK_FREE(stk, heap)  TLSX_SessionTicket_Free((SessionTicket*)(stk),(heap))
 6472
 6473#else
 6474
 6475#define WOLF_STK_FREE(a, b) WC_DO_NOTHING
 6476#define WOLF_STK_VALIDATE_REQUEST(a) WC_DO_NOTHING
 6477#define WOLF_STK_GET_SIZE(a, b)      0
 6478#define WOLF_STK_WRITE(a, b, c)      0
 6479#define WOLF_STK_PARSE(a, b, c, d)   0
 6480
 6481#endif /* HAVE_SESSION_TICKET */
 6482
 6483#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
 6484/******************************************************************************/
 6485/* Encrypt-then-MAC                                                           */
 6486/******************************************************************************/
 6487
 6488#ifndef WOLFSSL_NO_TLS12
 6489static int TLSX_EncryptThenMac_Use(WOLFSSL* ssl);
 6490
 6491/**
 6492 * Get the size of the Encrypt-Then-MAC extension.
 6493 *
 6494 * msgType  Type of message to put extension into.
 6495 * pSz      Size of extension data.
 6496 * return SANITY_MSG_E when the message is not allowed to have extension and
 6497 *        0 otherwise.
 6498 */
 6499static int TLSX_EncryptThenMac_GetSize(byte msgType, word16* pSz)
 6500{
 6501    (void)pSz;
 6502
 6503    if (msgType != client_hello && msgType != server_hello) {
 6504        WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
 6505        return SANITY_MSG_E;
 6506    }
 6507
 6508    /* Empty extension */
 6509
 6510    return 0;
 6511}
 6512
 6513/**
 6514 * Write the Encrypt-Then-MAC extension.
 6515 *
 6516 * data     Unused
 6517 * output   Extension data buffer. Unused.
 6518 * msgType  Type of message to put extension into.
 6519 * pSz      Size of extension data.
 6520 * return SANITY_MSG_E when the message is not allowed to have extension and
 6521 *        0 otherwise.
 6522 */
 6523static int TLSX_EncryptThenMac_Write(void* data, byte* output, byte msgType,
 6524                                     word16* pSz)
 6525{
 6526    (void)data;
 6527    (void)output;
 6528    (void)pSz;
 6529
 6530    if (msgType != client_hello && msgType != server_hello) {
 6531        WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
 6532        return SANITY_MSG_E;
 6533    }
 6534
 6535    /* Empty extension */
 6536
 6537    return 0;
 6538}
 6539
 6540/**
 6541 * Parse the Encrypt-Then-MAC extension.
 6542 *
 6543 * ssl      SSL object
 6544 * input    Extension data buffer.
 6545 * length   Length of this extension's data.
 6546 * msgType  Type of message to extension appeared in.
 6547 * return SANITY_MSG_E when the message is not allowed to have extension,
 6548 *        BUFFER_ERROR when the extension's data is invalid,
 6549 *        MEMORY_E when unable to allocate memory and
 6550 *        0 otherwise.
 6551 */
 6552static int TLSX_EncryptThenMac_Parse(WOLFSSL* ssl, const byte* input,
 6553                                     word16 length, byte msgType)
 6554{
 6555    int ret;
 6556
 6557    (void)input;
 6558
 6559    if (msgType != client_hello && msgType != server_hello) {
 6560        WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
 6561        return SANITY_MSG_E;
 6562    }
 6563
 6564    /* Empty extension */
 6565    if (length != 0)
 6566        return BUFFER_ERROR;
 6567
 6568    if (msgType == client_hello) {
 6569        /* Check the user hasn't disallowed use of Encrypt-Then-Mac. */
 6570        if (!ssl->options.disallowEncThenMac) {
 6571            ssl->options.encThenMac = 1;
 6572            /* Set the extension reply. */
 6573            ret = TLSX_EncryptThenMac_Use(ssl);
 6574            if (ret != 0)
 6575                return ret;
 6576        }
 6577        return 0;
 6578    }
 6579
 6580    /* Server Hello */
 6581    if (ssl->options.disallowEncThenMac) {
 6582        WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
 6583        return SANITY_MSG_E;
 6584    }
 6585
 6586    ssl->options.encThenMac = 1;
 6587    return 0;
 6588
 6589}
 6590
 6591/**
 6592 * Add the Encrypt-Then-MAC extension to list.
 6593 *
 6594 * ssl      SSL object
 6595 * return MEMORY_E when unable to allocate memory and 0 otherwise.
 6596 */
 6597static int TLSX_EncryptThenMac_Use(WOLFSSL* ssl)
 6598{
 6599    int   ret = 0;
 6600    TLSX* extension;
 6601
 6602    /* Find the Encrypt-Then-Mac extension if it exists. */
 6603    extension = TLSX_Find(ssl->extensions, TLSX_ENCRYPT_THEN_MAC);
 6604    if (extension == NULL) {
 6605        /* Push new Encrypt-Then-Mac extension. */
 6606        ret = TLSX_Push(&ssl->extensions, TLSX_ENCRYPT_THEN_MAC, NULL,
 6607            ssl->heap);
 6608        if (ret != 0)
 6609            return ret;
 6610    }
 6611
 6612    return 0;
 6613}
 6614
 6615/**
 6616 * Set the Encrypt-Then-MAC extension as one to respond too.
 6617 *
 6618 * ssl      SSL object
 6619 * return EXT_MISSING when EncryptThenMac extension not in list.
 6620 */
 6621int TLSX_EncryptThenMac_Respond(WOLFSSL* ssl)
 6622{
 6623    TLSX* extension;
 6624
 6625    extension = TLSX_Find(ssl->extensions, TLSX_ENCRYPT_THEN_MAC);
 6626    if (extension == NULL)
 6627        return EXT_MISSING;
 6628    extension->resp = 1;
 6629
 6630    return 0;
 6631}
 6632
 6633#define ETM_GET_SIZE  TLSX_EncryptThenMac_GetSize
 6634#define ETM_WRITE     TLSX_EncryptThenMac_Write
 6635#define ETM_PARSE     TLSX_EncryptThenMac_Parse
 6636
 6637#else
 6638
 6639#define ETM_GET_SIZE(a, b)    0
 6640#define ETM_WRITE(a, b, c, d) 0
 6641#define ETM_PARSE(a, b, c, d) 0
 6642
 6643#endif /* !WOLFSSL_NO_TLS12 */
 6644
 6645#endif /* HAVE_ENCRYPT_THEN_MAC && !WOLFSSL_AEAD_ONLY */
 6646
 6647
 6648#ifdef WOLFSSL_SRTP
 6649
 6650/******************************************************************************/
 6651/* DTLS SRTP (Secure Real-time Transport Protocol)                            */
 6652/******************************************************************************/
 6653
 6654/* Only support single SRTP profile */
 6655typedef struct TlsxSrtp {
 6656    word16 profileCount;
 6657    word16 ids; /* selected bits */
 6658} TlsxSrtp;
 6659
 6660#ifndef NO_WOLFSSL_SERVER
 6661static int TLSX_UseSRTP_GetSize(TlsxSrtp *srtp)
 6662{
 6663    /*   SRTP Profile Len (2)
 6664     *      SRTP Profiles (2)
 6665     *   MKI (master key id) Length */
 6666    return (OPAQUE16_LEN + (srtp->profileCount * OPAQUE16_LEN) + 1);
 6667}
 6668#endif
 6669
 6670static TlsxSrtp* TLSX_UseSRTP_New(word16 ids, void* heap)
 6671{
 6672    TlsxSrtp* srtp;
 6673    int i;
 6674
 6675    srtp = (TlsxSrtp*)XMALLOC(sizeof(TlsxSrtp), heap, DYNAMIC_TYPE_TLSX);
 6676    if (srtp == NULL) {
 6677        WOLFSSL_MSG("TLSX SRTP Memory failure");
 6678        return NULL;
 6679    }
 6680
 6681    /* count and test each bit set */
 6682    srtp->profileCount = 0;
 6683    for (i=0; i<16; i++) {
 6684        if (ids & (1 << i)) {
 6685            srtp->profileCount++;
 6686        }
 6687    }
 6688    srtp->ids = ids;
 6689
 6690    return srtp;
 6691}
 6692
 6693static void TLSX_UseSRTP_Free(TlsxSrtp *srtp, void* heap)
 6694{
 6695    XFREE(srtp, heap, DYNAMIC_TYPE_TLSX);
 6696    (void)heap;
 6697}
 6698
 6699#ifndef NO_WOLFSSL_SERVER
 6700static int TLSX_UseSRTP_Parse(WOLFSSL* ssl, const byte* input, word16 length,
 6701    byte isRequest)
 6702{
 6703    int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG);
 6704    word16 profile_len = 0;
 6705    word16 profile_value = 0;
 6706    word16 offset = 0;
 6707    int i;
 6708    TlsxSrtp* srtp = NULL;
 6709
 6710    if (length < OPAQUE16_LEN) {
 6711        return BUFFER_ERROR;
 6712    }
 6713
 6714    /* reset selected DTLS SRTP profile ID */
 6715    ssl->dtlsSrtpId = 0;
 6716
 6717    /* total length, not include itself */
 6718    ato16(input, &profile_len);
 6719    offset += OPAQUE16_LEN;
 6720    /* Check profile length is not bigger than remaining length. */
 6721    if (profile_len > length - offset) {
 6722        return BUFFER_ERROR;
 6723    }
 6724    /* Protection profiles are 2 bytes long - ensure not an odd no. bytes. */
 6725    if ((profile_len & 1) == 1) {
 6726        return BUFFER_ERROR;
 6727    }
 6728    /* Ignoring srtp_mki field - SRTP Make Key Identifier.
 6729     * Defined to be 0..255 bytes long.
 6730     */
 6731    if ((length - profile_len - offset) > 255) {
 6732        return BUFFER_ERROR;
 6733    }
 6734
 6735    if (!isRequest) {
 6736#ifndef NO_WOLFSSL_CLIENT
 6737        /* Only one SRTP Protection Profile can be chosen. */
 6738        if (profile_len != OPAQUE16_LEN) {
 6739            return BUFFER_ERROR;
 6740        }
 6741
 6742        ato16(input + offset, &profile_value);
 6743
 6744        /* check that the profile received was in the ones we support */
 6745        if (profile_value < 16 &&
 6746                               (ssl->dtlsSrtpProfiles & (1 << profile_value))) {
 6747            ssl->dtlsSrtpId = profile_value;
 6748            ret = 0; /* success */
 6749        }
 6750#endif
 6751    }
 6752    else {
 6753        /* parse remainder one profile at a time, looking for match in CTX */
 6754        ret = 0;
 6755        for (i = 0; i < profile_len; i += OPAQUE16_LEN) {
 6756            ato16(input + offset + i, &profile_value);
 6757            /* find first match */
 6758            if (profile_value < 16 &&
 6759                                 ssl->dtlsSrtpProfiles & (1 << profile_value)) {
 6760                ssl->dtlsSrtpId = profile_value;
 6761
 6762                /* make sure we respond with selected SRTP id selected */
 6763                srtp = TLSX_UseSRTP_New((1 << profile_value), ssl->heap);
 6764                if (srtp != NULL) {
 6765                    ret = TLSX_Push(&ssl->extensions, TLSX_USE_SRTP,
 6766                        (void*)srtp, ssl->heap);
 6767                    if (ret == 0) {
 6768                        TLSX_SetResponse(ssl, TLSX_USE_SRTP);
 6769                        /* successfully set extension */
 6770                    }
 6771                }
 6772                else {
 6773                    ret = MEMORY_E;
 6774                }
 6775                break;
 6776            }
 6777        }
 6778    }
 6779
 6780    if (ret == 0 && ssl->dtlsSrtpId == 0) {
 6781        WOLFSSL_MSG("TLSX_UseSRTP_Parse profile not found!");
 6782        /* not fatal */
 6783    }
 6784    else if (ret != 0) {
 6785        ssl->dtlsSrtpId = 0;
 6786        TLSX_UseSRTP_Free(srtp, ssl->heap);
 6787    }
 6788
 6789    return ret;
 6790}
 6791
 6792static word16 TLSX_UseSRTP_Write(TlsxSrtp* srtp, byte* output)
 6793{
 6794    word16 offset = 0;
 6795    int i, j;
 6796
 6797    c16toa(srtp->profileCount * 2, output + offset);
 6798    offset += OPAQUE16_LEN;
 6799    j = 0;
 6800    for (i = 0; i < srtp->profileCount; i++) {
 6801        for (; j < 16; j++) {
 6802            if (srtp->ids & (1 << j)) {
 6803                c16toa(j, output + offset);
 6804                offset += OPAQUE16_LEN;
 6805            }
 6806        }
 6807    }
 6808    output[offset++] = 0x00; /* MKI Length */
 6809
 6810    return offset;
 6811}
 6812#endif
 6813
 6814static int TLSX_UseSRTP(TLSX** extensions, word16 profiles, void* heap)
 6815{
 6816    int ret = 0;
 6817    TLSX* extension;
 6818
 6819    if (extensions == NULL) {
 6820        return BAD_FUNC_ARG;
 6821    }
 6822
 6823    extension = TLSX_Find(*extensions, TLSX_USE_SRTP);
 6824    if (extension == NULL) {
 6825        TlsxSrtp* srtp = TLSX_UseSRTP_New(profiles, heap);
 6826        if (srtp == NULL) {
 6827            return MEMORY_E;
 6828        }
 6829
 6830        ret = TLSX_Push(extensions, TLSX_USE_SRTP, (void*)srtp, heap);
 6831        if (ret != 0) {
 6832            TLSX_UseSRTP_Free(srtp, heap);
 6833        }
 6834    }
 6835
 6836    return ret;
 6837}
 6838
 6839#ifndef NO_WOLFSSL_SERVER
 6840    #define SRTP_FREE     TLSX_UseSRTP_Free
 6841    #define SRTP_PARSE    TLSX_UseSRTP_Parse
 6842    #define SRTP_WRITE    TLSX_UseSRTP_Write
 6843    #define SRTP_GET_SIZE TLSX_UseSRTP_GetSize
 6844#else
 6845    #define SRTP_FREE(a, b) WC_DO_NOTHING
 6846    #define SRTP_PARSE(a, b, c, d)      0
 6847    #define SRTP_WRITE(a, b)            0
 6848    #define SRTP_GET_SIZE(a)            0
 6849#endif
 6850
 6851#endif /* WOLFSSL_SRTP */
 6852
 6853
 6854/******************************************************************************/
 6855/* Supported Versions                                                         */
 6856/******************************************************************************/
 6857
 6858#ifdef WOLFSSL_TLS13
 6859static WC_INLINE int versionIsGreater(byte isDtls, byte a, byte b)
 6860{
 6861    (void)isDtls;
 6862
 6863#ifdef WOLFSSL_DTLS
 6864    /* DTLS version increases backwards (-1,-2,-3,etc) */
 6865    if (isDtls)
 6866        return a < b;
 6867#endif /* WOLFSSL_DTLS */
 6868
 6869    return a > b;
 6870}
 6871
 6872static WC_INLINE int versionIsLesser(byte isDtls, byte a, byte b)
 6873{
 6874    (void)isDtls;
 6875
 6876#ifdef WOLFSSL_DTLS
 6877    /* DTLS version increases backwards (-1,-2,-3,etc) */
 6878    if (isDtls)
 6879        return a > b;
 6880#endif /* WOLFSSL_DTLS */
 6881
 6882    return a < b;
 6883}
 6884
 6885static WC_INLINE int versionIsAtLeast(byte isDtls, byte a, byte b)
 6886{
 6887    (void)isDtls;
 6888
 6889#ifdef WOLFSSL_DTLS
 6890    /* DTLS version increases backwards (-1,-2,-3,etc) */
 6891    if (isDtls)
 6892        return a <= b;
 6893#endif /* WOLFSSL_DTLS */
 6894
 6895    return a >= b;
 6896}
 6897
 6898static WC_INLINE int versionIsLessEqual(byte isDtls, byte a, byte b)
 6899{
 6900    (void)isDtls;
 6901
 6902#ifdef WOLFSSL_DTLS
 6903    /* DTLS version increases backwards (-1,-2,-3,etc) */
 6904    if (isDtls)
 6905        return a >= b;
 6906#endif /* WOLFSSL_DTLS */
 6907
 6908    return a <= b;
 6909}
 6910
 6911/* Return the size of the SupportedVersions extension's data.
 6912 *
 6913 * data       The SSL/TLS object.
 6914 * msgType The type of the message this extension is being written into.
 6915 * returns the length of data that will be in the extension.
 6916 */
 6917static int TLSX_SupportedVersions_GetSize(void* data, byte msgType, word16* pSz)
 6918{
 6919    WOLFSSL* ssl = (WOLFSSL*)data;
 6920    byte tls13Minor, tls12Minor, tls11Minor, isDtls;
 6921
 6922    isDtls = !!ssl->options.dtls;
 6923    tls13Minor = (byte)(isDtls ? DTLSv1_3_MINOR : TLSv1_3_MINOR);
 6924    tls12Minor = (byte)(isDtls ? DTLSv1_2_MINOR : TLSv1_2_MINOR);
 6925    tls11Minor = (byte)(isDtls ? DTLS_MINOR : TLSv1_1_MINOR);
 6926
 6927    /* unused on some configuration */
 6928    (void)tls12Minor;
 6929    (void)tls13Minor;
 6930    (void)tls11Minor;
 6931
 6932    if (msgType == client_hello) {
 6933        /* TLS v1.2 and TLS v1.3  */
 6934        int cnt = 0;
 6935
 6936        if (versionIsLessEqual(isDtls, ssl->options.minDowngrade, tls13Minor)
 6937        #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || \
 6938            defined(WOLFSSL_WPAS_SMALL)
 6939            && (ssl->options.mask & WOLFSSL_OP_NO_TLSv1_3) == 0
 6940        #endif
 6941        ) {
 6942            cnt++;
 6943        }
 6944
 6945        if (ssl->options.downgrade) {
 6946    #ifndef WOLFSSL_NO_TLS12
 6947            if (versionIsLessEqual(
 6948                    isDtls, ssl->options.minDowngrade, tls12Minor)
 6949#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) ||                       \
 6950    defined(WOLFSSL_WPAS_SMALL)
 6951                && (ssl->options.mask & WOLFSSL_OP_NO_TLSv1_2) == 0
 6952#endif
 6953            ) {
 6954                cnt++;
 6955            }
 6956#endif
 6957    #ifndef NO_OLD_TLS
 6958            if (versionIsLessEqual(
 6959                    isDtls, ssl->options.minDowngrade, tls11Minor)
 6960            #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || \
 6961                defined(WOLFSSL_WPAS_SMALL)
 6962                && (ssl->options.mask & WOLFSSL_OP_NO_TLSv1_1) == 0
 6963            #endif
 6964            ) {
 6965                cnt++;
 6966            }
 6967        #ifdef WOLFSSL_ALLOW_TLSV10
 6968            if (!ssl->options.dtls && (ssl->options.minDowngrade <= TLSv1_MINOR)
 6969            #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || \
 6970                defined(WOLFSSL_WPAS_SMALL)
 6971                && (ssl->options.mask & WOLFSSL_OP_NO_TLSv1) == 0
 6972            #endif
 6973            ) {
 6974                cnt++;
 6975            }
 6976        #endif
 6977    #endif
 6978        }
 6979
 6980        *pSz += (word16)(OPAQUE8_LEN + cnt * OPAQUE16_LEN);
 6981    }
 6982    else if (msgType == server_hello || msgType == hello_retry_request) {
 6983        *pSz += OPAQUE16_LEN;
 6984    }
 6985    else {
 6986        WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
 6987        return SANITY_MSG_E;
 6988    }
 6989
 6990    return 0;
 6991}
 6992
 6993/* Writes the SupportedVersions extension into the buffer.
 6994 *
 6995 * data    The SSL/TLS object.
 6996 * output  The buffer to write the extension into.
 6997 * msgType The type of the message this extension is being written into.
 6998 * returns the length of data that was written.
 6999 */
 7000static int TLSX_SupportedVersions_Write(void* data, byte* output,
 7001                                        byte msgType, word16* pSz)
 7002{
 7003    WOLFSSL* ssl = (WOLFSSL*)data;
 7004    byte tls13minor, tls12minor, tls11minor, isDtls = 0;
 7005
 7006    tls13minor = (byte)TLSv1_3_MINOR;
 7007    tls12minor = (byte)TLSv1_2_MINOR;
 7008    tls11minor = (byte)TLSv1_1_MINOR;
 7009
 7010    /* unused in some configuration */
 7011    (void)tls11minor;
 7012    (void)tls12minor;
 7013
 7014#ifdef WOLFSSL_DTLS13
 7015    if (ssl->options.dtls) {
 7016        tls13minor = (byte)DTLSv1_3_MINOR;
 7017    #ifndef WOLFSSL_NO_TLS12
 7018        tls12minor = (byte)DTLSv1_2_MINOR;
 7019    #endif
 7020    #ifndef NO_OLD_TLS
 7021        tls11minor = (byte)DTLS_MINOR;
 7022    #endif
 7023        isDtls = 1;
 7024    }
 7025#endif /* WOLFSSL_DTLS13 */
 7026
 7027    if (msgType == client_hello) {
 7028        byte major = ssl->ctx->method->version.major;
 7029
 7030        byte* cnt = output++;
 7031        *cnt = 0;
 7032
 7033        if (versionIsLessEqual(isDtls, ssl->options.minDowngrade, tls13minor)
 7034#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) ||                       \
 7035    defined(WOLFSSL_WPAS_SMALL)
 7036            && (ssl->options.mask & WOLFSSL_OP_NO_TLSv1_3) == 0
 7037#endif
 7038        ) {
 7039            *cnt += OPAQUE16_LEN;
 7040        #ifdef WOLFSSL_TLS13_DRAFT
 7041            /* The TLS draft major number. */
 7042            *(output++) = TLS_DRAFT_MAJOR;
 7043            /* Version of draft supported. */
 7044            *(output++) = TLS_DRAFT_MINOR;
 7045        #else
 7046            *(output++) = major;
 7047            *(output++) = tls13minor;
 7048        #endif
 7049        }
 7050
 7051        if (ssl->options.downgrade) {
 7052        #ifndef WOLFSSL_NO_TLS12
 7053            if (versionIsLessEqual(isDtls, ssl->options.minDowngrade, tls12minor)
 7054#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || \
 7055                defined(WOLFSSL_WPAS_SMALL)
 7056                && (ssl->options.mask & WOLFSSL_OP_NO_TLSv1_2) == 0
 7057            #endif
 7058            ) {
 7059                *cnt += OPAQUE16_LEN;
 7060                *(output++) = major;
 7061                *(output++) = tls12minor;
 7062            }
 7063        #endif
 7064
 7065    #ifndef NO_OLD_TLS
 7066            if (versionIsLessEqual(isDtls, ssl->options.minDowngrade, tls11minor)
 7067            #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || \
 7068                defined(WOLFSSL_WPAS_SMALL)
 7069                && (ssl->options.mask & WOLFSSL_OP_NO_TLSv1_1) == 0
 7070            #endif
 7071            ) {
 7072                *cnt += OPAQUE16_LEN;
 7073                *(output++) = major;
 7074                *(output++) = tls11minor;
 7075            }
 7076        #ifdef WOLFSSL_ALLOW_TLSV10
 7077            if (!ssl->options.dtls && (ssl->options.minDowngrade <= TLSv1_MINOR)
 7078            #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || \
 7079                defined(WOLFSSL_WPAS_SMALL)
 7080                && (ssl->options.mask & WOLFSSL_OP_NO_TLSv1) == 0
 7081            #endif
 7082            ) {
 7083                *cnt += OPAQUE16_LEN;
 7084                *(output++) = major;
 7085                *(output++) = (byte)TLSv1_MINOR;
 7086            }
 7087        #endif
 7088    #endif
 7089        }
 7090
 7091        *pSz += (word16)(OPAQUE8_LEN + *cnt);
 7092    }
 7093    else if (msgType == server_hello || msgType == hello_retry_request) {
 7094        output[0] = ssl->version.major;
 7095        output[1] = ssl->version.minor;
 7096
 7097        *pSz += OPAQUE16_LEN;
 7098    }
 7099    else {
 7100        WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
 7101        return SANITY_MSG_E;
 7102    }
 7103
 7104    return 0;
 7105}
 7106
 7107/* Parse the SupportedVersions extension.
 7108 *
 7109 * ssl     The SSL/TLS object.
 7110 * input   The buffer with the extension data.
 7111 * length  The length of the extension data.
 7112 * msgType The type of the message this extension is being parsed from.
 7113 * pv      The output ProtocolVersion for the negotiated version
 7114 * opts    The output options structure. Can be NULL.
 7115 * exts    The output extensions list. Can be NULL.
 7116 * returns 0 on success, otherwise failure.
 7117 */
 7118int TLSX_SupportedVersions_Parse(const WOLFSSL* ssl, const byte* input,
 7119        word16 length, byte msgType, ProtocolVersion* pv, Options* opts,
 7120        TLSX** exts)
 7121{
 7122    /* The client's greatest minor version that we support */
 7123    byte clientGreatestMinor = SSLv3_MINOR;
 7124    int ret;
 7125    byte major, minor;
 7126    byte tls13minor, tls12minor;
 7127    byte isDtls;
 7128
 7129    tls13minor = TLSv1_3_MINOR;
 7130    tls12minor = TLSv1_2_MINOR;
 7131    isDtls = ssl->options.dtls == 1;
 7132
 7133#ifdef WOLFSSL_DTLS13
 7134    if (ssl->options.dtls) {
 7135        tls13minor = DTLSv1_3_MINOR;
 7136        tls12minor = DTLSv1_2_MINOR;
 7137        clientGreatestMinor = DTLS_MINOR;
 7138    }
 7139#endif /* WOLFSSL_DTLS13 */
 7140
 7141    if (msgType == client_hello) {
 7142        int i;
 7143        int len;
 7144        int set = 0;
 7145
 7146        /* Must contain a length and at least one version. */
 7147        if (length < OPAQUE8_LEN + OPAQUE16_LEN || (length & 1) != 1
 7148            || length > MAX_SV_EXT_LEN) {
 7149            return BUFFER_ERROR;
 7150        }
 7151
 7152        len = *input;
 7153
 7154        /* Protocol version array must fill rest of data. */
 7155        if (length != (word16)OPAQUE8_LEN + len)
 7156            return BUFFER_ERROR;
 7157
 7158        input++;
 7159
 7160        /* Find first match. */
 7161        for (i = 0; i < len; i += OPAQUE16_LEN) {
 7162            major = input[i];
 7163            minor = input[i + OPAQUE8_LEN];
 7164
 7165#ifdef WOLFSSL_TLS13_DRAFT
 7166            if (major == TLS_DRAFT_MAJOR && minor == TLS_DRAFT_MINOR) {
 7167                major = SSLv3_MAJOR;
 7168                minor = TLSv1_3_MINOR;
 7169            }
 7170#else
 7171            if (major == TLS_DRAFT_MAJOR)
 7172                continue;
 7173#endif
 7174
 7175            if (major != ssl->ctx->method->version.major)
 7176                continue;
 7177
 7178            /* No upgrade allowed. */
 7179            if (versionIsGreater(isDtls, minor, ssl->version.minor))
 7180                continue;
 7181
 7182            /* Check downgrade. */
 7183            if (versionIsLesser(isDtls, minor, ssl->version.minor)) {
 7184                if (!ssl->options.downgrade)
 7185                    continue;
 7186
 7187                if (versionIsLesser(isDtls, minor, ssl->options.minDowngrade))
 7188                    continue;
 7189            }
 7190            if (versionIsGreater(isDtls, minor, clientGreatestMinor))
 7191                clientGreatestMinor = minor;
 7192
 7193            set = 1;
 7194        }
 7195        if (!set) {
 7196            /* No common supported version was negotiated */
 7197            SendAlert((WOLFSSL*)ssl, alert_fatal,
 7198                      wolfssl_alert_protocol_version);
 7199            WOLFSSL_ERROR_VERBOSE(VERSION_ERROR);
 7200            return VERSION_ERROR;
 7201        }
 7202        pv->minor = clientGreatestMinor;
 7203        if (versionIsAtLeast(isDtls, clientGreatestMinor, tls13minor)) {
 7204            if (opts != NULL)
 7205                opts->tls1_3 = 1;
 7206
 7207            /* TLS v1.3 requires supported version extension */
 7208            if (exts != NULL &&
 7209                    TLSX_Find(*exts, TLSX_SUPPORTED_VERSIONS) == NULL) {
 7210                ret = TLSX_Push(exts,
 7211                          TLSX_SUPPORTED_VERSIONS, ssl, ssl->heap);
 7212                if (ret != 0) {
 7213                    return ret;
 7214                }
 7215                /* *exts should be pointing to the TLSX_SUPPORTED_VERSIONS
 7216                 * ext in the list since it was pushed. */
 7217                (*exts)->resp = 1;
 7218            }
 7219        }
 7220
 7221    }
 7222    else if (msgType == server_hello || msgType == hello_retry_request) {
 7223        /* Must contain one version. */
 7224        if (length != OPAQUE16_LEN)
 7225            return BUFFER_ERROR;
 7226
 7227        major = input[0];
 7228        minor = input[OPAQUE8_LEN];
 7229
 7230        if (major != ssl->ctx->method->version.major) {
 7231            WOLFSSL_ERROR_VERBOSE(VERSION_ERROR);
 7232            return VERSION_ERROR;
 7233        }
 7234
 7235        /* Can't downgrade with this extension below TLS v1.3. */
 7236        if (versionIsLesser(isDtls, minor, tls13minor)) {
 7237            WOLFSSL_ERROR_VERBOSE(VERSION_ERROR);
 7238            return VERSION_ERROR;
 7239        }
 7240
 7241        /* Version is TLS v1.2 to handle downgrading from TLS v1.3+. */
 7242        if (ssl->options.downgrade && ssl->version.minor == tls12minor) {
 7243            /* Set minor version back to TLS v1.3+ */
 7244            pv->minor = ssl->ctx->method->version.minor;
 7245        }
 7246
 7247        /* No upgrade allowed. */
 7248        if (versionIsLesser(isDtls, ssl->version.minor, minor)) {
 7249            WOLFSSL_ERROR_VERBOSE(VERSION_ERROR);
 7250            return VERSION_ERROR;
 7251        }
 7252
 7253        /* Check downgrade. */
 7254        if (versionIsGreater(isDtls, ssl->version.minor, minor)) {
 7255            if (!ssl->options.downgrade) {
 7256                WOLFSSL_ERROR_VERBOSE(VERSION_ERROR);
 7257                return VERSION_ERROR;
 7258            }
 7259
 7260            if (versionIsLesser(
 7261                    isDtls, minor, ssl->options.minDowngrade)) {
 7262                WOLFSSL_ERROR_VERBOSE(VERSION_ERROR);
 7263                return VERSION_ERROR;
 7264            }
 7265
 7266            /* Downgrade the version. */
 7267            pv->minor = minor;
 7268        }
 7269    }
 7270    else {
 7271        WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
 7272        return SANITY_MSG_E;
 7273    }
 7274
 7275    return 0;
 7276}
 7277
 7278/* Sets a new SupportedVersions extension into the extension list.
 7279 *
 7280 * extensions  The list of extensions.
 7281 * data        The extensions specific data.
 7282 * heap        The heap used for allocation.
 7283 * returns 0 on success, otherwise failure.
 7284 */
 7285static int TLSX_SetSupportedVersions(TLSX** extensions, const void* data,
 7286                                     void* heap)
 7287{
 7288    if (extensions == NULL || data == NULL)
 7289        return BAD_FUNC_ARG;
 7290
 7291    return TLSX_Push(extensions, TLSX_SUPPORTED_VERSIONS, data, heap);
 7292}
 7293
 7294#define SV_GET_SIZE  TLSX_SupportedVersions_GetSize
 7295#define SV_WRITE     TLSX_SupportedVersions_Write
 7296#define SV_PARSE     TLSX_SupportedVersions_Parse
 7297
 7298#else
 7299
 7300#define SV_GET_SIZE(a, b, c) 0
 7301#define SV_WRITE(a, b, c, d) 0
 7302#define SV_PARSE(a, b, c, d, e, f, g) 0
 7303
 7304#endif /* WOLFSSL_TLS13 */
 7305
 7306#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_SEND_HRR_COOKIE)
 7307
 7308/******************************************************************************/
 7309/* Cookie                                                                     */
 7310/******************************************************************************/
 7311
 7312/* Free the cookie data.
 7313 *
 7314 * cookie  Cookie data.
 7315 * heap    The heap used for allocation.
 7316 */
 7317static void TLSX_Cookie_FreeAll(Cookie* cookie, void* heap)
 7318{
 7319    (void)heap;
 7320
 7321    XFREE(cookie, heap, DYNAMIC_TYPE_TLSX);
 7322}
 7323
 7324/* Get the size of the encoded Cookie extension.
 7325 * In messages: ClientHello and HelloRetryRequest.
 7326 *
 7327 * cookie   The cookie to write.
 7328 * msgType  The type of the message this extension is being written into.
 7329 * returns the number of bytes of the encoded Cookie extension.
 7330 */
 7331static int TLSX_Cookie_GetSize(Cookie* cookie, byte msgType, word16* pSz)
 7332{
 7333    if (msgType == client_hello || msgType == hello_retry_request) {
 7334        *pSz += OPAQUE16_LEN + cookie->len;
 7335    }
 7336    else {
 7337        WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
 7338        return SANITY_MSG_E;
 7339    }
 7340    return 0;
 7341}
 7342
 7343/* Writes the Cookie extension into the output buffer.
 7344 * Assumes that the the output buffer is big enough to hold data.
 7345 * In messages: ClientHello and HelloRetryRequest.
 7346 *
 7347 * cookie   The cookie to write.
 7348 * output   The buffer to write into.
 7349 * msgType  The type of the message this extension is being written into.
 7350 * returns the number of bytes written into the buffer.
 7351 */
 7352static int TLSX_Cookie_Write(Cookie* cookie, byte* output, byte msgType,
 7353                             word16* pSz)
 7354{
 7355    if (msgType == client_hello || msgType == hello_retry_request) {
 7356        c16toa(cookie->len, output);
 7357        output += OPAQUE16_LEN;
 7358        XMEMCPY(output, cookie->data, cookie->len);
 7359        *pSz += OPAQUE16_LEN + cookie->len;
 7360    }
 7361    else {
 7362        WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
 7363        return SANITY_MSG_E;
 7364    }
 7365    return 0;
 7366}
 7367
 7368/* Parse the Cookie extension.
 7369 * In messages: ClientHello and HelloRetryRequest.
 7370 *
 7371 * ssl      The SSL/TLS object.
 7372 * input    The extension data.
 7373 * length   The length of the extension data.
 7374 * msgType  The type of the message this extension is being parsed from.
 7375 * returns 0 on success and other values indicate failure.
 7376 */
 7377static int TLSX_Cookie_Parse(WOLFSSL* ssl, const byte* input, word16 length,
 7378                             byte msgType)
 7379{
 7380    word16  len;
 7381    word16  idx = 0;
 7382    TLSX*   extension;
 7383    Cookie* cookie;
 7384
 7385    if (msgType != client_hello && msgType != hello_retry_request) {
 7386        WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
 7387        return SANITY_MSG_E;
 7388    }
 7389
 7390    /* Message contains length and Cookie which must be at least one byte
 7391     * in length.
 7392     */
 7393    if (length < OPAQUE16_LEN + 1)
 7394        return BUFFER_E;
 7395    ato16(input + idx, &len);
 7396    idx += OPAQUE16_LEN;
 7397    if (length - idx != len)
 7398        return BUFFER_E;
 7399
 7400    if (msgType == hello_retry_request) {
 7401        ssl->options.hrrSentCookie = 1;
 7402        return TLSX_Cookie_Use(ssl, input + idx, len, NULL, 0, 1,
 7403                               &ssl->extensions);
 7404    }
 7405
 7406    /* client_hello */
 7407    extension = TLSX_Find(ssl->extensions, TLSX_COOKIE);
 7408    if (extension == NULL) {
 7409#ifdef WOLFSSL_DTLS13
 7410        if (ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version))
 7411            /* Allow a cookie extension with DTLS 1.3 because it is possible
 7412             * that a different SSL instance sent the cookie but we are now
 7413             * receiving it. */
 7414            return TLSX_Cookie_Use(ssl, input + idx, len, NULL, 0, 0,
 7415                                   &ssl->extensions);
 7416        else
 7417#endif
 7418        {
 7419            WOLFSSL_ERROR_VERBOSE(HRR_COOKIE_ERROR);
 7420            return HRR_COOKIE_ERROR;
 7421        }
 7422    }
 7423
 7424    cookie = (Cookie*)extension->data;
 7425    if (cookie->len != len || XMEMCMP(cookie->data, input + idx, len) != 0) {
 7426        WOLFSSL_ERROR_VERBOSE(HRR_COOKIE_ERROR);
 7427        return HRR_COOKIE_ERROR;
 7428    }
 7429
 7430    /* Request seen. */
 7431    extension->resp = 0;
 7432
 7433    return 0;
 7434}
 7435
 7436/* Use the data to create a new Cookie object in the extensions.
 7437 *
 7438 * ssl    SSL/TLS object.
 7439 * data   Cookie data.
 7440 * len    Length of cookie data in bytes.
 7441 * mac    MAC data.
 7442 * macSz  Length of MAC data in bytes.
 7443 * resp   Indicates the extension will go into a response (HelloRetryRequest).
 7444 * returns 0 on success and other values indicate failure.
 7445 */
 7446int TLSX_Cookie_Use(const WOLFSSL* ssl, const byte* data, word16 len, byte* mac,
 7447                    byte macSz, int resp, TLSX** exts)
 7448{
 7449    int     ret = 0;
 7450    TLSX*   extension;
 7451    Cookie* cookie;
 7452
 7453    /* Find the cookie extension if it exists. */
 7454    extension = TLSX_Find(*exts, TLSX_COOKIE);
 7455    if (extension == NULL) {
 7456        /* Push new cookie extension. */
 7457        ret = TLSX_Push(exts, TLSX_COOKIE, NULL, ssl->heap);
 7458        if (ret != 0)
 7459            return ret;
 7460
 7461        extension = TLSX_Find(*exts, TLSX_COOKIE);
 7462        if (extension == NULL)
 7463            return MEMORY_E;
 7464    }
 7465
 7466    cookie = (Cookie*)XMALLOC(sizeof(Cookie) + len + macSz, ssl->heap,
 7467                              DYNAMIC_TYPE_TLSX);
 7468    if (cookie == NULL)
 7469        return MEMORY_E;
 7470
 7471    cookie->len = len + macSz;
 7472    XMEMCPY(cookie->data, data, len);
 7473    if (mac != NULL)
 7474        XMEMCPY(cookie->data + len, mac, macSz);
 7475
 7476    XFREE(extension->data, ssl->heap, DYNAMIC_TYPE_TLSX);
 7477
 7478    extension->data = (void*)cookie;
 7479    extension->resp = (byte)resp;
 7480
 7481    return 0;
 7482}
 7483
 7484#define CKE_FREE_ALL  TLSX_Cookie_FreeAll
 7485#define CKE_GET_SIZE  TLSX_Cookie_GetSize
 7486#define CKE_WRITE     TLSX_Cookie_Write
 7487#define CKE_PARSE     TLSX_Cookie_Parse
 7488
 7489#else
 7490
 7491#define CKE_FREE_ALL(a, b)    WC_DO_NOTHING
 7492#define CKE_GET_SIZE(a, b, c) 0
 7493#define CKE_WRITE(a, b, c, d) 0
 7494#define CKE_PARSE(a, b, c, d) 0
 7495
 7496#endif
 7497
 7498#if defined(WOLFSSL_TLS13) && !defined(NO_CERTS) && \
 7499    !defined(WOLFSSL_NO_CA_NAMES) && defined(OPENSSL_EXTRA)
 7500/* Currently only settable through compatibility API */
 7501/******************************************************************************/
 7502/* Certificate Authorities                                                       */
 7503/******************************************************************************/
 7504
 7505static word16 TLSX_CA_Names_GetSize(void* data)
 7506{
 7507    WOLFSSL* ssl = (WOLFSSL*)data;
 7508    WOLF_STACK_OF(WOLFSSL_X509_NAME)* names;
 7509    word32 size = 0;
 7510
 7511    /* Length of names */
 7512    size += OPAQUE16_LEN;
 7513    for (names = SSL_PRIORITY_CA_NAMES(ssl); names != NULL; names = names->next) {
 7514        byte seq[MAX_SEQ_SZ];
 7515        WOLFSSL_X509_NAME* name = names->data.name;
 7516
 7517        if (name != NULL) {
 7518            /* 16-bit length | SEQ | Len | DER of name */
 7519            size += (word32)(OPAQUE16_LEN + SetSequence(name->rawLen, seq) +
 7520                             name->rawLen);
 7521            if (size > WOLFSSL_MAX_16BIT) {
 7522                return 0;
 7523            }
 7524        }
 7525    }
 7526    return (word16)size;
 7527}
 7528
 7529static word16 TLSX_CA_Names_Write(void* data, byte* output)
 7530{
 7531    WOLFSSL* ssl = (WOLFSSL*)data;
 7532    WOLF_STACK_OF(WOLFSSL_X509_NAME)* names;
 7533    byte* len;
 7534
 7535    /* Reserve space for the length value */
 7536    len = output;
 7537    output += OPAQUE16_LEN;
 7538    for (names = SSL_PRIORITY_CA_NAMES(ssl); names != NULL; names = names->next) {
 7539        byte seq[MAX_SEQ_SZ];
 7540        WOLFSSL_X509_NAME* name = names->data.name;
 7541
 7542        if (name != NULL) {
 7543            c16toa((word16)name->rawLen +
 7544                   (word16)SetSequence(name->rawLen, seq), output);
 7545            output += OPAQUE16_LEN;
 7546            output += SetSequence(name->rawLen, output);
 7547            XMEMCPY(output, name->raw, name->rawLen);
 7548            output += name->rawLen;
 7549        }
 7550    }
 7551    /* Write the total length */
 7552    c16toa((word16)(output - len - OPAQUE16_LEN), len);
 7553    return (word16)(output - len);
 7554}
 7555
 7556static int TLSX_CA_Names_Parse(WOLFSSL *ssl, const byte* input,
 7557                                  word16 length, byte isRequest)
 7558{
 7559    word16 extLen;
 7560
 7561    (void)isRequest;
 7562
 7563    wolfSSL_sk_X509_NAME_pop_free(ssl->peer_ca_names, NULL);
 7564    ssl->peer_ca_names = wolfSSL_sk_X509_NAME_new(NULL);
 7565    if (ssl->peer_ca_names == NULL)
 7566        return MEMORY_ERROR;
 7567
 7568    if (length < OPAQUE16_LEN)
 7569        return BUFFER_ERROR;
 7570
 7571    ato16(input, &extLen);
 7572    input += OPAQUE16_LEN;
 7573    length -= OPAQUE16_LEN;
 7574    if (extLen != length)
 7575        return BUFFER_ERROR;
 7576
 7577    while (length) {
 7578        word16 idx = 0;
 7579        WOLFSSL_X509_NAME* name = NULL;
 7580        int ret = 0;
 7581        int didInit = FALSE;
 7582        /* Use a DecodedCert struct to get access to GetName to
 7583         * parse DN name */
 7584#ifdef WOLFSSL_SMALL_STACK
 7585        DecodedCert *cert = (DecodedCert *)XMALLOC(
 7586            sizeof(*cert), ssl->heap, DYNAMIC_TYPE_DCERT);
 7587        if (cert == NULL)
 7588            return MEMORY_ERROR;
 7589#else
 7590        DecodedCert cert[1];
 7591#endif
 7592
 7593        if (length < OPAQUE16_LEN) {
 7594            ret = BUFFER_ERROR;
 7595        }
 7596
 7597        if (ret == 0) {
 7598            ato16(input, &extLen);
 7599            idx += OPAQUE16_LEN;
 7600
 7601            if (extLen > length - idx)
 7602                ret = BUFFER_ERROR;
 7603        }
 7604
 7605        if (ret == 0) {
 7606            InitDecodedCert(cert, input + idx, extLen, ssl->heap);
 7607            didInit = TRUE;
 7608            idx += extLen;
 7609            ret = GetName(cert, ASN_SUBJECT, extLen);
 7610        }
 7611
 7612        if (ret == 0 && (name = wolfSSL_X509_NAME_new()) == NULL)
 7613            ret = MEMORY_ERROR;
 7614
 7615        if (ret == 0) {
 7616            CopyDecodedName(name, cert, ASN_SUBJECT);
 7617            if (wolfSSL_sk_X509_NAME_push(ssl->peer_ca_names, name) <= 0) {
 7618                wolfSSL_X509_NAME_free(name);
 7619                ret = MEMORY_ERROR;
 7620            }
 7621        }
 7622
 7623        if (didInit)
 7624            FreeDecodedCert(cert);
 7625
 7626        WC_FREE_VAR_EX(cert, ssl->heap, DYNAMIC_TYPE_DCERT);
 7627        if (ret != 0)
 7628            return ret;
 7629
 7630        input += idx;
 7631        length -= idx;
 7632    }
 7633    return 0;
 7634}
 7635
 7636#define CAN_GET_SIZE(data)      TLSX_CA_Names_GetSize(data)
 7637#define CAN_WRITE(data, output) TLSX_CA_Names_Write(data, output)
 7638#define CAN_PARSE(ssl, input, length, isRequest) \
 7639                                TLSX_CA_Names_Parse(ssl, input, length, isRequest)
 7640
 7641#else
 7642
 7643#define CAN_GET_SIZE(data)                       0
 7644#define CAN_WRITE(data, output)                  0
 7645#define CAN_PARSE(ssl, input, length, isRequest) 0
 7646
 7647#endif
 7648
 7649#if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
 7650/******************************************************************************/
 7651/* Signature Algorithms                                                       */
 7652/******************************************************************************/
 7653
 7654/* Return the size of the SignatureAlgorithms extension's data.
 7655 *
 7656 * data  Unused
 7657 * returns the length of data that will be in the extension.
 7658 */
 7659
 7660static word16 TLSX_SignatureAlgorithms_GetSize(void* data)
 7661{
 7662    SignatureAlgorithms* sa = (SignatureAlgorithms*)data;
 7663
 7664    if (sa->hashSigAlgoSz == 0)
 7665        return OPAQUE16_LEN + WOLFSSL_SUITES(sa->ssl)->hashSigAlgoSz;
 7666    else
 7667        return OPAQUE16_LEN + sa->hashSigAlgoSz;
 7668}
 7669
 7670/* Creates a bit string of supported hash algorithms with RSA PSS.
 7671 * The bit string is used when determining which signature algorithm to use
 7672 * when creating the CertificateVerify message.
 7673 * Note: Valid data has an even length as each signature algorithm is two bytes.
 7674 *
 7675 * ssl     The SSL/TLS object.
 7676 * input   The buffer with the list of supported signature algorithms.
 7677 * length  The length of the list in bytes.
 7678 * returns 0 on success, BUFFER_ERROR when the length is not even.
 7679 */
 7680static int TLSX_SignatureAlgorithms_MapPss(WOLFSSL *ssl, const byte* input,
 7681                                           word16 length)
 7682{
 7683    word16 i;
 7684
 7685    if ((length & 1) == 1)
 7686        return BUFFER_ERROR;
 7687
 7688    ssl->pssAlgo = 0;
 7689    for (i = 0; i < length; i += 2) {
 7690        if (input[i] == rsa_pss_sa_algo && input[i + 1] <= sha512_mac)
 7691            ssl->pssAlgo |= 1 << input[i + 1];
 7692    #ifdef WOLFSSL_TLS13
 7693        if (input[i] == rsa_pss_sa_algo && input[i + 1] >= pss_sha256 &&
 7694                                                   input[i + 1] <= pss_sha512) {
 7695            ssl->pssAlgo |= 1 << input[i + 1];
 7696        }
 7697    #endif
 7698    }
 7699
 7700    return 0;
 7701}
 7702
 7703/* Writes the SignatureAlgorithms extension into the buffer.
 7704 *
 7705 * data    Unused
 7706 * output  The buffer to write the extension into.
 7707 * returns the length of data that was written.
 7708 */
 7709static word16 TLSX_SignatureAlgorithms_Write(void* data, byte* output)
 7710{
 7711    SignatureAlgorithms* sa = (SignatureAlgorithms*)data;
 7712    const Suites* suites = WOLFSSL_SUITES(sa->ssl);
 7713    word16 hashSigAlgoSz;
 7714
 7715    if (sa->hashSigAlgoSz == 0) {
 7716        c16toa(suites->hashSigAlgoSz, output);
 7717        XMEMCPY(output + OPAQUE16_LEN, suites->hashSigAlgo,
 7718                suites->hashSigAlgoSz);
 7719        hashSigAlgoSz = suites->hashSigAlgoSz;
 7720    }
 7721    else {
 7722        c16toa(sa->hashSigAlgoSz, output);
 7723        XMEMCPY(output + OPAQUE16_LEN, sa->hashSigAlgo,
 7724                sa->hashSigAlgoSz);
 7725        hashSigAlgoSz = sa->hashSigAlgoSz;
 7726    }
 7727
 7728#ifndef NO_RSA
 7729    TLSX_SignatureAlgorithms_MapPss(sa->ssl, output + OPAQUE16_LEN,
 7730            hashSigAlgoSz);
 7731#endif
 7732
 7733    return OPAQUE16_LEN + hashSigAlgoSz;
 7734}
 7735
 7736/* Parse the SignatureAlgorithms extension.
 7737 *
 7738 * ssl     The SSL/TLS object.
 7739 * input   The buffer with the extension data.
 7740 * length  The length of the extension data.
 7741 * returns 0 on success, otherwise failure.
 7742 */
 7743static int TLSX_SignatureAlgorithms_Parse(WOLFSSL *ssl, const byte* input,
 7744                                  word16 length, byte isRequest, Suites* suites)
 7745{
 7746    word16 len;
 7747
 7748    if (!isRequest)
 7749        return BUFFER_ERROR;
 7750
 7751    /* Must contain a length and at least algorithm. */
 7752    if (length < OPAQUE16_LEN + OPAQUE16_LEN || (length & 1) != 0)
 7753        return BUFFER_ERROR;
 7754
 7755    ato16(input, &len);
 7756    input += OPAQUE16_LEN;
 7757
 7758    /* Algorithm array must fill rest of data. */
 7759    if (length != OPAQUE16_LEN + len)
 7760        return BUFFER_ERROR;
 7761
 7762    /* Truncate hashSigAlgo list if too long. */
 7763    suites->hashSigAlgoSz = len;
 7764    /* Sig Algo list size must be even. */
 7765    if (suites->hashSigAlgoSz % 2 != 0)
 7766        return BUFFER_ERROR;
 7767    if (suites->hashSigAlgoSz > WOLFSSL_MAX_SIGALGO) {
 7768        WOLFSSL_MSG("TLSX SigAlgo list exceeds max, truncating");
 7769        suites->hashSigAlgoSz = WOLFSSL_MAX_SIGALGO;
 7770    }
 7771    XMEMCPY(suites->hashSigAlgo, input, suites->hashSigAlgoSz);
 7772
 7773    return TLSX_SignatureAlgorithms_MapPss(ssl, input, suites->hashSigAlgoSz);
 7774}
 7775
 7776/* Sets a new SignatureAlgorithms extension into the extension list.
 7777 *
 7778 * extensions  The list of extensions.
 7779 * data        The extensions specific data.
 7780 * heap        The heap used for allocation.
 7781 * returns 0 on success, otherwise failure.
 7782 */
 7783static int TLSX_SetSignatureAlgorithms(TLSX** extensions, WOLFSSL* ssl,
 7784                                       void* heap)
 7785{
 7786    SignatureAlgorithms* sa;
 7787    int ret;
 7788
 7789    if (extensions == NULL)
 7790        return BAD_FUNC_ARG;
 7791
 7792    /* Already present */
 7793    if (TLSX_Find(*extensions, TLSX_SIGNATURE_ALGORITHMS) != NULL)
 7794        return 0;
 7795
 7796    sa = TLSX_SignatureAlgorithms_New(ssl, 0, heap);
 7797    if (sa == NULL)
 7798        return MEMORY_ERROR;
 7799
 7800    ret = TLSX_Push(extensions, TLSX_SIGNATURE_ALGORITHMS, sa, heap);
 7801    if (ret != 0)
 7802        TLSX_SignatureAlgorithms_FreeAll(sa, heap);
 7803    return ret;
 7804}
 7805
 7806SignatureAlgorithms* TLSX_SignatureAlgorithms_New(WOLFSSL* ssl,
 7807        word16 hashSigAlgoSz, void* heap)
 7808{
 7809    SignatureAlgorithms* sa;
 7810    (void)heap;
 7811
 7812    sa = (SignatureAlgorithms*)XMALLOC(sizeof(*sa) + hashSigAlgoSz, heap,
 7813                                       DYNAMIC_TYPE_TLSX);
 7814    if (sa != NULL) {
 7815        XMEMSET(sa, 0, sizeof(*sa) + hashSigAlgoSz);
 7816        sa->ssl = ssl;
 7817        sa->hashSigAlgoSz = hashSigAlgoSz;
 7818    }
 7819    return sa;
 7820}
 7821
 7822void TLSX_SignatureAlgorithms_FreeAll(SignatureAlgorithms* sa,
 7823                                             void* heap)
 7824{
 7825    XFREE(sa, heap, DYNAMIC_TYPE_TLSX);
 7826    (void)heap;
 7827}
 7828
 7829#define SA_GET_SIZE  TLSX_SignatureAlgorithms_GetSize
 7830#define SA_WRITE     TLSX_SignatureAlgorithms_Write
 7831#define SA_PARSE     TLSX_SignatureAlgorithms_Parse
 7832#define SA_FREE_ALL  TLSX_SignatureAlgorithms_FreeAll
 7833#endif
 7834/******************************************************************************/
 7835/* Signature Algorithms Certificate                                           */
 7836/******************************************************************************/
 7837
 7838#if defined(WOLFSSL_TLS13) && !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
 7839/* Return the size of the SignatureAlgorithms extension's data.
 7840 *
 7841 * data  Unused
 7842 * returns the length of data that will be in the extension.
 7843 */
 7844static word16 TLSX_SignatureAlgorithmsCert_GetSize(void* data)
 7845{
 7846    WOLFSSL* ssl = (WOLFSSL*)data;
 7847
 7848    return OPAQUE16_LEN + ssl->certHashSigAlgoSz;
 7849}
 7850
 7851/* Writes the SignatureAlgorithmsCert extension into the buffer.
 7852 *
 7853 * data    Unused
 7854 * output  The buffer to write the extension into.
 7855 * returns the length of data that was written.
 7856 */
 7857static word16 TLSX_SignatureAlgorithmsCert_Write(void* data, byte* output)
 7858{
 7859    WOLFSSL* ssl = (WOLFSSL*)data;
 7860
 7861    c16toa(ssl->certHashSigAlgoSz, output);
 7862    XMEMCPY(output + OPAQUE16_LEN, ssl->certHashSigAlgo,
 7863            ssl->certHashSigAlgoSz);
 7864
 7865    return OPAQUE16_LEN + ssl->certHashSigAlgoSz;
 7866}
 7867
 7868/* Parse the SignatureAlgorithmsCert extension.
 7869 *
 7870 * ssl     The SSL/TLS object.
 7871 * input   The buffer with the extension data.
 7872 * length  The length of the extension data.
 7873 * returns 0 on success, otherwise failure.
 7874 */
 7875static int TLSX_SignatureAlgorithmsCert_Parse(WOLFSSL *ssl, const byte* input,
 7876                                              word16 length, byte isRequest)
 7877{
 7878    word16 len;
 7879
 7880    if (!isRequest)
 7881        return BUFFER_ERROR;
 7882
 7883    /* Must contain a length and at least algorithm. */
 7884    if (length < OPAQUE16_LEN + OPAQUE16_LEN || (length & 1) != 0)
 7885        return BUFFER_ERROR;
 7886
 7887    ato16(input, &len);
 7888    input += OPAQUE16_LEN;
 7889
 7890    /* Algorithm array must fill rest of data. */
 7891    if (length != OPAQUE16_LEN + len)
 7892        return BUFFER_ERROR;
 7893
 7894    /* truncate hashSigAlgo list if too long */
 7895    ssl->certHashSigAlgoSz = len;
 7896    if (ssl->certHashSigAlgoSz > WOLFSSL_MAX_SIGALGO) {
 7897        WOLFSSL_MSG("TLSX SigAlgo list exceeds max, truncating");
 7898        ssl->certHashSigAlgoSz = WOLFSSL_MAX_SIGALGO;
 7899    }
 7900    XMEMCPY(ssl->certHashSigAlgo, input, ssl->certHashSigAlgoSz);
 7901
 7902    return 0;
 7903}
 7904
 7905/* Sets a new SignatureAlgorithmsCert extension into the extension list.
 7906 *
 7907 * extensions  The list of extensions.
 7908 * data        The extensions specific data.
 7909 * heap        The heap used for allocation.
 7910 * returns 0 on success, otherwise failure.
 7911 */
 7912static int TLSX_SetSignatureAlgorithmsCert(TLSX** extensions,
 7913        const WOLFSSL* data, void* heap)
 7914{
 7915    if (extensions == NULL)
 7916        return BAD_FUNC_ARG;
 7917
 7918    return TLSX_Push(extensions, TLSX_SIGNATURE_ALGORITHMS_CERT, data, heap);
 7919}
 7920
 7921#define SAC_GET_SIZE  TLSX_SignatureAlgorithmsCert_GetSize
 7922#define SAC_WRITE     TLSX_SignatureAlgorithmsCert_Write
 7923#define SAC_PARSE     TLSX_SignatureAlgorithmsCert_Parse
 7924#endif /* WOLFSSL_TLS13 */
 7925
 7926
 7927/******************************************************************************/
 7928/* Key Share                                                                  */
 7929/******************************************************************************/
 7930
 7931#ifndef MAX_KEYSHARE_NAMED_GROUPS
 7932    #if defined(WOLFSSL_HAVE_MLKEM) && !defined(WOLFSSL_MLKEM_NO_MAKE_KEY)
 7933        #define MAX_KEYSHARE_NAMED_GROUPS    24
 7934    #else
 7935        #define MAX_KEYSHARE_NAMED_GROUPS    12
 7936    #endif
 7937#endif
 7938
 7939#if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES)
 7940/* Create a key share entry using named Diffie-Hellman parameters group.
 7941 * Generates a key pair.
 7942 *
 7943 * ssl   The SSL/TLS object.
 7944 * kse   The key share entry object.
 7945 * returns 0 on success, otherwise failure.
 7946 */
 7947static int TLSX_KeyShare_GenDhKey(WOLFSSL *ssl, KeyShareEntry* kse)
 7948{
 7949    int ret = 0;
 7950#if !defined(NO_DH) && (!defined(NO_CERTS) || !defined(NO_PSK))
 7951    word32 pSz = 0, pvtSz = 0;
 7952    DhKey* dhKey = (DhKey*)kse->key;
 7953
 7954    /* Pick the parameters from the named group. */
 7955#ifdef HAVE_PUBLIC_FFDHE
 7956    const DhParams* params = NULL;
 7957    switch (kse->group) {
 7958    #ifdef HAVE_FFDHE_2048
 7959        case WOLFSSL_FFDHE_2048:
 7960            params = wc_Dh_ffdhe2048_Get();
 7961            pvtSz = 29;
 7962            break;
 7963    #endif
 7964    #ifdef HAVE_FFDHE_3072
 7965        case WOLFSSL_FFDHE_3072:
 7966            params = wc_Dh_ffdhe3072_Get();
 7967            pvtSz = 34;
 7968            break;
 7969    #endif
 7970    #ifdef HAVE_FFDHE_4096
 7971        case WOLFSSL_FFDHE_4096:
 7972            params = wc_Dh_ffdhe4096_Get();
 7973            pvtSz = 39;
 7974            break;
 7975    #endif
 7976    #ifdef HAVE_FFDHE_6144
 7977        case WOLFSSL_FFDHE_6144:
 7978            params = wc_Dh_ffdhe6144_Get();
 7979            pvtSz = 46;
 7980            break;
 7981    #endif
 7982    #ifdef HAVE_FFDHE_8192
 7983        case WOLFSSL_FFDHE_8192:
 7984            params = wc_Dh_ffdhe8192_Get();
 7985            pvtSz = 52;
 7986            break;
 7987    #endif
 7988        default:
 7989            break;
 7990    }
 7991    if (params == NULL)
 7992        return BAD_FUNC_ARG;
 7993    pSz = params->p_len;
 7994#else
 7995    pvtSz = wc_DhGetNamedKeyMinSize(kse->group);
 7996    if (pvtSz == 0) {
 7997        return BAD_FUNC_ARG;
 7998    }
 7999    ret = wc_DhGetNamedKeyParamSize(kse->group, &pSz, NULL, NULL);
 8000    if (ret != 0) {
 8001        return BAD_FUNC_ARG;
 8002    }
 8003#endif
 8004
 8005    /* Trigger Key Generation */
 8006    if (kse->pubKey == NULL || kse->privKey == NULL) {
 8007        if (kse->key == NULL) {
 8008            kse->key = (DhKey*)XMALLOC(sizeof(DhKey), ssl->heap,
 8009                DYNAMIC_TYPE_DH);
 8010            if (kse->key == NULL)
 8011                return MEMORY_E;
 8012
 8013            /* Setup Key */
 8014            ret = wc_InitDhKey_ex((DhKey*)kse->key, ssl->heap, ssl->devId);
 8015            if (ret == 0) {
 8016                dhKey = (DhKey*)kse->key;
 8017            #ifdef HAVE_PUBLIC_FFDHE
 8018                ret = wc_DhSetKey(dhKey, params->p, params->p_len, params->g,
 8019                                                                 params->g_len);
 8020            #else
 8021                ret = wc_DhSetNamedKey(dhKey, kse->group);
 8022            #endif
 8023            }
 8024        #if defined(WC_DH_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW) && \
 8025            defined(WC_ASYNC_ENABLE_DH)
 8026            /* Only set non-blocking context when async device is active. With
 8027             * INVALID_DEVID there is no async loop to retry on MP_WOULDBLOCK, so
 8028             * skip non-blocking setup and use blocking mode instead. */
 8029            if (ret == 0 && ssl->devId != INVALID_DEVID) {
 8030                DhNb* dhNb = (DhNb*)XMALLOC(sizeof(DhNb), ssl->heap,
 8031                                            DYNAMIC_TYPE_TMP_BUFFER);
 8032                if (dhNb == NULL) {
 8033                    ret = MEMORY_E;
 8034                }
 8035                else {
 8036                    ret = wc_DhSetNonBlock((DhKey*)kse->key, dhNb);
 8037                    if (ret != 0) {
 8038                        XFREE(dhNb, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8039                    }
 8040                }
 8041            }
 8042        #endif /* WC_DH_NONBLOCK && WOLFSSL_ASYNC_CRYPT_SW &&
 8043                  WC_ASYNC_ENABLE_DH */
 8044        }
 8045
 8046        /* Allocate space for the private and public key */
 8047        if (ret == 0 && kse->pubKey == NULL) {
 8048            kse->pubKey = (byte*)XMALLOC(pSz, ssl->heap,
 8049                DYNAMIC_TYPE_PUBLIC_KEY);
 8050            if (kse->pubKey == NULL)
 8051                ret = MEMORY_E;
 8052        }
 8053
 8054        if (ret == 0 && kse->privKey == NULL) {
 8055            kse->privKey = (byte*)XMALLOC(pvtSz, ssl->heap,
 8056                DYNAMIC_TYPE_PRIVATE_KEY);
 8057            if (kse->privKey == NULL)
 8058                ret = MEMORY_E;
 8059        }
 8060
 8061        if (ret == 0) {
 8062        #if defined(WOLFSSL_STATIC_EPHEMERAL) && defined(WOLFSSL_DH_EXTRA)
 8063            ret = wolfSSL_StaticEphemeralKeyLoad(ssl, WC_PK_TYPE_DH, kse->key);
 8064            kse->pubKeyLen = pSz;
 8065            kse->keyLen = pvtSz;
 8066            if (ret == 0) {
 8067                ret = wc_DhExportKeyPair(dhKey,
 8068                    (byte*)kse->privKey, &kse->keyLen, /* private */
 8069                    kse->pubKey, &kse->pubKeyLen /* public */
 8070                );
 8071            }
 8072            else
 8073        #endif
 8074            {
 8075                /* Generate a new key pair */
 8076                /* For async this is called once and when event is done, the
 8077                 *   provided buffers will be populated.
 8078                 * Final processing is zero pad below. */
 8079                kse->pubKeyLen = pSz;
 8080                kse->keyLen = pvtSz;
 8081                ret = DhGenKeyPair(ssl, dhKey,
 8082                    (byte*)kse->privKey, &kse->keyLen, /* private */
 8083                    kse->pubKey, &kse->pubKeyLen /* public */
 8084                );
 8085            #ifdef WOLFSSL_ASYNC_CRYPT
 8086                if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
 8087                    return ret;
 8088                }
 8089            #endif
 8090            }
 8091        }
 8092    }
 8093
 8094    if (ret == 0) {
 8095        if (pSz != kse->pubKeyLen) {
 8096            /* Zero pad the front of the public key to match prime "p" size */
 8097            XMEMMOVE(kse->pubKey + pSz - kse->pubKeyLen, kse->pubKey,
 8098                kse->pubKeyLen);
 8099            XMEMSET(kse->pubKey, 0, pSz - kse->pubKeyLen);
 8100            kse->pubKeyLen = pSz;
 8101        }
 8102
 8103        if (pvtSz != kse->keyLen) {
 8104            /* Zero pad the front of the private key */
 8105            XMEMMOVE(kse->privKey + pvtSz - kse->keyLen, kse->privKey,
 8106                kse->keyLen);
 8107            XMEMSET(kse->privKey, 0, pvtSz - kse->keyLen);
 8108            kse->keyLen = pvtSz;
 8109        }
 8110
 8111    #ifdef WOLFSSL_DEBUG_TLS
 8112        WOLFSSL_MSG("Public DH Key");
 8113        WOLFSSL_BUFFER(kse->pubKey, kse->pubKeyLen);
 8114    #endif
 8115    }
 8116
 8117    /* Always release the DH key to free up memory.
 8118     * The DhKey will be setup again in TLSX_KeyShare_ProcessDh */
 8119    if (dhKey != NULL) {
 8120    #if defined(WC_DH_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW) && \
 8121        defined(WC_ASYNC_ENABLE_DH)
 8122        if (dhKey->nb != NULL) {
 8123            XFREE(dhKey->nb, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8124            dhKey->nb = NULL;
 8125        }
 8126    #endif
 8127        wc_FreeDhKey(dhKey);
 8128    }
 8129    XFREE(kse->key, ssl->heap, DYNAMIC_TYPE_DH);
 8130    kse->key = NULL;
 8131
 8132    if (ret != 0) {
 8133        /* Cleanup on error, otherwise data owned by key share entry */
 8134        if (kse->privKey) {
 8135            ForceZero(kse->privKey, pvtSz);
 8136            XFREE(kse->privKey, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
 8137            kse->privKey = NULL;
 8138        }
 8139        XFREE(kse->pubKey, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
 8140        kse->pubKey = NULL;
 8141    }
 8142#else
 8143    (void)ssl;
 8144    (void)kse;
 8145
 8146    ret = NOT_COMPILED_IN;
 8147    WOLFSSL_ERROR_VERBOSE(ret);
 8148#endif
 8149
 8150    return ret;
 8151}
 8152
 8153/* Create a key share entry using X25519 parameters group.
 8154 * Generates a key pair.
 8155 *
 8156 * ssl   The SSL/TLS object.
 8157 * kse   The key share entry object.
 8158 * returns 0 on success, otherwise failure.
 8159 */
 8160static int TLSX_KeyShare_GenX25519Key(WOLFSSL *ssl, KeyShareEntry* kse)
 8161{
 8162    int ret = 0;
 8163#ifdef HAVE_CURVE25519
 8164    curve25519_key* key = (curve25519_key*)kse->key;
 8165
 8166    if (kse->key == NULL) {
 8167        /* Allocate a Curve25519 key to hold private key. */
 8168        kse->key = (curve25519_key*)XMALLOC(sizeof(curve25519_key), ssl->heap,
 8169                                                      DYNAMIC_TYPE_PRIVATE_KEY);
 8170        if (kse->key == NULL) {
 8171            WOLFSSL_MSG("GenX25519Key memory error");
 8172            return MEMORY_E;
 8173        }
 8174
 8175        /* Make an Curve25519 key. */
 8176        ret = wc_curve25519_init_ex((curve25519_key*)kse->key, ssl->heap,
 8177            ssl->devId);
 8178        if (ret == 0) {
 8179            /* setting "key" means okay to call wc_curve25519_free */
 8180            key = (curve25519_key*)kse->key;
 8181            kse->keyLen = CURVE25519_KEYSIZE;
 8182        }
 8183    #if defined(WC_X25519_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW) && \
 8184        defined(WC_ASYNC_ENABLE_X25519)
 8185        /* Only set non-blocking context when async device is active. With
 8186         * INVALID_DEVID there is no async loop to retry on FP_WOULDBLOCK, so
 8187         * skip non-blocking setup and use blocking mode instead. */
 8188        if (ret == 0 && ssl->devId != INVALID_DEVID) {
 8189            x25519_nb_ctx_t* nb_ctx = (x25519_nb_ctx_t*)XMALLOC(
 8190                sizeof(x25519_nb_ctx_t), ssl->heap,
 8191                DYNAMIC_TYPE_TMP_BUFFER);
 8192            if (nb_ctx == NULL) {
 8193                ret = MEMORY_E;
 8194            }
 8195            else {
 8196                ret = wc_curve25519_set_nonblock(key, nb_ctx);
 8197                if (ret != 0) {
 8198                    XFREE(nb_ctx, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8199                }
 8200            }
 8201        }
 8202    #endif /* WC_X25519_NONBLOCK && WOLFSSL_ASYNC_CRYPT_SW &&
 8203              WC_ASYNC_ENABLE_X25519 */
 8204        if (ret == 0) {
 8205        #ifdef WOLFSSL_STATIC_EPHEMERAL
 8206            ret = wolfSSL_StaticEphemeralKeyLoad(ssl, WC_PK_TYPE_CURVE25519, kse->key);
 8207            if (ret != 0) /* on failure, fallback to local key generation */
 8208        #endif
 8209            {
 8210            #ifdef WOLFSSL_ASYNC_CRYPT
 8211                /* initialize event */
 8212                ret = wolfSSL_AsyncInit(ssl, &key->asyncDev,
 8213                    WC_ASYNC_FLAG_NONE);
 8214                if (ret != 0)
 8215                    return ret;
 8216            #endif
 8217                ret = wc_curve25519_make_key(ssl->rng, CURVE25519_KEYSIZE, key);
 8218
 8219                /* Handle async pending response */
 8220            #ifdef WOLFSSL_ASYNC_CRYPT
 8221                if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
 8222                    return wolfSSL_AsyncPush(ssl, &key->asyncDev);
 8223                }
 8224            #endif /* WOLFSSL_ASYNC_CRYPT */
 8225            }
 8226        }
 8227    }
 8228
 8229    if (ret == 0 && kse->pubKey == NULL) {
 8230        /* Allocate space for the public key. */
 8231        kse->pubKey = (byte*)XMALLOC(CURVE25519_KEYSIZE, ssl->heap,
 8232                                                       DYNAMIC_TYPE_PUBLIC_KEY);
 8233        if (kse->pubKey == NULL) {
 8234            WOLFSSL_MSG("GenX25519Key pub memory error");
 8235            ret = MEMORY_E;
 8236        }
 8237    }
 8238
 8239    if (ret == 0) {
 8240        /* Export Curve25519 public key. */
 8241        kse->pubKeyLen = CURVE25519_KEYSIZE;
 8242        if (wc_curve25519_export_public_ex(key, kse->pubKey, &kse->pubKeyLen,
 8243                                                  EC25519_LITTLE_ENDIAN) != 0) {
 8244            ret = ECC_EXPORT_ERROR;
 8245            WOLFSSL_ERROR_VERBOSE(ret);
 8246        }
 8247        kse->pubKeyLen = CURVE25519_KEYSIZE; /* always CURVE25519_KEYSIZE */
 8248    }
 8249
 8250#ifdef WOLFSSL_DEBUG_TLS
 8251    if (ret == 0) {
 8252        WOLFSSL_MSG("Public Curve25519 Key");
 8253        WOLFSSL_BUFFER(kse->pubKey, kse->pubKeyLen);
 8254    }
 8255#endif
 8256
 8257    if (ret != 0) {
 8258        /* Data owned by key share entry otherwise. */
 8259        XFREE(kse->pubKey, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
 8260        kse->pubKey = NULL;
 8261        if (key != NULL) {
 8262        #if defined(WC_X25519_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW)
 8263            if (key->nb_ctx != NULL) {
 8264                XFREE(key->nb_ctx, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8265            }
 8266        #endif
 8267            wc_curve25519_free(key);
 8268        }
 8269        XFREE(kse->key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
 8270        kse->key = NULL;
 8271    }
 8272#else
 8273    (void)ssl;
 8274    (void)kse;
 8275
 8276    ret = NOT_COMPILED_IN;
 8277    WOLFSSL_ERROR_VERBOSE(ret);
 8278#endif /* HAVE_CURVE25519 */
 8279
 8280    return ret;
 8281}
 8282
 8283/* Create a key share entry using X448 parameters group.
 8284 * Generates a key pair.
 8285 *
 8286 * ssl   The SSL/TLS object.
 8287 * kse   The key share entry object.
 8288 * returns 0 on success, otherwise failure.
 8289 */
 8290static int TLSX_KeyShare_GenX448Key(WOLFSSL *ssl, KeyShareEntry* kse)
 8291{
 8292    int ret = 0;
 8293#ifdef HAVE_CURVE448
 8294    curve448_key* key = (curve448_key*)kse->key;
 8295
 8296    if (kse->key == NULL) {
 8297        /* Allocate a Curve448 key to hold private key. */
 8298        kse->key = (curve448_key*)XMALLOC(sizeof(curve448_key), ssl->heap,
 8299                                                      DYNAMIC_TYPE_PRIVATE_KEY);
 8300        if (kse->key == NULL) {
 8301            WOLFSSL_MSG("GenX448Key memory error");
 8302            return MEMORY_E;
 8303        }
 8304
 8305        /* Make an Curve448 key. */
 8306        ret = wc_curve448_init((curve448_key*)kse->key);
 8307        if (ret == 0) {
 8308            key = (curve448_key*)kse->key;
 8309            kse->keyLen = CURVE448_KEY_SIZE;
 8310
 8311            #ifdef WOLFSSL_STATIC_EPHEMERAL
 8312            ret = wolfSSL_StaticEphemeralKeyLoad(ssl, WC_PK_TYPE_CURVE448, kse->key);
 8313            if (ret != 0)
 8314        #endif
 8315            {
 8316                ret = wc_curve448_make_key(ssl->rng, CURVE448_KEY_SIZE, key);
 8317            }
 8318        }
 8319    }
 8320
 8321    if (ret == 0 && kse->pubKey == NULL) {
 8322        /* Allocate space for the public key. */
 8323        kse->pubKey = (byte*)XMALLOC(CURVE448_KEY_SIZE, ssl->heap,
 8324                                                       DYNAMIC_TYPE_PUBLIC_KEY);
 8325        if (kse->pubKey == NULL) {
 8326            WOLFSSL_MSG("GenX448Key pub memory error");
 8327            ret = MEMORY_E;
 8328        }
 8329    }
 8330
 8331    if (ret == 0) {
 8332        /* Export Curve448 public key. */
 8333        kse->pubKeyLen = CURVE448_KEY_SIZE;
 8334        if (wc_curve448_export_public_ex(key, kse->pubKey, &kse->pubKeyLen,
 8335                                                    EC448_LITTLE_ENDIAN) != 0) {
 8336            ret = ECC_EXPORT_ERROR;
 8337        }
 8338        kse->pubKeyLen = CURVE448_KEY_SIZE; /* always CURVE448_KEY_SIZE */
 8339    }
 8340
 8341#ifdef WOLFSSL_DEBUG_TLS
 8342    if (ret == 0) {
 8343        WOLFSSL_MSG("Public Curve448 Key");
 8344        WOLFSSL_BUFFER(kse->pubKey, kse->pubKeyLen);
 8345    }
 8346#endif
 8347
 8348    if (ret != 0) {
 8349        /* Data owned by key share entry otherwise. */
 8350        XFREE(kse->pubKey, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
 8351        kse->pubKey = NULL;
 8352        if (key != NULL)
 8353            wc_curve448_free(key);
 8354        XFREE(kse->key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
 8355        kse->key = NULL;
 8356    }
 8357#else
 8358    (void)ssl;
 8359    (void)kse;
 8360
 8361    ret = NOT_COMPILED_IN;
 8362    WOLFSSL_ERROR_VERBOSE(ret);
 8363#endif /* HAVE_CURVE448 */
 8364
 8365    return ret;
 8366}
 8367
 8368/* Create a key share entry using named elliptic curve parameters group.
 8369 * Generates a key pair.
 8370 *
 8371 * ssl   The SSL/TLS object.
 8372 * kse   The key share entry object.
 8373 * returns 0 on success, otherwise failure.
 8374 */
 8375static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse)
 8376{
 8377    int ret = 0;
 8378#if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT)
 8379    word32 keySize = 0;
 8380    word16 curveId = (word16) ECC_CURVE_INVALID;
 8381    ecc_key* eccKey = (ecc_key*)kse->key;
 8382
 8383    /* Translate named group to a curve id. */
 8384    switch (kse->group) {
 8385    #if (!defined(NO_ECC256)  || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 256
 8386        #ifndef NO_ECC_SECP
 8387        case WOLFSSL_ECC_SECP256R1:
 8388            curveId = ECC_SECP256R1;
 8389            break;
 8390        #endif /* !NO_ECC_SECP */
 8391        #ifdef WOLFSSL_SM2
 8392        case WOLFSSL_ECC_SM2P256V1:
 8393            curveId = ECC_SM2P256V1;
 8394            break;
 8395        #endif /* !WOLFSSL_SM2 */
 8396        #ifdef HAVE_ECC_BRAINPOOL
 8397        case WOLFSSL_ECC_BRAINPOOLP256R1TLS13:
 8398            curveId = ECC_BRAINPOOLP256R1;
 8399            break;
 8400        #endif /* HAVE_ECC_BRAINPOOL */
 8401    #endif
 8402    #if (defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 384
 8403        #ifndef NO_ECC_SECP
 8404        case WOLFSSL_ECC_SECP384R1:
 8405            curveId = ECC_SECP384R1;
 8406            break;
 8407        #endif /* !NO_ECC_SECP */
 8408        #ifdef HAVE_ECC_BRAINPOOL
 8409        case WOLFSSL_ECC_BRAINPOOLP384R1TLS13:
 8410            curveId = ECC_BRAINPOOLP384R1;
 8411            break;
 8412        #endif /* HAVE_ECC_BRAINPOOL */
 8413    #endif
 8414    #if (defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 512
 8415        #ifdef HAVE_ECC_BRAINPOOL
 8416        case WOLFSSL_ECC_BRAINPOOLP512R1TLS13:
 8417            curveId = ECC_BRAINPOOLP512R1;
 8418            break;
 8419        #endif /* HAVE_ECC_BRAINPOOL */
 8420    #endif
 8421    #if (defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 521
 8422        #ifndef NO_ECC_SECP
 8423        case WOLFSSL_ECC_SECP521R1:
 8424            curveId = ECC_SECP521R1;
 8425            break;
 8426        #endif /* !NO_ECC_SECP */
 8427    #endif
 8428        default:
 8429            WOLFSSL_ERROR_VERBOSE(BAD_FUNC_ARG);
 8430            return BAD_FUNC_ARG;
 8431    }
 8432
 8433    {
 8434        int size = wc_ecc_get_curve_size_from_id(curveId);
 8435        if (size < 0) {
 8436            WOLFSSL_ERROR_VERBOSE(size);
 8437            return size;
 8438        }
 8439        keySize = (word32)size;
 8440    }
 8441
 8442    if (kse->key == NULL) {
 8443        /* Allocate an ECC key to hold private key. */
 8444        kse->key = (byte*)XMALLOC(sizeof(ecc_key), ssl->heap, DYNAMIC_TYPE_ECC);
 8445        if (kse->key == NULL) {
 8446            WOLFSSL_MSG_EX("Failed to allocate %d bytes, ssl->heap: %p",
 8447                           (int)sizeof(ecc_key), (wc_ptr_t)ssl->heap);
 8448            WOLFSSL_MSG("EccTempKey Memory error!");
 8449            return MEMORY_E;
 8450        }
 8451
 8452        /* Initialize an ECC key struct for the ephemeral key */
 8453        ret = wc_ecc_init_ex((ecc_key*)kse->key, ssl->heap, ssl->devId);
 8454
 8455    #if defined(WC_ECC_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW) && \
 8456        defined(WC_ASYNC_ENABLE_ECC)
 8457        /* Only set non-blocking context when async device is active. With
 8458         * INVALID_DEVID there is no async loop to retry on FP_WOULDBLOCK, so
 8459         * skip non-blocking setup and use blocking mode instead. */
 8460        if (ret == 0 && ssl->devId != INVALID_DEVID) {
 8461            ecc_nb_ctx_t* eccNbCtx = (ecc_nb_ctx_t*)XMALLOC(
 8462                sizeof(ecc_nb_ctx_t), ssl->heap,
 8463                DYNAMIC_TYPE_TMP_BUFFER);
 8464            if (eccNbCtx == NULL) {
 8465                ret = MEMORY_E;
 8466            }
 8467            else {
 8468                ret = wc_ecc_set_nonblock((ecc_key*)kse->key, eccNbCtx);
 8469                if (ret != 0) {
 8470                    XFREE(eccNbCtx, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8471                }
 8472            }
 8473        }
 8474    #endif /* WC_ECC_NONBLOCK && WOLFSSL_ASYNC_CRYPT_SW &&
 8475              WC_ASYNC_ENABLE_ECC */
 8476
 8477        if (ret == 0) {
 8478            kse->keyLen = keySize;
 8479            kse->pubKeyLen = keySize * 2 + 1;
 8480
 8481        #if defined(WOLFSSL_RENESAS_TSIP_TLS)
 8482            ret = tsip_Tls13GenEccKeyPair(ssl, kse);
 8483            if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
 8484                return ret;
 8485            }
 8486        #endif
 8487            /* setting eccKey means okay to call wc_ecc_free */
 8488            eccKey = (ecc_key*)kse->key;
 8489
 8490        #ifdef WOLFSSL_STATIC_EPHEMERAL
 8491            ret = wolfSSL_StaticEphemeralKeyLoad(ssl, WC_PK_TYPE_ECDH, kse->key);
 8492            if (ret != 0 || eccKey->dp->id != curveId)
 8493        #endif
 8494            {
 8495                /* set curve info for EccMakeKey "peer" info */
 8496                ret = wc_ecc_set_curve(eccKey, (int)kse->keyLen, curveId);
 8497                if (ret == 0) {
 8498            #ifdef WOLFSSL_ASYNC_CRYPT
 8499                    /* Detect when private key generation is done */
 8500                    if (ssl->error == WC_NO_ERR_TRACE(WC_PENDING_E) &&
 8501                            eccKey->type == ECC_PRIVATEKEY) {
 8502                        ret = 0; /* ECC Key Generation is done */
 8503                    }
 8504                    else
 8505            #endif
 8506                    {
 8507                        /* Generate ephemeral ECC key */
 8508                        /* For async this is called once and when event is done, the
 8509                        *   provided buffers in key be populated.
 8510                        * Final processing is x963 key export below. */
 8511                        ret = EccMakeKey(ssl, eccKey, eccKey);
 8512                    }
 8513                }
 8514            #ifdef WOLFSSL_ASYNC_CRYPT
 8515                if (ret == WC_NO_ERR_TRACE(WC_PENDING_E))
 8516                    return ret;
 8517            #endif
 8518            }
 8519        }
 8520    }
 8521
 8522    if (ret == 0 && kse->pubKey == NULL) {
 8523        /* Allocate space for the public key */
 8524        kse->pubKey = (byte*)XMALLOC(kse->pubKeyLen, ssl->heap,
 8525            DYNAMIC_TYPE_PUBLIC_KEY);
 8526        if (kse->pubKey == NULL) {
 8527            WOLFSSL_MSG("Key data Memory error");
 8528            ret = MEMORY_E;
 8529        }
 8530    }
 8531
 8532    if (ret == 0) {
 8533        XMEMSET(kse->pubKey, 0, kse->pubKeyLen);
 8534
 8535        /* Export public key. */
 8536        PRIVATE_KEY_UNLOCK();
 8537        if (wc_ecc_export_x963(eccKey, kse->pubKey, &kse->pubKeyLen) != 0) {
 8538            ret = ECC_EXPORT_ERROR;
 8539            WOLFSSL_ERROR_VERBOSE(ret);
 8540        }
 8541        PRIVATE_KEY_LOCK();
 8542    }
 8543#ifdef WOLFSSL_DEBUG_TLS
 8544    if (ret == 0) {
 8545        WOLFSSL_MSG("Public ECC Key");
 8546        WOLFSSL_BUFFER(kse->pubKey, kse->pubKeyLen);
 8547    }
 8548#endif
 8549
 8550    if (ret != 0) {
 8551        /* Cleanup on error, otherwise data owned by key share entry */
 8552        XFREE(kse->pubKey, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
 8553        kse->pubKey = NULL;
 8554        if (eccKey != NULL) {
 8555    #if defined(WC_ECC_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW) && \
 8556        defined(WC_ASYNC_ENABLE_ECC)
 8557            if (eccKey->nb_ctx != NULL) {
 8558                XFREE(eccKey->nb_ctx, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8559            }
 8560    #endif
 8561            wc_ecc_free(eccKey);
 8562        }
 8563        XFREE(kse->key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
 8564        kse->key = NULL;
 8565    }
 8566#else
 8567    (void)ssl;
 8568    (void)kse;
 8569
 8570    ret = NOT_COMPILED_IN;
 8571    WOLFSSL_ERROR_VERBOSE(ret);
 8572#endif /* HAVE_ECC && HAVE_ECC_KEY_EXPORT */
 8573
 8574    return ret;
 8575}
 8576
 8577#ifdef WOLFSSL_HAVE_MLKEM
 8578#if (defined(WOLFSSL_MLKEM_CACHE_A) || \
 8579    (defined(HAVE_PKCS11) && !defined(NO_PKCS11_MLKEM))) && \
 8580    !defined(WOLFSSL_TLSX_PQC_MLKEM_STORE_PRIV_KEY)
 8581    /* Store KyberKey object rather than private key bytes in key share entry.
 8582     * Improves performance at cost of more dynamic memory being used. */
 8583    #define WOLFSSL_TLSX_PQC_MLKEM_STORE_OBJ
 8584#endif
 8585#if defined(WOLFSSL_TLSX_PQC_MLKEM_STORE_PRIV_KEY) && \
 8586    defined(WOLFSSL_TLSX_PQC_MLKEM_STORE_OBJ)
 8587    #error "Choose WOLFSSL_TLSX_PQC_MLKEM_STORE_PRIV_KEY or "
 8588           "WOLFSSL_TLSX_PQC_MLKEM_STORE_OBJ"
 8589#endif
 8590
 8591#if !defined(WOLFSSL_MLKEM_NO_MAKE_KEY) || \
 8592    !defined(WOLFSSL_MLKEM_NO_ENCAPSULATE) || \
 8593    (!defined(WOLFSSL_MLKEM_NO_DECAPSULATE) && \
 8594     !defined(WOLFSSL_TLSX_PQC_MLKEM_STORE_OBJ))
 8595static int mlkem_id2type(int id, int *type)
 8596{
 8597    int ret = 0;
 8598
 8599    switch (id) {
 8600#ifndef WOLFSSL_NO_ML_KEM
 8601    #ifndef WOLFSSL_NO_ML_KEM_512
 8602        case WOLFSSL_ML_KEM_512:
 8603            *type = WC_ML_KEM_512;
 8604            break;
 8605    #endif
 8606    #ifndef WOLFSSL_NO_ML_KEM_768
 8607        case WOLFSSL_ML_KEM_768:
 8608            *type = WC_ML_KEM_768;
 8609            break;
 8610    #endif
 8611    #ifndef WOLFSSL_NO_ML_KEM_1024
 8612        case WOLFSSL_ML_KEM_1024:
 8613            *type = WC_ML_KEM_1024;
 8614            break;
 8615    #endif
 8616#endif
 8617#ifdef WOLFSSL_MLKEM_KYBER
 8618    #ifdef WOLFSSL_KYBER512
 8619        case WOLFSSL_KYBER_LEVEL1:
 8620            *type = KYBER512;
 8621            break;
 8622    #endif
 8623    #ifdef WOLFSSL_KYBER768
 8624        case WOLFSSL_KYBER_LEVEL3:
 8625            *type = KYBER768;
 8626            break;
 8627    #endif
 8628    #ifdef WOLFSSL_KYBER1024
 8629        case WOLFSSL_KYBER_LEVEL5:
 8630            *type = KYBER1024;
 8631            break;
 8632    #endif
 8633#endif
 8634        default:
 8635            ret = NOT_COMPILED_IN;
 8636            break;
 8637    }
 8638
 8639    return ret;
 8640}
 8641#endif
 8642
 8643#if defined(WOLFSSL_NO_ML_KEM_768) && defined(WOLFSSL_NO_ML_KEM_1024) && \
 8644    defined(WOLFSSL_PQC_HYBRIDS)
 8645    #error "PQC hybrid combinations require either ML-KEM 768 or ML-KEM 1024"
 8646#endif
 8647
 8648/* Structures and objects needed for hybrid key exchanges using both classic
 8649 * ECDHE and PQC KEM key material. */
 8650typedef struct PqcHybridMapping {
 8651    int hybrid;
 8652    int ecc;
 8653    int pqc;
 8654    int pqc_first;
 8655} PqcHybridMapping;
 8656
 8657static const PqcHybridMapping pqc_hybrid_mapping[] = {
 8658#ifndef WOLFSSL_NO_ML_KEM
 8659#ifdef WOLFSSL_PQC_HYBRIDS
 8660    {WOLFSSL_SECP256R1MLKEM768, WOLFSSL_ECC_SECP256R1, WOLFSSL_ML_KEM_768, 0},
 8661    {WOLFSSL_SECP384R1MLKEM1024, WOLFSSL_ECC_SECP384R1, WOLFSSL_ML_KEM_1024, 0},
 8662#endif /* WOLFSSL_PQC_HYBRIDS */
 8663#ifdef WOLFSSL_EXTRA_PQC_HYBRIDS
 8664    {WOLFSSL_SECP256R1MLKEM512, WOLFSSL_ECC_SECP256R1, WOLFSSL_ML_KEM_512, 0},
 8665    {WOLFSSL_SECP384R1MLKEM768, WOLFSSL_ECC_SECP384R1, WOLFSSL_ML_KEM_768, 0},
 8666    {WOLFSSL_SECP521R1MLKEM1024, WOLFSSL_ECC_SECP521R1, WOLFSSL_ML_KEM_1024, 0},
 8667#ifdef WOLFSSL_ML_KEM_USE_OLD_IDS
 8668    {WOLFSSL_P256_ML_KEM_512_OLD, WOLFSSL_ECC_SECP256R1, WOLFSSL_ML_KEM_512, 0},
 8669    {WOLFSSL_P384_ML_KEM_768_OLD, WOLFSSL_ECC_SECP384R1, WOLFSSL_ML_KEM_768, 0},
 8670    {WOLFSSL_P521_ML_KEM_1024_OLD, WOLFSSL_ECC_SECP521R1, WOLFSSL_ML_KEM_1024, 0},
 8671#endif /* WOLFSSL_ML_KEM_USE_OLD_IDS */
 8672#endif /* WOLFSSL_EXTRA_PQC_HYBRIDS */
 8673#ifdef HAVE_CURVE25519
 8674#ifdef WOLFSSL_PQC_HYBRIDS
 8675    {WOLFSSL_X25519MLKEM768, WOLFSSL_ECC_X25519, WOLFSSL_ML_KEM_768, 1},
 8676#endif /* WOLFSSL_PQC_HYBRIDS */
 8677#ifdef WOLFSSL_EXTRA_PQC_HYBRIDS
 8678    {WOLFSSL_X25519MLKEM512, WOLFSSL_ECC_X25519, WOLFSSL_ML_KEM_512, 1},
 8679#endif /* WOLFSSL_EXTRA_PQC_HYBRIDS */
 8680#endif /* HAVE_CURVE25519 */
 8681#ifdef HAVE_CURVE448
 8682#ifdef WOLFSSL_EXTRA_PQC_HYBRIDS
 8683    {WOLFSSL_X448MLKEM768, WOLFSSL_ECC_X448, WOLFSSL_ML_KEM_768, 1},
 8684#endif /* WOLFSSL_EXTRA_PQC_HYBRIDS */
 8685#endif /* HAVE_CURVE448 */
 8686#endif /* WOLFSSL_NO_ML_KEM */
 8687#ifdef WOLFSSL_MLKEM_KYBER
 8688    {WOLFSSL_P256_KYBER_LEVEL1, WOLFSSL_ECC_SECP256R1, WOLFSSL_KYBER_LEVEL1, 0},
 8689    {WOLFSSL_P384_KYBER_LEVEL3, WOLFSSL_ECC_SECP384R1, WOLFSSL_KYBER_LEVEL3, 0},
 8690    {WOLFSSL_P256_KYBER_LEVEL3, WOLFSSL_ECC_SECP256R1, WOLFSSL_KYBER_LEVEL3, 0},
 8691    {WOLFSSL_P521_KYBER_LEVEL5, WOLFSSL_ECC_SECP521R1, WOLFSSL_KYBER_LEVEL5, 0},
 8692#ifdef HAVE_CURVE25519
 8693    {WOLFSSL_X25519_KYBER_LEVEL1, WOLFSSL_ECC_X25519, WOLFSSL_KYBER_LEVEL1, 0},
 8694    {WOLFSSL_X25519_KYBER_LEVEL3, WOLFSSL_ECC_X25519, WOLFSSL_KYBER_LEVEL3, 0},
 8695#endif
 8696#ifdef HAVE_CURVE448
 8697    {WOLFSSL_X448_KYBER_LEVEL3, WOLFSSL_ECC_X448, WOLFSSL_KYBER_LEVEL3, 0},
 8698#endif
 8699#endif /* WOLFSSL_MLKEM_KYBER */
 8700    {0, 0, 0, 0}
 8701};
 8702
 8703/* Map an ecc-pqc hybrid group into its ecc group and pqc kem group. */
 8704static void findEccPqc(int *ecc, int *pqc, int *pqc_first, int group)
 8705{
 8706    int i;
 8707
 8708    if (pqc != NULL)
 8709        *pqc = 0;
 8710    if (ecc != NULL)
 8711        *ecc = 0;
 8712    if (pqc_first != NULL)
 8713        *pqc_first = 0;
 8714
 8715    for (i = 0; pqc_hybrid_mapping[i].hybrid != 0; i++) {
 8716        if (pqc_hybrid_mapping[i].hybrid == group) {
 8717            if (pqc != NULL)
 8718                *pqc = pqc_hybrid_mapping[i].pqc;
 8719            if (ecc != NULL)
 8720                *ecc = pqc_hybrid_mapping[i].ecc;
 8721            if (pqc_first != NULL)
 8722                *pqc_first = pqc_hybrid_mapping[i].pqc_first;
 8723            break;
 8724        }
 8725    }
 8726}
 8727
 8728#ifndef WOLFSSL_MLKEM_NO_MAKE_KEY
 8729/* Create a key share entry using pqc parameters group on the client side.
 8730 * Generates a key pair.
 8731 *
 8732 * ssl   The SSL/TLS object.
 8733 * kse   The key share entry object.
 8734 * returns 0 on success, otherwise failure.
 8735 */
 8736static int TLSX_KeyShare_GenPqcKeyClient(WOLFSSL *ssl, KeyShareEntry* kse)
 8737{
 8738    int ret = 0;
 8739    int type = 0;
 8740#ifndef WOLFSSL_TLSX_PQC_MLKEM_STORE_OBJ
 8741        WC_DECLARE_VAR(kem, KyberKey, 1, 0);
 8742    byte* privKey = NULL;
 8743    word32 privSz = 0;
 8744#else
 8745    KyberKey* kem = NULL;
 8746#endif
 8747
 8748    /* This gets called twice. Once during parsing of the key share and once
 8749     * during the population of the extension. No need to do work the second
 8750     * time. Just return success if its already been done. */
 8751    if (kse->pubKey != NULL) {
 8752        return ret;
 8753    }
 8754
 8755    /* Get the type of key we need from the key share group. */
 8756    ret = mlkem_id2type(kse->group, &type);
 8757    if (ret == WC_NO_ERR_TRACE(NOT_COMPILED_IN)) {
 8758        WOLFSSL_MSG("Invalid Kyber algorithm specified.");
 8759        ret = BAD_FUNC_ARG;
 8760    }
 8761
 8762#ifndef WOLFSSL_TLSX_PQC_MLKEM_STORE_OBJ
 8763
 8764    #ifdef WOLFSSL_SMALL_STACK
 8765    if (ret == 0) {
 8766        kem = (KyberKey *)XMALLOC(sizeof(*kem), ssl->heap,
 8767                                  DYNAMIC_TYPE_PRIVATE_KEY);
 8768        if (kem == NULL) {
 8769            WOLFSSL_MSG("KEM memory allocation failure");
 8770            ret = MEMORY_ERROR;
 8771        }
 8772    }
 8773    #endif /* WOLFSSL_SMALL_STACK */
 8774
 8775    if (ret == 0) {
 8776        ret = wc_KyberKey_Init(type, kem, ssl->heap, ssl->devId);
 8777        if (ret != 0) {
 8778            WOLFSSL_MSG("Failed to initialize Kyber Key.");
 8779        }
 8780    }
 8781
 8782    if (ret == 0) {
 8783        ret = wc_KyberKey_PrivateKeySize(kem, &privSz);
 8784    }
 8785    if (ret == 0) {
 8786        ret = wc_KyberKey_PublicKeySize(kem, &kse->pubKeyLen);
 8787    }
 8788
 8789    if (ret == 0) {
 8790        privKey = (byte*)XMALLOC(privSz, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
 8791        if (privKey == NULL) {
 8792            WOLFSSL_MSG("privkey memory allocation failure");
 8793            ret = MEMORY_ERROR;
 8794        }
 8795    }
 8796#else
 8797    if (ret == 0) {
 8798        /* Allocate a Kyber key to hold private key. */
 8799        kem = (KyberKey*)XMALLOC(sizeof(KyberKey), ssl->heap,
 8800                                 DYNAMIC_TYPE_PRIVATE_KEY);
 8801        if (kem == NULL) {
 8802            WOLFSSL_MSG("KEM memory allocation failure");
 8803            ret = MEMORY_ERROR;
 8804        }
 8805    }
 8806    if (ret == 0) {
 8807        ret = wc_KyberKey_Init(type, kem, ssl->heap, ssl->devId);
 8808        if (ret != 0) {
 8809            WOLFSSL_MSG("Failed to initialize Kyber Key.");
 8810        }
 8811    }
 8812    if (ret == 0) {
 8813        ret = wc_KyberKey_PublicKeySize(kem, &kse->pubKeyLen);
 8814    }
 8815#endif
 8816
 8817    if (ret == 0) {
 8818        kse->pubKey = (byte*)XMALLOC(kse->pubKeyLen, ssl->heap,
 8819                                     DYNAMIC_TYPE_PUBLIC_KEY);
 8820        if (kse->pubKey == NULL) {
 8821            WOLFSSL_MSG("pubkey memory allocation failure");
 8822            ret = MEMORY_ERROR;
 8823        }
 8824    }
 8825
 8826    if (ret == 0) {
 8827        ret = wc_KyberKey_MakeKey(kem, ssl->rng);
 8828        if (ret != 0) {
 8829            WOLFSSL_MSG("Kyber keygen failure");
 8830        }
 8831    }
 8832    if (ret == 0) {
 8833        ret = wc_KyberKey_EncodePublicKey(kem, kse->pubKey,
 8834                                          kse->pubKeyLen);
 8835    }
 8836
 8837#ifndef WOLFSSL_TLSX_PQC_MLKEM_STORE_OBJ
 8838    if (ret == 0) {
 8839        PRIVATE_KEY_UNLOCK();
 8840        ret = wc_KyberKey_EncodePrivateKey(kem, privKey, privSz);
 8841        PRIVATE_KEY_LOCK();
 8842    }
 8843#endif
 8844
 8845#ifdef WOLFSSL_DEBUG_TLS
 8846    WOLFSSL_MSG("Public Kyber Key");
 8847    WOLFSSL_BUFFER(kse->pubKey, kse->pubKeyLen );
 8848#endif
 8849
 8850    if (ret != 0) {
 8851        /* Data owned by key share entry otherwise. */
 8852        wc_KyberKey_Free(kem);
 8853        XFREE(kse->pubKey, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
 8854        kse->pubKey = NULL;
 8855    #ifndef WOLFSSL_TLSX_PQC_MLKEM_STORE_OBJ
 8856        if (privKey) {
 8857            ForceZero(privKey, privSz);
 8858            XFREE(privKey, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
 8859            privKey = NULL;
 8860        }
 8861    #else
 8862        XFREE(kem, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
 8863        kse->key = NULL;
 8864    #endif
 8865    }
 8866    else {
 8867    #ifndef WOLFSSL_TLSX_PQC_MLKEM_STORE_OBJ
 8868        wc_KyberKey_Free(kem);
 8869        kse->privKey = (byte*)privKey;
 8870        kse->privKeyLen = privSz;
 8871    #else
 8872        kse->key = kem;
 8873    #endif
 8874    }
 8875
 8876    #if !defined(WOLFSSL_TLSX_PQC_MLKEM_STORE_OBJ) && \
 8877        defined(WOLFSSL_SMALL_STACK)
 8878    XFREE(kem, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
 8879    #endif
 8880
 8881    return ret;
 8882}
 8883
 8884/* Create a key share entry using both ecdhe and pqc parameters groups.
 8885 * Generates two key pairs on the client side.
 8886 *
 8887 * ssl   The SSL/TLS object.
 8888 * kse   The key share entry object.
 8889 * returns 0 on success, otherwise failure.
 8890 */
 8891static int TLSX_KeyShare_GenPqcHybridKeyClient(WOLFSSL *ssl, KeyShareEntry* kse)
 8892{
 8893    int ret = 0;
 8894    KeyShareEntry *ecc_kse = NULL;
 8895    KeyShareEntry *pqc_kse = NULL;
 8896    int pqc_group = 0;
 8897    int ecc_group = 0;
 8898    int pqc_first = 0;
 8899
 8900    /* This gets called twice. Once during parsing of the key share and once
 8901     * during the population of the extension. No need to do work the second
 8902     * time. Just return success if its already been done. */
 8903    if (kse->pubKey != NULL) {
 8904        return ret;
 8905    }
 8906
 8907    /* Determine the ECC and PQC group of the hybrid combination */
 8908    findEccPqc(&ecc_group, &pqc_group, &pqc_first, kse->group);
 8909    if (ecc_group == 0 || pqc_group == 0) {
 8910        WOLFSSL_MSG("Invalid hybrid group");
 8911        ret = BAD_FUNC_ARG;
 8912    }
 8913
 8914    if (ret == 0) {
 8915        ecc_kse = (KeyShareEntry*)XMALLOC(sizeof(*ecc_kse), ssl->heap,
 8916                   DYNAMIC_TYPE_TLSX);
 8917        if (ecc_kse == NULL) {
 8918            WOLFSSL_MSG("kse memory allocation failure");
 8919            ret = MEMORY_ERROR;
 8920        }
 8921        else {
 8922            XMEMSET(ecc_kse, 0, sizeof(*ecc_kse));
 8923        }
 8924    }
 8925    if (ret == 0) {
 8926        pqc_kse = (KeyShareEntry*)XMALLOC(sizeof(*pqc_kse), ssl->heap,
 8927                   DYNAMIC_TYPE_TLSX);
 8928        if (pqc_kse == NULL) {
 8929            WOLFSSL_MSG("kse memory allocation failure");
 8930            ret = MEMORY_ERROR;
 8931        }
 8932        else {
 8933            XMEMSET(pqc_kse, 0, sizeof(*pqc_kse));
 8934        }
 8935    }
 8936
 8937    /* Generate ECC key share part */
 8938    if (ret == 0) {
 8939        ecc_kse->group = ecc_group;
 8940
 8941    #ifdef WOLFSSL_ASYNC_CRYPT
 8942        /* Check if the provided kse already contains an ECC key and the
 8943         * last error was WC_PENDING_E. In this case, we already tried to
 8944         * generate an ECC key. Hence, we have to restore it. */
 8945        if (kse->key != NULL && kse->keyLen > 0 &&
 8946            kse->lastRet == WC_NO_ERR_TRACE(WC_PENDING_E)) {
 8947            ecc_kse->key = kse->key;
 8948            ecc_kse->keyLen = kse->keyLen;
 8949            ecc_kse->pubKeyLen = kse->pubKeyLen;
 8950            ecc_kse->lastRet = kse->lastRet;
 8951            kse->key = NULL;
 8952        }
 8953    #endif
 8954
 8955    #ifdef HAVE_CURVE25519
 8956        if (ecc_group == WOLFSSL_ECC_X25519) {
 8957            ret = TLSX_KeyShare_GenX25519Key(ssl, ecc_kse);
 8958        }
 8959        else
 8960    #endif
 8961    #ifdef HAVE_CURVE448
 8962        if (ecc_group == WOLFSSL_ECC_X448) {
 8963            ret = TLSX_KeyShare_GenX448Key(ssl, ecc_kse);
 8964        }
 8965        else
 8966    #endif
 8967        {
 8968            ret = TLSX_KeyShare_GenEccKey(ssl, ecc_kse);
 8969        }
 8970
 8971    #ifdef WOLFSSL_ASYNC_CRYPT
 8972        if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
 8973            /* Store the generated ECC key in the provided kse to later
 8974             * restore it.*/
 8975            kse->key = ecc_kse->key;
 8976            kse->keyLen = ecc_kse->keyLen;
 8977            kse->pubKeyLen = ecc_kse->pubKeyLen;
 8978            ecc_kse->key = NULL;
 8979        }
 8980    #endif
 8981    }
 8982
 8983    /* Generate PQC key share part */
 8984    if (ret == 0) {
 8985        pqc_kse->group = pqc_group;
 8986        ret = TLSX_KeyShare_GenPqcKeyClient(ssl, pqc_kse);
 8987        /* No error message, TLSX_KeyShare_GenPqcKeyClient will do it. */
 8988    }
 8989
 8990    /* Allocate memory for combined public key */
 8991    if (ret == 0) {
 8992        kse->pubKey = (byte*)XMALLOC(ecc_kse->pubKeyLen + pqc_kse->pubKeyLen,
 8993                                     ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
 8994        if (kse->pubKey == NULL) {
 8995            WOLFSSL_MSG("pubkey memory allocation failure");
 8996            ret = MEMORY_ERROR;
 8997        }
 8998    }
 8999
 9000    /* Create combined public key. The order of classic/pqc key material is
 9001     * indicated by the pqc_first variable. */
 9002    if (ret == 0) {
 9003        if (pqc_first) {
 9004            XMEMCPY(kse->pubKey, pqc_kse->pubKey, pqc_kse->pubKeyLen);
 9005            XMEMCPY(kse->pubKey + pqc_kse->pubKeyLen, ecc_kse->pubKey,
 9006                    ecc_kse->pubKeyLen);
 9007        }
 9008        else {
 9009            XMEMCPY(kse->pubKey, ecc_kse->pubKey, ecc_kse->pubKeyLen);
 9010            XMEMCPY(kse->pubKey + ecc_kse->pubKeyLen, pqc_kse->pubKey,
 9011                    pqc_kse->pubKeyLen);
 9012        }
 9013        kse->pubKeyLen = ecc_kse->pubKeyLen + pqc_kse->pubKeyLen;
 9014    }
 9015
 9016    /* Store the private keys.
 9017     * Note we are saving the PQC private key and ECC private key
 9018     * separately. That's because the ECC private key is not simply a
 9019     * buffer. Its is an ecc_key struct. */
 9020    if (ret == 0) {
 9021    #ifndef WOLFSSL_TLSX_PQC_MLKEM_STORE_OBJ
 9022        /* PQC private key is an encoded byte array */
 9023        kse->privKey = pqc_kse->privKey;
 9024        kse->privKeyLen = pqc_kse->privKeyLen;
 9025        pqc_kse->privKey = NULL;
 9026    #else
 9027        /* PQC private key is a pointer to KyberKey object */
 9028        kse->privKey = (byte*)pqc_kse->key;
 9029        kse->privKeyLen = 0;
 9030        pqc_kse->key = NULL;
 9031    #endif
 9032        /* ECC private key is a pointer to ecc_key object */
 9033        kse->key = ecc_kse->key;
 9034        kse->keyLen = ecc_kse->keyLen;
 9035        ecc_kse->key = NULL;
 9036    }
 9037
 9038#ifdef WOLFSSL_DEBUG_TLS
 9039    WOLFSSL_MSG("Public Kyber Key");
 9040    WOLFSSL_BUFFER(kse->pubKey, kse->pubKeyLen );
 9041#endif
 9042
 9043    TLSX_KeyShare_FreeAll(ecc_kse, ssl->heap);
 9044    TLSX_KeyShare_FreeAll(pqc_kse, ssl->heap);
 9045
 9046    return ret;
 9047}
 9048#endif /* !WOLFSSL_MLKEM_NO_MAKE_KEY */
 9049#endif /* WOLFSSL_HAVE_MLKEM */
 9050
 9051/* Generate a secret/key using the key share entry.
 9052 *
 9053 * ssl  The SSL/TLS object.
 9054 * kse  The key share entry holding peer data.
 9055 */
 9056int TLSX_KeyShare_GenKey(WOLFSSL *ssl, KeyShareEntry *kse)
 9057{
 9058    int ret;
 9059    /* Named FFDHE groups have a bit set to identify them. */
 9060    if (WOLFSSL_NAMED_GROUP_IS_FFDHE(kse->group))
 9061        ret = TLSX_KeyShare_GenDhKey(ssl, kse);
 9062    else if (kse->group == WOLFSSL_ECC_X25519)
 9063        ret = TLSX_KeyShare_GenX25519Key(ssl, kse);
 9064    else if (kse->group == WOLFSSL_ECC_X448)
 9065        ret = TLSX_KeyShare_GenX448Key(ssl, kse);
 9066#if defined(WOLFSSL_HAVE_MLKEM) && !defined(WOLFSSL_MLKEM_NO_MAKE_KEY)
 9067    else if (WOLFSSL_NAMED_GROUP_IS_PQC(kse->group))
 9068        ret = TLSX_KeyShare_GenPqcKeyClient(ssl, kse);
 9069    else if (WOLFSSL_NAMED_GROUP_IS_PQC_HYBRID(kse->group))
 9070        ret = TLSX_KeyShare_GenPqcHybridKeyClient(ssl, kse);
 9071#endif
 9072    else
 9073        ret = TLSX_KeyShare_GenEccKey(ssl, kse);
 9074#ifdef WOLFSSL_ASYNC_CRYPT
 9075    kse->lastRet = ret;
 9076#endif
 9077    return ret;
 9078}
 9079
 9080/* Free the key share dynamic data.
 9081 *
 9082 * list  The linked list of key share entry objects.
 9083 * heap  The heap used for allocation.
 9084 */
 9085static void TLSX_KeyShare_FreeAll(KeyShareEntry* list, void* heap)
 9086{
 9087    KeyShareEntry* current;
 9088
 9089    while ((current = list) != NULL) {
 9090        list = current->next;
 9091        if (WOLFSSL_NAMED_GROUP_IS_FFDHE(current->group)) {
 9092#ifndef NO_DH
 9093        #if defined(WC_DH_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW) && \
 9094            defined(WC_ASYNC_ENABLE_DH)
 9095            if (current->key != NULL &&
 9096                    ((DhKey*)current->key)->nb != NULL) {
 9097                XFREE(((DhKey*)current->key)->nb, heap,
 9098                    DYNAMIC_TYPE_TMP_BUFFER);
 9099                ((DhKey*)current->key)->nb = NULL;
 9100            }
 9101        #endif
 9102            wc_FreeDhKey((DhKey*)current->key);
 9103            if (current->privKey != NULL && current->privKeyLen > 0) {
 9104                ForceZero(current->privKey, current->privKeyLen);
 9105            }
 9106#endif
 9107        }
 9108        else if (current->group == WOLFSSL_ECC_X25519) {
 9109#ifdef HAVE_CURVE25519
 9110        #if defined(WC_X25519_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW)
 9111            if (current->key != NULL &&
 9112                    ((curve25519_key*)current->key)->nb_ctx != NULL) {
 9113                XFREE(((curve25519_key*)current->key)->nb_ctx, heap,
 9114                    DYNAMIC_TYPE_TMP_BUFFER);
 9115            }
 9116        #endif
 9117            wc_curve25519_free((curve25519_key*)current->key);
 9118#endif
 9119        }
 9120        else if (current->group == WOLFSSL_ECC_X448) {
 9121#ifdef HAVE_CURVE448
 9122            wc_curve448_free((curve448_key*)current->key);
 9123#endif
 9124        }
 9125        else if (WOLFSSL_NAMED_GROUP_IS_PQC(current->group)) {
 9126#ifdef WOLFSSL_HAVE_MLKEM
 9127            wc_KyberKey_Free((KyberKey*)current->key);
 9128        #ifndef WOLFSSL_TLSX_PQC_MLKEM_STORE_OBJ
 9129            if (current->privKey != NULL) {
 9130                ForceZero(current->privKey, current->privKeyLen);
 9131            }
 9132        #endif
 9133#endif
 9134        }
 9135        else if (WOLFSSL_NAMED_GROUP_IS_PQC_HYBRID(current->group)) {
 9136#ifdef WOLFSSL_HAVE_MLKEM
 9137            int ecc_group = 0;
 9138            findEccPqc(&ecc_group, NULL, NULL, current->group);
 9139
 9140            /* Free PQC private key */
 9141        #ifdef WOLFSSL_TLSX_PQC_MLKEM_STORE_OBJ
 9142            wc_KyberKey_Free((KyberKey*)current->privKey);
 9143        #else
 9144            if (current->privKey != NULL) {
 9145                ForceZero(current->privKey, current->privKeyLen);
 9146            }
 9147        #endif
 9148
 9149            /* Free ECC private key */
 9150            if (ecc_group == WOLFSSL_ECC_X25519) {
 9151            #ifdef HAVE_CURVE25519
 9152                wc_curve25519_free((curve25519_key*)current->key);
 9153            #endif
 9154            }
 9155            else if (ecc_group == WOLFSSL_ECC_X448) {
 9156            #ifdef HAVE_CURVE448
 9157                wc_curve448_free((curve448_key*)current->key);
 9158            #endif
 9159            }
 9160            else {
 9161            #ifdef HAVE_ECC
 9162                #if defined(WC_ECC_NONBLOCK) && \
 9163                    defined(WOLFSSL_ASYNC_CRYPT_SW) && \
 9164                    defined(WC_ASYNC_ENABLE_ECC)
 9165                if (current->key != NULL &&
 9166                        ((ecc_key*)current->key)->nb_ctx != NULL) {
 9167                    XFREE(((ecc_key*)current->key)->nb_ctx, heap,
 9168                        DYNAMIC_TYPE_TMP_BUFFER);
 9169                }
 9170                #endif
 9171                wc_ecc_free((ecc_key*)current->key);
 9172            #endif
 9173            }
 9174#endif
 9175        }
 9176        else {
 9177#ifdef HAVE_ECC
 9178        #if defined(WC_ECC_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW) && \
 9179            defined(WC_ASYNC_ENABLE_ECC)
 9180            if (current->key != NULL &&
 9181                    ((ecc_key*)current->key)->nb_ctx != NULL) {
 9182                XFREE(((ecc_key*)current->key)->nb_ctx, heap,
 9183                    DYNAMIC_TYPE_TMP_BUFFER);
 9184            }
 9185        #endif
 9186            wc_ecc_free((ecc_key*)current->key);
 9187#endif
 9188        }
 9189        XFREE(current->key, heap, DYNAMIC_TYPE_PRIVATE_KEY);
 9190    #if !defined(NO_DH) || defined(WOLFSSL_HAVE_MLKEM)
 9191        XFREE(current->privKey, heap, DYNAMIC_TYPE_PRIVATE_KEY);
 9192    #endif
 9193        XFREE(current->pubKey, heap, DYNAMIC_TYPE_PUBLIC_KEY);
 9194        XFREE(current->ke, heap, DYNAMIC_TYPE_PUBLIC_KEY);
 9195        XFREE(current, heap, DYNAMIC_TYPE_TLSX);
 9196    }
 9197
 9198    (void)heap;
 9199}
 9200
 9201/* Get the size of the encoded key share extension.
 9202 *
 9203 * list     The linked list of key share extensions.
 9204 * msgType  The type of the message this extension is being written into.
 9205 * returns the number of bytes of the encoded key share extension.
 9206 */
 9207static word16 TLSX_KeyShare_GetSize(KeyShareEntry* list, byte msgType)
 9208{
 9209    word16         len = 0;
 9210    byte           isRequest = (msgType == client_hello);
 9211    KeyShareEntry* current;
 9212
 9213    /* The named group the server wants to use. */
 9214    if (msgType == hello_retry_request)
 9215        return OPAQUE16_LEN;
 9216
 9217    /* List of key exchange groups. */
 9218    if (isRequest)
 9219        len += OPAQUE16_LEN;
 9220    while ((current = list) != NULL) {
 9221        list = current->next;
 9222
 9223        if (!isRequest && current->pubKey == NULL)
 9224            continue;
 9225
 9226        len += (word16)(KE_GROUP_LEN + OPAQUE16_LEN + current->pubKeyLen);
 9227    }
 9228
 9229    return len;
 9230}
 9231
 9232/* Writes the key share extension into the output buffer.
 9233 * Assumes that the the output buffer is big enough to hold data.
 9234 *
 9235 * list     The linked list of key share entries.
 9236 * output   The buffer to write into.
 9237 * msgType  The type of the message this extension is being written into.
 9238 * returns the number of bytes written into the buffer.
 9239 */
 9240static word16 TLSX_KeyShare_Write(KeyShareEntry* list, byte* output,
 9241                                  byte msgType)
 9242{
 9243    word16         i = 0;
 9244    byte           isRequest = (msgType == client_hello);
 9245    KeyShareEntry* current;
 9246
 9247    if (msgType == hello_retry_request) {
 9248        c16toa(list->group, output);
 9249        return OPAQUE16_LEN;
 9250    }
 9251
 9252    /* ClientHello has a list but ServerHello is only the chosen. */
 9253    if (isRequest)
 9254        i += OPAQUE16_LEN;
 9255
 9256    /* Write out all in the list. */
 9257    while ((current = list) != NULL) {
 9258        list = current->next;
 9259
 9260        if (!isRequest && current->pubKey == NULL)
 9261            continue;
 9262
 9263        c16toa(current->group, &output[i]);
 9264        i += KE_GROUP_LEN;
 9265        c16toa((word16)(current->pubKeyLen), &output[i]);
 9266        i += OPAQUE16_LEN;
 9267        XMEMCPY(&output[i], current->pubKey, current->pubKeyLen);
 9268        i += (word16)current->pubKeyLen;
 9269    }
 9270    /* Write the length of the list if required. */
 9271    if (isRequest)
 9272        c16toa(i - OPAQUE16_LEN, output);
 9273
 9274    return i;
 9275}
 9276
 9277/* Process the DH key share extension on the client side.
 9278 *
 9279 * ssl            The SSL/TLS object.
 9280 * keyShareEntry  The key share entry object to use to calculate shared secret.
 9281 * returns 0 on success and other values indicate failure.
 9282 */
 9283static int TLSX_KeyShare_ProcessDh(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
 9284{
 9285    int ret = 0;
 9286#if !defined(NO_DH) && (!defined(NO_CERTS) || !defined(NO_PSK))
 9287    word32 pSz = 0;
 9288    DhKey* dhKey = (DhKey*)keyShareEntry->key;
 9289
 9290#ifdef HAVE_PUBLIC_FFDHE
 9291    const DhParams* params = NULL;
 9292    switch (keyShareEntry->group) {
 9293    #ifdef HAVE_FFDHE_2048
 9294        case WOLFSSL_FFDHE_2048:
 9295            params = wc_Dh_ffdhe2048_Get();
 9296            break;
 9297    #endif
 9298    #ifdef HAVE_FFDHE_3072
 9299        case WOLFSSL_FFDHE_3072:
 9300            params = wc_Dh_ffdhe3072_Get();
 9301            break;
 9302    #endif
 9303    #ifdef HAVE_FFDHE_4096
 9304        case WOLFSSL_FFDHE_4096:
 9305            params = wc_Dh_ffdhe4096_Get();
 9306            break;
 9307    #endif
 9308    #ifdef HAVE_FFDHE_6144
 9309        case WOLFSSL_FFDHE_6144:
 9310            params = wc_Dh_ffdhe6144_Get();
 9311            break;
 9312    #endif
 9313    #ifdef HAVE_FFDHE_8192
 9314        case WOLFSSL_FFDHE_8192:
 9315            params = wc_Dh_ffdhe8192_Get();
 9316            break;
 9317    #endif
 9318        default:
 9319            break;
 9320    }
 9321    if (params == NULL) {
 9322        WOLFSSL_ERROR_VERBOSE(PEER_KEY_ERROR);
 9323        return PEER_KEY_ERROR;
 9324    }
 9325    pSz = params->p_len;
 9326#else
 9327    ret = wc_DhGetNamedKeyParamSize(keyShareEntry->group, &pSz, NULL, NULL);
 9328    if (ret != 0 || pSz == 0) {
 9329        WOLFSSL_ERROR_VERBOSE(PEER_KEY_ERROR);
 9330        return PEER_KEY_ERROR;
 9331    }
 9332#endif
 9333
 9334    /* RFC 8446 Section 4.2.8.1: FFDHE key_exchange values are left-padded with
 9335     * zeros to the size of the named-group prime. Reject any peer key share
 9336     * whose byte length does not match the expected prime size. */
 9337    if (keyShareEntry->keLen != pSz) {
 9338        WOLFSSL_ERROR_VERBOSE(PEER_KEY_ERROR);
 9339        return PEER_KEY_ERROR;
 9340    }
 9341
 9342    /* if DhKey is not setup, do it now */
 9343    if (keyShareEntry->key == NULL) {
 9344        keyShareEntry->key = (DhKey*)XMALLOC(sizeof(DhKey), ssl->heap,
 9345            DYNAMIC_TYPE_DH);
 9346        if (keyShareEntry->key == NULL)
 9347            return MEMORY_E;
 9348
 9349        /* Setup Key */
 9350        ret = wc_InitDhKey_ex((DhKey*)keyShareEntry->key, ssl->heap, ssl->devId);
 9351        if (ret == 0) {
 9352            dhKey = (DhKey*)keyShareEntry->key;
 9353        /* Set key */
 9354        #ifdef HAVE_PUBLIC_FFDHE
 9355            ret = wc_DhSetKey(dhKey, params->p, params->p_len, params->g,
 9356                                                                params->g_len);
 9357        #else
 9358            ret = wc_DhSetNamedKey(dhKey, keyShareEntry->group);
 9359        #endif
 9360        }
 9361    #if defined(WC_DH_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW) && \
 9362        defined(WC_ASYNC_ENABLE_DH)
 9363        /* Only set non-blocking context when async device is active. With
 9364         * INVALID_DEVID there is no async loop to retry on MP_WOULDBLOCK, so
 9365         * skip non-blocking setup and use blocking mode instead. */
 9366        if (ret == 0 && ssl->devId != INVALID_DEVID) {
 9367            DhNb* dhNb = (DhNb*)XMALLOC(sizeof(DhNb), ssl->heap,
 9368                                        DYNAMIC_TYPE_TMP_BUFFER);
 9369            if (dhNb == NULL) {
 9370                ret = MEMORY_E;
 9371            }
 9372            else {
 9373                ret = wc_DhSetNonBlock((DhKey*)keyShareEntry->key, dhNb);
 9374                if (ret != 0) {
 9375                    XFREE(dhNb, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
 9376                }
 9377            }
 9378        }
 9379    #endif /* WC_DH_NONBLOCK && WOLFSSL_ASYNC_CRYPT_SW &&
 9380              WC_ASYNC_ENABLE_DH */
 9381    }
 9382
 9383    if (ret == 0
 9384    #ifdef WOLFSSL_ASYNC_CRYPT
 9385        && keyShareEntry->lastRet == 0 /* don't enter here if WC_PENDING_E */
 9386    #endif
 9387    ) {
 9388    #ifdef WOLFSSL_DEBUG_TLS
 9389        WOLFSSL_MSG("Peer DH Key");
 9390        WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen);
 9391    #endif
 9392
 9393        ssl->options.dhKeySz = (word16)pSz;
 9394
 9395        /* Derive secret from private key and peer's public key. */
 9396        ret = DhAgree(ssl, dhKey,
 9397            (const byte*)keyShareEntry->privKey, keyShareEntry->keyLen, /* our private */
 9398            keyShareEntry->ke, keyShareEntry->keLen,                    /* peer's public key */
 9399            ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz,    /* secret */
 9400            NULL, 0
 9401        );
 9402    #ifdef WOLFSSL_ASYNC_CRYPT
 9403        if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
 9404            return ret;
 9405        }
 9406    #endif
 9407    }
 9408
 9409    /* RFC 8446 Section 7.4.1:
 9410     *     ... left-padded with zeros up to the size of the prime. ...
 9411     */
 9412    if (ret == 0 && (word32)ssl->options.dhKeySz > ssl->arrays->preMasterSz) {
 9413        word32 diff = (word32)ssl->options.dhKeySz - ssl->arrays->preMasterSz;
 9414        XMEMMOVE(ssl->arrays->preMasterSecret + diff,
 9415                        ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz);
 9416        XMEMSET(ssl->arrays->preMasterSecret, 0, diff);
 9417        ssl->arrays->preMasterSz = ssl->options.dhKeySz;
 9418    }
 9419
 9420    /* done with key share, release resources */
 9421    if (dhKey) {
 9422    #if defined(WC_DH_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW) && \
 9423        defined(WC_ASYNC_ENABLE_DH)
 9424        if (dhKey->nb != NULL) {
 9425            XFREE(dhKey->nb, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
 9426            dhKey->nb = NULL;
 9427        }
 9428    #endif
 9429        wc_FreeDhKey(dhKey);
 9430    }
 9431    XFREE(keyShareEntry->key, ssl->heap, DYNAMIC_TYPE_DH);
 9432    keyShareEntry->key = NULL;
 9433    if (keyShareEntry->privKey) {
 9434        ForceZero(keyShareEntry->privKey, keyShareEntry->keyLen);
 9435        XFREE(keyShareEntry->privKey, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
 9436        keyShareEntry->privKey = NULL;
 9437    }
 9438    XFREE(keyShareEntry->pubKey, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
 9439    keyShareEntry->pubKey = NULL;
 9440    XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
 9441    keyShareEntry->ke = NULL;
 9442#else
 9443    (void)ssl;
 9444    (void)keyShareEntry;
 9445    ret = PEER_KEY_ERROR;
 9446    WOLFSSL_ERROR_VERBOSE(ret);
 9447#endif
 9448    return ret;
 9449}
 9450
 9451/* Process the X25519 key share extension on the client side.
 9452 *
 9453 * ssl            The SSL/TLS object.
 9454 * keyShareEntry  The key share entry object to use to calculate shared secret.
 9455 * ssOutput       The destination buffer for the shared secret.
 9456 * ssOutSz        The size of the generated shared secret.
 9457 *
 9458 * returns 0 on success and other values indicate failure.
 9459 */
 9460static int TLSX_KeyShare_ProcessX25519_ex(WOLFSSL* ssl,
 9461                                          KeyShareEntry* keyShareEntry,
 9462                                          unsigned char* ssOutput,
 9463                                          word32* ssOutSz)
 9464{
 9465    int ret = 0;
 9466
 9467#ifdef HAVE_CURVE25519
 9468    curve25519_key* key = (curve25519_key*)keyShareEntry->key;
 9469
 9470#ifdef WOLFSSL_ASYNC_CRYPT
 9471    if (keyShareEntry->lastRet == 0) /* don't enter here if WC_PENDING_E */
 9472#endif
 9473    {
 9474    #ifdef HAVE_ECC
 9475        if (ssl->peerEccKey != NULL) {
 9476            wc_ecc_free(ssl->peerEccKey);
 9477            ssl->peerEccKey = NULL;
 9478            ssl->peerEccKeyPresent = 0;
 9479        }
 9480    #endif
 9481
 9482        ssl->peerX25519Key = (curve25519_key*)XMALLOC(sizeof(curve25519_key),
 9483                                        ssl->heap, DYNAMIC_TYPE_TLSX);
 9484        if (ssl->peerX25519Key == NULL) {
 9485            WOLFSSL_MSG("PeerX25519Key Memory error");
 9486            return MEMORY_ERROR;
 9487        }
 9488        ret = wc_curve25519_init(ssl->peerX25519Key);
 9489        if (ret != 0) {
 9490            XFREE(ssl->peerX25519Key, ssl->heap, DYNAMIC_TYPE_TLSX);
 9491            ssl->peerX25519Key = NULL;
 9492            return ret;
 9493        }
 9494    #ifdef WOLFSSL_DEBUG_TLS
 9495        WOLFSSL_MSG("Peer Curve25519 Key");
 9496        WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen);
 9497    #endif
 9498
 9499        if (wc_curve25519_check_public(keyShareEntry->ke, keyShareEntry->keLen,
 9500                                                  EC25519_LITTLE_ENDIAN) != 0) {
 9501            ret = ECC_PEERKEY_ERROR;
 9502            WOLFSSL_ERROR_VERBOSE(ret);
 9503        }
 9504
 9505        if (ret == 0) {
 9506            if (wc_curve25519_import_public_ex(keyShareEntry->ke,
 9507                                        keyShareEntry->keLen,
 9508                                        ssl->peerX25519Key,
 9509                                        EC25519_LITTLE_ENDIAN) != 0) {
 9510                ret = ECC_PEERKEY_ERROR;
 9511                WOLFSSL_ERROR_VERBOSE(ret);
 9512            }
 9513        }
 9514
 9515        if (ret == 0) {
 9516            ssl->ecdhCurveOID = ECC_X25519_OID;
 9517            ssl->peerX25519KeyPresent = 1;
 9518        }
 9519    }
 9520
 9521    if (ret == 0 && key == NULL)
 9522        ret = BAD_FUNC_ARG;
 9523    if (ret == 0) {
 9524    #ifdef WOLFSSL_CURVE25519_BLINDING
 9525        ret = wc_curve25519_set_rng(key, ssl->rng);
 9526    }
 9527    if (ret == 0) {
 9528    #endif
 9529    #ifdef WOLFSSL_ASYNC_CRYPT
 9530        if (keyShareEntry->lastRet != WC_NO_ERR_TRACE(WC_PENDING_E))
 9531    #endif
 9532        {
 9533        #ifdef WOLFSSL_ASYNC_CRYPT
 9534            /* initialize event */
 9535            ret = wolfSSL_AsyncInit(ssl, &key->asyncDev,
 9536                WC_ASYNC_FLAG_CALL_AGAIN);
 9537            if (ret != 0)
 9538                return ret;
 9539        #endif
 9540            ret = wc_curve25519_shared_secret_ex(key, ssl->peerX25519Key,
 9541                        ssOutput, ssOutSz, EC25519_LITTLE_ENDIAN);
 9542        #ifdef WOLFSSL_ASYNC_CRYPT
 9543            if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
 9544                return wolfSSL_AsyncPush(ssl, &key->asyncDev);
 9545            }
 9546        #endif
 9547        }
 9548        /* On CALL_AGAIN re-entry (lastRet == PENDING): the block above
 9549         * is skipped entirely, so wc_curve25519_shared_secret_ex is not
 9550         * called again. ret stays 0 from initialization, and execution
 9551         * falls through to the cleanup code below. */
 9552    }
 9553
 9554    /* done with key share, release resources */
 9555    if (ssl->peerX25519Key != NULL) {
 9556        wc_curve25519_free(ssl->peerX25519Key);
 9557        XFREE(ssl->peerX25519Key, ssl->heap, DYNAMIC_TYPE_TLSX);
 9558        ssl->peerX25519Key = NULL;
 9559        ssl->peerX25519KeyPresent = 0;
 9560    }
 9561    if (keyShareEntry->key != NULL) {
 9562    #if defined(WC_X25519_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW)
 9563        if (((curve25519_key*)keyShareEntry->key)->nb_ctx != NULL) {
 9564            XFREE(((curve25519_key*)keyShareEntry->key)->nb_ctx, ssl->heap,
 9565                DYNAMIC_TYPE_TMP_BUFFER);
 9566        }
 9567    #endif
 9568        wc_curve25519_free((curve25519_key*)keyShareEntry->key);
 9569        XFREE(keyShareEntry->key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
 9570        keyShareEntry->key = NULL;
 9571    }
 9572    XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
 9573    keyShareEntry->ke = NULL;
 9574#else
 9575    (void)ssl;
 9576    (void)keyShareEntry;
 9577    (void)ssOutput;
 9578    (void)ssOutSz;
 9579
 9580    ret = PEER_KEY_ERROR;
 9581    WOLFSSL_ERROR_VERBOSE(ret);
 9582#endif /* HAVE_CURVE25519 */
 9583
 9584    return ret;
 9585}
 9586
 9587/* Process the X25519 key share extension on the client side.
 9588 *
 9589 * ssl            The SSL/TLS object.
 9590 * keyShareEntry  The key share entry object to use to calculate shared secret.
 9591 *
 9592 * returns 0 on success and other values indicate failure.
 9593 */
 9594static int TLSX_KeyShare_ProcessX25519(WOLFSSL* ssl,
 9595                                       KeyShareEntry* keyShareEntry)
 9596{
 9597    return TLSX_KeyShare_ProcessX25519_ex(ssl, keyShareEntry,
 9598                ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz);
 9599}
 9600
 9601/* Process the X448 key share extension on the client side.
 9602 *
 9603 * ssl            The SSL/TLS object.
 9604 * keyShareEntry  The key share entry object to use to calculate shared secret.
 9605 * ssOutput       The destination buffer for the shared secret.
 9606 * ssOutSz        The size of the generated shared secret.
 9607 *
 9608 * returns 0 on success and other values indicate failure.
 9609 */
 9610static int TLSX_KeyShare_ProcessX448_ex(WOLFSSL* ssl,
 9611                                        KeyShareEntry* keyShareEntry,
 9612                                        unsigned char* ssOutput,
 9613                                        word32* ssOutSz)
 9614{
 9615    int ret;
 9616
 9617#ifdef HAVE_CURVE448
 9618    curve448_key* key = (curve448_key*)keyShareEntry->key;
 9619    curve448_key* peerX448Key;
 9620
 9621#ifdef HAVE_ECC
 9622    if (ssl->peerEccKey != NULL) {
 9623        wc_ecc_free(ssl->peerEccKey);
 9624        ssl->peerEccKey = NULL;
 9625        ssl->peerEccKeyPresent = 0;
 9626    }
 9627#endif
 9628
 9629    peerX448Key = (curve448_key*)XMALLOC(sizeof(curve448_key), ssl->heap,
 9630                                                             DYNAMIC_TYPE_TLSX);
 9631    if (peerX448Key == NULL) {
 9632        WOLFSSL_MSG("PeerEccKey Memory error");
 9633        return MEMORY_ERROR;
 9634    }
 9635    ret = wc_curve448_init(peerX448Key);
 9636    if (ret != 0) {
 9637        XFREE(peerX448Key, ssl->heap, DYNAMIC_TYPE_TLSX);
 9638        return ret;
 9639    }
 9640#ifdef WOLFSSL_DEBUG_TLS
 9641    WOLFSSL_MSG("Peer Curve448 Key");
 9642    WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen);
 9643#endif
 9644
 9645    if (wc_curve448_check_public(keyShareEntry->ke, keyShareEntry->keLen,
 9646                                                    EC448_LITTLE_ENDIAN) != 0) {
 9647        ret = ECC_PEERKEY_ERROR;
 9648        WOLFSSL_ERROR_VERBOSE(ret);
 9649    }
 9650
 9651    if (ret == 0) {
 9652        if (wc_curve448_import_public_ex(keyShareEntry->ke,
 9653                                              keyShareEntry->keLen, peerX448Key,
 9654                                              EC448_LITTLE_ENDIAN) != 0) {
 9655            ret = ECC_PEERKEY_ERROR;
 9656            WOLFSSL_ERROR_VERBOSE(ret);
 9657        }
 9658    }
 9659
 9660    if (ret == 0) {
 9661        ssl->ecdhCurveOID = ECC_X448_OID;
 9662
 9663        ret = wc_curve448_shared_secret_ex(key, peerX448Key,
 9664                    ssOutput, ssOutSz, EC448_LITTLE_ENDIAN);
 9665    }
 9666
 9667    wc_curve448_free(peerX448Key);
 9668    XFREE(peerX448Key, ssl->heap, DYNAMIC_TYPE_TLSX);
 9669    wc_curve448_free((curve448_key*)keyShareEntry->key);
 9670    XFREE(keyShareEntry->key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
 9671    keyShareEntry->key = NULL;
 9672    XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
 9673    keyShareEntry->ke = NULL;
 9674#else
 9675    (void)ssl;
 9676    (void)keyShareEntry;
 9677    (void)ssOutput;
 9678    (void)ssOutSz;
 9679
 9680    ret = PEER_KEY_ERROR;
 9681    WOLFSSL_ERROR_VERBOSE(ret);
 9682#endif /* HAVE_CURVE448 */
 9683
 9684    return ret;
 9685}
 9686
 9687/* Process the X448 key share extension on the client side.
 9688 *
 9689 * ssl            The SSL/TLS object.
 9690 * keyShareEntry  The key share entry object to use to calculate shared secret.
 9691 * returns 0 on success and other values indicate failure.
 9692 */
 9693static int TLSX_KeyShare_ProcessX448(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
 9694{
 9695    return TLSX_KeyShare_ProcessX448_ex(ssl, keyShareEntry,
 9696                ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz);
 9697}
 9698
 9699/* Process the ECC key share extension on the client side.
 9700 *
 9701 * ssl            The SSL/TLS object.
 9702 * keyShareEntry  The key share entry object to use to calculate shared secret.
 9703 * ssOutput       The destination buffer for the shared secret.
 9704 * ssOutSz        The size of the generated shared secret.
 9705 *
 9706 * returns 0 on success and other values indicate failure.
 9707 */
 9708static int TLSX_KeyShare_ProcessEcc_ex(WOLFSSL* ssl,
 9709                                       KeyShareEntry* keyShareEntry,
 9710                                       unsigned char* ssOutput,
 9711                                       word32* ssOutSz)
 9712{
 9713    int ret = 0;
 9714#ifdef HAVE_ECC
 9715    int curveId = ECC_CURVE_INVALID;
 9716    ecc_key* eccKey = (ecc_key*)keyShareEntry->key;
 9717
 9718    /* find supported curve */
 9719    switch (keyShareEntry->group) {
 9720    #if (!defined(NO_ECC256)  || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 256
 9721        #ifndef NO_ECC_SECP
 9722        case WOLFSSL_ECC_SECP256R1:
 9723            curveId = ECC_SECP256R1;
 9724            break;
 9725        #endif /* !NO_ECC_SECP */
 9726        #ifdef WOLFSSL_SM2
 9727        case WOLFSSL_ECC_SM2P256V1:
 9728            curveId = ECC_SM2P256V1;
 9729            break;
 9730        #endif /* WOLFSSL_SM2 */
 9731        #ifdef HAVE_ECC_BRAINPOOL
 9732        case WOLFSSL_ECC_BRAINPOOLP256R1TLS13:
 9733            curveId = ECC_BRAINPOOLP256R1;
 9734            break;
 9735        #endif /* HAVE_ECC_BRAINPOOL */
 9736    #endif
 9737    #if (defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 384
 9738        #ifndef NO_ECC_SECP
 9739        case WOLFSSL_ECC_SECP384R1:
 9740            curveId = ECC_SECP384R1;
 9741            break;
 9742        #endif /* !NO_ECC_SECP */
 9743        #ifdef HAVE_ECC_BRAINPOOL
 9744        case WOLFSSL_ECC_BRAINPOOLP384R1TLS13:
 9745            curveId = ECC_BRAINPOOLP384R1;
 9746            break;
 9747        #endif /* HAVE_ECC_BRAINPOOL */
 9748    #endif
 9749    #if (defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 512
 9750        #ifdef HAVE_ECC_BRAINPOOL
 9751        case WOLFSSL_ECC_BRAINPOOLP512R1TLS13:
 9752            curveId = ECC_BRAINPOOLP512R1;
 9753            break;
 9754        #endif /* HAVE_ECC_BRAINPOOL */
 9755    #endif
 9756    #if (defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 521
 9757        #ifndef NO_ECC_SECP
 9758        case WOLFSSL_ECC_SECP521R1:
 9759            curveId = ECC_SECP521R1;
 9760            break;
 9761        #endif /* !NO_ECC_SECP */
 9762    #endif
 9763    #if defined(HAVE_X448) && ECC_MIN_KEY_SZ <= 448
 9764        case WOLFSSL_ECC_X448:
 9765            curveId = ECC_X448;
 9766            break;
 9767    #endif
 9768        default:
 9769            /* unsupported curve */
 9770            WOLFSSL_ERROR_VERBOSE(ECC_PEERKEY_ERROR);
 9771            return ECC_PEERKEY_ERROR;
 9772    }
 9773
 9774#ifdef WOLFSSL_ASYNC_CRYPT
 9775    if (keyShareEntry->lastRet == 0) /* don't enter here if WC_PENDING_E */
 9776#endif
 9777    {
 9778    #ifdef WOLFSSL_DEBUG_TLS
 9779        WOLFSSL_MSG("Peer ECC Key");
 9780        WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen);
 9781    #endif
 9782
 9783        if (ssl->peerEccKey != NULL) {
 9784            wc_ecc_free(ssl->peerEccKey);
 9785            XFREE(ssl->peerEccKey, ssl->heap, DYNAMIC_TYPE_ECC);
 9786            ssl->peerEccKeyPresent = 0;
 9787        }
 9788#if defined(WOLFSSL_RENESAS_TSIP_TLS)
 9789        ret = tsip_Tls13GenSharedSecret(ssl, keyShareEntry);
 9790        if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
 9791            return ret;
 9792        }
 9793        ret = 0;
 9794#endif
 9795
 9796        ssl->peerEccKey = (ecc_key*)XMALLOC(sizeof(ecc_key), ssl->heap,
 9797                                            DYNAMIC_TYPE_ECC);
 9798        if (ssl->peerEccKey == NULL) {
 9799            WOLFSSL_MSG("PeerEccKey Memory error");
 9800            ret = MEMORY_ERROR;
 9801        }
 9802
 9803        if (ret == 0) {
 9804            ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, ssl->devId);
 9805        }
 9806
 9807        /* Point is validated by import function. */
 9808        if (ret == 0) {
 9809#if !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS)
 9810            ret = wc_ecc_import_x963_ex2(keyShareEntry->ke,
 9811                keyShareEntry->keLen, ssl->peerEccKey, curveId, 1);
 9812#else
 9813            /* FIPS has validation define on. */
 9814            ret = wc_ecc_import_x963_ex(keyShareEntry->ke,
 9815                keyShareEntry->keLen, ssl->peerEccKey, curveId);
 9816#endif
 9817            if (ret != 0) {
 9818                ret = ECC_PEERKEY_ERROR;
 9819                WOLFSSL_ERROR_VERBOSE(ret);
 9820            }
 9821        }
 9822
 9823        if (ret == 0) {
 9824            ssl->ecdhCurveOID = ssl->peerEccKey->dp->oidSum;
 9825            ssl->peerEccKeyPresent = 1;
 9826        }
 9827    }
 9828
 9829    if (ret == 0 && eccKey == NULL)
 9830        ret = BAD_FUNC_ARG;
 9831    if (ret == 0) {
 9832        ret = EccSharedSecret(ssl, eccKey, ssl->peerEccKey,
 9833            keyShareEntry->ke, &keyShareEntry->keLen,
 9834            ssOutput, ssOutSz, ssl->options.side);
 9835    #ifdef WOLFSSL_ASYNC_CRYPT
 9836        if (ret == WC_NO_ERR_TRACE(WC_PENDING_E))
 9837            return ret;
 9838    #endif
 9839    }
 9840
 9841    /* done with key share, release resources */
 9842    if (ssl->peerEccKey != NULL
 9843    #ifdef HAVE_PK_CALLBACKS
 9844        && ssl->ctx->EccSharedSecretCb == NULL
 9845    #endif
 9846    ) {
 9847        wc_ecc_free(ssl->peerEccKey);
 9848        XFREE(ssl->peerEccKey, ssl->heap, DYNAMIC_TYPE_ECC);
 9849        ssl->peerEccKey = NULL;
 9850        ssl->peerEccKeyPresent = 0;
 9851    }
 9852    if (eccKey != NULL) {
 9853    #if defined(WC_ECC_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW) && \
 9854        defined(WC_ASYNC_ENABLE_ECC)
 9855        if (eccKey->nb_ctx != NULL) {
 9856            XFREE(eccKey->nb_ctx, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
 9857        }
 9858    #endif
 9859        wc_ecc_free(eccKey);
 9860        XFREE(keyShareEntry->key, ssl->heap, DYNAMIC_TYPE_ECC);
 9861        keyShareEntry->key = NULL;
 9862    }
 9863    XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
 9864    keyShareEntry->ke = NULL;
 9865#else
 9866    (void)ssl;
 9867    (void)keyShareEntry;
 9868    (void)ssOutput;
 9869    (void)ssOutSz;
 9870
 9871    ret = PEER_KEY_ERROR;
 9872    WOLFSSL_ERROR_VERBOSE(ret);
 9873#endif /* HAVE_ECC */
 9874
 9875    return ret;
 9876}
 9877
 9878/* Process the ECC key share extension on the client side.
 9879 *
 9880 * ssl            The SSL/TLS object.
 9881 * keyShareEntry  The key share entry object to use to calculate shared secret.
 9882 * returns 0 on success and other values indicate failure.
 9883 */
 9884static int TLSX_KeyShare_ProcessEcc(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
 9885{
 9886    return TLSX_KeyShare_ProcessEcc_ex(ssl, keyShareEntry,
 9887                ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz);
 9888}
 9889
 9890#if defined(WOLFSSL_HAVE_MLKEM) && !defined(WOLFSSL_MLKEM_NO_DECAPSULATE)
 9891/* Process the Kyber key share extension on the client side.
 9892 *
 9893 * ssl            The SSL/TLS object.
 9894 * keyShareEntry  The key share entry object to use to calculate shared secret.
 9895 * ssOutput       The destination buffer for the shared secret.
 9896 * ssOutSz        The size of the generated shared secret.
 9897 *
 9898 * returns 0 on success and other values indicate failure.
 9899 */
 9900static int TLSX_KeyShare_ProcessPqcClient_ex(WOLFSSL* ssl,
 9901                                             KeyShareEntry* keyShareEntry,
 9902                                             unsigned char* ssOutput,
 9903                                             word32* ssOutSz)
 9904{
 9905    int       ret = 0;
 9906    KyberKey* kem = (KyberKey*)keyShareEntry->key;
 9907#ifndef WOLFSSL_TLSX_PQC_MLKEM_STORE_OBJ
 9908    word32    privSz = 0;
 9909#endif
 9910    word32    ctSz = 0;
 9911    word32    ssSz = 0;
 9912
 9913    if (ssl->options.side == WOLFSSL_SERVER_END) {
 9914        /* I am the server, the shared secret has already been generated and
 9915         * is in ssl->arrays->preMasterSecret, so nothing really to do here. */
 9916        return 0;
 9917    }
 9918
 9919    if (keyShareEntry->ke == NULL) {
 9920        WOLFSSL_MSG("Invalid PQC algorithm specified.");
 9921        return BAD_FUNC_ARG;
 9922    }
 9923    if (ssOutSz == NULL)
 9924        return BAD_FUNC_ARG;
 9925
 9926#ifndef WOLFSSL_TLSX_PQC_MLKEM_STORE_OBJ
 9927    if (kem == NULL) {
 9928        int type = 0;
 9929
 9930        /* Allocate a Kyber key to hold private key. */
 9931        kem = (KyberKey*) XMALLOC(sizeof(KyberKey), ssl->heap,
 9932                                  DYNAMIC_TYPE_PRIVATE_KEY);
 9933        if (kem == NULL) {
 9934            WOLFSSL_MSG("GenPqcKey memory error");
 9935            ret = MEMORY_E;
 9936        }
 9937        if (ret == 0) {
 9938            ret = mlkem_id2type(keyShareEntry->group, &type);
 9939        }
 9940        if (ret != 0) {
 9941            WOLFSSL_MSG("Invalid PQC algorithm specified.");
 9942            ret = BAD_FUNC_ARG;
 9943        }
 9944        if (ret == 0) {
 9945            ret = wc_KyberKey_Init(type, kem, ssl->heap, ssl->devId);
 9946            if (ret != 0) {
 9947                WOLFSSL_MSG("Error creating Kyber KEM");
 9948            }
 9949        }
 9950    }
 9951#else
 9952    if (kem == NULL || keyShareEntry->privKeyLen != 0) {
 9953        WOLFSSL_MSG("Invalid Kyber key.");
 9954        ret = BAD_FUNC_ARG;
 9955    }
 9956#endif
 9957
 9958    if (ret == 0) {
 9959        ret = wc_KyberKey_SharedSecretSize(kem, &ssSz);
 9960    }
 9961    if (ret == 0) {
 9962        ret = wc_KyberKey_CipherTextSize(kem, &ctSz);
 9963    }
 9964
 9965#ifndef WOLFSSL_TLSX_PQC_MLKEM_STORE_OBJ
 9966    if (ret == 0) {
 9967        ret = wc_KyberKey_PrivateKeySize(kem, &privSz);
 9968    }
 9969    if (ret == 0 && privSz != keyShareEntry->privKeyLen) {
 9970        WOLFSSL_MSG("Invalid private key size.");
 9971        ret = BAD_FUNC_ARG;
 9972    }
 9973    if (ret == 0) {
 9974        PRIVATE_KEY_UNLOCK();
 9975        ret = wc_KyberKey_DecodePrivateKey(kem, keyShareEntry->privKey, privSz);
 9976        PRIVATE_KEY_LOCK();
 9977    }
 9978#endif
 9979
 9980    if (ret == 0 && keyShareEntry->keLen < ctSz) {
 9981        WOLFSSL_MSG("PQC key share data too short for ciphertext.");
 9982        ret = BUFFER_E;
 9983    }
 9984    if (ret == 0) {
 9985        PRIVATE_KEY_UNLOCK();
 9986        ret = wc_KyberKey_Decapsulate(kem, ssOutput,
 9987                                      keyShareEntry->ke, ctSz);
 9988        PRIVATE_KEY_LOCK();
 9989        if (ret != 0) {
 9990            WOLFSSL_MSG("wc_KyberKey decapsulation failure.");
 9991            ret = BAD_FUNC_ARG;
 9992        }
 9993    }
 9994    if (ret == 0) {
 9995        *ssOutSz = ssSz;
 9996    }
 9997
 9998    wc_KyberKey_Free(kem);
 9999
10000    XFREE(kem, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
10001    keyShareEntry->key = NULL;
10002
10003    XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
10004    keyShareEntry->ke = NULL;
10005
10006    return ret;
10007}
10008
10009/* Process the Kyber key share extension on the client side.
10010 *
10011 * ssl            The SSL/TLS object.
10012 * keyShareEntry  The key share entry object to use to calculate shared secret.
10013 *
10014 * returns 0 on success and other values indicate failure.
10015 */
10016static int TLSX_KeyShare_ProcessPqcClient(WOLFSSL* ssl,
10017                                          KeyShareEntry* keyShareEntry)
10018{
10019    return TLSX_KeyShare_ProcessPqcClient_ex(ssl, keyShareEntry,
10020                                             ssl->arrays->preMasterSecret,
10021                                             &ssl->arrays->preMasterSz);
10022}
10023
10024/* Process the hybrid key share extension on the client side.
10025 *
10026 * ssl            The SSL/TLS object.
10027 * keyShareEntry  The key share entry object to use to calculate shared secret.
10028 * returns 0 on success and other values indicate failure.
10029 */
10030static int TLSX_KeyShare_ProcessPqcHybridClient(WOLFSSL* ssl,
10031                                                KeyShareEntry* keyShareEntry)
10032{
10033    int      ret = 0;
10034    int      pqc_group = 0;
10035    int      ecc_group = 0;
10036    int      pqc_first = 0;
10037    KeyShareEntry* pqc_kse = NULL;
10038    KeyShareEntry *ecc_kse = NULL;
10039    word32   ctSz = 0;
10040    word32   ssSzPqc = 0;
10041
10042    if (ssl->options.side == WOLFSSL_SERVER_END) {
10043        /* I am the server, the shared secret has already been generated and
10044         * is in ssl->arrays->preMasterSecret, so nothing really to do here. */
10045        return 0;
10046    }
10047
10048    if (keyShareEntry->ke == NULL) {
10049        WOLFSSL_MSG("Invalid PQC algorithm specified.");
10050        return BAD_FUNC_ARG;
10051    }
10052
10053    /* I am the client, both the PQC ciphertext and the ECHD public key are in
10054     * keyShareEntry->ke */
10055
10056    /* Determine the ECC and PQC group of the hybrid combination */
10057    findEccPqc(&ecc_group, &pqc_group, &pqc_first, keyShareEntry->group);
10058    if (ecc_group == 0 || pqc_group == 0) {
10059        WOLFSSL_MSG("Invalid hybrid group");
10060        ret = BAD_FUNC_ARG;
10061    }
10062
10063    if (ret == 0) {
10064        ecc_kse = (KeyShareEntry*)XMALLOC(sizeof(*ecc_kse), ssl->heap,
10065                   DYNAMIC_TYPE_TLSX);
10066        if (ecc_kse == NULL) {
10067            WOLFSSL_MSG("kse memory allocation failure");
10068            ret = MEMORY_ERROR;
10069        }
10070        else {
10071            XMEMSET(ecc_kse, 0, sizeof(*ecc_kse));
10072        }
10073    }
10074    if (ret == 0) {
10075        pqc_kse = (KeyShareEntry*)XMALLOC(sizeof(*pqc_kse), ssl->heap,
10076                   DYNAMIC_TYPE_TLSX);
10077        if (pqc_kse == NULL) {
10078            WOLFSSL_MSG("kse memory allocation failure");
10079            ret = MEMORY_ERROR;
10080        }
10081        else {
10082            XMEMSET(pqc_kse, 0, sizeof(*pqc_kse));
10083        }
10084    }
10085
10086    /* The ciphertext and shared secret sizes of a KEM are fixed. Hence, we
10087     * decode these sizes to separate the KEM ciphertext from the ECDH public
10088     * key. */
10089    if (ret == 0) {
10090    #ifndef WOLFSSL_TLSX_PQC_MLKEM_STORE_OBJ
10091        int type;
10092
10093        pqc_kse->privKey = keyShareEntry->privKey;
10094
10095        ret = mlkem_id2type(pqc_group, &type);
10096        if (ret != 0) {
10097            WOLFSSL_MSG("Invalid Kyber algorithm specified.");
10098            ret = BAD_FUNC_ARG;
10099        }
10100        if (ret == 0) {
10101            pqc_kse->key = XMALLOC(sizeof(KyberKey), ssl->heap,
10102                                DYNAMIC_TYPE_PRIVATE_KEY);
10103            if (pqc_kse->key == NULL) {
10104                WOLFSSL_MSG("GenPqcKey memory error");
10105                ret = MEMORY_E;
10106            }
10107        }
10108        if (ret == 0) {
10109            ret = wc_KyberKey_Init(type, (KyberKey*)pqc_kse->key,
10110                                   ssl->heap, ssl->devId);
10111            if (ret != 0) {
10112                WOLFSSL_MSG("Error creating Kyber KEM");
10113            }
10114        }
10115    #else
10116        pqc_kse->key = keyShareEntry->privKey;
10117    #endif
10118
10119        pqc_kse->group = pqc_group;
10120        pqc_kse->privKeyLen = keyShareEntry->privKeyLen;
10121
10122        if (ret == 0) {
10123            ret = wc_KyberKey_SharedSecretSize((KyberKey*)pqc_kse->key,
10124                                               &ssSzPqc);
10125        }
10126        if (ret == 0) {
10127            ret = wc_KyberKey_CipherTextSize((KyberKey*)pqc_kse->key,
10128                                             &ctSz);
10129            if (ret == 0 && keyShareEntry->keLen <= ctSz) {
10130                WOLFSSL_MSG("Invalid ciphertext size.");
10131                ret = BAD_FUNC_ARG;
10132            }
10133        }
10134        if (ret == 0) {
10135            pqc_kse->keLen = ctSz;
10136            pqc_kse->ke = (byte*)XMALLOC(pqc_kse->keLen, ssl->heap,
10137                                         DYNAMIC_TYPE_PUBLIC_KEY);
10138            if (pqc_kse->ke == NULL) {
10139                WOLFSSL_MSG("pqc_kse memory allocation failure");
10140                ret = MEMORY_ERROR;
10141            }
10142            /* Copy the PQC KEM ciphertext. Depending on the pqc_first flag,
10143             * the KEM ciphertext comes before or after the ECDH public key. */
10144            if (ret == 0) {
10145                int offset = keyShareEntry->keLen - ctSz;
10146
10147                if (pqc_first)
10148                    offset = 0;
10149
10150                XMEMCPY(pqc_kse->ke, keyShareEntry->ke + offset, ctSz);
10151            }
10152        }
10153    }
10154
10155    if (ret == 0) {
10156        ecc_kse->group = ecc_group;
10157        ecc_kse->keLen = keyShareEntry->keLen - ctSz;
10158        ecc_kse->key = keyShareEntry->key;
10159        ecc_kse->ke = (byte*)XMALLOC(ecc_kse->keLen, ssl->heap,
10160                                        DYNAMIC_TYPE_PUBLIC_KEY);
10161        if (ecc_kse->ke == NULL) {
10162            WOLFSSL_MSG("ecc_kse memory allocation failure");
10163            ret = MEMORY_ERROR;
10164        }
10165        /* Copy the ECDH public key. Depending on the pqc_first flag, the
10166         * KEM ciphertext comes before or after the ECDH public key. */
10167        if (ret == 0) {
10168            int offset = 0;
10169
10170            if (pqc_first)
10171                offset = ctSz;
10172
10173            XMEMCPY(ecc_kse->ke, keyShareEntry->ke + offset, ecc_kse->keLen);
10174        }
10175    #ifdef WOLFSSL_ASYNC_CRYPT
10176        ecc_kse->lastRet = keyShareEntry->lastRet;
10177    #endif
10178    }
10179
10180    /* Process ECDH key share part. The generated shared secret is directly
10181     * stored in the ssl->arrays->preMasterSecret buffer. Depending on the
10182     * pqc_first flag, the ECDH shared secret part goes before or after the
10183     * KEM part. */
10184    if (ret == 0) {
10185        int offset = 0;
10186
10187        if (pqc_first)
10188            offset = ssSzPqc;
10189
10190    #ifdef HAVE_CURVE25519
10191        if (ecc_group == WOLFSSL_ECC_X25519) {
10192            ret = TLSX_KeyShare_ProcessX25519_ex(ssl, ecc_kse,
10193                    ssl->arrays->preMasterSecret + offset,
10194                    &ssl->arrays->preMasterSz);
10195        }
10196        else
10197    #endif
10198    #ifdef HAVE_CURVE448
10199        if (ecc_group == WOLFSSL_ECC_X448) {
10200            ret = TLSX_KeyShare_ProcessX448_ex(ssl, ecc_kse,
10201                    ssl->arrays->preMasterSecret + offset,
10202                    &ssl->arrays->preMasterSz);
10203        }
10204        else
10205    #endif
10206        {
10207            ret = TLSX_KeyShare_ProcessEcc_ex(ssl, ecc_kse,
10208                    ssl->arrays->preMasterSecret + offset,
10209                    &ssl->arrays->preMasterSz);
10210        }
10211
10212    #ifdef WOLFSSL_ASYNC_CRYPT
10213        if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
10214            keyShareEntry->lastRet = WC_PENDING_E;
10215            /* Prevent freeing of the ECC and ML-KEM private keys */
10216            ecc_kse->key = NULL;
10217            pqc_kse->privKey = NULL;
10218        }
10219        else
10220    #endif
10221        {
10222            /* Re-sync keyShareEntry->key with ecc_kse->key. ecc_kse->key was
10223             * aliased to keyShareEntry->key above. The inner Process*_ex
10224             * either ran its end-of-function cleanup and set ecc_kse->key
10225             * to NULL (so the outer pointer must also become NULL to avoid
10226             * UAF/double-free in TLSX_KeyShare_FreeAll), or returned early
10227             * before cleanup with ecc_kse->key still pointing at the live
10228             * key (so the outer pointer must keep that pointer for later
10229             * freeing). Mirroring whatever the inner left in ecc_kse->key
10230             * handles both cases correctly. */
10231            keyShareEntry->key = ecc_kse->key;
10232        }
10233    }
10234
10235    if (ret == 0) {
10236        if ((ssl->arrays->preMasterSz + ssSzPqc) > ENCRYPT_LEN) {
10237            WOLFSSL_MSG("shared secret is too long.");
10238            ret = LENGTH_ERROR;
10239        }
10240    }
10241
10242    /* Process PQC KEM key share part. Depending on the pqc_first flag, the
10243     * KEM shared secret part goes before or after the ECDH part. */
10244    if (ret == 0) {
10245        int offset = ssl->arrays->preMasterSz;
10246
10247        if (pqc_first)
10248            offset = 0;
10249
10250        ret = TLSX_KeyShare_ProcessPqcClient_ex(ssl, pqc_kse,
10251                ssl->arrays->preMasterSecret + offset, &ssSzPqc);
10252    }
10253
10254    if (ret == 0) {
10255        keyShareEntry->privKey = (byte*)pqc_kse->key;
10256
10257        ssl->arrays->preMasterSz += ssSzPqc;
10258    }
10259    else
10260#ifdef WOLFSSL_ASYNC_CRYPT
10261        if (ret != WC_NO_ERR_TRACE(WC_PENDING_E))
10262#endif
10263    {
10264        /* Clear the pre master secret buffer to prevent leaking any
10265         * intermediate keys in the error case. Do not use preMasterSz
10266         * here as it may already been set to the ECC shared secret size,
10267         * which would be too small due to the PQC offset case. */
10268        ForceZero(ssl->arrays->preMasterSecret, ENCRYPT_LEN);
10269
10270        /* Prevent FreeAll from freeing pointers owned by keyShareEntry. */
10271        if (ecc_kse != NULL)
10272            ecc_kse->key = NULL;
10273        if (pqc_kse != NULL) {
10274        #ifndef WOLFSSL_TLSX_PQC_MLKEM_STORE_OBJ
10275            pqc_kse->privKey = NULL;
10276        #else
10277            pqc_kse->key = NULL;
10278        #endif
10279        }
10280    }
10281
10282    TLSX_KeyShare_FreeAll(ecc_kse, ssl->heap);
10283    TLSX_KeyShare_FreeAll(pqc_kse, ssl->heap);
10284
10285    return ret;
10286}
10287#endif /* WOLFSSL_HAVE_MLKEM && !WOLFSSL_MLKEM_NO_DECAPSULATE */
10288
10289/* Process the key share extension on the client side.
10290 *
10291 * ssl            The SSL/TLS object.
10292 * keyShareEntry  The key share entry object to use to calculate shared secret.
10293 * returns 0 on success and other values indicate failure.
10294 */
10295static int TLSX_KeyShare_Process(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
10296{
10297    int ret;
10298
10299#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
10300    keyShareEntry->session = ssl->session->namedGroup;
10301    ssl->session->namedGroup = keyShareEntry->group;
10302#endif
10303    /* reset the pre master secret size */
10304    if (ssl->arrays->preMasterSz == 0)
10305        ssl->arrays->preMasterSz = ENCRYPT_LEN;
10306
10307    /* Use Key Share Data from server. */
10308    if (WOLFSSL_NAMED_GROUP_IS_FFDHE(keyShareEntry->group))
10309        ret = TLSX_KeyShare_ProcessDh(ssl, keyShareEntry);
10310    else if (keyShareEntry->group == WOLFSSL_ECC_X25519)
10311        ret = TLSX_KeyShare_ProcessX25519(ssl, keyShareEntry);
10312    else if (keyShareEntry->group == WOLFSSL_ECC_X448)
10313        ret = TLSX_KeyShare_ProcessX448(ssl, keyShareEntry);
10314#if defined(WOLFSSL_HAVE_MLKEM) && !defined(WOLFSSL_MLKEM_NO_DECAPSULATE)
10315    else if (WOLFSSL_NAMED_GROUP_IS_PQC(keyShareEntry->group))
10316        ret = TLSX_KeyShare_ProcessPqcClient(ssl, keyShareEntry);
10317    else if (WOLFSSL_NAMED_GROUP_IS_PQC_HYBRID(keyShareEntry->group))
10318        ret = TLSX_KeyShare_ProcessPqcHybridClient(ssl, keyShareEntry);
10319#endif
10320    else
10321        ret = TLSX_KeyShare_ProcessEcc(ssl, keyShareEntry);
10322
10323#ifdef WOLFSSL_DEBUG_TLS
10324    if (ret == 0) {
10325        WOLFSSL_MSG("KE Secret");
10326        WOLFSSL_BUFFER(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz);
10327    }
10328#endif
10329#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
10330    keyShareEntry->derived = (ret == 0);
10331#endif
10332#ifdef WOLFSSL_ASYNC_CRYPT
10333    keyShareEntry->lastRet = ret;
10334#endif
10335
10336    return ret;
10337}
10338
10339/* Parse an entry of the KeyShare extension.
10340 *
10341 * ssl     The SSL/TLS object.
10342 * input   The extension data.
10343 * length  The length of the extension data.
10344 * kse     The new key share entry object.
10345 * returns a positive number to indicate amount of data parsed and a negative
10346 * number on error.
10347 */
10348static int TLSX_KeyShareEntry_Parse(const WOLFSSL* ssl, const byte* input,
10349            word16 length, KeyShareEntry **kse, word16* seenGroups,
10350            int* seenGroupsCnt, TLSX** extensions)
10351{
10352    int    ret;
10353    word16 group;
10354    word16 keLen;
10355    int    offset = 0;
10356    byte*  ke;
10357    int    i;
10358
10359    if (length < OPAQUE16_LEN + OPAQUE16_LEN)
10360        return BUFFER_ERROR;
10361    /* Named group */
10362    ato16(&input[offset], &group);
10363    offset += OPAQUE16_LEN;
10364    /* Key exchange data - public key. */
10365    ato16(&input[offset], &keLen);
10366    offset += OPAQUE16_LEN;
10367    if (keLen == 0)
10368        return BUFFER_ERROR;
10369    if (keLen > length - offset)
10370        return BUFFER_ERROR;
10371
10372    if (seenGroups != NULL) {
10373        if (*seenGroupsCnt >= MAX_KEYSHARE_NAMED_GROUPS) {
10374            return BAD_KEY_SHARE_DATA;
10375        }
10376        for (i = 0; i < *seenGroupsCnt; i++) {
10377            if (seenGroups[i] == group) {
10378                return BAD_KEY_SHARE_DATA;
10379            }
10380        }
10381        seenGroups[i] = group;
10382        *seenGroupsCnt = i + 1;
10383    }
10384
10385    /* Store a copy in the key share object. */
10386    ke = (byte*)XMALLOC(keLen, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
10387    if (ke == NULL)
10388        return MEMORY_E;
10389    XMEMCPY(ke, &input[offset], keLen);
10390
10391    /* Populate a key share object in the extension. */
10392    ret = TLSX_KeyShare_Use(ssl, group, keLen, ke, kse, extensions);
10393    if (ret != 0) {
10394        XFREE(ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
10395        return ret;
10396    }
10397
10398    /* Total length of the parsed data. */
10399    return offset + keLen;
10400}
10401
10402/* Searches the groups sent for the specified named group.
10403 *
10404 * ssl    SSL/TLS object.
10405 * name   Group name to match.
10406 * returns 1 when the extension has the group name and 0 otherwise.
10407 */
10408static int TLSX_KeyShare_Find(WOLFSSL* ssl, word16 group)
10409{
10410    TLSX*          extension;
10411    KeyShareEntry* list;
10412
10413    extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
10414    if (extension == NULL) {
10415        extension = TLSX_Find(ssl->ctx->extensions, TLSX_KEY_SHARE);
10416        if (extension == NULL)
10417            return 0;
10418    }
10419
10420    list = (KeyShareEntry*)extension->data;
10421    while (list != NULL) {
10422        if (list->group == group)
10423            return 1;
10424        list = list->next;
10425    }
10426
10427    return 0;
10428}
10429
10430
10431/* Searches the supported groups extension for the specified named group.
10432 *
10433 * ssl   The SSL/TLS object.
10434 * name  The group name to match.
10435 * returns 1 when the extension has the group name and 0 otherwise.
10436 */
10437static int TLSX_SupportedGroups_Find(const WOLFSSL* ssl, word16 name,
10438                                     TLSX* extensions)
10439{
10440#ifdef HAVE_SUPPORTED_CURVES
10441    TLSX*          extension;
10442    SupportedCurve* curve = NULL;
10443
10444    if ((extension = TLSX_Find(extensions, TLSX_SUPPORTED_GROUPS)) == NULL) {
10445        if ((extension = TLSX_Find(ssl->ctx->extensions,
10446                                              TLSX_SUPPORTED_GROUPS)) == NULL) {
10447            return 0;
10448        }
10449    }
10450
10451    for (curve = (SupportedCurve*)extension->data; curve; curve = curve->next) {
10452        if (curve->name == name)
10453            return 1;
10454    }
10455#endif
10456
10457    (void)ssl;
10458    (void)name;
10459
10460    return 0;
10461}
10462
10463int TLSX_KeyShare_Parse_ClientHello(const WOLFSSL* ssl,
10464        const byte* input, word16 length, TLSX** extensions)
10465{
10466    int ret;
10467    int    offset = 0;
10468    word16 len;
10469    TLSX*  extension;
10470    word16 seenGroups[MAX_KEYSHARE_NAMED_GROUPS];
10471    int    seenGroupsCnt = 0;
10472
10473    /* Add a KeyShare extension if it doesn't exist even if peer sent no
10474     * entries. The presence of this extension signals that the peer can be
10475     * negotiated with. */
10476    extension = TLSX_Find(*extensions, TLSX_KEY_SHARE);
10477    if (extension == NULL) {
10478        /* Push new KeyShare extension. */
10479        ret = TLSX_Push(extensions, TLSX_KEY_SHARE, NULL, ssl->heap);
10480        if (ret != 0)
10481            return ret;
10482    }
10483
10484    if (length < OPAQUE16_LEN)
10485        return BUFFER_ERROR;
10486
10487    /* ClientHello contains zero or more key share entries. Limits extension
10488     * length to 2^16-1 and subtracting 4 bytes for header size per RFC 8446 */
10489    ato16(input, &len);
10490    if ((len != length - OPAQUE16_LEN) ||
10491         length > (MAX_EXT_DATA_LEN - HELLO_EXT_SZ)) {
10492        return BUFFER_ERROR;
10493    }
10494    offset += OPAQUE16_LEN;
10495
10496    while (offset < (int)length) {
10497        ret = TLSX_KeyShareEntry_Parse(ssl, &input[offset],
10498                length - (word16)offset, NULL, seenGroups, &seenGroupsCnt,
10499                extensions);
10500        if (ret < 0)
10501            return ret;
10502
10503        offset += ret;
10504    }
10505
10506    return 0;
10507}
10508
10509/* Parse the KeyShare extension.
10510 * Different formats in different messages.
10511 *
10512 * ssl      The SSL/TLS object.
10513 * input    The extension data.
10514 * length   The length of the extension data.
10515 * msgType  The type of the message this extension is being parsed from.
10516 * returns 0 on success and other values indicate failure.
10517 */
10518int TLSX_KeyShare_Parse(WOLFSSL* ssl, const byte* input, word16 length,
10519                               byte msgType)
10520{
10521    int ret = 0;
10522    KeyShareEntry *keyShareEntry = NULL;
10523    word16 group;
10524
10525    if (msgType == client_hello) {
10526        ret = TLSX_KeyShare_Parse_ClientHello(ssl, input, length,
10527                                              &ssl->extensions);
10528    }
10529    else if (msgType == server_hello) {
10530        int len;
10531
10532        if (length < OPAQUE16_LEN)
10533            return BUFFER_ERROR;
10534
10535        ssl->options.shSentKeyShare = 1;
10536
10537        /* The data is the named group the server wants to use. */
10538        ato16(input, &group);
10539
10540        /* Check the selected group was supported by ClientHello extensions. */
10541        if (!TLSX_SupportedGroups_Find(ssl, group, ssl->extensions)) {
10542            WOLFSSL_ERROR_VERBOSE(BAD_KEY_SHARE_DATA);
10543            return BAD_KEY_SHARE_DATA;
10544        }
10545
10546        /* Check if the group was sent. */
10547        if (!TLSX_KeyShare_Find(ssl, group)) {
10548            WOLFSSL_ERROR_VERBOSE(BAD_KEY_SHARE_DATA);
10549            return BAD_KEY_SHARE_DATA;
10550        }
10551
10552        /* ServerHello contains one key share entry. */
10553        len = TLSX_KeyShareEntry_Parse(ssl, input, length, &keyShareEntry, NULL,
10554                NULL, &ssl->extensions);
10555        if (len != (int)length)
10556            return BUFFER_ERROR;
10557
10558        /* Not in list sent if there isn't a private key. */
10559        if (keyShareEntry == NULL || (keyShareEntry->key == NULL
10560        #if !defined(NO_DH) || defined(WOLFSSL_HAVE_MLKEM)
10561            && keyShareEntry->privKey == NULL
10562        #endif
10563        )) {
10564            WOLFSSL_ERROR_VERBOSE(BAD_KEY_SHARE_DATA);
10565            return BAD_KEY_SHARE_DATA;
10566        }
10567
10568        /* Process the entry to calculate the secret. */
10569        ret = TLSX_KeyShare_Process(ssl, keyShareEntry);
10570        if (ret == 0)
10571            ssl->session->namedGroup = ssl->namedGroup = group;
10572    }
10573    else if (msgType == hello_retry_request) {
10574        if (length != OPAQUE16_LEN)
10575            return BUFFER_ERROR;
10576
10577        ssl->options.hrrSentKeyShare = 1;
10578
10579        /* The data is the named group the server wants to use. */
10580        ato16(input, &group);
10581
10582    #ifdef WOLFSSL_ASYNC_CRYPT
10583        /* only perform find and clear TLSX if not returning from async */
10584        if (ssl->error != WC_NO_ERR_TRACE(WC_PENDING_E))
10585    #endif
10586        {
10587            /* Check the selected group was supported by ClientHello extensions.
10588             */
10589            if (!TLSX_SupportedGroups_Find(ssl, group, ssl->extensions)) {
10590                WOLFSSL_ERROR_VERBOSE(BAD_KEY_SHARE_DATA);
10591                return BAD_KEY_SHARE_DATA;
10592            }
10593
10594            /* Make sure KeyShare for server requested group was not sent in
10595             * ClientHello. */
10596            if (TLSX_KeyShare_Find(ssl, group)) {
10597                WOLFSSL_ERROR_VERBOSE(BAD_KEY_SHARE_DATA);
10598                return BAD_KEY_SHARE_DATA;
10599            }
10600
10601            /* Clear out unusable key shares. */
10602            ret = TLSX_KeyShare_Empty(ssl);
10603            if (ret != 0)
10604                return ret;
10605        }
10606
10607        ret = TLSX_KeyShare_Use(ssl, group, 0, NULL, NULL, &ssl->extensions);
10608        if (ret == 0)
10609            ssl->session->namedGroup = ssl->namedGroup = group;
10610    }
10611    else {
10612        /* Not a message type that is allowed to have this extension. */
10613        WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
10614        return SANITY_MSG_E;
10615    }
10616
10617    return ret;
10618}
10619
10620/* Create a new key share entry and put it into the list.
10621 *
10622 * list           The linked list of key share entries.
10623 * group          The named group.
10624 * heap           The memory to allocate with.
10625 * keyShareEntry  The new key share entry object.
10626 * returns 0 on success and other values indicate failure.
10627 */
10628static int TLSX_KeyShare_New(KeyShareEntry** list, int group, void *heap,
10629                             KeyShareEntry** keyShareEntry)
10630{
10631    KeyShareEntry* kse;
10632    KeyShareEntry** next;
10633
10634    kse = (KeyShareEntry*)XMALLOC(sizeof(KeyShareEntry), heap,
10635                                  DYNAMIC_TYPE_TLSX);
10636    if (kse == NULL)
10637        return MEMORY_E;
10638
10639    XMEMSET(kse, 0, sizeof(*kse));
10640    kse->group = (word16)group;
10641
10642    /* Add it to the back and maintain the links. */
10643    while (*list != NULL) {
10644        /* Assign to temporary to work around compiler bug found by customer. */
10645        next = &((*list)->next);
10646        list = next;
10647    }
10648    *list = kse;
10649    *keyShareEntry = kse;
10650
10651    (void)heap;
10652
10653    return 0;
10654}
10655
10656#if defined(WOLFSSL_HAVE_MLKEM) && !defined(WOLFSSL_MLKEM_NO_ENCAPSULATE)
10657/* Process the Kyber key share extension on the server side.
10658 *
10659 * ssl            The SSL/TLS object.
10660 * keyShareEntry  The key share entry object to be sent to the client.
10661 * data           The key share data received from the client.
10662 * len            The length of the key share data from the client.
10663 * ssOutput       The destination buffer for the shared secret.
10664 * ssOutSz        The size of the generated shared secret.
10665 *
10666 * returns 0 on success and other values indicate failure.
10667 */
10668static int TLSX_KeyShare_HandlePqcKeyServer(WOLFSSL* ssl,
10669    KeyShareEntry* keyShareEntry, byte* clientData, word16 clientLen,
10670    unsigned char* ssOutput, word32* ssOutSz)
10671{
10672    /* We are on the server side. The key share contains a PQC KEM public key
10673     * that we are using for an encapsulate operation. The resulting ciphertext
10674     * is stored in the server key share. */
10675    KyberKey* kemKey = (KyberKey*)keyShareEntry->key;
10676    byte* ciphertext = NULL;
10677    int ret = 0;
10678    word32 pubSz = 0;
10679    word32 ctSz = 0;
10680    word32 ssSz = 0;
10681
10682    if (clientData == NULL) {
10683        WOLFSSL_MSG("No KEM public key from the client.");
10684        return BAD_FUNC_ARG;
10685    }
10686
10687    if (kemKey == NULL) {
10688        int type = 0;
10689
10690        /* Allocate a Kyber key to hold private key. */
10691        kemKey = (KyberKey*) XMALLOC(sizeof(KyberKey), ssl->heap,
10692                                     DYNAMIC_TYPE_PRIVATE_KEY);
10693        if (kemKey == NULL) {
10694            WOLFSSL_MSG("GenPqcKey memory error");
10695            ret = MEMORY_E;
10696        }
10697        if (ret == 0) {
10698            ret = mlkem_id2type(keyShareEntry->group, &type);
10699        }
10700        if (ret != 0) {
10701            WOLFSSL_MSG("Invalid PQC algorithm specified.");
10702            ret = BAD_FUNC_ARG;
10703        }
10704        if (ret == 0) {
10705            ret = wc_KyberKey_Init(type, kemKey, ssl->heap, ssl->devId);
10706            if (ret != 0) {
10707                WOLFSSL_MSG("Error creating Kyber KEM");
10708            }
10709        }
10710    }
10711
10712    if (ret == 0) {
10713        ret = wc_KyberKey_PublicKeySize(kemKey, &pubSz);
10714    }
10715    if (ret == 0) {
10716        ret = wc_KyberKey_CipherTextSize(kemKey, &ctSz);
10717    }
10718    if (ret == 0) {
10719        ret = wc_KyberKey_SharedSecretSize(kemKey, &ssSz);
10720    }
10721
10722    if (ret == 0 && clientLen != pubSz) {
10723        WOLFSSL_MSG("Invalid public key.");
10724        ret = BAD_FUNC_ARG;
10725    }
10726
10727    if (ret == 0) {
10728        ciphertext = (byte*)XMALLOC(ctSz, ssl->heap, DYNAMIC_TYPE_TLSX);
10729
10730        if (ciphertext == NULL) {
10731            WOLFSSL_MSG("Ciphertext memory allocation failure.");
10732            ret = MEMORY_E;
10733        }
10734    }
10735
10736    if (ret == 0) {
10737        ret = wc_KyberKey_DecodePublicKey(kemKey, clientData, pubSz);
10738    }
10739    if (ret == 0) {
10740        ret = wc_KyberKey_Encapsulate(kemKey, ciphertext,
10741                                      ssOutput, ssl->rng);
10742        if (ret != 0) {
10743            WOLFSSL_MSG("wc_KyberKey encapsulation failure.");
10744        }
10745    }
10746
10747    if (ret == 0) {
10748        XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
10749
10750        *ssOutSz = ssSz;
10751        keyShareEntry->ke = NULL;
10752        keyShareEntry->keLen = 0;
10753
10754        XFREE(keyShareEntry->pubKey, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
10755        keyShareEntry->pubKey = ciphertext;
10756        keyShareEntry->pubKeyLen = ctSz;
10757        ciphertext = NULL;
10758
10759        /* Set namedGroup so wolfSSL_get_curve_name() can function properly on
10760         * the server side. */
10761        ssl->namedGroup = keyShareEntry->group;
10762    }
10763
10764    XFREE(ciphertext, ssl->heap, DYNAMIC_TYPE_TLSX);
10765
10766    wc_KyberKey_Free(kemKey);
10767    XFREE(kemKey, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
10768    keyShareEntry->key = NULL;
10769    return ret;
10770}
10771
10772int TLSX_KeyShare_HandlePqcHybridKeyServer(WOLFSSL* ssl,
10773    KeyShareEntry* keyShareEntry, byte* data, word16 len)
10774{
10775    /* I am the server. The data parameter is the concatenation of the client's
10776     * ECDH public key and the KEM public key. I need to generate a matching
10777     * public key for ECDH and encapsulate a shared secret using the KEM public
10778     * key. We send the ECDH public key and the KEM ciphertext back to the
10779     * client. Additionally, we create the ECDH shared secret here already.
10780     */
10781    int    type;
10782    byte*  ciphertext = NULL;
10783    int    ret = 0;
10784    int    pqc_group = 0;
10785    int    ecc_group = 0;
10786    int    pqc_first = 0;
10787    KeyShareEntry *ecc_kse = NULL;
10788    KeyShareEntry *pqc_kse = NULL;
10789    word32 pubSz = 0;
10790    word32 ctSz = 0;
10791    word32 ssSzPqc = 0;
10792
10793    if (data == NULL) {
10794        WOLFSSL_MSG("No hybrid key share data from the client.");
10795        return BAD_FUNC_ARG;
10796    }
10797
10798    /* Determine the ECC and PQC group of the hybrid combination */
10799    findEccPqc(&ecc_group, &pqc_group, &pqc_first, keyShareEntry->group);
10800    if (ecc_group == 0 || pqc_group == 0) {
10801        WOLFSSL_MSG("Invalid hybrid group");
10802        ret = BAD_FUNC_ARG;
10803    }
10804
10805    if (ret == 0) {
10806        ecc_kse = (KeyShareEntry*)XMALLOC(sizeof(*ecc_kse), ssl->heap,
10807                   DYNAMIC_TYPE_TLSX);
10808        pqc_kse = (KeyShareEntry*)XMALLOC(sizeof(*pqc_kse), ssl->heap,
10809                   DYNAMIC_TYPE_TLSX);
10810        if (ecc_kse == NULL || pqc_kse == NULL) {
10811            WOLFSSL_MSG("kse memory allocation failure");
10812            ret = MEMORY_ERROR;
10813        }
10814    }
10815    if (ret == 0) {
10816        XMEMSET(ecc_kse, 0, sizeof(*ecc_kse));
10817        ecc_kse->group = ecc_group;
10818        XMEMSET(pqc_kse, 0, sizeof(*pqc_kse));
10819        pqc_kse->group = pqc_group;
10820    }
10821
10822    /* The ciphertext and shared secret sizes of a KEM are fixed. Hence, we
10823     * decode these sizes to properly concatenate the KEM ciphertext with the
10824     * ECDH public key. */
10825    if (ret == 0) {
10826        /* Allocate a Kyber key to hold private key. */
10827        pqc_kse->key = (KyberKey*) XMALLOC(sizeof(KyberKey), ssl->heap,
10828                                           DYNAMIC_TYPE_PRIVATE_KEY);
10829        if (pqc_kse->key == NULL) {
10830            WOLFSSL_MSG("GenPqcKey memory error");
10831            ret = MEMORY_E;
10832        }
10833        if (ret == 0) {
10834            ret = mlkem_id2type(pqc_kse->group, &type);
10835        }
10836        if (ret != 0) {
10837            WOLFSSL_MSG("Invalid PQC algorithm specified.");
10838            ret = BAD_FUNC_ARG;
10839        }
10840        if (ret == 0) {
10841            ret = wc_KyberKey_Init(type, (KyberKey*)pqc_kse->key,
10842                                   ssl->heap, ssl->devId);
10843            if (ret != 0) {
10844                WOLFSSL_MSG("Error creating Kyber KEM");
10845            }
10846        }
10847        if (ret == 0) {
10848            ret = wc_KyberKey_SharedSecretSize((KyberKey*)pqc_kse->key,
10849                                               &ssSzPqc);
10850        }
10851        if (ret == 0) {
10852            ret = wc_KyberKey_CipherTextSize((KyberKey*)pqc_kse->key,
10853                                             &ctSz);
10854        }
10855        if (ret == 0) {
10856            ret = wc_KyberKey_PublicKeySize((KyberKey*)pqc_kse->key,
10857                                            &pubSz);
10858        }
10859    }
10860
10861#ifdef WOLFSSL_ASYNC_CRYPT
10862    if (ret == 0) {
10863        /* Check if the provided kse already contains ECC data and the
10864        * last error was WC_PENDING_E. In this case, we already tried to
10865        * process ECC kse data. Hence, we have to restore it. */
10866        if (keyShareEntry->key != NULL && keyShareEntry->keyLen > 0 &&
10867            keyShareEntry->lastRet == WC_NO_ERR_TRACE(WC_PENDING_E)) {
10868            ecc_kse->key = keyShareEntry->key;
10869            ecc_kse->keyLen = keyShareEntry->keyLen;
10870            ecc_kse->pubKey = keyShareEntry->pubKey;
10871            ecc_kse->pubKeyLen = keyShareEntry->pubKeyLen;
10872            ecc_kse->lastRet = keyShareEntry->lastRet;
10873            keyShareEntry->key = NULL;
10874            keyShareEntry->pubKey = NULL;
10875        }
10876    }
10877#endif
10878
10879    /* Generate the ECDH key share part to be sent to the client */
10880    if (ret == 0 && ecc_group != 0 && ecc_kse->pubKey == NULL) {
10881    #ifdef HAVE_CURVE25519
10882        if (ecc_group == WOLFSSL_ECC_X25519) {
10883            ret = TLSX_KeyShare_GenX25519Key(ssl, ecc_kse);
10884        }
10885        else
10886    #endif
10887    #ifdef HAVE_CURVE448
10888        if (ecc_group == WOLFSSL_ECC_X448) {
10889            ret = TLSX_KeyShare_GenX448Key(ssl, ecc_kse);
10890        }
10891        else
10892    #endif
10893        {
10894            ret = TLSX_KeyShare_GenEccKey(ssl, ecc_kse);
10895        }
10896    #ifdef WOLFSSL_ASYNC_CRYPT
10897        if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
10898            /* Store the generated ECC key in the provided kse to later
10899             * restore it.*/
10900            keyShareEntry->key = ecc_kse->key;
10901            keyShareEntry->keyLen = ecc_kse->keyLen;
10902            keyShareEntry->pubKeyLen = ecc_kse->pubKeyLen;
10903            keyShareEntry->lastRet = WC_PENDING_E;
10904            ecc_kse->key = NULL;
10905        }
10906        else if (ret == 0 &&
10907                 keyShareEntry->lastRet == WC_NO_ERR_TRACE(WC_PENDING_E)) {
10908            keyShareEntry->lastRet = 0;
10909            ecc_kse->lastRet = 0;
10910        }
10911    #endif
10912    }
10913
10914    if (ret == 0 && len != pubSz + ecc_kse->pubKeyLen) {
10915        WOLFSSL_MSG("Invalid public key.");
10916        ret = BAD_FUNC_ARG;
10917    }
10918
10919    /* Allocate buffer for the concatenated client key share data
10920     * (PQC KEM ciphertext + ECDH public key) */
10921    if (ret == 0) {
10922        ciphertext = (byte*)XMALLOC(ecc_kse->pubKeyLen + ctSz, ssl->heap,
10923            DYNAMIC_TYPE_TLSX);
10924
10925        if (ciphertext == NULL) {
10926            WOLFSSL_MSG("Ciphertext memory allocation failure.");
10927            ret = MEMORY_E;
10928        }
10929    }
10930
10931    /* Process ECDH key share part. The generated shared secret is directly
10932     * stored in the ssl->arrays->preMasterSecret buffer. Depending on the
10933     * pqc_first flag, the ECDH shared secret part goes before or after the
10934     * KEM part. */
10935    if (ret == 0) {
10936        ecc_kse->keLen = len - pubSz;
10937        ecc_kse->ke = (byte*)XMALLOC(ecc_kse->keLen, ssl->heap,
10938                                     DYNAMIC_TYPE_PUBLIC_KEY);
10939        if (ecc_kse->ke == NULL) {
10940            WOLFSSL_MSG("ecc_kse memory allocation failure");
10941            ret = MEMORY_ERROR;
10942        }
10943        if (ret == 0) {
10944            int pubOffset = 0;
10945            int ssOffset = 0;
10946
10947            if (pqc_first) {
10948                pubOffset = pubSz;
10949                ssOffset = ssSzPqc;
10950            }
10951
10952            XMEMCPY(ecc_kse->ke, data + pubOffset, ecc_kse->keLen);
10953
10954        #ifdef HAVE_CURVE25519
10955            if (ecc_group == WOLFSSL_ECC_X25519) {
10956                ret = TLSX_KeyShare_ProcessX25519_ex(ssl, ecc_kse,
10957                        ssl->arrays->preMasterSecret + ssOffset,
10958                        &ssl->arrays->preMasterSz);
10959            }
10960            else
10961        #endif
10962        #ifdef HAVE_CURVE448
10963            if (ecc_group == WOLFSSL_ECC_X448) {
10964                ret = TLSX_KeyShare_ProcessX448_ex(ssl, ecc_kse,
10965                        ssl->arrays->preMasterSecret + ssOffset,
10966                        &ssl->arrays->preMasterSz);
10967            }
10968            else
10969        #endif
10970            {
10971                ret = TLSX_KeyShare_ProcessEcc_ex(ssl, ecc_kse,
10972                        ssl->arrays->preMasterSecret + ssOffset,
10973                        &ssl->arrays->preMasterSz);
10974            }
10975        }
10976        if (ret == 0) {
10977            if (ssl->arrays->preMasterSz != ecc_kse->keyLen) {
10978                WOLFSSL_MSG("Data length mismatch.");
10979                ret = BAD_FUNC_ARG;
10980            }
10981        }
10982    #ifdef WOLFSSL_ASYNC_CRYPT
10983        else if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
10984            keyShareEntry->lastRet = WC_PENDING_E;
10985            keyShareEntry->key = ecc_kse->key;
10986            keyShareEntry->pubKey = ecc_kse->pubKey;
10987            keyShareEntry->pubKeyLen = ecc_kse->pubKeyLen;
10988            ecc_kse->key = NULL;
10989            ecc_kse->pubKey = NULL;
10990        }
10991    #endif
10992    }
10993
10994    if (ret == 0 && ssl->arrays->preMasterSz + ssSzPqc > ENCRYPT_LEN) {
10995        WOLFSSL_MSG("shared secret is too long.");
10996        ret = LENGTH_ERROR;
10997    }
10998
10999    /* Process PQC KEM key share part. Depending on the pqc_first flag, the
11000     * KEM shared secret part goes before or after the ECDH part. */
11001    if (ret == 0) {
11002        int input_offset = ecc_kse->keLen;
11003        int output_offset = ssl->arrays->preMasterSz;
11004
11005        if (pqc_first) {
11006            input_offset = 0;
11007            output_offset = 0;
11008        }
11009
11010        ret = TLSX_KeyShare_HandlePqcKeyServer(ssl, pqc_kse,
11011                data + input_offset, pubSz,
11012                ssl->arrays->preMasterSecret + output_offset, &ssSzPqc);
11013    }
11014
11015    if (ret == 0) {
11016        XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
11017
11018        ssl->arrays->preMasterSz += ssSzPqc;
11019        keyShareEntry->ke = NULL;
11020        keyShareEntry->keLen = 0;
11021
11022        /* Concatenate the ECDH public key and the PQC KEM ciphertext. Based on
11023         * the pqc_first flag, the ECDH public key goes before or after the KEM
11024         * ciphertext. */
11025        if (pqc_first) {
11026            XMEMCPY(ciphertext, pqc_kse->pubKey, ctSz);
11027            XMEMCPY(ciphertext + ctSz, ecc_kse->pubKey, ecc_kse->pubKeyLen);
11028        }
11029        else {
11030            XMEMCPY(ciphertext, ecc_kse->pubKey, ecc_kse->pubKeyLen);
11031            XMEMCPY(ciphertext + ecc_kse->pubKeyLen, pqc_kse->pubKey, ctSz);
11032        }
11033
11034        XFREE(keyShareEntry->pubKey, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
11035        keyShareEntry->pubKey = ciphertext;
11036        keyShareEntry->pubKeyLen = ecc_kse->pubKeyLen + ctSz;
11037        ciphertext = NULL;
11038
11039        /* Set namedGroup so wolfSSL_get_curve_name() can function properly on
11040         * the server side. */
11041        ssl->namedGroup = keyShareEntry->group;
11042    }
11043    else
11044#ifdef WOLFSSL_ASYNC_CRYPT
11045        if (ret != WC_NO_ERR_TRACE(WC_PENDING_E))
11046#endif
11047    {
11048        /* Clear the pre master secret buffer to prevent leaking any
11049         * intermediate keys in the error case. Do not use preMasterSz
11050         * here as it may already been set to the ECC shared secret size,
11051         * which would be too small due to the PQC offset case. */
11052        ForceZero(ssl->arrays->preMasterSecret, ENCRYPT_LEN);
11053    }
11054
11055    TLSX_KeyShare_FreeAll(ecc_kse, ssl->heap);
11056    TLSX_KeyShare_FreeAll(pqc_kse, ssl->heap);
11057    XFREE(ciphertext, ssl->heap, DYNAMIC_TYPE_TLSX);
11058    return ret;
11059}
11060#endif /* WOLFSSL_HAVE_MLKEM && !WOLFSSL_MLKEM_NO_ENCAPSULATE */
11061
11062/* Use the data to create a new key share object in the extensions.
11063 *
11064 * ssl    The SSL/TLS object.
11065 * group  The named group.
11066 * len    The length of the public key data.
11067 * data   The public key data.
11068 * kse    The new key share entry object.
11069 * returns 0 on success and other values indicate failure.
11070 */
11071int TLSX_KeyShare_Use(const WOLFSSL* ssl, word16 group, word16 len, byte* data,
11072                      KeyShareEntry **kse, TLSX** extensions)
11073{
11074    int            ret = 0;
11075    TLSX*          extension;
11076    KeyShareEntry* keyShareEntry = NULL;
11077
11078    /* Find the KeyShare extension if it exists. */
11079    extension = TLSX_Find(*extensions, TLSX_KEY_SHARE);
11080    if (extension == NULL) {
11081        /* Push new KeyShare extension. */
11082        ret = TLSX_Push(extensions, TLSX_KEY_SHARE, NULL, ssl->heap);
11083        if (ret != 0)
11084            return ret;
11085
11086        extension = TLSX_Find(*extensions, TLSX_KEY_SHARE);
11087        if (extension == NULL)
11088            return MEMORY_E;
11089    }
11090    extension->resp = 0;
11091
11092    /* Try to find the key share entry with this group. */
11093    keyShareEntry = (KeyShareEntry*)extension->data;
11094    while (keyShareEntry != NULL) {
11095    #if defined(WOLFSSL_ML_KEM_USE_OLD_IDS) && \
11096                                             defined (WOLFSSL_EXTRA_PQC_HYBRIDS)
11097        if ((group == WOLFSSL_P256_ML_KEM_512_OLD &&
11098                keyShareEntry->group == WOLFSSL_SECP256R1MLKEM512) ||
11099            (group == WOLFSSL_P384_ML_KEM_768_OLD &&
11100                keyShareEntry->group == WOLFSSL_SECP384R1MLKEM768) ||
11101            (group == WOLFSSL_P521_ML_KEM_1024_OLD &&
11102                keyShareEntry->group == WOLFSSL_SECP521R1MLKEM1024)) {
11103            keyShareEntry->group = group;
11104            break;
11105        }
11106        else
11107    #endif /* WOLFSSL_ML_KEM_USE_OLD_IDS && WOLFSSL_EXTRA_PQC_HYBRIDS */
11108        if (keyShareEntry->group == group)
11109            break;
11110        keyShareEntry = keyShareEntry->next;
11111    }
11112
11113    /* Create a new key share entry if not found. */
11114    if (keyShareEntry == NULL) {
11115        ret = TLSX_KeyShare_New((KeyShareEntry**)&extension->data, group,
11116                                ssl->heap, &keyShareEntry);
11117        if (ret != 0)
11118            return ret;
11119    }
11120
11121    if (data != NULL) {
11122        /* Store the peer data in the key share object. */
11123        XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
11124        keyShareEntry->ke = data;
11125        keyShareEntry->keLen = len;
11126    }
11127    else {
11128        /* Generate a key pair. Casting to non-const since changes inside are
11129         * minimal but would require an extensive redesign to refactor. Also
11130         * this path shouldn't be taken when parsing a ClientHello in stateless
11131         * mode. */
11132        ret = TLSX_KeyShare_GenKey((WOLFSSL*)ssl, keyShareEntry);
11133        if (ret != 0)
11134            return ret;
11135    }
11136
11137    if (kse != NULL)
11138        *kse = keyShareEntry;
11139
11140    return 0;
11141}
11142
11143/* Set an empty Key Share extension.
11144 *
11145 * ssl  The SSL/TLS object.
11146 * returns 0 on success and other values indicate failure.
11147 */
11148int TLSX_KeyShare_Empty(WOLFSSL* ssl)
11149{
11150    int   ret = 0;
11151    TLSX* extension;
11152
11153    /* Find the KeyShare extension if it exists. */
11154    extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
11155    if (extension == NULL) {
11156        /* Push new KeyShare extension. */
11157        ret = TLSX_Push(&ssl->extensions, TLSX_KEY_SHARE, NULL, ssl->heap);
11158    }
11159    else if (extension->data != NULL) {
11160        TLSX_KeyShare_FreeAll((KeyShareEntry*)extension->data, ssl->heap);
11161        extension->data = NULL;
11162    }
11163
11164    return ret;
11165}
11166
11167static const word16 preferredGroup[] = {
11168    /* Sort by strength, but prefer non-experimental PQ/T hybrid groups */
11169#if defined(WOLFSSL_HAVE_MLKEM) && !defined(WOLFSSL_NO_ML_KEM) && \
11170    defined(WOLFSSL_PQC_HYBRIDS)
11171    #if !defined(WOLFSSL_NO_ML_KEM_768) && defined(HAVE_CURVE25519) && \
11172        ECC_MIN_KEY_SZ <= 256
11173    WOLFSSL_X25519MLKEM768,
11174    #endif
11175    #if !defined(WOLFSSL_NO_ML_KEM_1024) && defined(HAVE_ECC) && \
11176        (defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)) && \
11177        ECC_MIN_KEY_SZ <= 384
11178    WOLFSSL_SECP384R1MLKEM1024,
11179    #endif
11180    #if !defined(WOLFSSL_NO_ML_KEM_768) && defined(HAVE_ECC) && \
11181        (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && \
11182        ECC_MIN_KEY_SZ <= 256
11183    WOLFSSL_SECP256R1MLKEM768,
11184    #endif
11185#endif /* WOLFSSL_HAVE_MLKEM && !WOLFSSL_NO_ML_KEM && WOLFSSL_PQC_HYBRIDS */
11186#if defined(WOLFSSL_HAVE_MLKEM) && !defined(WOLFSSL_NO_ML_KEM) && \
11187    !defined(WOLFSSL_NO_ML_KEM_1024) && !defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE)
11188    WOLFSSL_ML_KEM_1024,
11189#endif
11190#if defined(HAVE_ECC) && (!defined(NO_ECC521) || \
11191    defined(HAVE_ALL_CURVES)) && !defined(NO_ECC_SECP) && ECC_MIN_KEY_SZ <= 521
11192    WOLFSSL_ECC_SECP521R1,
11193#endif
11194#if defined(HAVE_ECC) && defined(HAVE_ECC512) && \
11195    defined(HAVE_ECC_BRAINPOOL) && ECC_MIN_KEY_SZ <= 512
11196    WOLFSSL_ECC_BRAINPOOLP512R1TLS13,
11197#endif
11198#if defined(WOLFSSL_HAVE_MLKEM) && !defined(WOLFSSL_NO_ML_KEM) && \
11199    !defined(WOLFSSL_NO_ML_KEM_768) && !defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE)
11200    WOLFSSL_ML_KEM_768,
11201#endif
11202#if defined(HAVE_ECC) && (!defined(NO_ECC384) || \
11203    defined(HAVE_ALL_CURVES)) && !defined(NO_ECC_SECP) && ECC_MIN_KEY_SZ <= 384
11204    WOLFSSL_ECC_SECP384R1,
11205#if defined(HAVE_ECC_BRAINPOOL)
11206    WOLFSSL_ECC_BRAINPOOLP384R1TLS13,
11207#endif
11208#endif
11209#if defined(HAVE_CURVE448) && ECC_MIN_KEY_SZ <= 448
11210    WOLFSSL_ECC_X448,
11211#endif
11212#if defined(WOLFSSL_HAVE_MLKEM) && !defined(WOLFSSL_NO_ML_KEM) && \
11213    !defined(WOLFSSL_NO_ML_KEM_512) && !defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE)
11214    WOLFSSL_ML_KEM_512,
11215#endif
11216#if defined(HAVE_ECC) && (!defined(NO_ECC256) || \
11217    defined(HAVE_ALL_CURVES)) && !defined(NO_ECC_SECP) && ECC_MIN_KEY_SZ <= 256
11218    WOLFSSL_ECC_SECP256R1,
11219#if !defined(HAVE_FIPS) && defined(WOLFSSL_SM2)
11220    WOLFSSL_ECC_SM2P256V1,
11221#endif
11222#if defined(HAVE_ECC_BRAINPOOL)
11223    WOLFSSL_ECC_BRAINPOOLP256R1TLS13,
11224#endif
11225#endif
11226#if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256
11227    WOLFSSL_ECC_X25519,
11228#endif
11229#if defined(HAVE_FFDHE_8192)
11230    WOLFSSL_FFDHE_8192,
11231#endif
11232#if defined(HAVE_FFDHE_6144)
11233    WOLFSSL_FFDHE_6144,
11234#endif
11235#if defined(HAVE_FFDHE_4096)
11236    WOLFSSL_FFDHE_4096,
11237#endif
11238#if defined(HAVE_FFDHE_3072)
11239    WOLFSSL_FFDHE_3072,
11240#endif
11241#if defined(HAVE_FFDHE_2048)
11242    WOLFSSL_FFDHE_2048,
11243#endif
11244#ifndef WOLFSSL_NO_ML_KEM
11245    #if !defined(WOLFSSL_NO_ML_KEM_1024) && \
11246        defined(WOLFSSL_EXTRA_PQC_HYBRIDS)
11247    WOLFSSL_SECP521R1MLKEM1024,
11248    #endif
11249    #if !defined(WOLFSSL_NO_ML_KEM_768) && \
11250        defined(WOLFSSL_EXTRA_PQC_HYBRIDS)
11251    WOLFSSL_SECP384R1MLKEM768,
11252    #if defined(HAVE_CURVE448) && ECC_MIN_KEY_SZ <= 448
11253    WOLFSSL_X448MLKEM768,
11254    #endif /* HAVE_CURVE448 */
11255    #endif
11256    #if !defined(WOLFSSL_NO_ML_KEM_512) && \
11257        defined(WOLFSSL_EXTRA_PQC_HYBRIDS)
11258    WOLFSSL_SECP256R1MLKEM512,
11259    #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256
11260    WOLFSSL_X25519MLKEM512,
11261    #endif /* HAVE_CURVE25519 */
11262    #endif
11263#endif /* !WOLFSSL_NO_ML_KEM */
11264#ifdef WOLFSSL_MLKEM_KYBER
11265    #ifdef WOLFSSL_KYBER1024
11266    WOLFSSL_KYBER_LEVEL5,
11267    WOLFSSL_P521_KYBER_LEVEL5,
11268    #endif
11269    #ifdef WOLFSSL_KYBER768
11270    WOLFSSL_KYBER_LEVEL3,
11271    WOLFSSL_P384_KYBER_LEVEL3,
11272    WOLFSSL_P256_KYBER_LEVEL3,
11273    #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256
11274    WOLFSSL_X25519_KYBER_LEVEL3,
11275    #endif
11276    #if defined(HAVE_CURVE448) && ECC_MIN_KEY_SZ <= 448
11277    WOLFSSL_X448_KYBER_LEVEL3,
11278    #endif
11279    #endif
11280    #ifdef WOLFSSL_KYBER512
11281    WOLFSSL_KYBER_LEVEL1,
11282    WOLFSSL_P256_KYBER_LEVEL1,
11283    #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256
11284    WOLFSSL_X25519_KYBER_LEVEL1,
11285    #endif
11286    #endif
11287#endif /* WOLFSSL_MLKEM_KYBER */
11288    WOLFSSL_NAMED_GROUP_INVALID
11289};
11290
11291#define PREFERRED_GROUP_SZ \
11292    ((sizeof(preferredGroup)/sizeof(*preferredGroup)) - 1)
11293                                            /* -1 for the invalid group */
11294
11295/* Examines the application specified group ranking and returns the rank of the
11296 * group.
11297 * If no group ranking set then all groups are rank 0 (highest).
11298 *
11299 * ssl    The SSL/TLS object.
11300 * group  The group to check ranking for.
11301 * returns ranking from 0 to MAX_GROUP_COUNT-1 or -1 when group not in list.
11302 */
11303static int TLSX_KeyShare_GroupRank(const WOLFSSL* ssl, int group)
11304{
11305    byte i;
11306    const word16* groups;
11307    byte numGroups;
11308
11309    if (ssl->numGroups == 0) {
11310        /* If the user didn't specify a group list with a preferred order,
11311         * use the internal preferred group list. */
11312        groups = preferredGroup;
11313        numGroups = PREFERRED_GROUP_SZ;
11314    }
11315    else {
11316        groups = ssl->group;
11317        numGroups = ssl->numGroups;
11318    }
11319
11320    for (i = 0; i < numGroups; i++) {
11321#if defined(WOLFSSL_ML_KEM_USE_OLD_IDS) && \
11322                                             defined (WOLFSSL_EXTRA_PQC_HYBRIDS)
11323        if ((group == WOLFSSL_P256_ML_KEM_512_OLD &&
11324             groups[i] == WOLFSSL_SECP256R1MLKEM512) ||
11325            (group == WOLFSSL_P384_ML_KEM_768_OLD &&
11326             groups[i] == WOLFSSL_SECP384R1MLKEM768) ||
11327            (group == WOLFSSL_P521_ML_KEM_1024_OLD &&
11328             groups[i] == WOLFSSL_SECP521R1MLKEM1024)) {
11329            return i;
11330        }
11331#endif
11332        if (groups[i] == (word16)group)
11333            return i;
11334    }
11335
11336    return WOLFSSL_FATAL_ERROR;
11337}
11338
11339/* Set a key share that is supported by the client into extensions.
11340 *
11341 * ssl  The SSL/TLS object.
11342 * returns BAD_KEY_SHARE_DATA if no supported group has a key share,
11343 * 0 if a supported group has a key share and other values indicate an error.
11344 */
11345int TLSX_KeyShare_SetSupported(const WOLFSSL* ssl, TLSX** extensions)
11346{
11347    int             ret;
11348#ifdef HAVE_SUPPORTED_CURVES
11349    TLSX*           extension;
11350    SupportedCurve* curve = NULL;
11351    SupportedCurve* preferredCurve = NULL;
11352    word16          name = WOLFSSL_NAMED_GROUP_INVALID;
11353    KeyShareEntry*  kse = NULL;
11354    int             preferredRank = WOLFSSL_MAX_GROUP_COUNT;
11355    int             rank;
11356
11357    extension = TLSX_Find(*extensions, TLSX_SUPPORTED_GROUPS);
11358    if (extension != NULL)
11359        curve = (SupportedCurve*)extension->data;
11360    for (; curve != NULL; curve = curve->next) {
11361        /* Use server's preference order. Common group was found but key share
11362         * was missing */
11363        if (!TLSX_IsGroupSupported(curve->name))
11364            continue;
11365        if (wolfSSL_curve_is_disabled(ssl, curve->name))
11366            continue;
11367
11368        rank = TLSX_KeyShare_GroupRank(ssl, curve->name);
11369        if (rank == -1)
11370            continue;
11371        if (rank < preferredRank) {
11372            preferredCurve = curve;
11373            preferredRank = rank;
11374        }
11375    }
11376    curve = preferredCurve;
11377
11378    if (curve == NULL) {
11379        byte i;
11380        /* Fallback to user selected group */
11381        preferredRank = WOLFSSL_MAX_GROUP_COUNT;
11382        for (i = 0; i < ssl->numGroups; i++) {
11383            rank = TLSX_KeyShare_GroupRank(ssl, ssl->group[i]);
11384            if (rank == -1)
11385                continue;
11386            if (rank < preferredRank) {
11387                name = ssl->group[i];
11388                preferredRank = rank;
11389            }
11390        }
11391        if (name == WOLFSSL_NAMED_GROUP_INVALID) {
11392            /* No group selected or specified by the server */
11393            WOLFSSL_ERROR_VERBOSE(BAD_KEY_SHARE_DATA);
11394            return BAD_KEY_SHARE_DATA;
11395        }
11396    }
11397    else {
11398        name = curve->name;
11399    }
11400
11401    #ifdef WOLFSSL_ASYNC_CRYPT
11402    /* Check the old key share data list. */
11403    extension = TLSX_Find(*extensions, TLSX_KEY_SHARE);
11404    if (extension != NULL) {
11405        kse = (KeyShareEntry*)extension->data;
11406        /* We should not be computing keys if we are only going to advertise
11407         * our choice here. */
11408        if (kse != NULL && kse->lastRet == WC_NO_ERR_TRACE(WC_PENDING_E)) {
11409            WOLFSSL_ERROR_VERBOSE(BAD_KEY_SHARE_DATA);
11410            return BAD_KEY_SHARE_DATA;
11411        }
11412    }
11413    #endif
11414
11415    /* Push new KeyShare extension. This will also free the old one */
11416    ret = TLSX_Push(extensions, TLSX_KEY_SHARE, NULL, ssl->heap);
11417    if (ret != 0)
11418        return ret;
11419    /* Extension got pushed to head */
11420    extension = *extensions;
11421    /* Push the selected curve */
11422    ret = TLSX_KeyShare_New((KeyShareEntry**)&extension->data, name,
11423                            ssl->heap, &kse);
11424    if (ret != 0)
11425        return ret;
11426    /* Set extension to be in response. */
11427    extension->resp = 1;
11428#else
11429
11430    (void)ssl;
11431
11432    WOLFSSL_ERROR_VERBOSE(NOT_COMPILED_IN);
11433    ret = NOT_COMPILED_IN;
11434#endif
11435
11436    return ret;
11437}
11438
11439#ifdef WOLFSSL_DUAL_ALG_CERTS
11440/* Writes the CKS objects of a list in a buffer. */
11441static word16 CKS_WRITE(WOLFSSL* ssl, byte* output)
11442{
11443    XMEMCPY(output, ssl->sigSpec, ssl->sigSpecSz);
11444    return ssl->sigSpecSz;
11445}
11446
11447static int TLSX_UseCKS(TLSX** extensions, WOLFSSL* ssl, void* heap)
11448{
11449    int ret = 0;
11450    TLSX* extension;
11451
11452    if (extensions == NULL) {
11453        return BAD_FUNC_ARG;
11454    }
11455
11456    extension = TLSX_Find(*extensions, TLSX_CKS);
11457    /* If it is already present, do nothing. */
11458    if (extension == NULL) {
11459        /* The data required is in the ssl struct, so push it in. */
11460        ret = TLSX_Push(extensions, TLSX_CKS, (void*)ssl, heap);
11461    }
11462
11463    return ret;
11464}
11465
11466int TLSX_CKS_Set(WOLFSSL* ssl, TLSX** extensions)
11467{
11468    int ret;
11469    TLSX* extension;
11470    /* Push new KeyShare extension. This will also free the old one */
11471    ret = TLSX_Push(extensions, TLSX_CKS, NULL, ssl->heap);
11472    if (ret != 0)
11473        return ret;
11474    /* Extension got pushed to head */
11475    extension = *extensions;
11476    /* Need ssl->sigSpecSz during extension length calculation. */
11477    extension->data = ssl;
11478    /* Set extension to be in response. */
11479    extension->resp = 1;
11480    return ret;
11481}
11482
11483int TLSX_CKS_Parse(WOLFSSL* ssl, byte* input, word16 length,
11484                   TLSX** extensions)
11485{
11486    int ret;
11487    int i, j;
11488
11489    (void) extensions;
11490
11491    /* Validating the input. */
11492    if (length == 0)
11493        return BUFFER_ERROR;
11494    for (i = 0; i < length; i++) {
11495        switch (input[i])
11496        {
11497            case WOLFSSL_CKS_SIGSPEC_NATIVE:
11498            case WOLFSSL_CKS_SIGSPEC_ALTERNATIVE:
11499            case WOLFSSL_CKS_SIGSPEC_BOTH:
11500                /* These are all valid values; do nothing */
11501                break;
11502            case WOLFSSL_CKS_SIGSPEC_EXTERNAL:
11503            default:
11504                /* All other values (including external) are not. */
11505                return BAD_FUNC_ARG;
11506        }
11507    }
11508
11509    /* This could be a situation where the client tried to start with TLS 1.3
11510     * when it sent ClientHello and the server down-graded to TLS 1.2. In that
11511     * case, erroring out because it is TLS 1.2 is not a reasonable thing to do.
11512     * In the case of TLS 1.2, the CKS values will be ignored. */
11513    if (!IsAtLeastTLSv1_3(ssl->version)) {
11514        ssl->sigSpec = NULL;
11515        ssl->sigSpecSz = 0;
11516        return 0;
11517    }
11518
11519    /* Extension data is valid, but if we are the server and we don't have an
11520     * alt private key, do not respond with CKS extension. */
11521    if (wolfSSL_is_server(ssl) && ssl->buffers.altKey == NULL) {
11522        ssl->sigSpec = NULL;
11523        ssl->sigSpecSz = 0;
11524        return 0;
11525    }
11526
11527    /* Copy as the lifetime of input seems to be ephemeral. */
11528    ssl->peerSigSpec = (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_TLSX);
11529    if (ssl->peerSigSpec == NULL) {
11530        return BUFFER_ERROR;
11531    }
11532    XMEMCPY(ssl->peerSigSpec, input, length);
11533    ssl->peerSigSpecSz = length;
11534
11535    /* If there is no preference set, use theirs... */
11536    if (ssl->sigSpec == NULL) {
11537        ret = wolfSSL_UseCKS(ssl, ssl->peerSigSpec, 1);
11538        if (ret == WOLFSSL_SUCCESS) {
11539            ret = TLSX_UseCKS(&ssl->extensions, ssl, ssl->heap);
11540            TLSX_SetResponse(ssl, TLSX_CKS);
11541        }
11542        return ret;
11543    }
11544
11545    /* ...otherwise, prioritize our preference. */
11546    for (i = 0; i < ssl->sigSpecSz; i++) {
11547        for (j = 0; j < length; j++) {
11548            if (ssl->sigSpec[i] == input[j]) {
11549                /* Got the match, set to this one. */
11550                ret = wolfSSL_UseCKS(ssl, &ssl->sigSpec[i], 1);
11551                if (ret == WOLFSSL_SUCCESS) {
11552                    ret = TLSX_UseCKS(&ssl->extensions, ssl, ssl->heap);
11553                    TLSX_SetResponse(ssl, TLSX_CKS);
11554                }
11555                return ret;
11556            }
11557        }
11558    }
11559
11560    /* No match found. Cannot continue. */
11561    return MATCH_SUITE_ERROR;
11562}
11563#endif /* WOLFSSL_DUAL_ALG_CERTS */
11564
11565/* Server side KSE processing */
11566int TLSX_KeyShare_Choose(const WOLFSSL *ssl, TLSX* extensions,
11567    byte cipherSuite0, byte cipherSuite, KeyShareEntry** kse, byte* searched)
11568{
11569    TLSX*          extension;
11570    KeyShareEntry* clientKSE = NULL;
11571    KeyShareEntry* list = NULL;
11572    KeyShareEntry* preferredKSE = NULL;
11573    int preferredRank = WOLFSSL_MAX_GROUP_COUNT;
11574    int rank;
11575
11576    (void)cipherSuite0;
11577    (void)cipherSuite;
11578
11579    if (ssl == NULL || ssl->options.side != WOLFSSL_SERVER_END)
11580        return BAD_FUNC_ARG;
11581
11582    *searched = 0;
11583
11584    /* Find the KeyShare extension if it exists. */
11585    extension = TLSX_Find(extensions, TLSX_KEY_SHARE);
11586    if (extension != NULL)
11587        list = (KeyShareEntry*)extension->data;
11588
11589    if (extension && extension->resp == 1) {
11590        /* Outside of the async case this path should not be taken. */
11591        int ret = WC_NO_ERR_TRACE(INCOMPLETE_DATA);
11592    #ifdef WOLFSSL_ASYNC_CRYPT
11593        /* in async case make sure key generation is finalized */
11594        KeyShareEntry* serverKSE = (KeyShareEntry*)extension->data;
11595        if (serverKSE && serverKSE->lastRet == WC_NO_ERR_TRACE(WC_PENDING_E)) {
11596            if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE)
11597                *searched = 1;
11598            ret = TLSX_KeyShare_GenKey((WOLFSSL*)ssl, serverKSE);
11599        }
11600        else
11601    #endif
11602        {
11603            ret = INCOMPLETE_DATA;
11604        }
11605        return ret;
11606    }
11607
11608    /* Use server's preference order. */
11609    for (clientKSE = list; clientKSE != NULL; clientKSE = clientKSE->next) {
11610        if (clientKSE->ke == NULL)
11611            continue;
11612
11613#ifdef WOLFSSL_SM2
11614        if ((cipherSuite0 == CIPHER_BYTE) &&
11615            ((cipherSuite == TLS_SM4_GCM_SM3) ||
11616             (cipherSuite == TLS_SM4_CCM_SM3))) {
11617           if (clientKSE->group != WOLFSSL_ECC_SM2P256V1) {
11618               continue;
11619           }
11620        }
11621        else if (clientKSE->group == WOLFSSL_ECC_SM2P256V1) {
11622           continue;
11623        }
11624#endif
11625
11626        /* Check consistency now - extensions in any order. */
11627        if (!TLSX_SupportedGroups_Find(ssl, clientKSE->group, extensions))
11628            continue;
11629
11630        if (!WOLFSSL_NAMED_GROUP_IS_FFDHE(clientKSE->group)) {
11631            /* Check max value supported. */
11632            if (clientKSE->group > WOLFSSL_ECC_MAX) {
11633#ifdef WOLFSSL_HAVE_MLKEM
11634                if (!WOLFSSL_NAMED_GROUP_IS_PQC(clientKSE->group) &&
11635                    !WOLFSSL_NAMED_GROUP_IS_PQC_HYBRID(clientKSE->group))
11636#endif
11637                    continue;
11638            }
11639            if (wolfSSL_curve_is_disabled(ssl, clientKSE->group))
11640                continue;
11641        }
11642        if (!TLSX_IsGroupSupported(clientKSE->group))
11643            continue;
11644
11645        rank = TLSX_KeyShare_GroupRank(ssl, clientKSE->group);
11646        if (rank == -1)
11647            continue;
11648        if (rank < preferredRank) {
11649            preferredKSE = clientKSE;
11650            preferredRank = rank;
11651        }
11652    }
11653    *kse = preferredKSE;
11654    *searched = 1;
11655    return 0;
11656}
11657
11658/* Server side KSE processing */
11659int TLSX_KeyShare_Setup(WOLFSSL *ssl, KeyShareEntry* clientKSE)
11660{
11661    int            ret;
11662    TLSX*          extension;
11663    KeyShareEntry* serverKSE;
11664    KeyShareEntry* list = NULL;
11665
11666    if (ssl == NULL || ssl->options.side != WOLFSSL_SERVER_END)
11667        return BAD_FUNC_ARG;
11668
11669    extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
11670    if (extension == NULL)
11671        return BAD_STATE_E;
11672
11673    if (clientKSE == NULL) {
11674#ifdef WOLFSSL_ASYNC_CRYPT
11675        /* Not necessarily an error. The key may have already been setup. */
11676        if (extension != NULL && extension->resp == 1) {
11677            serverKSE = (KeyShareEntry*)extension->data;
11678            if (serverKSE != NULL) {
11679                /* in async case make sure key generation is finalized */
11680                if (serverKSE->lastRet == WC_NO_ERR_TRACE(WC_PENDING_E))
11681                    return TLSX_KeyShare_GenKey((WOLFSSL*)ssl, serverKSE);
11682                else if (serverKSE->lastRet == 0)
11683                    return 0;
11684            }
11685        }
11686#endif
11687        return BAD_FUNC_ARG;
11688    }
11689
11690    /* Generate a new key pair except in the case of PQC KEM because we
11691     * are going to encapsulate and that does not require us to generate a
11692     * key pair.
11693     */
11694    ret = TLSX_KeyShare_New(&list, clientKSE->group, ssl->heap, &serverKSE);
11695    if (ret != 0)
11696        return ret;
11697
11698    if (clientKSE->key == NULL) {
11699#if defined(WOLFSSL_HAVE_MLKEM) && !defined(WOLFSSL_MLKEM_NO_ENCAPSULATE)
11700        if (WOLFSSL_NAMED_GROUP_IS_PQC(clientKSE->group)) {
11701            ret = TLSX_KeyShare_HandlePqcKeyServer(ssl, serverKSE,
11702                    clientKSE->ke, clientKSE->keLen,
11703                    ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz);
11704        }
11705        else if (WOLFSSL_NAMED_GROUP_IS_PQC_HYBRID(clientKSE->group)) {
11706            ret = TLSX_KeyShare_HandlePqcHybridKeyServer(ssl, serverKSE,
11707                    clientKSE->ke, clientKSE->keLen);
11708        }
11709        else
11710#endif
11711        {
11712            ret = TLSX_KeyShare_GenKey(ssl, serverKSE);
11713        }
11714
11715        /* for async do setup of serverKSE below, but return WC_PENDING_E */
11716        if (ret != 0
11717        #ifdef WOLFSSL_ASYNC_CRYPT
11718            && ret != WC_NO_ERR_TRACE(WC_PENDING_E)
11719        #endif
11720        ) {
11721            TLSX_KeyShare_FreeAll(list, ssl->heap);
11722            return ret;
11723        }
11724    }
11725    else {
11726        /* transfer buffers to serverKSE */
11727        serverKSE->key = clientKSE->key;
11728        clientKSE->key = NULL;
11729        serverKSE->keyLen = clientKSE->keyLen;
11730        serverKSE->pubKey = clientKSE->pubKey;
11731        clientKSE->pubKey = NULL;
11732        serverKSE->pubKeyLen = clientKSE->pubKeyLen;
11733    #ifndef NO_DH
11734        serverKSE->privKey = clientKSE->privKey;
11735        clientKSE->privKey = NULL;
11736    #endif
11737    }
11738    serverKSE->ke = clientKSE->ke;
11739    serverKSE->keLen = clientKSE->keLen;
11740    clientKSE->ke = NULL;
11741    clientKSE->keLen = 0;
11742    ssl->namedGroup = serverKSE->group;
11743
11744    TLSX_KeyShare_FreeAll((KeyShareEntry*)extension->data, ssl->heap);
11745    extension->data = (void *)serverKSE;
11746
11747    extension->resp = 1;
11748    return ret;
11749}
11750
11751/* Ensure there is a key pair that can be used for key exchange.
11752 *
11753 * ssl  The SSL/TLS object.
11754 * doHelloRetry If set to non-zero will do hello_retry
11755 * returns 0 on success and other values indicate failure.
11756 */
11757int TLSX_KeyShare_Establish(WOLFSSL *ssl, int* doHelloRetry)
11758{
11759    int            ret;
11760    KeyShareEntry* clientKSE = NULL;
11761    byte           searched = 0;
11762
11763    *doHelloRetry = 0;
11764
11765    ret = TLSX_KeyShare_Choose(ssl, ssl->extensions, ssl->cipher.cipherSuite0,
11766        ssl->cipher.cipherSuite, &clientKSE, &searched);
11767    if (ret != 0 || !searched)
11768        return ret;
11769
11770    /* No supported group found - send HelloRetryRequest. */
11771    if (clientKSE == NULL) {
11772        /* Set KEY_SHARE_ERROR to indicate HelloRetryRequest required. */
11773        *doHelloRetry = 1;
11774        return TLSX_KeyShare_SetSupported(ssl, &ssl->extensions);
11775    }
11776
11777    return TLSX_KeyShare_Setup(ssl, clientKSE);
11778}
11779
11780/* Derive the shared secret of the key exchange.
11781 *
11782 * ssl  The SSL/TLS object.
11783 * returns 0 on success and other values indicate failure.
11784 */
11785int TLSX_KeyShare_DeriveSecret(WOLFSSL *ssl)
11786{
11787    int            ret;
11788    TLSX*          extension;
11789    KeyShareEntry* list = NULL;
11790
11791#ifdef WOLFSSL_ASYNC_CRYPT
11792    ret = wolfSSL_AsyncPop(ssl, NULL);
11793    /* Check for error */
11794    if (ret != WC_NO_ERR_TRACE(WC_NO_PENDING_E) && ret < 0) {
11795        return ret;
11796    }
11797#endif
11798
11799    /* Find the KeyShare extension if it exists. */
11800    extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
11801    if (extension != NULL)
11802        list = (KeyShareEntry*)extension->data;
11803
11804    if (list == NULL)
11805        return KEY_SHARE_ERROR;
11806
11807    /* Calculate secret. */
11808    ret = TLSX_KeyShare_Process(ssl, list);
11809
11810    return ret;
11811}
11812
11813#define KS_FREE_ALL  TLSX_KeyShare_FreeAll
11814#define KS_GET_SIZE  TLSX_KeyShare_GetSize
11815#define KS_WRITE     TLSX_KeyShare_Write
11816#define KS_PARSE     TLSX_KeyShare_Parse
11817
11818#else
11819
11820#define KS_FREE_ALL(a, b) WC_DO_NOTHING
11821#define KS_GET_SIZE(a, b)    0
11822#define KS_WRITE(a, b, c)    0
11823#define KS_PARSE(a, b, c, d) 0
11824
11825#endif /* WOLFSSL_TLS13 */
11826
11827/******************************************************************************/
11828/* Pre-Shared Key                                                             */
11829/******************************************************************************/
11830
11831#if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK))
11832/* Free the pre-shared key dynamic data.
11833 *
11834 * list  The linked list of key share entry objects.
11835 * heap  The heap used for allocation.
11836 */
11837static void TLSX_PreSharedKey_FreeAll(PreSharedKey* list, void* heap)
11838{
11839    PreSharedKey* current;
11840
11841    while ((current = list) != NULL) {
11842        list = current->next;
11843        XFREE(current->identity, heap, DYNAMIC_TYPE_TLSX);
11844        XFREE(current, heap, DYNAMIC_TYPE_TLSX);
11845    }
11846
11847    (void)heap;
11848}
11849
11850/* Get the size of the encoded pre shared key extension.
11851 *
11852 * list     The linked list of pre-shared key extensions.
11853 * msgType  The type of the message this extension is being written into.
11854 * returns the number of bytes of the encoded pre-shared key extension or
11855 * SANITY_MSG_E to indicate invalid message type.
11856 */
11857static int TLSX_PreSharedKey_GetSize(PreSharedKey* list, byte msgType,
11858                                     word16* pSz)
11859{
11860    if (msgType == client_hello) {
11861        /* Length of identities + Length of binders. */
11862        word32 len = OPAQUE16_LEN + OPAQUE16_LEN;
11863        while (list != NULL) {
11864            /* Each entry has: identity, ticket age and binder. */
11865            len += OPAQUE16_LEN + list->identityLen + OPAQUE32_LEN +
11866                   OPAQUE8_LEN + (word32)list->binderLen;
11867            if (len > WOLFSSL_MAX_16BIT) {
11868                WOLFSSL_ERROR_VERBOSE(LENGTH_ERROR);
11869                return LENGTH_ERROR;
11870            }
11871            list = list->next;
11872        }
11873        if ((word32)*pSz + len > WOLFSSL_MAX_16BIT) {
11874            WOLFSSL_ERROR_VERBOSE(LENGTH_ERROR);
11875            return LENGTH_ERROR;
11876        }
11877        *pSz += (word16)len;
11878        return 0;
11879    }
11880
11881    if (msgType == server_hello) {
11882        *pSz += OPAQUE16_LEN;
11883        return 0;
11884    }
11885
11886    WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
11887    return SANITY_MSG_E;
11888}
11889
11890/* The number of bytes to be written for the binders.
11891 *
11892 * list     The linked list of pre-shared key extensions.
11893 * msgType  The type of the message this extension is being written into.
11894 * returns the number of bytes of the encoded pre-shared key extension or
11895 * SANITY_MSG_E to indicate invalid message type.
11896 */
11897int TLSX_PreSharedKey_GetSizeBinders(PreSharedKey* list, byte msgType,
11898                                     word16* pSz)
11899{
11900    word32 len;
11901
11902    if (msgType != client_hello) {
11903        WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
11904        return SANITY_MSG_E;
11905    }
11906
11907    /* Length of all binders. */
11908    len = OPAQUE16_LEN;
11909    while (list != NULL) {
11910        len += OPAQUE8_LEN + (word32)list->binderLen;
11911        if (len > WOLFSSL_MAX_16BIT) {
11912            WOLFSSL_ERROR_VERBOSE(LENGTH_ERROR);
11913            return LENGTH_ERROR;
11914        }
11915        list = list->next;
11916    }
11917
11918    *pSz = (word16)len;
11919    return 0;
11920}
11921
11922/* Writes the pre-shared key extension into the output buffer - binders only.
11923 * Assumes that the the output buffer is big enough to hold data.
11924 *
11925 * list     The linked list of key share entries.
11926 * output   The buffer to write into.
11927 * msgType  The type of the message this extension is being written into.
11928 * returns the number of bytes written into the buffer.
11929 */
11930int TLSX_PreSharedKey_WriteBinders(PreSharedKey* list, byte* output,
11931                                   byte msgType, word16* pSz)
11932{
11933    PreSharedKey* current = list;
11934    word16 idx = 0;
11935    word16 lenIdx;
11936    word16 len;
11937
11938    if (msgType != client_hello) {
11939        WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
11940        return SANITY_MSG_E;
11941    }
11942
11943    /* Skip length of all binders. */
11944    lenIdx = idx;
11945    idx += OPAQUE16_LEN;
11946    while (current != NULL) {
11947        /* Binder data length. */
11948        output[idx++] = (byte)current->binderLen;
11949        /* Binder data. */
11950        XMEMCPY(output + idx, current->binder, current->binderLen);
11951        idx += (word16)current->binderLen;
11952
11953        current = current->next;
11954    }
11955    /* Length of the binders. */
11956    len = idx - lenIdx - OPAQUE16_LEN;
11957    c16toa(len, output + lenIdx);
11958
11959    *pSz = idx;
11960    return 0;
11961}
11962
11963
11964/* Writes the pre-shared key extension into the output buffer.
11965 * Assumes that the the output buffer is big enough to hold data.
11966 *
11967 * list     The linked list of key share entries.
11968 * output   The buffer to write into.
11969 * msgType  The type of the message this extension is being written into.
11970 * returns the number of bytes written into the buffer.
11971 */
11972static int TLSX_PreSharedKey_Write(PreSharedKey* list, byte* output,
11973                                   byte msgType, word16* pSz)
11974{
11975    if (msgType == client_hello) {
11976        PreSharedKey* current = list;
11977        word16 idx = 0;
11978        word16 lenIdx;
11979        word16 len;
11980        int ret;
11981
11982        /* Write identities only. Binders after HMACing over this. */
11983        lenIdx = idx;
11984        idx += OPAQUE16_LEN;
11985        while (current != NULL) {
11986            /* Identity length */
11987            c16toa(current->identityLen, output + idx);
11988            idx += OPAQUE16_LEN;
11989            /* Identity data */
11990            XMEMCPY(output + idx, current->identity, current->identityLen);
11991            idx += current->identityLen;
11992
11993            /* Obfuscated ticket age. */
11994            c32toa(current->ticketAge, output + idx);
11995            idx += OPAQUE32_LEN;
11996
11997            current = current->next;
11998        }
11999        /* Length of the identities. */
12000        len = idx - lenIdx - OPAQUE16_LEN;
12001        c16toa(len, output + lenIdx);
12002
12003        /* Don't include binders here.
12004         * The binders are based on the hash of all the ClientHello data up to
12005         * and include the identities written above.
12006         */
12007        ret = TLSX_PreSharedKey_GetSizeBinders(list, msgType, &len);
12008        if (ret < 0)
12009            return ret;
12010        *pSz += idx + len;
12011    }
12012    else if (msgType == server_hello) {
12013        word16 i;
12014
12015        /* Find the index of the chosen identity. */
12016        for (i=0; list != NULL && !list->chosen; i++)
12017            list = list->next;
12018        if (list == NULL) {
12019            WOLFSSL_ERROR_VERBOSE(BUILD_MSG_ERROR);
12020            return BUILD_MSG_ERROR;
12021        }
12022
12023        /* The index of the identity chosen by the server from the list supplied
12024         * by the client.
12025         */
12026        c16toa(i, output);
12027        *pSz += OPAQUE16_LEN;
12028    }
12029    else {
12030        WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
12031        return SANITY_MSG_E;
12032    }
12033
12034    return 0;
12035}
12036
12037int TLSX_PreSharedKey_Parse_ClientHello(TLSX** extensions, const byte* input,
12038                                        word16 length, void* heap)
12039{
12040
12041    int    ret;
12042    word16 len;
12043    word16 idx = 0;
12044    TLSX*         extension;
12045    PreSharedKey* list;
12046
12047    TLSX_Remove(extensions, TLSX_PRE_SHARED_KEY, heap);
12048
12049    /* Length of identities and of binders. */
12050    if ((int)(length - idx) < OPAQUE16_LEN + OPAQUE16_LEN)
12051        return BUFFER_E;
12052
12053    /* Length of identities. */
12054    ato16(input + idx, &len);
12055    idx += OPAQUE16_LEN;
12056    if (len < MIN_PSK_ID_LEN || length - idx < len)
12057        return BUFFER_E;
12058
12059    /* Create a pre-shared key object for each identity. */
12060    while (len > 0) {
12061        const byte* identity;
12062        word16      identityLen;
12063        word32      age;
12064
12065        if (len < OPAQUE16_LEN)
12066            return BUFFER_E;
12067
12068        /* Length of identity. */
12069        ato16(input + idx, &identityLen);
12070        idx += OPAQUE16_LEN;
12071        if (len < OPAQUE16_LEN + identityLen + OPAQUE32_LEN ||
12072                identityLen > MAX_PSK_ID_LEN)
12073            return BUFFER_E;
12074        /* Cache identity pointer. */
12075        identity = input + idx;
12076        idx += identityLen;
12077        /* Ticket age. */
12078        ato32(input + idx, &age);
12079        idx += OPAQUE32_LEN;
12080
12081        ret = TLSX_PreSharedKey_Use(extensions, identity, identityLen, age, no_mac,
12082                                    0, 0, 1, NULL, heap);
12083        if (ret != 0)
12084            return ret;
12085
12086        /* Done with this identity. */
12087        len -= OPAQUE16_LEN + identityLen + OPAQUE32_LEN;
12088    }
12089
12090    /* Find the list of identities sent to server. */
12091    extension = TLSX_Find(*extensions, TLSX_PRE_SHARED_KEY);
12092    if (extension == NULL)
12093        return PSK_KEY_ERROR;
12094    list = (PreSharedKey*)extension->data;
12095
12096    /* Length of binders. */
12097    if (idx + OPAQUE16_LEN > length)
12098        return BUFFER_E;
12099    ato16(input + idx, &len);
12100    idx += OPAQUE16_LEN;
12101    if (len < MIN_PSK_BINDERS_LEN || length - idx < len)
12102        return BUFFER_E;
12103
12104    /* Set binder for each identity. */
12105    while (list != NULL && len > 0) {
12106        /* Length of binder */
12107        list->binderLen = input[idx++];
12108        if (list->binderLen < WC_SHA256_DIGEST_SIZE ||
12109                list->binderLen > WC_MAX_DIGEST_SIZE)
12110            return BUFFER_E;
12111        if (len < OPAQUE8_LEN + list->binderLen)
12112            return BUFFER_E;
12113
12114        /* Copy binder into static buffer. */
12115        XMEMCPY(list->binder, input + idx, list->binderLen);
12116        idx += (word16)list->binderLen;
12117
12118        /* Done with binder entry. */
12119        len -= OPAQUE8_LEN + (word16)list->binderLen;
12120
12121        /* Next identity. */
12122        list = list->next;
12123    }
12124    if (list != NULL || len != 0)
12125        return BUFFER_E;
12126
12127    return 0;
12128
12129}
12130
12131/* Parse the pre-shared key extension.
12132 * Different formats in different messages.
12133 *
12134 * ssl      The SSL/TLS object.
12135 * input    The extension data.
12136 * length   The length of the extension data.
12137 * msgType  The type of the message this extension is being parsed from.
12138 * returns 0 on success and other values indicate failure.
12139 */
12140static int TLSX_PreSharedKey_Parse(WOLFSSL* ssl, const byte* input,
12141                                   word16 length, byte msgType)
12142{
12143
12144    if (msgType == client_hello) {
12145        return TLSX_PreSharedKey_Parse_ClientHello(&ssl->extensions, input,
12146                                                   length, ssl->heap);
12147    }
12148
12149    if (msgType == server_hello) {
12150        word16 idx;
12151        PreSharedKey* list;
12152        TLSX*         extension;
12153
12154        /* Index of identity chosen by server. */
12155        if (length != OPAQUE16_LEN)
12156            return BUFFER_E;
12157        ato16(input, &idx);
12158
12159    #ifdef WOLFSSL_EARLY_DATA
12160        ssl->options.pskIdIndex = idx + 1;
12161    #endif
12162
12163        /* Find the list of identities sent to server. */
12164        extension = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY);
12165        if (extension == NULL)
12166            return INCOMPLETE_DATA;
12167        list = (PreSharedKey*)extension->data;
12168
12169        /* Mark the identity as chosen. */
12170        for (; list != NULL && idx > 0; idx--)
12171            list = list->next;
12172        if (list == NULL) {
12173            WOLFSSL_ERROR_VERBOSE(PSK_KEY_ERROR);
12174            return PSK_KEY_ERROR;
12175        }
12176        list->chosen = 1;
12177
12178        if (list->resumption) {
12179           /* Check that the session's details are the same as the server's. */
12180           if (ssl->options.cipherSuite0  != ssl->session->cipherSuite0       ||
12181               ssl->options.cipherSuite   != ssl->session->cipherSuite        ||
12182               ssl->session->version.major != ssl->ctx->method->version.major ||
12183               ssl->session->version.minor != ssl->ctx->method->version.minor) {
12184                WOLFSSL_ERROR_VERBOSE(PSK_KEY_ERROR);
12185               return PSK_KEY_ERROR;
12186           }
12187        }
12188
12189        return 0;
12190    }
12191
12192    WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
12193    return SANITY_MSG_E;
12194}
12195
12196/* Create a new pre-shared key and put it into the list.
12197 *
12198 * list          The linked list of pre-shared key.
12199 * identity      The identity.
12200 * len           The length of the identity data.
12201 * heap          The memory to allocate with.
12202 * preSharedKey  The new pre-shared key object.
12203 * returns 0 on success and other values indicate failure.
12204 */
12205static int TLSX_PreSharedKey_New(PreSharedKey** list, const byte* identity,
12206                                 word16 len, void *heap,
12207                                 PreSharedKey** preSharedKey)
12208{
12209    PreSharedKey* psk;
12210    PreSharedKey** next;
12211
12212    psk = (PreSharedKey*)XMALLOC(sizeof(PreSharedKey), heap, DYNAMIC_TYPE_TLSX);
12213    if (psk == NULL)
12214        return MEMORY_E;
12215    XMEMSET(psk, 0, sizeof(*psk));
12216
12217    /* Make a copy of the identity data. */
12218    psk->identity = (byte*)XMALLOC(len + NULL_TERM_LEN, heap,
12219                                   DYNAMIC_TYPE_TLSX);
12220    if (psk->identity == NULL) {
12221        XFREE(psk, heap, DYNAMIC_TYPE_TLSX);
12222        return MEMORY_E;
12223    }
12224    XMEMCPY(psk->identity, identity, len);
12225    psk->identityLen = len;
12226    /* Use a NULL terminator in case it is a C string */
12227    psk->identity[psk->identityLen] = '\0';
12228
12229    /* Add it to the end and maintain the links. */
12230    while (*list != NULL) {
12231        /* Assign to temporary to work around compiler bug found by customer. */
12232        next = &((*list)->next);
12233        list = next;
12234    }
12235    *list = psk;
12236    *preSharedKey = psk;
12237
12238    (void)heap;
12239
12240    return 0;
12241}
12242
12243static WC_INLINE byte GetHmacLength(int hmac)
12244{
12245    switch (hmac) {
12246    #ifndef NO_SHA256
12247        case sha256_mac:
12248            return WC_SHA256_DIGEST_SIZE;
12249    #endif
12250    #ifdef WOLFSSL_SHA384
12251        case sha384_mac:
12252            return WC_SHA384_DIGEST_SIZE;
12253    #endif
12254    #ifdef WOLFSSL_SHA512
12255        case sha512_mac:
12256            return WC_SHA512_DIGEST_SIZE;
12257    #endif
12258    #ifdef WOLFSSL_SM3
12259        case sm3_mac:
12260            return WC_SM3_DIGEST_SIZE;
12261    #endif
12262        default:
12263            break;
12264    }
12265    return 0;
12266}
12267
12268/* Use the data to create a new pre-shared key object in the extensions.
12269 *
12270 * ssl           The SSL/TLS object.
12271 * identity      The identity.
12272 * len           The length of the identity data.
12273 * age           The age of the identity.
12274 * hmac          The HMAC algorithm.
12275 * cipherSuite0  The first byte of the cipher suite to use.
12276 * cipherSuite   The second byte of the cipher suite to use.
12277 * resumption    The PSK is for resumption of a session.
12278 * preSharedKey  The new pre-shared key object.
12279 * returns 0 on success and other values indicate failure.
12280 */
12281int TLSX_PreSharedKey_Use(TLSX** extensions, const byte* identity, word16 len,
12282                          word32 age, byte hmac, byte cipherSuite0,
12283                          byte cipherSuite, byte resumption,
12284                          PreSharedKey **preSharedKey, void* heap)
12285{
12286    int           ret = 0;
12287    TLSX*         extension;
12288    PreSharedKey* psk = NULL;
12289
12290    /* Find the pre-shared key extension if it exists. */
12291    extension = TLSX_Find(*extensions, TLSX_PRE_SHARED_KEY);
12292    if (extension == NULL) {
12293        /* Push new pre-shared key extension. */
12294        ret = TLSX_Push(extensions, TLSX_PRE_SHARED_KEY, NULL, heap);
12295        if (ret != 0)
12296            return ret;
12297
12298        extension = TLSX_Find(*extensions, TLSX_PRE_SHARED_KEY);
12299        if (extension == NULL)
12300            return MEMORY_E;
12301    }
12302
12303    /* Try to find the pre-shared key with this identity. */
12304    psk = (PreSharedKey*)extension->data;
12305    while (psk != NULL) {
12306        if ((psk->identityLen == len) &&
12307               (XMEMCMP(psk->identity, identity, len) == 0)) {
12308            break;
12309        }
12310        psk = psk->next;
12311    }
12312
12313    /* Create a new pre-shared key object if not found. */
12314    if (psk == NULL) {
12315        ret = TLSX_PreSharedKey_New((PreSharedKey**)&extension->data, identity,
12316                                    len, heap, &psk);
12317        if (ret != 0)
12318            return ret;
12319    }
12320
12321    /* Update/set age and HMAC algorithm. */
12322    psk->ticketAge    = age;
12323    psk->hmac         = hmac;
12324    psk->cipherSuite0 = cipherSuite0;
12325    psk->cipherSuite  = cipherSuite;
12326    psk->resumption   = resumption;
12327    psk->binderLen    = GetHmacLength(psk->hmac);
12328
12329    if (preSharedKey != NULL)
12330        *preSharedKey = psk;
12331
12332    return 0;
12333}
12334
12335#define PSK_FREE_ALL  TLSX_PreSharedKey_FreeAll
12336#define PSK_GET_SIZE  TLSX_PreSharedKey_GetSize
12337#define PSK_WRITE     TLSX_PreSharedKey_Write
12338#define PSK_PARSE     TLSX_PreSharedKey_Parse
12339
12340#else
12341
12342#define PSK_FREE_ALL(a, b) WC_DO_NOTHING
12343#define PSK_GET_SIZE(a, b, c) 0
12344#define PSK_WRITE(a, b, c, d) 0
12345#define PSK_PARSE(a, b, c, d) 0
12346
12347#endif
12348
12349/******************************************************************************/
12350/* Certificate Authentication with External Pre-Shared Key                    */
12351/******************************************************************************/
12352
12353#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_CERT_WITH_EXTERN_PSK) && \
12354    !defined(NO_PSK)
12355
12356static int TLSX_CertWithExternPsk_GetSize(byte msgType, word16* pSz)
12357{
12358    (void)msgType;
12359    (void)pSz;
12360    /* Zero-length extension - nothing to add. */
12361    return 0;
12362}
12363
12364static int TLSX_CertWithExternPsk_Write(byte* output, byte msgType,
12365    word16* pSz)
12366{
12367    (void)output;
12368    (void)msgType;
12369    (void)pSz;
12370    /* Zero-length extension - nothing to write. */
12371    return 0;
12372}
12373
12374static int TLSX_CertWithExternPsk_Parse(WOLFSSL* ssl, byte msgType)
12375{
12376    if (msgType == client_hello) {
12377        /* Server has not opted in - treat the extension as unknown. */
12378        if (!ssl->options.certWithExternPsk)
12379            return 0;
12380        /* Record that the client offered the extension, leaving resp=0.
12381         * CheckPreSharedKeys() is the sole writer that flips resp to 1, and
12382         * only after confirming that a non-ticket PSK was matched. */
12383        if (TLSX_Find(ssl->extensions, TLSX_CERT_WITH_EXTERN_PSK) == NULL) {
12384            return TLSX_Push(&ssl->extensions, TLSX_CERT_WITH_EXTERN_PSK,
12385                NULL, ssl->heap);
12386        }
12387        return 0;
12388    }
12389
12390    if (msgType == server_hello) {
12391        if (TLSX_Find(ssl->extensions, TLSX_CERT_WITH_EXTERN_PSK) == NULL) {
12392            WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
12393            return EXT_NOT_ALLOWED;
12394        }
12395        ssl->options.certWithExternPsk = 1;
12396        return 0;
12397    }
12398
12399    WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
12400    return SANITY_MSG_E;
12401}
12402
12403int TLSX_CertWithExternPsk_Use(WOLFSSL* ssl)
12404{
12405    TLSX* extension = TLSX_Find(ssl->extensions, TLSX_CERT_WITH_EXTERN_PSK);
12406
12407    if (extension == NULL) {
12408        int ret = TLSX_Push(&ssl->extensions, TLSX_CERT_WITH_EXTERN_PSK, NULL,
12409            ssl->heap);
12410        if (ret != 0)
12411            return ret;
12412        extension = TLSX_Find(ssl->extensions, TLSX_CERT_WITH_EXTERN_PSK);
12413        if (extension == NULL)
12414            return MEMORY_E;
12415    }
12416    extension->resp = 1;
12417    return 0;
12418}
12419
12420#define PSK_WITH_CERT_GET_SIZE  TLSX_CertWithExternPsk_GetSize
12421#define PSK_WITH_CERT_WRITE     TLSX_CertWithExternPsk_Write
12422#define PSK_WITH_CERT_PARSE     TLSX_CertWithExternPsk_Parse
12423
12424#else
12425
12426#define PSK_WITH_CERT_GET_SIZE(a, b) 0
12427#define PSK_WITH_CERT_WRITE(a, b, c) 0
12428#define PSK_WITH_CERT_PARSE(a, b) 0
12429
12430#endif /* WOLFSSL_TLS13 && WOLFSSL_CERT_WITH_EXTERN_PSK */
12431
12432/******************************************************************************/
12433/* PSK Key Exchange Modes                                                     */
12434/******************************************************************************/
12435
12436#if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK))
12437/* Get the size of the encoded PSK KE modes extension.
12438 * Only in ClientHello.
12439 *
12440 * modes    The PSK KE mode bit string.
12441 * msgType  The type of the message this extension is being written into.
12442 * returns the number of bytes of the encoded PSK KE mode extension.
12443 */
12444static int TLSX_PskKeModes_GetSize(byte modes, byte msgType, word16* pSz)
12445{
12446    if (msgType == client_hello) {
12447        /* Format: Len | Modes* */
12448        word16 len = OPAQUE8_LEN;
12449        /* Check whether each possible mode is to be written. */
12450        if (modes & (1 << PSK_KE))
12451            len += OPAQUE8_LEN;
12452        if (modes & (1 << PSK_DHE_KE))
12453            len += OPAQUE8_LEN;
12454        *pSz += len;
12455        return 0;
12456    }
12457
12458    WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
12459    return SANITY_MSG_E;
12460}
12461
12462/* Writes the PSK KE modes extension into the output buffer.
12463 * Assumes that the the output buffer is big enough to hold data.
12464 * Only in ClientHello.
12465 *
12466 * modes    The PSK KE mode bit string.
12467 * output   The buffer to write into.
12468 * msgType  The type of the message this extension is being written into.
12469 * returns the number of bytes written into the buffer.
12470 */
12471static int TLSX_PskKeModes_Write(byte modes, byte* output, byte msgType,
12472                                 word16* pSz)
12473{
12474    if (msgType == client_hello) {
12475        /* Format: Len | Modes* */
12476        word16 idx = OPAQUE8_LEN;
12477
12478        /* Write out each possible mode. */
12479        if (modes & (1 << PSK_KE))
12480            output[idx++] = PSK_KE;
12481        if (modes & (1 << PSK_DHE_KE))
12482            output[idx++] = PSK_DHE_KE;
12483        /* Write out length of mode list. */
12484        output[0] = (byte)(idx - OPAQUE8_LEN);
12485
12486        *pSz += idx;
12487        return 0;
12488    }
12489
12490    WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
12491    return SANITY_MSG_E;
12492}
12493
12494int TLSX_PskKeyModes_Parse_Modes(const byte* input, word16 length, byte msgType,
12495                                byte* modes)
12496{
12497    if (msgType == client_hello) {
12498        /* Format: Len | Modes* */
12499        int   idx = 0;
12500        word16 len;
12501        *modes = 0;
12502
12503        /* Ensure length byte exists. */
12504        if (length < OPAQUE8_LEN)
12505            return BUFFER_E;
12506
12507        /* Get length of mode list and ensure that is the only data. */
12508        len = input[0];
12509        if (length - OPAQUE8_LEN != len)
12510            return BUFFER_E;
12511
12512        idx = OPAQUE8_LEN;
12513        /* Set a bit for each recognized modes. */
12514        while (len > 0) {
12515            /* Ignore unrecognized modes.  */
12516            if (input[idx] <= PSK_DHE_KE)
12517               *modes |= 1 << input[idx];
12518            idx++;
12519            len--;
12520        }
12521        return 0;
12522    }
12523
12524    WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
12525    return SANITY_MSG_E;
12526}
12527
12528/* Parse the PSK KE modes extension.
12529 * Only in ClientHello.
12530 *
12531 * ssl      The SSL/TLS object.
12532 * input    The extension data.
12533 * length   The length of the extension data.
12534 * msgType  The type of the message this extension is being parsed from.
12535 * returns 0 on success and other values indicate failure.
12536 */
12537static int TLSX_PskKeModes_Parse(WOLFSSL* ssl, const byte* input, word16 length,
12538                                 byte msgType)
12539{
12540    int    ret;
12541    byte modes;
12542
12543    ret = TLSX_PskKeyModes_Parse_Modes(input, length, msgType, &modes);
12544    if (ret == 0)
12545        ret = TLSX_PskKeyModes_Use(ssl, modes);
12546
12547    if (ret != 0) {
12548        WOLFSSL_ERROR_VERBOSE(ret);
12549    }
12550
12551    return ret;
12552}
12553
12554/* Use the data to create a new PSK Key Exchange Modes object in the extensions.
12555 *
12556 * ssl    The SSL/TLS object.
12557 * modes  The PSK key exchange modes.
12558 * returns 0 on success and other values indicate failure.
12559 */
12560int TLSX_PskKeyModes_Use(WOLFSSL* ssl, byte modes)
12561{
12562    int           ret = 0;
12563    TLSX*         extension;
12564
12565    /* Find the PSK key exchange modes extension if it exists. */
12566    extension = TLSX_Find(ssl->extensions, TLSX_PSK_KEY_EXCHANGE_MODES);
12567    if (extension == NULL) {
12568        /* Push new PSK key exchange modes extension. */
12569        ret = TLSX_Push(&ssl->extensions, TLSX_PSK_KEY_EXCHANGE_MODES, NULL,
12570            ssl->heap);
12571        if (ret != 0)
12572            return ret;
12573
12574        extension = TLSX_Find(ssl->extensions, TLSX_PSK_KEY_EXCHANGE_MODES);
12575        if (extension == NULL)
12576            return MEMORY_E;
12577    }
12578
12579    extension->val = modes;
12580
12581    return 0;
12582}
12583
12584#define PKM_GET_SIZE  TLSX_PskKeModes_GetSize
12585#define PKM_WRITE     TLSX_PskKeModes_Write
12586#define PKM_PARSE     TLSX_PskKeModes_Parse
12587
12588#else
12589
12590#define PKM_GET_SIZE(a, b, c) 0
12591#define PKM_WRITE(a, b, c, d) 0
12592#define PKM_PARSE(a, b, c, d) 0
12593
12594#endif
12595
12596/******************************************************************************/
12597/* Post-Handshake Authentication                                              */
12598/******************************************************************************/
12599
12600#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
12601/* Get the size of the encoded Post-Handshake Authentication extension.
12602 * Only in ClientHello.
12603 *
12604 * msgType  The type of the message this extension is being written into.
12605 * returns the number of bytes of the encoded Post-Handshake Authentication
12606 * extension.
12607 */
12608static int TLSX_PostHandAuth_GetSize(byte msgType, word16* pSz)
12609{
12610    if (msgType == client_hello) {
12611        *pSz += 0;
12612        return 0;
12613    }
12614
12615    WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
12616    return SANITY_MSG_E;
12617}
12618
12619/* Writes the Post-Handshake Authentication extension into the output buffer.
12620 * Assumes that the the output buffer is big enough to hold data.
12621 * Only in ClientHello.
12622 *
12623 * output   The buffer to write into.
12624 * msgType  The type of the message this extension is being written into.
12625 * returns the number of bytes written into the buffer.
12626 */
12627static int TLSX_PostHandAuth_Write(byte* output, byte msgType, word16* pSz)
12628{
12629    (void)output;
12630
12631    if (msgType == client_hello) {
12632        *pSz += 0;
12633        return 0;
12634    }
12635
12636    WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
12637    return SANITY_MSG_E;
12638}
12639
12640/* Parse the Post-Handshake Authentication extension.
12641 * Only in ClientHello.
12642 *
12643 * ssl      The SSL/TLS object.
12644 * input    The extension data.
12645 * length   The length of the extension data.
12646 * msgType  The type of the message this extension is being parsed from.
12647 * returns 0 on success and other values indicate failure.
12648 */
12649static int TLSX_PostHandAuth_Parse(WOLFSSL* ssl, const byte* input,
12650                                   word16 length, byte msgType)
12651{
12652    (void)input;
12653
12654    if (msgType == client_hello) {
12655        /* Ensure extension is empty. */
12656        if (length != 0)
12657            return BUFFER_E;
12658
12659        ssl->options.postHandshakeAuth = 1;
12660        return 0;
12661    }
12662
12663    WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
12664    return SANITY_MSG_E;
12665}
12666
12667/* Create a new Post-handshake authentication object in the extensions.
12668 *
12669 * ssl    The SSL/TLS object.
12670 * returns 0 on success and other values indicate failure.
12671 */
12672static int TLSX_PostHandAuth_Use(WOLFSSL* ssl)
12673{
12674    int   ret = 0;
12675    TLSX* extension;
12676
12677    /* Find the PSK key exchange modes extension if it exists. */
12678    extension = TLSX_Find(ssl->extensions, TLSX_POST_HANDSHAKE_AUTH);
12679    if (extension == NULL) {
12680        /* Push new Post-handshake Authentication extension. */
12681        ret = TLSX_Push(&ssl->extensions, TLSX_POST_HANDSHAKE_AUTH, NULL,
12682            ssl->heap);
12683        if (ret != 0)
12684            return ret;
12685    }
12686
12687    return 0;
12688}
12689
12690#define PHA_GET_SIZE  TLSX_PostHandAuth_GetSize
12691#define PHA_WRITE     TLSX_PostHandAuth_Write
12692#define PHA_PARSE     TLSX_PostHandAuth_Parse
12693
12694#else
12695
12696#define PHA_GET_SIZE(a, b)    0
12697#define PHA_WRITE(a, b, c)    0
12698#define PHA_PARSE(a, b, c, d) 0
12699
12700#endif
12701
12702/******************************************************************************/
12703/* Early Data Indication                                                      */
12704/******************************************************************************/
12705
12706#ifdef WOLFSSL_EARLY_DATA
12707/* Get the size of the encoded Early Data Indication extension.
12708 * In messages: ClientHello, EncryptedExtensions and NewSessionTicket.
12709 *
12710 * msgType  The type of the message this extension is being written into.
12711 * returns the number of bytes of the encoded Early Data Indication extension.
12712 */
12713static int TLSX_EarlyData_GetSize(byte msgType, word16* pSz)
12714{
12715    int ret = 0;
12716
12717    if (msgType == client_hello || msgType == encrypted_extensions)
12718        *pSz += 0;
12719    else if (msgType == session_ticket)
12720        *pSz += OPAQUE32_LEN;
12721    else {
12722        ret = SANITY_MSG_E;
12723        WOLFSSL_ERROR_VERBOSE(ret);
12724    }
12725
12726    return ret;
12727}
12728
12729/* Writes the Early Data Indicator extension into the output buffer.
12730 * Assumes that the the output buffer is big enough to hold data.
12731 * In messages: ClientHello, EncryptedExtensions and NewSessionTicket.
12732 *
12733 * maxSz    The maximum early data size.
12734 * output   The buffer to write into.
12735 * msgType  The type of the message this extension is being written into.
12736 * returns the number of bytes written into the buffer.
12737 */
12738static int TLSX_EarlyData_Write(word32 maxSz, byte* output, byte msgType,
12739                                word16* pSz)
12740{
12741    if (msgType == client_hello || msgType == encrypted_extensions)
12742        return 0;
12743    else if (msgType == session_ticket) {
12744        c32toa(maxSz, output);
12745        *pSz += OPAQUE32_LEN;
12746        return 0;
12747    }
12748
12749    WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
12750    return SANITY_MSG_E;
12751}
12752
12753/* Parse the Early Data Indicator extension.
12754 * In messages: ClientHello, EncryptedExtensions and NewSessionTicket.
12755 *
12756 * ssl      The SSL/TLS object.
12757 * input    The extension data.
12758 * length   The length of the extension data.
12759 * msgType  The type of the message this extension is being parsed from.
12760 * returns 0 on success and other values indicate failure.
12761 */
12762static int TLSX_EarlyData_Parse(WOLFSSL* ssl, const byte* input, word16 length,
12763                                 byte msgType)
12764{
12765    WOLFSSL_ENTER("TLSX_EarlyData_Parse");
12766    if (msgType == client_hello) {
12767        if (length != 0)
12768            return BUFFER_E;
12769
12770        if (ssl->earlyData == expecting_early_data) {
12771
12772            if (ssl->options.maxEarlyDataSz != 0)
12773                ssl->earlyDataStatus = WOLFSSL_EARLY_DATA_ACCEPTED;
12774            else
12775                ssl->earlyDataStatus = WOLFSSL_EARLY_DATA_REJECTED;
12776
12777            return TLSX_EarlyData_Use(ssl, 0, 0);
12778        }
12779        ssl->earlyData = early_data_ext;
12780
12781        return 0;
12782    }
12783    if (msgType == encrypted_extensions) {
12784        if (length != 0)
12785            return BUFFER_E;
12786
12787        /* Ensure the index of PSK identity chosen by server is 0.
12788         * Index is plus one to handle 'not set' value of 0.
12789         */
12790        if (ssl->options.pskIdIndex != 1) {
12791            WOLFSSL_ERROR_VERBOSE(PSK_KEY_ERROR);
12792            return PSK_KEY_ERROR;
12793        }
12794
12795        if (ssl->options.side == WOLFSSL_CLIENT_END) {
12796            /* the extension from server comes in */
12797            ssl->earlyDataStatus = WOLFSSL_EARLY_DATA_ACCEPTED;
12798        }
12799
12800        return TLSX_EarlyData_Use(ssl, 1, 1);
12801    }
12802    if (msgType == session_ticket) {
12803        word32 maxSz;
12804
12805        if (length != OPAQUE32_LEN)
12806            return BUFFER_E;
12807        ato32(input, &maxSz);
12808
12809        ssl->session->maxEarlyDataSz = maxSz;
12810        return 0;
12811    }
12812
12813    WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
12814    return SANITY_MSG_E;
12815}
12816
12817/* Use the data to create a new Early Data object in the extensions.
12818 *
12819 * ssl    The SSL/TLS object.
12820 * maxSz  The maximum early data size.
12821 * is_response   if this extension is part of a response
12822 * returns 0 on success and other values indicate failure.
12823 */
12824int TLSX_EarlyData_Use(WOLFSSL* ssl, word32 maxSz, int is_response)
12825{
12826    int   ret = 0;
12827    TLSX* extension;
12828
12829    /* Find the early data extension if it exists. */
12830    extension = TLSX_Find(ssl->extensions, TLSX_EARLY_DATA);
12831    if (extension == NULL) {
12832        /* Push new early data extension. */
12833        ret = TLSX_Push(&ssl->extensions, TLSX_EARLY_DATA, NULL, ssl->heap);
12834        if (ret != 0)
12835            return ret;
12836
12837        extension = TLSX_Find(ssl->extensions, TLSX_EARLY_DATA);
12838        if (extension == NULL)
12839            return MEMORY_E;
12840    }
12841
12842    extension->resp = is_response;
12843    /* In QUIC, earlydata size is either 0 or 0xffffffff.
12844     * Override any size between, possibly left from our initial value */
12845    extension->val  = (WOLFSSL_IS_QUIC(ssl) && is_response && maxSz > 0) ?
12846                       WOLFSSL_MAX_32BIT : maxSz;
12847
12848    return 0;
12849}
12850
12851#define EDI_GET_SIZE  TLSX_EarlyData_GetSize
12852#define EDI_WRITE     TLSX_EarlyData_Write
12853#define EDI_PARSE     TLSX_EarlyData_Parse
12854
12855#else
12856
12857#define EDI_GET_SIZE(a, b)    0
12858#define EDI_WRITE(a, b, c, d) 0
12859#define EDI_PARSE(a, b, c, d) 0
12860
12861#endif
12862
12863/******************************************************************************/
12864/* QUIC transport parameter extension                                         */
12865/******************************************************************************/
12866#ifdef WOLFSSL_QUIC
12867
12868static word16 TLSX_QuicTP_GetSize(TLSX* extension)
12869{
12870    const QuicTransportParam *tp = (QuicTransportParam*)extension->data;
12871
12872    return tp ? tp->len : 0;
12873}
12874
12875int TLSX_QuicTP_Use(WOLFSSL* ssl, TLSX_Type ext_type, int is_response)
12876{
12877    int ret = 0;
12878    TLSX* extension;
12879
12880    WOLFSSL_ENTER("TLSX_QuicTP_Use");
12881    if (ssl->quic.transport_local == NULL) {
12882        /* RFC9000, ch 7.3: "An endpoint MUST treat the absence of [...]
12883         *     from either endpoint [...] as a connection error of type
12884         *     TRANSPORT_PARAMETER_ERROR."
12885         */
12886        ret = QUIC_TP_MISSING_E;
12887        goto cleanup;
12888    }
12889
12890    extension = TLSX_Find(ssl->extensions, ext_type);
12891    if (extension == NULL) {
12892        ret = TLSX_Push(&ssl->extensions, ext_type, NULL, ssl->heap);
12893        if (ret != 0)
12894            goto cleanup;
12895
12896        extension = TLSX_Find(ssl->extensions, ext_type);
12897        if (extension == NULL) {
12898            ret = MEMORY_E;
12899            goto cleanup;
12900        }
12901    }
12902    if (extension->data) {
12903        QuicTransportParam_free((QuicTransportParam*)extension->data, ssl->heap);
12904        extension->data = NULL;
12905    }
12906    extension->resp = is_response;
12907    extension->data = (void*)QuicTransportParam_dup(ssl->quic.transport_local, ssl->heap);
12908    if (!extension->data) {
12909        ret = MEMORY_E;
12910        goto cleanup;
12911    }
12912
12913cleanup:
12914    WOLFSSL_LEAVE("TLSX_QuicTP_Use", ret);
12915    return ret;
12916}
12917
12918static word16 TLSX_QuicTP_Write(QuicTransportParam *tp, byte* output)
12919{
12920    word16 len = 0;
12921
12922    WOLFSSL_ENTER("TLSX_QuicTP_Write");
12923    if (tp && tp->len) {
12924        XMEMCPY(output, tp->data, tp->len);
12925        len = tp->len;
12926    }
12927    WOLFSSL_LEAVE("TLSX_QuicTP_Write", len);
12928    return len;
12929}
12930
12931static int TLSX_QuicTP_Parse(WOLFSSL *ssl, const byte *input, size_t len, int ext_type, int msgType)
12932{
12933    const QuicTransportParam *tp, **ptp;
12934
12935    (void)msgType;
12936    tp = QuicTransportParam_new(input, len, ssl->heap);
12937    if (!tp) {
12938        return MEMORY_E;
12939    }
12940    ptp = (ext_type == TLSX_KEY_QUIC_TP_PARAMS_DRAFT) ?
12941        &ssl->quic.transport_peer_draft : &ssl->quic.transport_peer;
12942    if (*ptp) {
12943        QTP_FREE(*ptp, ssl->heap);
12944    }
12945    *ptp = tp;
12946    return 0;
12947}
12948
12949#define QTP_GET_SIZE    TLSX_QuicTP_GetSize
12950#define QTP_USE         TLSX_QuicTP_Use
12951#define QTP_WRITE       TLSX_QuicTP_Write
12952#define QTP_PARSE       TLSX_QuicTP_Parse
12953
12954#endif /* WOLFSSL_QUIC */
12955
12956#if defined(WOLFSSL_DTLS_CID)
12957#define CID_GET_SIZE  TLSX_ConnectionID_GetSize
12958#define CID_WRITE  TLSX_ConnectionID_Write
12959#define CID_PARSE  TLSX_ConnectionID_Parse
12960#define CID_FREE  TLSX_ConnectionID_Free
12961#else
12962#define CID_GET_SIZE(a) 0
12963#define CID_WRITE(a, b) 0
12964#define CID_PARSE(a, b, c, d) 0
12965#define CID_FREE(a, b) 0
12966#endif /* defined(WOLFSSL_DTLS_CID) */
12967
12968#if defined(HAVE_RPK)
12969/******************************************************************************/
12970/* Client_Certificate_Type extension                                          */
12971/******************************************************************************/
12972/* return 1 if specified type is included in the given list, otherwise 0 */
12973static int IsCertTypeListed(byte type, byte cnt, const byte* list)
12974{
12975    int ret = 0;
12976    int i;
12977
12978    if (cnt == 0 || list == NULL)
12979        return ret;
12980
12981    if (cnt > 0 && cnt <= MAX_CLIENT_CERT_TYPE_CNT) {
12982        for (i = 0; i < cnt; i++) {
12983            if (list[i] == type)
12984                return 1;
12985        }
12986    }
12987    return 0;
12988}
12989
12990/* Search both arrays from above to find a common value between the two given
12991 * arrays(a and b). return 1 if it finds a common value, otherwise return 0.
12992 */
12993static int GetCommonItem(const byte* a, byte aLen, const byte* b, byte bLen,
12994                                                                    byte* type)
12995{
12996    int i, j;
12997
12998    if (a == NULL || b == NULL)
12999        return 0;
13000
13001    for (i = 0; i < aLen; i++) {
13002        for (j = 0; j < bLen; j++) {
13003            if (a[i] == b[j]) {
13004                *type = a[i];
13005                return 1;
13006            }
13007        }
13008    }
13009    return 0;
13010}
13011
13012/* Creates a "client certificate type" extension if necessary.
13013 * Returns 0 if no error occurred, negative value otherwise.
13014 * A return of 0, it does not indicae that the extension was created.
13015 */
13016static int TLSX_ClientCertificateType_Use(WOLFSSL* ssl, byte isServer)
13017{
13018    int ret = 0;
13019
13020    if (ssl == NULL)
13021        return BAD_FUNC_ARG;
13022
13023    if (isServer) {
13024        /* [in server side]
13025         */
13026
13027        if (IsCertTypeListed(WOLFSSL_CERT_TYPE_RPK,
13028                        ssl->options.rpkConfig.preferred_ClientCertTypeCnt,
13029                        ssl->options.rpkConfig.preferred_ClientCertTypes)) {
13030
13031            WOLFSSL_MSG("Adding Client Certificate Type extension");
13032            ret = TLSX_Push(&ssl->extensions, TLSX_CLIENT_CERTIFICATE_TYPE, ssl,
13033                                                                    ssl->heap);
13034            if (ret == 0) {
13035                TLSX_SetResponse(ssl, TLSX_CLIENT_CERTIFICATE_TYPE);
13036            }
13037        }
13038    }
13039    else {
13040        /* [in client side]
13041         * This extension MUST be omitted from the ClientHello unless the RPK
13042         * certificate is preferred by the user and actually loaded.
13043         */
13044
13045        if (IsCertTypeListed(WOLFSSL_CERT_TYPE_RPK,
13046                        ssl->options.rpkConfig.preferred_ClientCertTypeCnt,
13047                        ssl->options.rpkConfig.preferred_ClientCertTypes)) {
13048
13049            if (ssl->options.rpkState.isRPKLoaded) {
13050
13051                ssl->options.rpkState.sending_ClientCertTypeCnt = 1;
13052                ssl->options.rpkState.sending_ClientCertTypes[0] =
13053                                                        WOLFSSL_CERT_TYPE_RPK;
13054
13055                /* Push new client_certificate_type extension. */
13056                WOLFSSL_MSG("Adding Client Certificate Type extension");
13057                ret = TLSX_Push(&ssl->extensions, TLSX_CLIENT_CERTIFICATE_TYPE,
13058                                                                ssl, ssl->heap);
13059            }
13060            else {
13061                WOLFSSL_MSG("Willing to use RPK cert but not loaded it");
13062            }
13063        }
13064        else {
13065            WOLFSSL_MSG("No will to use RPK cert");
13066        }
13067    }
13068    return ret;
13069}
13070
13071/* Parse a "client certificate type" extension received from peer.
13072 * returns 0 on success and other values indicate failure.
13073 */
13074static int TLSX_ClientCertificateType_Parse(WOLFSSL* ssl, const byte* input,
13075                                                word16 length, byte msgType)
13076{
13077    byte typeCnt;
13078    int idx = 0;
13079    int ret = 0;
13080    int i;
13081    int populate = 0;
13082    byte  cmnType;
13083
13084
13085    if (msgType == client_hello) {
13086        /* [parse ClientHello in server end]
13087         * case 1) if peer verify is disabled, this extension must be omitted
13088         *         from ServerHello.
13089         * case 2) if user have not set his preference, find X509 in parsed
13090         *         result, then populate "Client Certificate Type" extension.
13091         * case 3) if user have not set his preference and X509 isn't included
13092         *         in parsed result, send "unsupported certificate" alert.
13093         * case 4) if user have set his preference, find a common cert type
13094         *         in users preference and received cert types.
13095         * case 5) if user have set his preference, but no common cert type
13096         *         found.
13097         */
13098
13099        /* case 1 */
13100        if (ssl->options.verifyNone) {
13101            return ret;
13102        }
13103
13104        /* parse extension */
13105        if (length < OPAQUE8_LEN)
13106            return BUFFER_E;
13107
13108        typeCnt = input[idx];
13109
13110        if (typeCnt > MAX_CLIENT_CERT_TYPE_CNT)
13111            return BUFFER_E;
13112
13113        if ((typeCnt + 1) * OPAQUE8_LEN != length){
13114            return BUFFER_E;
13115        }
13116
13117        ssl->options.rpkState.received_ClientCertTypeCnt = input[idx];
13118        idx += OPAQUE8_LEN;
13119
13120        for (i = 0; i < typeCnt; i++) {
13121            ssl->options.rpkState.received_ClientCertTypes[i] = input[idx];
13122            idx += OPAQUE8_LEN;
13123        }
13124
13125        if (ssl->options.rpkConfig.preferred_ClientCertTypeCnt == 0) {
13126            /* case 2 */
13127            if (IsCertTypeListed(WOLFSSL_CERT_TYPE_X509,
13128                            ssl->options.rpkState.received_ClientCertTypeCnt,
13129                            ssl->options.rpkState.received_ClientCertTypes)) {
13130
13131                ssl->options.rpkState.sending_ClientCertTypeCnt = 1;
13132                ssl->options.rpkState.sending_ClientCertTypes[0] =
13133                                                        WOLFSSL_CERT_TYPE_X509;
13134                populate = 1;
13135            }
13136            /* case 3 */
13137            else {
13138                WOLFSSL_MSG("No common cert type found in client_certificate_type ext");
13139                SendAlert(ssl, alert_fatal, unsupported_certificate);
13140                return UNSUPPORTED_CERTIFICATE;
13141            }
13142        }
13143        else if (ssl->options.rpkConfig.preferred_ClientCertTypeCnt > 0) {
13144            /* case 4 */
13145            if (GetCommonItem(
13146                            ssl->options.rpkConfig.preferred_ClientCertTypes,
13147                            ssl->options.rpkConfig.preferred_ClientCertTypeCnt,
13148                            ssl->options.rpkState.received_ClientCertTypes,
13149                            ssl->options.rpkState.received_ClientCertTypeCnt,
13150                            &cmnType)) {
13151                ssl->options.rpkState.sending_ClientCertTypeCnt  = 1;
13152                ssl->options.rpkState.sending_ClientCertTypes[0] = cmnType;
13153                populate = 1;
13154            }
13155            /* case 5 */
13156            else {
13157                WOLFSSL_MSG("No common cert type found in client_certificate_type ext");
13158                SendAlert(ssl, alert_fatal, unsupported_certificate);
13159                return UNSUPPORTED_CERTIFICATE;
13160            }
13161        }
13162
13163        /* populate client_certificate_type extension */
13164        if (populate) {
13165            WOLFSSL_MSG("Adding Client Certificate Type extension");
13166            ret = TLSX_Push(&ssl->extensions, TLSX_CLIENT_CERTIFICATE_TYPE, ssl,
13167                                                                    ssl->heap);
13168            if (ret == 0) {
13169                TLSX_SetResponse(ssl, TLSX_CLIENT_CERTIFICATE_TYPE);
13170            }
13171        }
13172    }
13173    else if (msgType == server_hello || msgType == encrypted_extensions) {
13174        /* parse it in client side */
13175        if (length == 1) {
13176            ssl->options.rpkState.received_ClientCertTypeCnt  = 1;
13177            ssl->options.rpkState.received_ClientCertTypes[0] = *input;
13178        }
13179        else {
13180            return BUFFER_E;
13181        }
13182    }
13183
13184    return ret;
13185}
13186
13187/* Write out the "client certificate type" extension data into the given buffer.
13188 * return the size wrote in the buffer on success, negative value on error.
13189 */
13190static word16 TLSX_ClientCertificateType_Write(void* data, byte* output,
13191                                              byte msgType)
13192{
13193    WOLFSSL* ssl = (WOLFSSL*)data;
13194    word16 idx = 0;
13195    byte cnt = 0;
13196    int i;
13197
13198    /* skip to write extension if count is zero */
13199    cnt = ssl->options.rpkState.sending_ClientCertTypeCnt;
13200
13201    if (cnt == 0)
13202        return 0;
13203
13204    if (msgType == client_hello) {
13205        /* client side */
13206
13207        *(output + idx) = cnt;
13208        idx += OPAQUE8_LEN;
13209
13210        for (i = 0; i < cnt; i++) {
13211            *(output + idx) = ssl->options.rpkState.sending_ClientCertTypes[i];
13212            idx += OPAQUE8_LEN;
13213        }
13214        return idx;
13215    }
13216    else if (msgType == server_hello || msgType == encrypted_extensions) {
13217        /* sever side */
13218        if (cnt == 1) {
13219            *(output + idx) = ssl->options.rpkState.sending_ClientCertTypes[0];
13220            idx += OPAQUE8_LEN;
13221        }
13222    }
13223    return idx;
13224}
13225
13226/* Calculate then return the size of the "client certificate type" extension
13227 * data.
13228 * return the extension data size on success, negative value on error.
13229*/
13230static int TLSX_ClientCertificateType_GetSize(WOLFSSL* ssl, byte msgType)
13231{
13232    int ret = 0;
13233    byte cnt;
13234
13235    if (ssl == NULL)
13236        return BAD_FUNC_ARG;
13237
13238    if (msgType == client_hello) {
13239        /* client side */
13240        cnt = ssl->options.rpkState.sending_ClientCertTypeCnt;
13241        ret = (int)(OPAQUE8_LEN + cnt * OPAQUE8_LEN);
13242    }
13243    else if (msgType == server_hello || msgType == encrypted_extensions) {
13244        /* server side */
13245        cnt = ssl->options.rpkState.sending_ClientCertTypeCnt;/* must be one */
13246        if (cnt != 1)
13247            return SANITY_MSG_E;
13248        ret = OPAQUE8_LEN;
13249    }
13250    else {
13251        return SANITY_MSG_E;
13252    }
13253    return ret;
13254}
13255
13256    #define CCT_GET_SIZE  TLSX_ClientCertificateType_GetSize
13257    #define CCT_WRITE     TLSX_ClientCertificateType_Write
13258    #define CCT_PARSE     TLSX_ClientCertificateType_Parse
13259#else
13260    #define CCT_GET_SIZE(a)  0
13261    #define CCT_WRITE(a, b)  0
13262    #define CCT_PARSE(a, b, c, d) 0
13263#endif /* HAVE_RPK */
13264
13265#if defined(HAVE_RPK)
13266/******************************************************************************/
13267/* Server_Certificate_Type extension                                          */
13268/******************************************************************************/
13269/* Creates a "server certificate type" extension if necessary.
13270 * Returns 0 if no error occurred, negative value otherwise.
13271 * A return of 0, it does not indicae that the extension was created.
13272 */
13273static int TLSX_ServerCertificateType_Use(WOLFSSL* ssl, byte isServer)
13274{
13275    int ret = 0;
13276    byte ctype;
13277
13278    if (ssl == NULL)
13279        return BAD_FUNC_ARG;
13280
13281    if (isServer) {
13282        /* [in server side] */
13283        /* find common cert type to both end */
13284        if (GetCommonItem(
13285                ssl->options.rpkConfig.preferred_ServerCertTypes,
13286                ssl->options.rpkConfig.preferred_ServerCertTypeCnt,
13287                ssl->options.rpkState.received_ServerCertTypes,
13288                ssl->options.rpkState.received_ServerCertTypeCnt,
13289                &ctype)) {
13290            ssl->options.rpkState.sending_ServerCertTypeCnt = 1;
13291            ssl->options.rpkState.sending_ServerCertTypes[0] = ctype;
13292
13293            /* Push new server_certificate_type extension. */
13294            WOLFSSL_MSG("Adding Server Certificate Type extension");
13295            ret = TLSX_Push(&ssl->extensions, TLSX_SERVER_CERTIFICATE_TYPE, ssl,
13296                                                                    ssl->heap);
13297            if (ret == 0) {
13298                TLSX_SetResponse(ssl, TLSX_SERVER_CERTIFICATE_TYPE);
13299            }
13300        }
13301        else {
13302            /* no common cert type found */
13303            WOLFSSL_MSG("No common cert type found in server_certificate_type ext");
13304            SendAlert(ssl, alert_fatal, unsupported_certificate);
13305            ret = UNSUPPORTED_CERTIFICATE;
13306        }
13307    }
13308    else {
13309        /* [in client side] */
13310        if (IsCertTypeListed(WOLFSSL_CERT_TYPE_RPK,
13311                            ssl->options.rpkConfig.preferred_ServerCertTypeCnt,
13312                            ssl->options.rpkConfig.preferred_ServerCertTypes)) {
13313
13314            ssl->options.rpkState.sending_ServerCertTypeCnt =
13315                        ssl->options.rpkConfig.preferred_ServerCertTypeCnt;
13316            XMEMCPY(ssl->options.rpkState.sending_ServerCertTypes,
13317                    ssl->options.rpkConfig.preferred_ServerCertTypes,
13318                    ssl->options.rpkConfig.preferred_ServerCertTypeCnt);
13319
13320            /* Push new server_certificate_type extension. */
13321            WOLFSSL_MSG("Adding Server Certificate Type extension");
13322            ret = TLSX_Push(&ssl->extensions, TLSX_SERVER_CERTIFICATE_TYPE, ssl,
13323                                                                    ssl->heap);
13324        }
13325        else {
13326            WOLFSSL_MSG("No will to accept RPK cert");
13327        }
13328    }
13329
13330    return ret;
13331}
13332
13333/* Parse a "server certificate type" extension received from peer.
13334 * returns 0 on success and other values indicate failure.
13335 */
13336static int TLSX_ServerCertificateType_Parse(WOLFSSL* ssl, const byte* input,
13337                                                word16 length, byte msgType)
13338{
13339    byte typeCnt;
13340    int idx = 0;
13341    int ret = 0;
13342    int i;
13343
13344    if (msgType == client_hello) {
13345        /* in server side */
13346
13347        if (length < OPAQUE8_LEN)
13348            return BUFFER_E;
13349
13350        typeCnt = input[idx];
13351
13352        if (typeCnt > MAX_SERVER_CERT_TYPE_CNT)
13353            return BUFFER_E;
13354
13355        if ((typeCnt + 1) * OPAQUE8_LEN != length){
13356            return BUFFER_E;
13357        }
13358        ssl->options.rpkState.received_ServerCertTypeCnt = input[idx];
13359        idx += OPAQUE8_LEN;
13360
13361        for (i = 0; i < typeCnt; i++) {
13362            ssl->options.rpkState.received_ServerCertTypes[i] = input[idx];
13363            idx += OPAQUE8_LEN;
13364        }
13365
13366        ret = TLSX_ServerCertificateType_Use(ssl, 1);
13367        if (ret == 0) {
13368            TLSX_SetResponse(ssl, TLSX_SERVER_CERTIFICATE_TYPE);
13369        }
13370    }
13371    else if (msgType == server_hello || msgType == encrypted_extensions) {
13372        /* in client side */
13373        if (length != 1)                     /* length slould be 1 */
13374            return BUFFER_E;
13375
13376        ssl->options.rpkState.received_ServerCertTypeCnt  = 1;
13377        ssl->options.rpkState.received_ServerCertTypes[0] = *input;
13378    }
13379
13380    return 0;
13381}
13382
13383/* Write out the "server certificate type" extension data into the given buffer.
13384 * return the size wrote in the buffer on success, negative value on error.
13385 */
13386static word16 TLSX_ServerCertificateType_Write(void* data, byte* output,
13387                                                                byte msgType)
13388{
13389    WOLFSSL* ssl = (WOLFSSL*)data;
13390    word16 idx = 0;
13391    int cnt = 0;
13392    int i;
13393
13394    /* skip to write extension if count is zero */
13395    cnt = ssl->options.rpkState.sending_ServerCertTypeCnt;
13396
13397    if (cnt == 0)
13398        return 0;
13399
13400    if (msgType == client_hello) {
13401        /* in client side */
13402
13403        *(output + idx) = cnt;
13404        idx += OPAQUE8_LEN;
13405
13406        for (i = 0; i < cnt; i++) {
13407            *(output + idx) = ssl->options.rpkState.sending_ServerCertTypes[i];
13408            idx += OPAQUE8_LEN;
13409        }
13410    }
13411    else if (msgType == server_hello || msgType == encrypted_extensions) {
13412        /* in server side */
13413        /* ensure cnt is one */
13414        if (cnt != 1)
13415            return 0;
13416
13417        *(output + idx) =  ssl->options.rpkState.sending_ServerCertTypes[0];
13418        idx += OPAQUE8_LEN;
13419    }
13420    return idx;
13421}
13422
13423/* Calculate then return the size of the "server certificate type" extension
13424 * data.
13425 * return the extension data size on success, negative value on error.
13426*/
13427static int TLSX_ServerCertificateType_GetSize(WOLFSSL* ssl, byte msgType)
13428{
13429    int ret = 0;
13430    int cnt;
13431
13432    if (ssl == NULL)
13433        return BAD_FUNC_ARG;
13434
13435    if (msgType == client_hello) {
13436        /* in clent side */
13437        cnt = ssl->options.rpkState.sending_ServerCertTypeCnt;
13438        if (cnt > 0) {
13439            ret = (int)(OPAQUE8_LEN + cnt * OPAQUE8_LEN);
13440        }
13441    }
13442    else if (msgType == server_hello || msgType == encrypted_extensions) {
13443        /* in server side */
13444        ret = (int)OPAQUE8_LEN;
13445    }
13446    else {
13447        return SANITY_MSG_E;
13448    }
13449    return ret;
13450}
13451
13452    #define SCT_GET_SIZE  TLSX_ServerCertificateType_GetSize
13453    #define SCT_WRITE     TLSX_ServerCertificateType_Write
13454    #define SCT_PARSE     TLSX_ServerCertificateType_Parse
13455#else
13456    #define SCT_GET_SIZE(a)  0
13457    #define SCT_WRITE(a, b)  0
13458    #define SCT_PARSE(a, b, c, d) 0
13459#endif /* HAVE_RPK */
13460
13461/******************************************************************************/
13462/* TLS Extensions Framework                                                   */
13463/******************************************************************************/
13464
13465/** Finds an extension in the provided list. */
13466TLSX* TLSX_Find(TLSX* list, TLSX_Type type)
13467{
13468    TLSX* extension = list;
13469
13470    while (extension && extension->type != type)
13471        extension = extension->next;
13472
13473    return extension;
13474}
13475
13476/** Remove an extension. */
13477void TLSX_Remove(TLSX** list, TLSX_Type type, void* heap)
13478{
13479    TLSX* extension;
13480    TLSX** next;
13481
13482    if (list == NULL)
13483        return;
13484
13485    extension = *list;
13486    next = list;
13487
13488    while (extension && extension->type != type) {
13489        next = &extension->next;
13490        extension = extension->next;
13491    }
13492
13493    if (extension) {
13494        *next = extension->next;
13495        extension->next = NULL;
13496        TLSX_FreeAll(extension, heap);
13497    }
13498}
13499
13500#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
13501#define GREASE_ECH_SIZE 160
13502#define TLS_INFO_CONST_STRING "tls ech"
13503#define TLS_INFO_CONST_STRING_SZ 7
13504
13505/* return status after setting up ech to write a grease ech */
13506static int TLSX_GreaseECH_Use(TLSX** extensions, void* heap, WC_RNG* rng)
13507{
13508    int ret = 0;
13509    WOLFSSL_ECH* ech;
13510
13511    if (extensions == NULL)
13512        return BAD_FUNC_ARG;
13513
13514    ech = (WOLFSSL_ECH*)XMALLOC(sizeof(WOLFSSL_ECH), heap,
13515        DYNAMIC_TYPE_TMP_BUFFER);
13516
13517    if (ech == NULL)
13518        return MEMORY_E;
13519
13520    ForceZero(ech, sizeof(WOLFSSL_ECH));
13521
13522    ech->state = ECH_WRITE_GREASE;
13523
13524    /* 0 for outer */
13525    ech->type = ECH_TYPE_OUTER;
13526    /* kemId */
13527    ech->kemId = DHKEM_X25519_HKDF_SHA256;
13528    /* cipherSuite kdf */
13529    ech->cipherSuite.kdfId = HKDF_SHA256;
13530    /* cipherSuite aead */
13531    ech->cipherSuite.aeadId = HPKE_AES_128_GCM;
13532
13533    /* random configId */
13534    ret = wc_RNG_GenerateByte(rng, &(ech->configId));
13535
13536    /* curve25519 encLen */
13537    ech->encLen = DHKEM_X25519_ENC_LEN;
13538
13539    if (ret == 0)
13540        ret = TLSX_Push(extensions, TLSX_ECH, ech, heap);
13541
13542    if (ret != 0) {
13543        XFREE(ech, heap, DYNAMIC_TYPE_TMP_BUFFER);
13544    }
13545
13546    return ret;
13547}
13548
13549/* return status after setting up ech to write real ech */
13550static int TLSX_ECH_Use(WOLFSSL_EchConfig* echConfig, TLSX** extensions,
13551    void* heap, WC_RNG* rng)
13552{
13553    int ret = 0;
13554    int suiteIndex;
13555    TLSX* echX;
13556    WOLFSSL_ECH* ech;
13557    if (extensions == NULL)
13558        return BAD_FUNC_ARG;
13559    /* skip if we already have an ech extension, we will for hrr */
13560    echX = TLSX_Find(*extensions, TLSX_ECH);
13561    if (echX != NULL)
13562        return 0;
13563    /* find a supported cipher suite */
13564    suiteIndex = EchConfigGetSupportedCipherSuite(echConfig);
13565    if (suiteIndex < 0)
13566        return suiteIndex;
13567    ech = (WOLFSSL_ECH*)XMALLOC(sizeof(WOLFSSL_ECH), heap,
13568        DYNAMIC_TYPE_TMP_BUFFER);
13569    if (ech == NULL)
13570        return MEMORY_E;
13571    ForceZero(ech, sizeof(WOLFSSL_ECH));
13572    ech->state = ECH_WRITE_REAL;
13573    ech->echConfig = echConfig;
13574    /* 0 for outer */
13575    ech->type = ECH_TYPE_OUTER;
13576    /* kemId */
13577    ech->kemId = echConfig->kemId;
13578    /* cipherSuite kdf */
13579    ech->cipherSuite.kdfId = echConfig->cipherSuites[suiteIndex].kdfId;
13580    /* cipherSuite aead */
13581    ech->cipherSuite.aeadId = echConfig->cipherSuites[suiteIndex].aeadId;
13582    /* configId */
13583    ech->configId = echConfig->configId;
13584    /* encLen */
13585    ech->encLen = wc_HpkeKemGetEncLen(echConfig->kemId);
13586    if (ech->encLen == 0) {
13587        XFREE(ech, heap, DYNAMIC_TYPE_TMP_BUFFER);
13588        return BAD_FUNC_ARG;
13589    }
13590    /* setup hpke */
13591    ech->hpke = (Hpke*)XMALLOC(sizeof(Hpke), heap, DYNAMIC_TYPE_TMP_BUFFER);
13592    if (ech->hpke == NULL) {
13593        XFREE(ech, heap, DYNAMIC_TYPE_TMP_BUFFER);
13594        return MEMORY_E;
13595    }
13596    ret = wc_HpkeInit(ech->hpke, ech->kemId, ech->cipherSuite.kdfId,
13597        ech->cipherSuite.aeadId, heap);
13598    /* setup the ephemeralKey */
13599    if (ret == 0)
13600        ret = wc_HpkeGenerateKeyPair(ech->hpke, &ech->ephemeralKey, rng);
13601    if (ret == 0) {
13602        ret = TLSX_Push(extensions, TLSX_ECH, ech, heap);
13603        if (ret != 0) {
13604            wc_HpkeFreeKey(ech->hpke, ech->hpke->kem, ech->ephemeralKey,
13605                ech->hpke->heap);
13606        }
13607    }
13608    if (ret != 0) {
13609        XFREE(ech->hpke, heap, DYNAMIC_TYPE_TMP_BUFFER);
13610        XFREE(ech, heap, DYNAMIC_TYPE_TMP_BUFFER);
13611    }
13612    return ret;
13613}
13614
13615/* return status after setting up ech to read and decrypt */
13616static int TLSX_ServerECH_Use(TLSX** extensions, void* heap,
13617    WOLFSSL_EchConfig* configs)
13618{
13619    int ret;
13620    WOLFSSL_ECH* ech;
13621    TLSX* echX;
13622    if (extensions == NULL)
13623        return BAD_FUNC_ARG;
13624    /* if we already have ech don't override it */
13625    echX = TLSX_Find(*extensions, TLSX_ECH);
13626    if (echX != NULL)
13627        return 0;
13628    ech = (WOLFSSL_ECH*)XMALLOC(sizeof(WOLFSSL_ECH), heap,
13629        DYNAMIC_TYPE_TMP_BUFFER);
13630    if (ech == NULL)
13631        return MEMORY_E;
13632    ForceZero(ech, sizeof(WOLFSSL_ECH));
13633    ech->state = ECH_WRITE_NONE;
13634    /* 0 for outer */
13635    ech->type = ECH_TYPE_OUTER;
13636    ech->echConfig = configs;
13637    /* setup the rest of the settings when we receive ech from the client */
13638    ret = TLSX_Push(extensions, TLSX_ECH, ech, heap);
13639    if (ret != 0)
13640        XFREE(ech, heap, DYNAMIC_TYPE_TMP_BUFFER);
13641    return ret;
13642}
13643
13644/* return status after writing the ech and updating offset */
13645static int TLSX_ECH_Write(WOLFSSL_ECH* ech, byte msgType, byte* writeBuf,
13646    word16* offset)
13647{
13648    int ret = 0;
13649    int rngRet = -1;
13650    word32 configsLen = 0;
13651    void* ephemeralKey = NULL;
13652    byte* writeBuf_p = writeBuf;
13653    WC_DECLARE_VAR(hpke, Hpke, 1, DYNAMIC_TYPE_TMP_BUFFER);
13654    WC_DECLARE_VAR(rng, WC_RNG, 1, DYNAMIC_TYPE_RNG);
13655
13656    WOLFSSL_MSG("TLSX_ECH_Write");
13657    if (msgType == hello_retry_request) {
13658        WC_ALLOC_VAR_EX(rng, WC_RNG, 1, NULL, DYNAMIC_TYPE_RNG, ret = MEMORY_E);
13659        if (ret == 0) {
13660            ret = wc_InitRng(rng);
13661        }
13662        if (ret == 0) {
13663            /* randomize confirmation in case ech is rejected */
13664            ret = wc_RNG_GenerateBlock(rng, writeBuf,
13665                    ECH_ACCEPT_CONFIRMATION_SZ);
13666            wc_FreeRng(rng);
13667        }
13668        if (ret == 0) {
13669            *offset += ECH_ACCEPT_CONFIRMATION_SZ;
13670            ech->confBuf = writeBuf;
13671        }
13672
13673        WC_FREE_VAR_EX(rng, NULL, DYNAMIC_TYPE_RNG);
13674        return ret;
13675    }
13676    if (ech->state == ECH_WRITE_NONE || ech->state == ECH_PARSED_INTERNAL)
13677        return 0;
13678    if (ech->state == ECH_WRITE_RETRY_CONFIGS) {
13679        /* get size then write */
13680        ret = GetEchConfigsEx(ech->echConfig, NULL, &configsLen);
13681        if (ret != WC_NO_ERR_TRACE(LENGTH_ONLY_E))
13682            return ret;
13683        ret = GetEchConfigsEx(ech->echConfig, writeBuf, &configsLen);
13684        if (ret != WOLFSSL_SUCCESS)
13685            return ret;
13686        *offset += configsLen;
13687        return 0;
13688    }
13689    /* type */
13690    *writeBuf_p = ech->type;
13691    writeBuf_p += sizeof(ech->type);
13692    /* outer has body, inner does not */
13693    if (ech->type == ECH_TYPE_OUTER) {
13694        /* kdfId */
13695        c16toa(ech->cipherSuite.kdfId, writeBuf_p);
13696        writeBuf_p += sizeof(ech->cipherSuite.kdfId);
13697        /* aeadId */
13698        c16toa(ech->cipherSuite.aeadId, writeBuf_p);
13699        writeBuf_p += sizeof(ech->cipherSuite.aeadId);
13700        /* configId */
13701        *writeBuf_p = ech->configId;
13702        writeBuf_p += sizeof(ech->configId);
13703        /* encLen */
13704        if (ech->hpkeContext == NULL) {
13705            c16toa(ech->encLen, writeBuf_p);
13706        }
13707        else {
13708            /* set to 0 if this is clientInner 2 */
13709            c16toa(0, writeBuf_p);
13710        }
13711        writeBuf_p += 2;
13712        if (ech->state == ECH_WRITE_GREASE) {
13713            WC_ALLOC_VAR_EX(hpke, Hpke, 1, NULL, DYNAMIC_TYPE_TMP_BUFFER, ret = MEMORY_E);
13714            WC_ALLOC_VAR_EX(rng, WC_RNG, 1, NULL, DYNAMIC_TYPE_RNG, ret = MEMORY_E);
13715            /* hpke init */
13716            if (ret == 0) {
13717                ret = wc_HpkeInit(hpke, ech->kemId, ech->cipherSuite.kdfId,
13718                    ech->cipherSuite.aeadId, NULL);
13719            }
13720            if (ret == 0)
13721                rngRet = ret = wc_InitRng(rng);
13722            /* create the ephemeralKey */
13723            if (ret == 0)
13724                ret = wc_HpkeGenerateKeyPair(hpke, &ephemeralKey, rng);
13725            /* enc */
13726            if (ret == 0) {
13727                ret = wc_HpkeSerializePublicKey(hpke, ephemeralKey, writeBuf_p,
13728                    &ech->encLen);
13729                writeBuf_p += ech->encLen;
13730            }
13731            if (ret == 0) {
13732                /* innerClientHelloLen */
13733                c16toa(GREASE_ECH_SIZE + ((writeBuf_p + 2 - writeBuf) % 32),
13734                    writeBuf_p);
13735                writeBuf_p += 2;
13736
13737                /* innerClientHello */
13738                ret = wc_RNG_GenerateBlock(rng, writeBuf_p, GREASE_ECH_SIZE +
13739                    ((writeBuf_p - writeBuf) % 32));
13740                writeBuf_p += GREASE_ECH_SIZE + ((writeBuf_p - writeBuf) % 32);
13741            }
13742            if (rngRet == 0)
13743                wc_FreeRng(rng);
13744            if (ephemeralKey != NULL)
13745                wc_HpkeFreeKey(hpke, hpke->kem, ephemeralKey, hpke->heap);
13746            WC_FREE_VAR_EX(hpke, NULL, DYNAMIC_TYPE_TMP_BUFFER);
13747            WC_FREE_VAR_EX(rng, NULL, DYNAMIC_TYPE_RNG);
13748        }
13749        else {
13750            /* only write enc if this is our first ech, no hpke context */
13751            if (ech->hpkeContext == NULL) {
13752                /* write enc to writeBuf_p */
13753                ret = wc_HpkeSerializePublicKey(ech->hpke, ech->ephemeralKey,
13754                    writeBuf_p, &ech->encLen);
13755                writeBuf_p += ech->encLen;
13756            }
13757            /* innerClientHelloLen */
13758            c16toa((word16)ech->innerClientHelloLen, writeBuf_p);
13759            writeBuf_p += 2;
13760            /* set payload offset for when we finalize */
13761            ech->outerClientPayload = writeBuf_p;
13762            /* write zeros for payload */
13763            XMEMSET(writeBuf_p, 0, ech->innerClientHelloLen);
13764            writeBuf_p += ech->innerClientHelloLen;
13765        }
13766    }
13767    if (ret == 0)
13768        *offset += (writeBuf_p - writeBuf);
13769    return ret;
13770}
13771
13772/* return the size needed for the ech extension */
13773static int TLSX_ECH_GetSize(WOLFSSL_ECH* ech, byte msgType)
13774{
13775    int ret;
13776    word32 size = 0;
13777
13778    if (ech->state == ECH_WRITE_GREASE) {
13779        size = sizeof(ech->type) + sizeof(ech->cipherSuite) +
13780            sizeof(ech->configId) + sizeof(word16) + ech->encLen +
13781            sizeof(word16);
13782
13783        size += GREASE_ECH_SIZE + (size % 32);
13784    }
13785    else if (msgType == hello_retry_request) {
13786        size = ECH_ACCEPT_CONFIRMATION_SZ;
13787    }
13788    else if (ech->state == ECH_WRITE_NONE ||
13789        ech->state == ECH_PARSED_INTERNAL) {
13790        size = 0;
13791    }
13792    else if (ech->state == ECH_WRITE_RETRY_CONFIGS) {
13793        /* get the size of the raw configs */
13794        ret = GetEchConfigsEx(ech->echConfig, NULL, &size);
13795
13796        if (ret != WC_NO_ERR_TRACE(LENGTH_ONLY_E))
13797            return ret;
13798    }
13799    else if (ech->type == ECH_TYPE_INNER)
13800    {
13801        size = sizeof(ech->type);
13802    }
13803    else
13804    {
13805        size = sizeof(ech->type) + sizeof(ech->cipherSuite) +
13806            sizeof(ech->configId) + sizeof(word16) + sizeof(word16) +
13807            ech->innerClientHelloLen;
13808        /* only set encLen if this is inner hello 1 */
13809        if (ech->hpkeContext == NULL)
13810            size += ech->encLen;
13811    }
13812
13813    return (int)size;
13814}
13815
13816/* rough check that inner hello fields do not exceed length of decrypted
13817 * information. Additionally, this function will check that all padding bytes
13818 * are zero and decrease the innerHelloLen accordingly if so.
13819 * returns 0 on success and otherwise failure */
13820static int TLSX_ECH_CheckInnerPadding(WOLFSSL* ssl, WOLFSSL_ECH* ech)
13821{
13822    int headerSz;
13823    const byte* innerCh;
13824    word32 innerChLen;
13825    word32 idx;
13826    byte sessionIdLen;
13827    word16 cipherSuitesLen;
13828    byte compressionLen;
13829    word16 extLen;
13830    byte acc = 0;
13831    word32 i;
13832
13833#ifdef WOLFSSL_DTLS13
13834    headerSz = ssl->options.dtls ? DTLS13_HANDSHAKE_HEADER_SZ :
13835                                   HANDSHAKE_HEADER_SZ;
13836#else
13837    (void)ssl;
13838
13839    headerSz = HANDSHAKE_HEADER_SZ;
13840#endif
13841
13842    innerCh = ech->innerClientHello + headerSz;
13843    innerChLen = ech->innerClientHelloLen;
13844
13845    idx = OPAQUE16_LEN + RAN_LEN;
13846    if (idx >= innerChLen)
13847        return BUFFER_ERROR;
13848
13849    sessionIdLen = innerCh[idx++];
13850    /* innerHello sessionID must initially be empty */
13851    if (sessionIdLen != 0)
13852        return INVALID_PARAMETER;
13853    idx += sessionIdLen;
13854    if (idx + OPAQUE16_LEN > innerChLen)
13855        return BUFFER_ERROR;
13856
13857    ato16(innerCh + idx, &cipherSuitesLen);
13858    idx += OPAQUE16_LEN + cipherSuitesLen;
13859    if (idx >= innerChLen)
13860        return BUFFER_ERROR;
13861
13862    compressionLen = innerCh[idx++];
13863    idx += compressionLen;
13864    if (idx + OPAQUE16_LEN > innerChLen)
13865        return BUFFER_ERROR;
13866
13867    ato16(innerCh + idx, &extLen);
13868    idx += OPAQUE16_LEN + extLen;
13869    if (idx > innerChLen)
13870        return BUFFER_ERROR;
13871
13872    /* should now be at the end of the innerHello
13873     * Per ECH spec all padding bytes MUST be 0 */
13874    for (i = idx; i < innerChLen; i++) {
13875        acc |= innerCh[i];
13876    }
13877    if (acc != 0) {
13878        return INVALID_PARAMETER;
13879    }
13880
13881    ech->innerClientHelloLen -= i - idx;
13882    return 0;
13883}
13884
13885/* Locate the given extension type, use the extOffset to start off after where a
13886 * previous call to this function ended
13887 *
13888 * outerCh          The outer ClientHello buffer.
13889 * chLen            Outer ClientHello length.
13890 * extType          Extension type to look for.
13891 * extLen           Out parameter, length of found extension.
13892 * extOffset        Offset into outer ClientHello to look for extension from.
13893 * extensionsStart  Start of outer ClientHello extensions.
13894 * extensionsLen    Length of outer ClientHello extensions.
13895 * returns 0 on success and otherwise failure.
13896 */
13897static const byte* TLSX_ECH_FindOuterExtension(const byte* outerCh,
13898    word32 chLen, word16 extType, word32* extLen, word32* extOffset,
13899    word16* extensionsStart, word16* extensionsLen)
13900{
13901    word32 idx = *extOffset;
13902    byte sessionIdLen;
13903    word16 cipherSuitesLen;
13904    byte compressionLen;
13905    word16 type;
13906    word16 len;
13907
13908    if (idx == 0) {
13909        idx = OPAQUE16_LEN + RAN_LEN;
13910        if (idx >= chLen)
13911            return NULL;
13912
13913        sessionIdLen = outerCh[idx++];
13914        idx += sessionIdLen;
13915        if (idx + OPAQUE16_LEN > chLen)
13916            return NULL;
13917
13918        ato16(outerCh + idx, &cipherSuitesLen);
13919        idx += OPAQUE16_LEN + cipherSuitesLen;
13920        if (idx >= chLen)
13921            return NULL;
13922
13923        compressionLen = outerCh[idx++];
13924        idx += compressionLen;
13925        if (idx + OPAQUE16_LEN > chLen)
13926            return NULL;
13927
13928        ato16(outerCh + idx, extensionsLen);
13929        idx += OPAQUE16_LEN;
13930        *extensionsStart = (word16)idx;
13931
13932        if (idx + *extensionsLen > chLen)
13933            return NULL;
13934    }
13935
13936    while (idx - *extensionsStart < *extensionsLen) {
13937        if (idx + OPAQUE16_LEN + OPAQUE16_LEN > chLen)
13938            return NULL;
13939
13940        ato16(outerCh + idx, &type);
13941        idx += OPAQUE16_LEN;
13942        ato16(outerCh + idx, &len);
13943        idx += OPAQUE16_LEN;
13944
13945        if (idx + len - *extensionsStart > *extensionsLen)
13946            return NULL;
13947
13948        if (type == extType) {
13949            *extLen = len + OPAQUE16_LEN + OPAQUE16_LEN;
13950            *extOffset = idx + len;
13951            return outerCh + idx - OPAQUE16_LEN - OPAQUE16_LEN;
13952        }
13953
13954        idx += len;
13955    }
13956
13957    return NULL;
13958}
13959
13960/* If newinnerCh is NULL, validate ordering and existence of references
13961 *   - updates newInnerChLen with total length of selected extensions
13962 * If newinnerCh is not NULL, copy extensions into newInnerCh
13963 *
13964 * outerCh          The outer ClientHello buffer.
13965 * outerChLen       Outer ClientHello length.
13966 * newInnerCh       The inner ClientHello buffer.
13967 * newInnerChLen    Inner ClientHello length.
13968 * numOuterRefs     Number of references described by OuterExtensions extension.
13969 * OuterRefTypes    References described by OuterExtensions extension.
13970 * returns 0 on success and otherwise failure.
13971 */
13972static int TLSX_ECH_CopyOuterExtensions(const byte* outerCh, word32 outerChLen,
13973    byte** newInnerCh, word32* newInnerChLen,
13974    word16 numOuterRefs, const byte* outerRefTypes)
13975{
13976    int ret = 0;
13977    word16 refType;
13978    word32 outerExtLen;
13979    word32 outerExtOffset = 0;
13980    word16 extsStart = 0;
13981    word16 extsLen = 0;
13982    const byte* outerExtData;
13983
13984    if (newInnerCh == NULL) {
13985        *newInnerChLen = 0;
13986    }
13987
13988    while (numOuterRefs-- > 0) {
13989        ato16(outerRefTypes, &refType);
13990
13991        if (refType == TLSXT_ECH) {
13992            WOLFSSL_MSG("ECH: ech_outer_extensions references ECH");
13993            ret = INVALID_PARAMETER;
13994            break;
13995        }
13996
13997        outerExtData = TLSX_ECH_FindOuterExtension(outerCh, outerChLen,
13998                            refType, &outerExtLen, &outerExtOffset,
13999                            &extsStart, &extsLen);
14000
14001        if (outerExtData == NULL) {
14002            WOLFSSL_MSG("ECH: referenced extension not in outer CH or out "
14003                        "of order");
14004            ret = INVALID_PARAMETER;
14005            break;
14006        }
14007
14008        if (newInnerCh == NULL) {
14009            *newInnerChLen += outerExtLen;
14010        }
14011        else {
14012            XMEMCPY(*newInnerCh, outerExtData, outerExtLen);
14013            *newInnerCh += outerExtLen;
14014        }
14015
14016        outerRefTypes += OPAQUE16_LEN;
14017    }
14018
14019    return ret;
14020}
14021
14022/* Expand ech_outer_extensions in the inner ClientHello by copying referenced
14023 * extensions from the outer ClientHello.
14024 * If the sessionID exists in the outer ClientHello then also copy that into the
14025 * expanded inner ClientHello.
14026 *
14027 * ssl      SSL/TLS object.
14028 * ech      ECH object.
14029 * heap     Heap hint.
14030 * returns 0 on success and otherwise failure.
14031 */
14032static int TLSX_ECH_ExpandOuterExtensions(WOLFSSL* ssl, WOLFSSL_ECH* ech,
14033    void* heap)
14034{
14035    int ret = 0;
14036    int headerSz;
14037    const byte* innerCh;
14038    word32 innerChLen;
14039    const byte* outerCh;
14040    word32 outerChLen;
14041    word32 idx;
14042    byte sessionIdLen;
14043    word16 cipherSuitesLen;
14044    byte compressionLen;
14045
14046    word32 innerExtIdx;
14047    word16 innerExtLen;
14048    word32 echOuterExtIdx = 0;
14049    word16 echOuterExtLen = 0;
14050    int foundEchOuter = 0;
14051    word16 numOuterRefs = 0;
14052    const byte* outerRefTypes = NULL;
14053    word32 extraSize = 0;
14054    byte* newInnerCh = NULL;
14055    byte* newInnerChRef;
14056    word32 newInnerChLen;
14057    word32 copyLen;
14058
14059    WOLFSSL_ENTER("TLSX_ExpandEchOuterExtensions");
14060
14061    if (ech == NULL || ech->innerClientHello == NULL || ech->aad == NULL)
14062        return BAD_FUNC_ARG;
14063
14064#ifdef WOLFSSL_DTLS13
14065    headerSz = ssl->options.dtls ? DTLS13_HANDSHAKE_HEADER_SZ :
14066                                   HANDSHAKE_HEADER_SZ;
14067#else
14068    headerSz = HANDSHAKE_HEADER_SZ;
14069#endif
14070
14071    innerCh = ech->innerClientHello + headerSz;
14072    innerChLen = ech->innerClientHelloLen;
14073    outerCh = ech->aad;
14074    outerChLen = ech->aadLen;
14075
14076    /* don't need to check for buffer overflows here since they are caught by
14077     * TLSX_ECH_CheckInnerPadding */
14078    idx = OPAQUE16_LEN + RAN_LEN;
14079
14080    sessionIdLen = innerCh[idx++];
14081    idx += sessionIdLen;
14082
14083    ato16(innerCh + idx, &cipherSuitesLen);
14084    idx += OPAQUE16_LEN + cipherSuitesLen;
14085
14086    compressionLen = innerCh[idx++];
14087    idx += compressionLen;
14088
14089    ato16(innerCh + idx, &innerExtLen);
14090    idx += OPAQUE16_LEN;
14091    innerExtIdx = idx;
14092
14093    /* validate ech_outer_extensions and calculate extra size */
14094    while (idx < innerChLen && (idx - innerExtIdx) < innerExtLen) {
14095        word16 type;
14096        word16 len;
14097        byte outerExtListLen;
14098
14099        if (idx + OPAQUE16_LEN + OPAQUE16_LEN > innerChLen)
14100            return BUFFER_ERROR;
14101
14102        ato16(innerCh + idx, &type);
14103        idx += OPAQUE16_LEN;
14104        ato16(innerCh + idx, &len);
14105        idx += OPAQUE16_LEN;
14106
14107        if (idx + len > innerChLen)
14108            return BUFFER_ERROR;
14109
14110        if (type == TLSXT_ECH_OUTER_EXTENSIONS) {
14111            if (foundEchOuter) {
14112                WOLFSSL_MSG("ECH: duplicate ech_outer_extensions");
14113                return INVALID_PARAMETER;
14114            }
14115            foundEchOuter = 1;
14116            echOuterExtIdx = idx - OPAQUE16_LEN - OPAQUE16_LEN;
14117            echOuterExtLen = len + OPAQUE16_LEN + OPAQUE16_LEN;
14118
14119            /* ech_outer_extensions data format: 1-byte length + extension types
14120             * ExtensionType OuterExtensions<2..254>; */
14121            if (len < 1)
14122                return BUFFER_ERROR;
14123            outerExtListLen = innerCh[idx];
14124            if (outerExtListLen + 1 != len || outerExtListLen < 2 ||
14125                    outerExtListLen == 255)
14126                return BUFFER_ERROR;
14127
14128            outerRefTypes = innerCh + idx + 1;
14129            numOuterRefs = outerExtListLen / OPAQUE16_LEN;
14130
14131            ret = TLSX_ECH_CopyOuterExtensions(outerCh, outerChLen, NULL,
14132                    &extraSize, numOuterRefs, outerRefTypes);
14133            if (ret != 0)
14134                return ret;
14135        }
14136
14137        idx += len;
14138    }
14139
14140    newInnerChLen = innerChLen - echOuterExtLen + extraSize - sessionIdLen +
14141                        ssl->session->sessionIDSz;
14142    if (newInnerChLen > 0xFFFF) {
14143        return BUFFER_E;
14144    }
14145
14146    if (!foundEchOuter && sessionIdLen == ssl->session->sessionIDSz) {
14147        /* no extensions + no sessionID to copy */
14148        WOLFSSL_MSG("ECH: no EchOuterExtensions extension found");
14149        return ret;
14150    }
14151    else {
14152        newInnerCh = (byte*)XMALLOC(newInnerChLen + headerSz, heap,
14153                                    DYNAMIC_TYPE_TMP_BUFFER);
14154        if (newInnerCh == NULL)
14155            return MEMORY_E;
14156    }
14157
14158    /* note: The first HANDSHAKE_HEADER_SZ bytes are reserved for the header
14159     * but not initialized here. The header will be properly set later by
14160     * AddTls13HandShakeHeader() in DoTls13ClientHello(). */
14161
14162    /* copy everything up to EchOuterExtensions */
14163    newInnerChRef = newInnerCh + headerSz;
14164    copyLen = OPAQUE16_LEN + RAN_LEN;
14165    XMEMCPY(newInnerChRef, innerCh, copyLen);
14166    newInnerChRef += copyLen;
14167
14168    *newInnerChRef = ssl->session->sessionIDSz;
14169    newInnerChRef += OPAQUE8_LEN;
14170
14171    copyLen = ssl->session->sessionIDSz;
14172    XMEMCPY(newInnerChRef, ssl->session->sessionID, copyLen);
14173    newInnerChRef += copyLen;
14174
14175    if (!foundEchOuter) {
14176        WOLFSSL_MSG("ECH: no EchOuterExtensions extension found");
14177
14178        copyLen = innerChLen - OPAQUE16_LEN - RAN_LEN - OPAQUE8_LEN -
14179                sessionIdLen;
14180        XMEMCPY(newInnerChRef, innerCh + OPAQUE16_LEN + RAN_LEN + OPAQUE8_LEN +
14181                sessionIdLen, copyLen);
14182    }
14183    else {
14184        innerExtIdx = headerSz + innerExtIdx - OPAQUE16_LEN -
14185            sessionIdLen + ssl->session->sessionIDSz;
14186
14187        copyLen = echOuterExtIdx - OPAQUE16_LEN - RAN_LEN - OPAQUE8_LEN -
14188                sessionIdLen;
14189        XMEMCPY(newInnerChRef, innerCh + OPAQUE16_LEN + RAN_LEN + OPAQUE8_LEN +
14190                sessionIdLen, copyLen);
14191        newInnerChRef += copyLen;
14192
14193        /* update extensions length in the new ClientHello */
14194        c16toa(innerExtLen - echOuterExtLen + (word16)extraSize,
14195                newInnerCh + innerExtIdx);
14196
14197        ret = TLSX_ECH_CopyOuterExtensions(outerCh, outerChLen, &newInnerChRef,
14198                &newInnerChLen, numOuterRefs, outerRefTypes);
14199        if (ret == 0) {
14200            /* copy remaining extensions after ech_outer_extensions */
14201            copyLen = innerChLen - (echOuterExtIdx + echOuterExtLen);
14202            XMEMCPY(newInnerChRef, innerCh + echOuterExtIdx + echOuterExtLen,
14203                    copyLen);
14204
14205            WOLFSSL_MSG("ECH: expanded ech_outer_extensions successfully");
14206        }
14207    }
14208
14209    if (ret == 0) {
14210        XFREE(ech->innerClientHello, heap, DYNAMIC_TYPE_TMP_BUFFER);
14211        ech->innerClientHello = newInnerCh;
14212        ech->innerClientHelloLen = newInnerChLen;
14213        newInnerCh = NULL;
14214    }
14215
14216    if (newInnerCh != NULL)
14217        XFREE(newInnerCh, heap, DYNAMIC_TYPE_TMP_BUFFER);
14218
14219    return ret;
14220}
14221
14222/* return status after attempting to open the hpke encrypted ech extension, if
14223 * successful the inner client hello will be stored in
14224 * ech->innerClientHelloLen */
14225static int TLSX_ExtractEch(WOLFSSL_ECH* ech, WOLFSSL_EchConfig* echConfig,
14226    byte* aad, word32 aadLen, void* heap)
14227{
14228    int ret = 0;
14229    int i;
14230    int allocatedHpke = 0;
14231    word32 rawConfigLen = 0;
14232    byte* info = NULL;
14233    word32 infoLen = 0;
14234    if (ech == NULL || echConfig == NULL || aad == NULL)
14235        return BAD_FUNC_ARG;
14236    /* verify the kem and key len */
14237    if (wc_HpkeKemGetEncLen(echConfig->kemId) != ech->encLen)
14238        return BAD_FUNC_ARG;
14239    /* verify the cipher suite */
14240    for (i = 0; i < echConfig->numCipherSuites; i++) {
14241        if (echConfig->cipherSuites[i].kdfId == ech->cipherSuite.kdfId &&
14242            echConfig->cipherSuites[i].aeadId == ech->cipherSuite.aeadId) {
14243            break;
14244        }
14245    }
14246    if (i >= echConfig->numCipherSuites) {
14247        return BAD_FUNC_ARG;
14248    }
14249    /* check if hpke already exists, may if HelloRetryRequest */
14250    if (ech->hpke == NULL) {
14251        allocatedHpke = 1;
14252        ech->hpke = (Hpke*)XMALLOC(sizeof(Hpke), heap, DYNAMIC_TYPE_TMP_BUFFER);
14253        if (ech->hpke == NULL)
14254            ret = MEMORY_E;
14255        /* init the hpke struct */
14256        if (ret == 0) {
14257            ret = wc_HpkeInit(ech->hpke, echConfig->kemId,
14258                ech->cipherSuite.kdfId, ech->cipherSuite.aeadId, heap);
14259        }
14260        if (ret == 0) {
14261            /* allocate hpkeContext */
14262            ech->hpkeContext =
14263                (HpkeBaseContext*)XMALLOC(sizeof(HpkeBaseContext),
14264                ech->hpke->heap, DYNAMIC_TYPE_TMP_BUFFER);
14265            if (ech->hpkeContext == NULL)
14266                ret = MEMORY_E;
14267        }
14268        /* get the rawConfigLen */
14269        if (ret == 0)
14270            ret = GetEchConfig(echConfig, NULL, &rawConfigLen);
14271        if (ret == WC_NO_ERR_TRACE(LENGTH_ONLY_E))
14272            ret = 0;
14273        /* create info */
14274        if (ret == 0) {
14275            infoLen = TLS_INFO_CONST_STRING_SZ + 1 + rawConfigLen;
14276            info = (byte*)XMALLOC(infoLen, heap, DYNAMIC_TYPE_TMP_BUFFER);
14277
14278            if (info == NULL)
14279                ret = MEMORY_E;
14280            else {
14281                XMEMCPY(info, (byte*)TLS_INFO_CONST_STRING,
14282                    TLS_INFO_CONST_STRING_SZ + 1);
14283                ret = GetEchConfig(echConfig, info +
14284                    TLS_INFO_CONST_STRING_SZ + 1, &rawConfigLen);
14285            }
14286        }
14287        /* init the context for opening */
14288        if (ret == 0) {
14289            ret = wc_HpkeInitOpenContext(ech->hpke, ech->hpkeContext,
14290                echConfig->receiverPrivkey, ech->enc, ech->encLen, info,
14291                infoLen);
14292        }
14293    }
14294    /* decrypt the ech payload */
14295    if (ret == 0) {
14296        ret = wc_HpkeContextOpenBase(ech->hpke, ech->hpkeContext, aad, aadLen,
14297            ech->outerClientPayload, ech->innerClientHelloLen,
14298            ech->innerClientHello + HANDSHAKE_HEADER_SZ);
14299    }
14300    /* only free hpke/hpkeContext if allocated in this call; otherwise preserve
14301     * them for clientHello2 */
14302    if (ret != 0 && allocatedHpke) {
14303        XFREE(ech->hpke, heap, DYNAMIC_TYPE_TMP_BUFFER);
14304        ech->hpke = NULL;
14305        XFREE(ech->hpkeContext, heap, DYNAMIC_TYPE_TMP_BUFFER);
14306        ech->hpkeContext = NULL;
14307    }
14308
14309    if (info != NULL)
14310        XFREE(info, heap, DYNAMIC_TYPE_TMP_BUFFER);
14311
14312    return ret;
14313}
14314
14315/* parse the ech extension, if internal update ech->state and return, if
14316 * external attempt to extract the inner client_hello, return the status */
14317static int TLSX_ECH_Parse(WOLFSSL* ssl, const byte* readBuf, word16 size,
14318    byte msgType)
14319{
14320    int ret = 0;
14321    TLSX* echX;
14322    WOLFSSL_ECH* ech;
14323    WOLFSSL_EchConfig* echConfig;
14324    byte* aadCopy;
14325    byte* readBuf_p = (byte*)readBuf;
14326    word32 offset = 0;
14327    word16 len;
14328    word16 tmpVal16;
14329    word16 lenCh;
14330
14331    WOLFSSL_MSG("TLSX_ECH_Parse");
14332    if (ssl->options.disableECH) {
14333        WOLFSSL_MSG("TLSX_ECH_Parse: ECH disabled. Ignoring.");
14334        return 0;
14335    }
14336    if (size == 0)
14337        return BAD_FUNC_ARG;
14338
14339    /* retry configs */
14340    if (msgType == encrypted_extensions) {
14341        /* configs must only be sent on ECH rejection (RFC9849, Section 5) */
14342        if (ssl->options.echAccepted) {
14343            SendAlert(ssl, alert_fatal, unsupported_extension);
14344            WOLFSSL_ERROR_VERBOSE(UNSUPPORTED_EXTENSION);
14345            return UNSUPPORTED_EXTENSION;
14346        }
14347
14348        ret = SetRetryConfigs(ssl, readBuf, (word32)size);
14349        if (ret == WC_NO_ERR_TRACE(UNSUPPORTED_SUITE) ||
14350                ret == WC_NO_ERR_TRACE(UNSUPPORTED_PROTO_VERSION)) {
14351            WOLFSSL_MSG("ECH retry configs had 'bad version' or 'bad suite'");
14352            ret = 0;
14353        }
14354
14355        if (ssl->echConfigs == NULL) {
14356            /* on GREASE connection configs must be checked syntactically and
14357             * must not be saved (RFC 9849, Section 6.2.1) */
14358            FreeEchConfigs(ssl->echRetryConfigs, ssl->heap);
14359            ssl->echRetryConfigs = NULL;
14360        }
14361
14362        /* retry configs may only be accepted at the point when ECH_REQUIRED is
14363         * sent */
14364        ssl->options.echRetryConfigsAccepted = 0;
14365    }
14366    /* HRR with special confirmation */
14367    else if (msgType == hello_retry_request && ssl->echConfigs != NULL) {
14368        /* length must be 8 */
14369        if (size != ECH_ACCEPT_CONFIRMATION_SZ)
14370            return BUFFER_ERROR;
14371
14372        /* get extension */
14373        echX = TLSX_Find(ssl->extensions, TLSX_ECH);
14374        if (echX == NULL)
14375            return BAD_FUNC_ARG;
14376        ech = (WOLFSSL_ECH*)echX->data;
14377
14378        ech->confBuf = (byte*)readBuf;
14379    }
14380    else if (msgType == client_hello && ssl->ctx->echConfigs != NULL) {
14381        /* get extension */
14382        echX = TLSX_Find(ssl->extensions, TLSX_ECH);
14383        if (echX == NULL)
14384            return BAD_FUNC_ARG;
14385        ech = (WOLFSSL_ECH*)echX->data;
14386
14387        /* if the first ECH was rejected or CH1 did not have ECH then there is
14388         * no need to decrypt this one */
14389        if (!ssl->options.echAccepted && ssl->options.serverState ==
14390                SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
14391            ech->state = ECH_WRITE_RETRY_CONFIGS;
14392            return 0;
14393        }
14394
14395        /* read the ech parameters before the payload */
14396        ech->type = *readBuf_p;
14397        readBuf_p++;
14398        offset += 1;
14399        if (ssl->options.echProcessingInner && ech->type == ECH_TYPE_INNER) {
14400            ech->state = ECH_PARSED_INTERNAL;
14401            return 0;
14402        }
14403        else if ((!ssl->options.echProcessingInner &&
14404                  ech->type != ECH_TYPE_OUTER) ||
14405                 (ssl->options.echProcessingInner &&
14406                  ech->type != ECH_TYPE_INNER)) {
14407            /* MUST process INNER in inner hello and OUTER in outer hello */
14408            return INVALID_PARAMETER;
14409        }
14410        /* Must have kdfId, aeadId, configId, enc len and payload len. */
14411        if (size < offset + 2 + 2 + 1 + 2 + 2) {
14412            return BUFFER_ERROR;
14413        }
14414        /* only get enc if we don't already have the hpke context */
14415        if (ech->hpkeContext == NULL) {
14416            /* kdfId */
14417            ato16(readBuf_p, &ech->cipherSuite.kdfId);
14418            readBuf_p += 2;
14419            offset += 2;
14420            /* aeadId */
14421            ato16(readBuf_p, &ech->cipherSuite.aeadId);
14422            readBuf_p += 2;
14423            offset += 2;
14424            /* configId */
14425            ech->configId = *readBuf_p;
14426            readBuf_p++;
14427            offset++;
14428            /* encLen */
14429            ato16(readBuf_p, &len);
14430            readBuf_p += 2;
14431            offset += 2;
14432            /* Check encLen isn't more than remaining bytes minus
14433             * payload length. */
14434            if (len > size - offset - 2) {
14435                return BUFFER_ERROR;
14436            }
14437            if (len > HPKE_Npk_MAX) {
14438                return BUFFER_ERROR;
14439            }
14440            /* read enc */
14441            XMEMCPY(ech->enc, readBuf_p, len);
14442            ech->encLen = len;
14443        }
14444        else {
14445            /* kdfId, aeadId, and configId must be the same as last time */
14446            /* kdfId */
14447            ato16(readBuf_p, &tmpVal16);
14448            if (tmpVal16 != ech->cipherSuite.kdfId) {
14449                return INVALID_PARAMETER;
14450            }
14451            readBuf_p += 2;
14452            offset += 2;
14453            /* aeadId */
14454            ato16(readBuf_p, &tmpVal16);
14455            if (tmpVal16 != ech->cipherSuite.aeadId) {
14456                return INVALID_PARAMETER;
14457            }
14458            readBuf_p += 2;
14459            offset += 2;
14460            /* configId */
14461            if (*readBuf_p != ech->configId) {
14462                return INVALID_PARAMETER;
14463            }
14464            readBuf_p++;
14465            offset++;
14466            /* on an HRR the enc value MUST be empty */
14467            ato16(readBuf_p, &len);
14468            if (len != 0) {
14469                return INVALID_PARAMETER;
14470            }
14471            readBuf_p += 2;
14472            offset += 2;
14473        }
14474        readBuf_p += len;
14475        offset += len;
14476        /* read payload (encrypted CH) len */
14477        ato16(readBuf_p, &lenCh);
14478        ech->innerClientHelloLen = lenCh;
14479        readBuf_p += 2;
14480        offset += 2;
14481        /* Check payload is no bigger than remaining bytes. */
14482        if (ech->innerClientHelloLen > size - offset) {
14483            return BUFFER_ERROR;
14484        }
14485        if (ech->innerClientHelloLen < WC_AES_BLOCK_SIZE) {
14486            return BUFFER_ERROR;
14487        }
14488        ech->innerClientHelloLen -= WC_AES_BLOCK_SIZE;
14489        ech->outerClientPayload = readBuf_p;
14490        /* make a copy of the aad */
14491        aadCopy = (byte*)XMALLOC(ech->aadLen, ssl->heap,
14492            DYNAMIC_TYPE_TMP_BUFFER);
14493        if (aadCopy == NULL)
14494            return MEMORY_E;
14495        XMEMCPY(aadCopy, ech->aad, ech->aadLen);
14496        /* set the ech payload of the copy to zeros */
14497        XMEMSET(aadCopy + (readBuf_p - ech->aad), 0,
14498            ech->innerClientHelloLen + WC_AES_BLOCK_SIZE);
14499        /* free the old ech when this is the second client hello */
14500        if (ech->innerClientHello != NULL)
14501            XFREE(ech->innerClientHello, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
14502        /* allocate the inner payload buffer */
14503        ech->innerClientHello =
14504            (byte*)XMALLOC(ech->innerClientHelloLen + HANDSHAKE_HEADER_SZ,
14505            ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
14506        if (ech->innerClientHello == NULL) {
14507            XFREE(aadCopy, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
14508            return MEMORY_E;
14509        }
14510        /* try to decrypt with matching configId */
14511        echConfig = ssl->ctx->echConfigs;
14512        while (echConfig != NULL) {
14513            if (echConfig->configId == ech->configId) {
14514                ret = TLSX_ExtractEch(ech, echConfig, aadCopy, ech->aadLen,
14515                    ssl->heap);
14516                break;
14517            }
14518            echConfig = echConfig->next;
14519        }
14520        /* otherwise, try to decrypt with all configs */
14521        if (echConfig == NULL || ret != 0) {
14522            echConfig = ssl->ctx->echConfigs;
14523            while (echConfig != NULL) {
14524                ret = TLSX_ExtractEch(ech, echConfig, aadCopy, ech->aadLen,
14525                    ssl->heap);
14526                if (ret == 0)
14527                    break;
14528                echConfig = echConfig->next;
14529            }
14530        }
14531        /* if we failed to extract/expand */
14532        if (ret != 0) {
14533            WOLFSSL_MSG("ECH rejected");
14534
14535            if (ssl->options.echAccepted == 1) {
14536                /* on SH2 this is fatal */
14537                SendAlert(ssl, alert_fatal, decrypt_error);
14538                WOLFSSL_ERROR_VERBOSE(DECRYPT_ERROR);
14539                ret = DECRYPT_ERROR;
14540            }
14541            else {
14542                /* on SH1 prepare to write retry configs */
14543                XFREE(ech->innerClientHello, ssl->heap,
14544                    DYNAMIC_TYPE_TMP_BUFFER);
14545                ech->innerClientHello = NULL;
14546                ech->state = ECH_WRITE_RETRY_CONFIGS;
14547                ret = 0;
14548            }
14549        }
14550        else {
14551            ret = TLSX_ECH_CheckInnerPadding(ssl, ech);
14552            if (ret == 0) {
14553                /* expand EchOuterExtensions if present.
14554                 * Also, if it exists, copy sessionID from outer hello */
14555                ret = TLSX_ECH_ExpandOuterExtensions(ssl, ech, ssl->heap);
14556            }
14557
14558            if (ret == 0){
14559                WOLFSSL_MSG("ECH accepted");
14560                ssl->options.echAccepted = 1;
14561            }
14562            else {
14563                WOLFSSL_MSG("ECH rejected");
14564            }
14565        }
14566        if (ret != 0) {
14567            XFREE(ech->innerClientHello, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
14568            ech->innerClientHello = NULL;
14569        }
14570
14571        XFREE(aadCopy, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
14572    }
14573
14574    return ret;
14575}
14576
14577/* free the ech struct and the dynamic buffer it uses */
14578static void TLSX_ECH_Free(WOLFSSL_ECH* ech, void* heap)
14579{
14580    XFREE(ech->innerClientHello, heap, DYNAMIC_TYPE_TMP_BUFFER);
14581    if (ech->hpke != NULL) {
14582        if (ech->ephemeralKey != NULL)
14583            wc_HpkeFreeKey(ech->hpke, ech->hpke->kem, ech->ephemeralKey,
14584                ech->hpke->heap);
14585        XFREE(ech->hpke, heap, DYNAMIC_TYPE_TMP_BUFFER);
14586    }
14587    if (ech->hpkeContext != NULL)
14588        XFREE(ech->hpkeContext, heap, DYNAMIC_TYPE_TMP_BUFFER);
14589    if (ech->privateName != NULL)
14590        XFREE((char*)ech->privateName, heap, DYNAMIC_TYPE_TMP_BUFFER);
14591
14592    XFREE(ech, heap, DYNAMIC_TYPE_TMP_BUFFER);
14593    (void)heap;
14594}
14595
14596/* encrypt the client hello and store it in ech->outerClientPayload, return
14597 * status */
14598int TLSX_FinalizeEch(WOLFSSL_ECH* ech, byte* aad, word32 aadLen)
14599{
14600    int ret = 0;
14601    void* receiverPubkey = NULL;
14602    byte* info = NULL;
14603    int infoLen = 0;
14604    byte* aadCopy = NULL;
14605    /* setup hpke context to seal, should be done at most once per connection */
14606    if (ech->hpkeContext == NULL) {
14607        /* import the server public key */
14608        ret = wc_HpkeDeserializePublicKey(ech->hpke, &receiverPubkey,
14609            ech->echConfig->receiverPubkey, ech->encLen);
14610        if (ret == 0) {
14611            /* allocate hpke context */
14612            ech->hpkeContext =
14613                (HpkeBaseContext*)XMALLOC(sizeof(HpkeBaseContext),
14614                ech->hpke->heap, DYNAMIC_TYPE_TMP_BUFFER);
14615            if (ech->hpkeContext == NULL)
14616                ret = MEMORY_E;
14617        }
14618        if (ret == 0) {
14619            /* create info */
14620            infoLen = TLS_INFO_CONST_STRING_SZ + 1 + ech->echConfig->rawLen;
14621            info = (byte*)XMALLOC(infoLen, ech->hpke->heap,
14622                DYNAMIC_TYPE_TMP_BUFFER);
14623            if (info == NULL)
14624                ret = MEMORY_E;
14625        }
14626        if (ret == 0) {
14627            /* puts the null byte in for me */
14628            XMEMCPY(info, (byte*)TLS_INFO_CONST_STRING,
14629                TLS_INFO_CONST_STRING_SZ + 1);
14630            XMEMCPY(info + TLS_INFO_CONST_STRING_SZ + 1,
14631                ech->echConfig->raw, ech->echConfig->rawLen);
14632            /* init the context for seal with info and keys */
14633            ret = wc_HpkeInitSealContext(ech->hpke, ech->hpkeContext,
14634                ech->ephemeralKey, receiverPubkey, info, infoLen);
14635        }
14636    }
14637    if (ret == 0) {
14638        /* make a copy of the aad since we overwrite it */
14639        aadCopy = (byte*)XMALLOC(aadLen, ech->hpke->heap,
14640            DYNAMIC_TYPE_TMP_BUFFER);
14641        if (aadCopy == NULL) {
14642            ret = MEMORY_E;
14643        }
14644    }
14645    if (ret == 0) {
14646        XMEMCPY(aadCopy, aad, aadLen);
14647        /* seal the payload with context */
14648        ret = wc_HpkeContextSealBase(ech->hpke, ech->hpkeContext, aadCopy,
14649            aadLen, ech->innerClientHello,
14650            ech->innerClientHelloLen - ech->hpke->Nt, ech->outerClientPayload);
14651    }
14652    if (info != NULL)
14653        XFREE(info, ech->hpke->heap, DYNAMIC_TYPE_TMP_BUFFER);
14654    if (aadCopy != NULL)
14655        XFREE(aadCopy, ech->hpke->heap, DYNAMIC_TYPE_TMP_BUFFER);
14656    if (receiverPubkey != NULL)
14657        wc_HpkeFreeKey(ech->hpke, ech->hpke->kem, receiverPubkey,
14658            ech->hpke->heap);
14659    return ret;
14660}
14661
14662#define GREASE_ECH_USE TLSX_GreaseECH_Use
14663#define ECH_USE TLSX_ECH_Use
14664#define SERVER_ECH_USE TLSX_ServerECH_Use
14665#define ECH_WRITE TLSX_ECH_Write
14666#define ECH_GET_SIZE TLSX_ECH_GetSize
14667#define ECH_PARSE TLSX_ECH_Parse
14668#define ECH_FREE TLSX_ECH_Free
14669
14670#endif
14671
14672/** Releases all extensions in the provided list. */
14673void TLSX_FreeAll(TLSX* list, void* heap)
14674{
14675    TLSX* extension;
14676
14677    while ((extension = list)) {
14678        list = extension->next;
14679
14680        switch (extension->type) {
14681#if defined(HAVE_RPK)
14682            case TLSX_CLIENT_CERTIFICATE_TYPE:
14683                WOLFSSL_MSG("Client Certificate Type extension free");
14684                /* nothing to do */
14685                break;
14686            case TLSX_SERVER_CERTIFICATE_TYPE:
14687                WOLFSSL_MSG("Server Certificate Type extension free");
14688                /* nothing to do */
14689                break;
14690#endif
14691
14692#ifdef HAVE_SNI
14693            case TLSX_SERVER_NAME:
14694                WOLFSSL_MSG("SNI extension free");
14695                SNI_FREE_ALL((SNI*)extension->data, heap);
14696                break;
14697#endif
14698
14699            case TLSX_TRUSTED_CA_KEYS:
14700                WOLFSSL_MSG("Trusted CA Indication extension free");
14701                TCA_FREE_ALL((TCA*)extension->data, heap);
14702                break;
14703
14704            case TLSX_MAX_FRAGMENT_LENGTH:
14705                WOLFSSL_MSG("Max Fragment Length extension free");
14706                MFL_FREE_ALL(extension->data, heap);
14707                break;
14708
14709            case TLSX_EXTENDED_MASTER_SECRET:
14710                WOLFSSL_MSG("Extended Master Secret free");
14711                /* Nothing to do. */
14712                break;
14713            case TLSX_TRUNCATED_HMAC:
14714                WOLFSSL_MSG("Truncated HMAC extension free");
14715                /* Nothing to do. */
14716                break;
14717
14718            case TLSX_SUPPORTED_GROUPS:
14719                WOLFSSL_MSG("Supported Groups extension free");
14720                EC_FREE_ALL((SupportedCurve*)extension->data, heap);
14721                break;
14722
14723            case TLSX_EC_POINT_FORMATS:
14724                WOLFSSL_MSG("Point Formats extension free");
14725                PF_FREE_ALL((PointFormat*)extension->data, heap);
14726                break;
14727
14728            case TLSX_STATUS_REQUEST:
14729                WOLFSSL_MSG("Certificate Status Request extension free");
14730                CSR_FREE_ALL((CertificateStatusRequest*)extension->data, heap);
14731                break;
14732
14733            case TLSX_STATUS_REQUEST_V2:
14734                WOLFSSL_MSG("Certificate Status Request v2 extension free");
14735                CSR2_FREE_ALL((CertificateStatusRequestItemV2*)extension->data,
14736                        heap);
14737                break;
14738
14739            case TLSX_RENEGOTIATION_INFO:
14740                WOLFSSL_MSG("Secure Renegotiation extension free");
14741                SCR_FREE_ALL(extension->data, heap);
14742                break;
14743
14744            case TLSX_SESSION_TICKET:
14745                WOLFSSL_MSG("Session Ticket extension free");
14746                WOLF_STK_FREE(extension->data, heap);
14747                break;
14748
14749            case TLSX_APPLICATION_LAYER_PROTOCOL:
14750                WOLFSSL_MSG("ALPN extension free");
14751                ALPN_FREE_ALL((ALPN*)extension->data, heap);
14752                break;
14753#if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
14754            case TLSX_SIGNATURE_ALGORITHMS:
14755                WOLFSSL_MSG("Signature Algorithms extension to free");
14756                SA_FREE_ALL((SignatureAlgorithms*)extension->data, heap);
14757                break;
14758#endif
14759#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
14760            case TLSX_ENCRYPT_THEN_MAC:
14761                WOLFSSL_MSG("Encrypt-Then-Mac extension free");
14762                break;
14763#endif
14764
14765#if defined(WOLFSSL_TLS13) || !defined(WOLFSSL_NO_TLS12) || !defined(NO_OLD_TLS)
14766    #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
14767            case TLSX_PRE_SHARED_KEY:
14768                WOLFSSL_MSG("Pre-Shared Key extension free");
14769                PSK_FREE_ALL((PreSharedKey*)extension->data, heap);
14770                break;
14771
14772        #ifdef WOLFSSL_TLS13
14773            case TLSX_PSK_KEY_EXCHANGE_MODES:
14774                WOLFSSL_MSG("PSK Key Exchange Modes extension free");
14775                break;
14776        #ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
14777            case TLSX_CERT_WITH_EXTERN_PSK:
14778                WOLFSSL_MSG("Cert with external PSK extension free");
14779                break;
14780        #endif
14781        #endif
14782    #endif
14783
14784            case TLSX_KEY_SHARE:
14785                WOLFSSL_MSG("Key Share extension free");
14786                KS_FREE_ALL((KeyShareEntry*)extension->data, heap);
14787                break;
14788#endif
14789#ifdef WOLFSSL_TLS13
14790            case TLSX_SUPPORTED_VERSIONS:
14791                WOLFSSL_MSG("Supported Versions extension free");
14792                break;
14793
14794            case TLSX_COOKIE:
14795                WOLFSSL_MSG("Cookie extension free");
14796                CKE_FREE_ALL((Cookie*)extension->data, heap);
14797                break;
14798
14799    #ifdef WOLFSSL_EARLY_DATA
14800            case TLSX_EARLY_DATA:
14801                WOLFSSL_MSG("Early Data extension free");
14802                break;
14803    #endif
14804
14805    #ifdef WOLFSSL_POST_HANDSHAKE_AUTH
14806            case TLSX_POST_HANDSHAKE_AUTH:
14807                WOLFSSL_MSG("Post-Handshake Authentication extension free");
14808                break;
14809    #endif
14810
14811    #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
14812            case TLSX_SIGNATURE_ALGORITHMS_CERT:
14813                WOLFSSL_MSG("Signature Algorithms extension free");
14814                break;
14815    #endif
14816    #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES)
14817            case TLSX_CERTIFICATE_AUTHORITIES:
14818                WOLFSSL_MSG("Certificate Authorities extension free");
14819                break;
14820    #endif
14821#endif
14822#ifdef WOLFSSL_SRTP
14823            case TLSX_USE_SRTP:
14824                WOLFSSL_MSG("SRTP extension free");
14825                SRTP_FREE((TlsxSrtp*)extension->data, heap);
14826                break;
14827#endif
14828
14829    #ifdef WOLFSSL_QUIC
14830            case TLSX_KEY_QUIC_TP_PARAMS:
14831                FALL_THROUGH;
14832            case TLSX_KEY_QUIC_TP_PARAMS_DRAFT:
14833                WOLFSSL_MSG("QUIC transport parameter free");
14834                QTP_FREE((QuicTransportParam*)extension->data, heap);
14835                break;
14836    #endif
14837
14838#ifdef WOLFSSL_DTLS_CID
14839            case TLSX_CONNECTION_ID:
14840                WOLFSSL_MSG("Connection ID extension free");
14841                CID_FREE((byte*)extension->data, heap);
14842                break;
14843#endif /* WOLFSSL_DTLS_CID */
14844#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
14845            case TLSX_ECH:
14846                WOLFSSL_MSG("ECH extension free");
14847                ECH_FREE((WOLFSSL_ECH*)extension->data, heap);
14848                break;
14849#endif
14850#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_DUAL_ALG_CERTS)
14851            case TLSX_CKS:
14852                WOLFSSL_MSG("CKS extension free");
14853                /* nothing to do */
14854                break;
14855#endif
14856            default:
14857                break;
14858        }
14859
14860        XFREE(extension, heap, DYNAMIC_TYPE_TLSX);
14861    }
14862
14863    (void)heap;
14864}
14865
14866/** Checks if the tls extensions are supported based on the protocol version. */
14867int TLSX_SupportExtensions(WOLFSSL* ssl) {
14868    return ssl && (IsTLS(ssl) || ssl->version.major == DTLS_MAJOR);
14869}
14870
14871/** Tells the buffered size of the extensions in a list. */
14872static int TLSX_GetSize(TLSX* list, byte* semaphore, byte msgType,
14873                        word16* pLength)
14874{
14875    int    ret = 0;
14876    TLSX*  extension;
14877    /* Use a word32 accumulator so that an extension whose contribution
14878     * pushes the running total past 0xFFFF is detected rather than
14879     * silently wrapped (the TLS extensions block length prefix on the
14880     * wire is a 2-byte field). Callees that take a word16* accumulator
14881     * are invoked via a per-iteration shim (`cbShim`) and their delta
14882     * is added back into the word32 total.
14883     *
14884     * MAINTAINER NOTE: do NOT pass &length to any *_GET_SIZE function
14885     * that expects a `word16*` out-parameter -- that would be a type
14886     * mismatch (UB) and would silently bypass the overflow detection
14887     * below. When adding a new extension case, either:
14888     *   - use `length += FOO_GET_SIZE(...)` when the helper returns a
14889     *     word16 by value, or
14890     *   - use the cbShim pattern: `cbShim = 0; ret = FOO_GET_SIZE(...,
14891     *     &cbShim); length += cbShim;`
14892     */
14893    word32 length = 0;
14894    word16 cbShim = 0;
14895    byte   isRequest = (msgType == client_hello ||
14896                        msgType == certificate_request);
14897    (void)cbShim;
14898
14899    while ((extension = list)) {
14900        list = extension->next;
14901
14902        /* only extensions marked as response are sent back to the client. */
14903        if (!isRequest && !extension->resp)
14904            continue; /* skip! */
14905
14906        /* ssl level extensions are expected to override ctx level ones. */
14907        if (!IS_OFF(semaphore, TLSX_ToSemaphore((word16)extension->type)))
14908            continue; /* skip! */
14909
14910        /* extension type + extension data length. */
14911        length += HELLO_EXT_TYPE_SZ + OPAQUE16_LEN;
14912
14913        switch (extension->type) {
14914#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_DUAL_ALG_CERTS)
14915            case TLSX_CKS:
14916                length += ((WOLFSSL*)extension->data)->sigSpecSz ;
14917                break;
14918#endif
14919#ifdef HAVE_SNI
14920            case TLSX_SERVER_NAME:
14921                /* SNI only sends the name on the request. */
14922                if (isRequest)
14923                    length += SNI_GET_SIZE((SNI*)extension->data);
14924                break;
14925#endif
14926
14927            case TLSX_TRUSTED_CA_KEYS:
14928                /* TCA only sends the list on the request. */
14929                if (isRequest) {
14930                    word16 tcaSz = TCA_GET_SIZE((TCA*)extension->data);
14931                    /* 0 on non-empty list means 16-bit overflow. */
14932                    if (tcaSz == 0 && extension->data != NULL) {
14933                        ret = LENGTH_ERROR;
14934                        break;
14935                    }
14936                    length += tcaSz;
14937                }
14938                break;
14939
14940            case TLSX_MAX_FRAGMENT_LENGTH:
14941                length += MFL_GET_SIZE(extension->data);
14942                break;
14943
14944            case TLSX_EXTENDED_MASTER_SECRET:
14945            case TLSX_TRUNCATED_HMAC:
14946                /* always empty. */
14947                break;
14948
14949            case TLSX_SUPPORTED_GROUPS:
14950                length += EC_GET_SIZE((SupportedCurve*)extension->data);
14951                break;
14952
14953            case TLSX_EC_POINT_FORMATS:
14954                length += PF_GET_SIZE((PointFormat*)extension->data);
14955                break;
14956
14957            case TLSX_STATUS_REQUEST:
14958                length += CSR_GET_SIZE(
14959                         (CertificateStatusRequest*)extension->data, isRequest);
14960                break;
14961
14962            case TLSX_STATUS_REQUEST_V2:
14963                length += CSR2_GET_SIZE(
14964                        (CertificateStatusRequestItemV2*)extension->data,
14965                        isRequest);
14966                break;
14967
14968            case TLSX_RENEGOTIATION_INFO:
14969                length += SCR_GET_SIZE((SecureRenegotiation*)extension->data,
14970                        isRequest);
14971                break;
14972
14973            case TLSX_SESSION_TICKET:
14974                length += WOLF_STK_GET_SIZE((SessionTicket*)extension->data,
14975                        isRequest);
14976                break;
14977
14978            case TLSX_APPLICATION_LAYER_PROTOCOL: {
14979                word16 alpnSz = ALPN_GET_SIZE((ALPN*)extension->data);
14980                /* 0 on non-empty list means 16-bit overflow. */
14981                if (alpnSz == 0 && extension->data != NULL) {
14982                    ret = LENGTH_ERROR;
14983                    break;
14984                }
14985                length += alpnSz;
14986                break;
14987            }
14988#if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
14989            case TLSX_SIGNATURE_ALGORITHMS:
14990                length += SA_GET_SIZE(extension->data);
14991                break;
14992#endif
14993#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
14994            case TLSX_ENCRYPT_THEN_MAC:
14995                cbShim = 0;
14996                ret = ETM_GET_SIZE(msgType, &cbShim);
14997                length += cbShim;
14998                break;
14999#endif /* HAVE_ENCRYPT_THEN_MAC */
15000
15001#if defined(WOLFSSL_TLS13) || !defined(WOLFSSL_NO_TLS12) || !defined(NO_OLD_TLS)
15002    #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
15003            case TLSX_PRE_SHARED_KEY:
15004                cbShim = 0;
15005                ret = PSK_GET_SIZE((PreSharedKey*)extension->data, msgType,
15006                                                                       &cbShim);
15007                length += cbShim;
15008                break;
15009        #ifdef WOLFSSL_TLS13
15010            case TLSX_PSK_KEY_EXCHANGE_MODES:
15011                cbShim = 0;
15012                ret = PKM_GET_SIZE((byte)extension->val, msgType, &cbShim);
15013                length += cbShim;
15014                break;
15015        #ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
15016            case TLSX_CERT_WITH_EXTERN_PSK:
15017                cbShim = 0;
15018                ret = PSK_WITH_CERT_GET_SIZE(msgType, &cbShim);
15019                length += cbShim;
15020                break;
15021        #endif
15022        #endif
15023    #endif
15024            case TLSX_KEY_SHARE:
15025                length += KS_GET_SIZE((KeyShareEntry*)extension->data, msgType);
15026                break;
15027#endif
15028
15029#ifdef WOLFSSL_TLS13
15030            case TLSX_SUPPORTED_VERSIONS:
15031                cbShim = 0;
15032                ret = SV_GET_SIZE(extension->data, msgType, &cbShim);
15033                length += cbShim;
15034                break;
15035
15036            case TLSX_COOKIE:
15037                cbShim = 0;
15038                ret = CKE_GET_SIZE((Cookie*)extension->data, msgType, &cbShim);
15039                length += cbShim;
15040                break;
15041
15042    #ifdef WOLFSSL_EARLY_DATA
15043            case TLSX_EARLY_DATA:
15044                cbShim = 0;
15045                ret = EDI_GET_SIZE(msgType, &cbShim);
15046                length += cbShim;
15047                break;
15048    #endif
15049
15050    #ifdef WOLFSSL_POST_HANDSHAKE_AUTH
15051            case TLSX_POST_HANDSHAKE_AUTH:
15052                cbShim = 0;
15053                ret = PHA_GET_SIZE(msgType, &cbShim);
15054                length += cbShim;
15055                break;
15056    #endif
15057
15058    #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
15059            case TLSX_SIGNATURE_ALGORITHMS_CERT:
15060                length += SAC_GET_SIZE(extension->data);
15061                break;
15062    #endif
15063
15064    #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES)
15065            case TLSX_CERTIFICATE_AUTHORITIES: {
15066                word16 canSz = CAN_GET_SIZE(extension->data);
15067                /* 0 on non-empty list means 16-bit overflow. */
15068                if (canSz == 0) {
15069                    ret = LENGTH_ERROR;
15070                    break;
15071                }
15072                length += canSz;
15073                break;
15074            }
15075    #endif
15076#endif
15077#ifdef WOLFSSL_SRTP
15078            case TLSX_USE_SRTP:
15079                length += SRTP_GET_SIZE((TlsxSrtp*)extension->data);
15080                break;
15081#endif
15082
15083#ifdef HAVE_RPK
15084            case TLSX_CLIENT_CERTIFICATE_TYPE:
15085                length += CCT_GET_SIZE((WOLFSSL*)extension->data, msgType);
15086                break;
15087
15088            case TLSX_SERVER_CERTIFICATE_TYPE:
15089                length += SCT_GET_SIZE((WOLFSSL*)extension->data, msgType);
15090                break;
15091#endif /* HAVE_RPK */
15092
15093#ifdef WOLFSSL_QUIC
15094            case TLSX_KEY_QUIC_TP_PARAMS:
15095                FALL_THROUGH; /* followed by */
15096            case TLSX_KEY_QUIC_TP_PARAMS_DRAFT:
15097                length += QTP_GET_SIZE(extension);
15098                break;
15099#endif
15100#ifdef WOLFSSL_DTLS_CID
15101            case TLSX_CONNECTION_ID:
15102                length += CID_GET_SIZE((byte*)extension->data);
15103                break;
15104#endif /* WOLFSSL_DTLS_CID */
15105#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
15106            case TLSX_ECH:
15107                length += ECH_GET_SIZE((WOLFSSL_ECH*)extension->data, msgType);
15108                break;
15109#endif
15110            default:
15111                break;
15112        }
15113
15114        if (ret != 0)
15115            return ret;
15116
15117        /* Early exit: stop accumulating as soon as the running total
15118         * cannot possibly fit the 2-byte wire length. Check *before*
15119         * marking the extension as processed so the semaphore is not
15120         * left in an inconsistent state on the error path. */
15121        if (length > WOLFSSL_MAX_16BIT) {
15122            WOLFSSL_MSG("TLSX_GetSize extension length exceeds word16");
15123            return BUFFER_E;
15124        }
15125
15126        /* marks the extension as processed so ctx level */
15127        /* extensions don't overlap with ssl level ones. */
15128        TURN_ON(semaphore, TLSX_ToSemaphore((word16)extension->type));
15129    }
15130
15131    if ((word32)*pLength + length > WOLFSSL_MAX_16BIT) {
15132        WOLFSSL_MSG("TLSX_GetSize total extensions length exceeds word16");
15133        return BUFFER_E;
15134    }
15135
15136    *pLength += (word16)length;
15137
15138    return ret;
15139}
15140
15141/** Writes the extensions of a list in a buffer. */
15142static int TLSX_Write(TLSX* list, byte* output, byte* semaphore,
15143                         byte msgType, word16* pOffset)
15144{
15145    int    ret = 0;
15146    TLSX*  extension;
15147    /* Use word32 to symmetrize with TLSX_GetSize -- a single extension can
15148     * contribute up to 0x10003 bytes (4-byte type/length header + 0xFFFF
15149     * payload), which would word16-overflow undetectably (e.g. wrap to a
15150     * value still above prevOffset). Per-iteration and aggregate bounds are
15151     * checked below before truncating back into the word16 wire fields.
15152     * Callees that take a word16* offset use the cbShim pattern (init to 0,
15153     * then add the returned delta to the word32 accumulator). */
15154    word32 offset = 0;
15155    word32 length_offset = 0;
15156    word32 prevOffset;
15157    word16 cbShim = 0;
15158    byte   isRequest = (msgType == client_hello ||
15159                        msgType == certificate_request);
15160    (void)cbShim;
15161
15162    while ((extension = list)) {
15163        list = extension->next;
15164
15165        /* only extensions marked as response are written in a response. */
15166        if (!isRequest && !extension->resp)
15167            continue; /* skip! */
15168
15169        /* ssl level extensions are expected to override ctx level ones. */
15170        if (!IS_OFF(semaphore, TLSX_ToSemaphore((word16)extension->type)))
15171            continue; /* skip! */
15172
15173        /* Snapshot offset to detect word16 wrap within this iteration;
15174         * see matching comment in TLSX_GetSize. */
15175        prevOffset = offset;
15176
15177        /* writes extension type. */
15178        c16toa((word16)extension->type, output + offset);
15179        offset += HELLO_EXT_TYPE_SZ + OPAQUE16_LEN;
15180        length_offset = offset;
15181
15182        /* extension data should be written internally. */
15183        switch (extension->type) {
15184#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_DUAL_ALG_CERTS)
15185            case TLSX_CKS:
15186                WOLFSSL_MSG("CKS extension to write");
15187                offset += CKS_WRITE(((WOLFSSL*)extension->data),
15188                                    output + offset);
15189                break;
15190#endif
15191#ifdef HAVE_SNI
15192            case TLSX_SERVER_NAME:
15193                if (isRequest) {
15194                    WOLFSSL_MSG("SNI extension to write");
15195                    offset += SNI_WRITE((SNI*)extension->data, output + offset);
15196                }
15197                break;
15198#endif
15199
15200            case TLSX_TRUSTED_CA_KEYS:
15201                WOLFSSL_MSG("Trusted CA Indication extension to write");
15202                if (isRequest) {
15203                    offset += TCA_WRITE((TCA*)extension->data, output + offset);
15204                }
15205                break;
15206
15207            case TLSX_MAX_FRAGMENT_LENGTH:
15208                WOLFSSL_MSG("Max Fragment Length extension to write");
15209                offset += MFL_WRITE((byte*)extension->data, output + offset);
15210                break;
15211
15212            case TLSX_EXTENDED_MASTER_SECRET:
15213                WOLFSSL_MSG("Extended Master Secret");
15214                /* always empty. */
15215                break;
15216
15217            case TLSX_TRUNCATED_HMAC:
15218                WOLFSSL_MSG("Truncated HMAC extension to write");
15219                /* always empty. */
15220                break;
15221
15222            case TLSX_SUPPORTED_GROUPS:
15223                WOLFSSL_MSG("Supported Groups extension to write");
15224                offset += EC_WRITE((SupportedCurve*)extension->data,
15225                                    output + offset);
15226                break;
15227
15228            case TLSX_EC_POINT_FORMATS:
15229                WOLFSSL_MSG("Point Formats extension to write");
15230                offset += PF_WRITE((PointFormat*)extension->data,
15231                                    output + offset);
15232                break;
15233
15234            case TLSX_STATUS_REQUEST:
15235                WOLFSSL_MSG("Certificate Status Request extension to write");
15236                ret = CSR_WRITE((CertificateStatusRequest*)extension->data,
15237                        output + offset, isRequest);
15238                if (ret > 0) {
15239                    offset += (word16)ret;
15240                    ret = 0;
15241                }
15242                break;
15243
15244            case TLSX_STATUS_REQUEST_V2:
15245                WOLFSSL_MSG("Certificate Status Request v2 extension to write");
15246                ret = CSR2_WRITE(
15247                        (CertificateStatusRequestItemV2*)extension->data,
15248                        output + offset, isRequest);
15249                if (ret > 0) {
15250                    offset += (word16)ret;
15251                    ret = 0;
15252                }
15253                break;
15254
15255            case TLSX_RENEGOTIATION_INFO:
15256                WOLFSSL_MSG("Secure Renegotiation extension to write");
15257                offset += SCR_WRITE((SecureRenegotiation*)extension->data,
15258                        output + offset, isRequest);
15259                break;
15260
15261            case TLSX_SESSION_TICKET:
15262                WOLFSSL_MSG("Session Ticket extension to write");
15263                offset += WOLF_STK_WRITE((SessionTicket*)extension->data,
15264                        output + offset, isRequest);
15265                break;
15266
15267            case TLSX_APPLICATION_LAYER_PROTOCOL:
15268                WOLFSSL_MSG("ALPN extension to write");
15269                offset += ALPN_WRITE((ALPN*)extension->data, output + offset);
15270                break;
15271#if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
15272            case TLSX_SIGNATURE_ALGORITHMS:
15273                WOLFSSL_MSG("Signature Algorithms extension to write");
15274                offset += SA_WRITE(extension->data, output + offset);
15275                break;
15276#endif
15277#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
15278            case TLSX_ENCRYPT_THEN_MAC:
15279                WOLFSSL_MSG("Encrypt-Then-Mac extension to write");
15280                cbShim = 0;
15281                ret = ETM_WRITE(extension->data, output, msgType, &cbShim);
15282                offset += cbShim;
15283                break;
15284#endif /* HAVE_ENCRYPT_THEN_MAC */
15285
15286#if defined(WOLFSSL_TLS13) || !defined(WOLFSSL_NO_TLS12) || !defined(NO_OLD_TLS)
15287    #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
15288            case TLSX_PRE_SHARED_KEY:
15289                WOLFSSL_MSG("Pre-Shared Key extension to write");
15290                cbShim = 0;
15291                ret = PSK_WRITE((PreSharedKey*)extension->data, output + offset,
15292                                                              msgType, &cbShim);
15293                offset += cbShim;
15294                break;
15295
15296        #ifdef WOLFSSL_TLS13
15297            case TLSX_PSK_KEY_EXCHANGE_MODES:
15298                WOLFSSL_MSG("PSK Key Exchange Modes extension to write");
15299                cbShim = 0;
15300                ret = PKM_WRITE((byte)extension->val, output + offset, msgType,
15301                                                                       &cbShim);
15302                offset += cbShim;
15303                break;
15304        #ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
15305            case TLSX_CERT_WITH_EXTERN_PSK:
15306                WOLFSSL_MSG("Cert with external PSK extension to write");
15307                cbShim = 0;
15308                ret = PSK_WITH_CERT_WRITE(output + offset, msgType, &cbShim);
15309                offset += cbShim;
15310                break;
15311        #endif
15312        #endif
15313    #endif
15314            case TLSX_KEY_SHARE:
15315                WOLFSSL_MSG("Key Share extension to write");
15316                offset += KS_WRITE((KeyShareEntry*)extension->data,
15317                                                      output + offset, msgType);
15318                break;
15319#endif
15320#ifdef WOLFSSL_TLS13
15321            case TLSX_SUPPORTED_VERSIONS:
15322                WOLFSSL_MSG("Supported Versions extension to write");
15323                cbShim = 0;
15324                ret = SV_WRITE(extension->data, output + offset, msgType,
15325                                                                       &cbShim);
15326                offset += cbShim;
15327                break;
15328
15329            case TLSX_COOKIE:
15330                WOLFSSL_MSG("Cookie extension to write");
15331                cbShim = 0;
15332                ret = CKE_WRITE((Cookie*)extension->data, output + offset,
15333                                msgType, &cbShim);
15334                offset += cbShim;
15335                break;
15336
15337    #ifdef WOLFSSL_EARLY_DATA
15338            case TLSX_EARLY_DATA:
15339                WOLFSSL_MSG("Early Data extension to write");
15340                cbShim = 0;
15341                ret = EDI_WRITE(extension->val, output + offset, msgType,
15342                                                                       &cbShim);
15343                offset += cbShim;
15344                break;
15345    #endif
15346
15347    #ifdef WOLFSSL_POST_HANDSHAKE_AUTH
15348            case TLSX_POST_HANDSHAKE_AUTH:
15349                WOLFSSL_MSG("Post-Handshake Authentication extension to write");
15350                cbShim = 0;
15351                ret = PHA_WRITE(output + offset, msgType, &cbShim);
15352                offset += cbShim;
15353                break;
15354    #endif
15355
15356    #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
15357            case TLSX_SIGNATURE_ALGORITHMS_CERT:
15358                WOLFSSL_MSG("Signature Algorithms extension to write");
15359                offset += SAC_WRITE(extension->data, output + offset);
15360                break;
15361    #endif
15362
15363    #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES)
15364            case TLSX_CERTIFICATE_AUTHORITIES:
15365                WOLFSSL_MSG("Certificate Authorities extension to write");
15366                offset += CAN_WRITE(extension->data, output + offset);
15367                break;
15368    #endif
15369#endif
15370#ifdef WOLFSSL_SRTP
15371            case TLSX_USE_SRTP:
15372                WOLFSSL_MSG("SRTP extension to write");
15373                offset += SRTP_WRITE((TlsxSrtp*)extension->data, output+offset);
15374                break;
15375#endif
15376
15377#ifdef HAVE_RPK
15378            case TLSX_CLIENT_CERTIFICATE_TYPE:
15379                WOLFSSL_MSG("Client Certificate Type extension to write");
15380                offset += CCT_WRITE(extension->data, output + offset, msgType);
15381                break;
15382
15383            case TLSX_SERVER_CERTIFICATE_TYPE:
15384                WOLFSSL_MSG("Server Certificate Type extension to write");
15385                offset += SCT_WRITE(extension->data, output + offset, msgType);
15386                break;
15387#endif /* HAVE_RPK */
15388
15389#ifdef WOLFSSL_QUIC
15390            case TLSX_KEY_QUIC_TP_PARAMS:
15391                FALL_THROUGH;
15392            case TLSX_KEY_QUIC_TP_PARAMS_DRAFT:
15393                WOLFSSL_MSG("QUIC transport parameter to write");
15394                offset += QTP_WRITE((QuicTransportParam*)extension->data,
15395                                    output + offset);
15396                break;
15397#endif
15398#ifdef WOLFSSL_DTLS_CID
15399            case TLSX_CONNECTION_ID:
15400                WOLFSSL_MSG("Connection ID extension to write");
15401                offset += CID_WRITE((byte*)extension->data, output+offset);
15402                break;
15403
15404#endif /* WOLFSSL_DTLS_CID */
15405#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
15406            case TLSX_ECH:
15407                WOLFSSL_MSG("ECH extension to write");
15408                cbShim = 0;
15409                ret = ECH_WRITE((WOLFSSL_ECH*)extension->data, msgType,
15410                    output + offset, &cbShim);
15411                offset += cbShim;
15412                break;
15413#endif
15414            default:
15415                break;
15416        }
15417
15418        /* Per-extension data length is a 2-byte wire field; reject any
15419         * single extension whose payload exceeds that before truncating. */
15420        if (offset - length_offset > WOLFSSL_MAX_16BIT) {
15421            WOLFSSL_MSG("TLSX_Write single extension length exceeds word16");
15422            return BUFFER_E;
15423        }
15424
15425        /* writes extension data length. */
15426        c16toa((word16)(offset - length_offset),
15427               output + length_offset - OPAQUE16_LEN);
15428
15429        /* marks the extension as processed so ctx level */
15430        /* extensions don't overlap with ssl level ones. */
15431        TURN_ON(semaphore, TLSX_ToSemaphore((word16)extension->type));
15432
15433        /* if we encountered an error propagate it */
15434        if (ret != 0)
15435            break;
15436
15437        if (offset <= prevOffset) {
15438            WOLFSSL_MSG("TLSX_Write extension made no progress");
15439            return BUFFER_E;
15440        }
15441    }
15442
15443    /* Only validate and commit the aggregate offset when the loop
15444     * completed without error; on the error path, leave *pOffset
15445     * unchanged and return the original failure reason so callers
15446     * see the real error instead of a masking BUFFER_E. */
15447    if (ret == 0) {
15448        if ((word32)*pOffset + offset > WOLFSSL_MAX_16BIT) {
15449            WOLFSSL_MSG("TLSX_Write total extensions length exceeds word16");
15450            return BUFFER_E;
15451        }
15452        *pOffset += (word16)offset;
15453    }
15454
15455    return ret;
15456}
15457
15458#ifdef HAVE_SUPPORTED_CURVES
15459
15460/* Populates the default supported groups / curves */
15461static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions)
15462{
15463    int ret = WOLFSSL_SUCCESS;
15464#ifdef WOLFSSL_TLS13
15465#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
15466    if (ssl->options.resuming && ssl->session->namedGroup != 0) {
15467        return TLSX_UseSupportedCurve(extensions, ssl->session->namedGroup,
15468                                                                     ssl->heap);
15469    }
15470#endif
15471
15472    if (ssl->numGroups != 0) {
15473        int i;
15474        for (i = 0; i < ssl->numGroups; i++) {
15475            ret = TLSX_UseSupportedCurve(extensions, ssl->group[i], ssl->heap);
15476            if (ret != WOLFSSL_SUCCESS)
15477                return ret;
15478        }
15479        return WOLFSSL_SUCCESS;
15480    }
15481#endif /* WOLFSSL_TLS13 */
15482
15483#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_HAVE_MLKEM) && \
15484    !defined(WOLFSSL_NO_ML_KEM) && defined(WOLFSSL_PQC_HYBRIDS)
15485    /* Prefer non-experimental PQ/T hybrid groups (only for TLS 1.3) */
15486    if (IsAtLeastTLSv1_3(ssl->version)) {
15487    #if !defined(WOLFSSL_NO_ML_KEM_768) && defined(HAVE_CURVE25519) && \
15488        ECC_MIN_KEY_SZ <= 256
15489        ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_X25519MLKEM768,
15490            ssl->heap);
15491        if (ret != WOLFSSL_SUCCESS) return ret;
15492    #endif
15493    #if !defined(WOLFSSL_NO_ML_KEM_1024) && defined(HAVE_ECC) && \
15494        (defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)) && \
15495        ECC_MIN_KEY_SZ <= 384
15496        ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_SECP384R1MLKEM1024,
15497            ssl->heap);
15498        if (ret != WOLFSSL_SUCCESS) return ret;
15499    #endif
15500    #if !defined(WOLFSSL_NO_ML_KEM_768) && defined(HAVE_ECC) && \
15501        (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && \
15502        ECC_MIN_KEY_SZ <= 256
15503        ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_SECP256R1MLKEM768,
15504            ssl->heap);
15505        if (ret != WOLFSSL_SUCCESS) return ret;
15506    #endif
15507    }
15508#endif
15509
15510#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_HAVE_MLKEM) && \
15511    !defined(WOLFSSL_NO_ML_KEM) && !defined(WOLFSSL_NO_ML_KEM_1024) && \
15512    !defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE)
15513    if (IsAtLeastTLSv1_3(ssl->version)) {
15514        ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_ML_KEM_1024,
15515                                     ssl->heap);
15516        if (ret != WOLFSSL_SUCCESS) return ret;
15517    }
15518#endif
15519
15520#if defined(HAVE_ECC)
15521    /* list in order by strength, since not all servers choose by strength */
15522    #if (defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 521
15523        #ifndef NO_ECC_SECP
15524        ret = TLSX_UseSupportedCurve(extensions,
15525                                        WOLFSSL_ECC_SECP521R1, ssl->heap);
15526        if (ret != WOLFSSL_SUCCESS) return ret;
15527        #endif
15528    #endif
15529    #if (defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 512
15530        #ifdef HAVE_ECC_BRAINPOOL
15531        if (IsAtLeastTLSv1_3(ssl->version)) {
15532            /* TLS 1.3 BrainpoolP512 curve */
15533            ret = TLSX_UseSupportedCurve(extensions,
15534                        WOLFSSL_ECC_BRAINPOOLP512R1TLS13, ssl->heap);
15535            if (ret != WOLFSSL_SUCCESS) return ret;
15536
15537            /* If TLS 1.2 is allowed, also add the TLS 1.2 curve */
15538            if (ssl->options.downgrade &&
15539                (ssl->options.minDowngrade <= TLSv1_2_MINOR ||
15540                    ssl->options.minDowngrade <= DTLSv1_2_MINOR)) {
15541                ret = TLSX_UseSupportedCurve(extensions,
15542                            WOLFSSL_ECC_BRAINPOOLP512R1, ssl->heap);
15543                if (ret != WOLFSSL_SUCCESS) return ret;
15544            }
15545        }
15546        else {
15547            /* TLS 1.2 only */
15548            ret = TLSX_UseSupportedCurve(extensions,
15549                WOLFSSL_ECC_BRAINPOOLP512R1, ssl->heap);
15550            if (ret != WOLFSSL_SUCCESS) return ret;
15551        }
15552        #endif
15553    #endif
15554#endif
15555
15556#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_HAVE_MLKEM) && \
15557    !defined(WOLFSSL_NO_ML_KEM) && !defined(WOLFSSL_NO_ML_KEM_768) && \
15558    !defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE)
15559    if (IsAtLeastTLSv1_3(ssl->version)) {
15560        ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_ML_KEM_768,
15561                                     ssl->heap);
15562        if (ret != WOLFSSL_SUCCESS) return ret;
15563    }
15564#endif
15565
15566#if defined(HAVE_ECC)
15567    #if (defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 384
15568        #ifndef NO_ECC_SECP
15569        ret = TLSX_UseSupportedCurve(extensions,
15570                                        WOLFSSL_ECC_SECP384R1, ssl->heap);
15571        if (ret != WOLFSSL_SUCCESS) return ret;
15572        #endif
15573        #ifdef HAVE_ECC_BRAINPOOL
15574        if (IsAtLeastTLSv1_3(ssl->version)) {
15575            /* TLS 1.3 BrainpoolP384 curve */
15576            ret = TLSX_UseSupportedCurve(extensions,
15577                        WOLFSSL_ECC_BRAINPOOLP384R1TLS13, ssl->heap);
15578            if (ret != WOLFSSL_SUCCESS) return ret;
15579
15580            /* If TLS 1.2 is allowed, also add the TLS 1.2 curve */
15581            if (ssl->options.downgrade &&
15582                (ssl->options.minDowngrade <= TLSv1_2_MINOR ||
15583                    ssl->options.minDowngrade <= DTLSv1_2_MINOR)) {
15584                ret = TLSX_UseSupportedCurve(extensions,
15585                            WOLFSSL_ECC_BRAINPOOLP384R1, ssl->heap);
15586                if (ret != WOLFSSL_SUCCESS) return ret;
15587            }
15588        }
15589        else {
15590            /* TLS 1.2 only */
15591            ret = TLSX_UseSupportedCurve(extensions,
15592                WOLFSSL_ECC_BRAINPOOLP384R1, ssl->heap);
15593            if (ret != WOLFSSL_SUCCESS) return ret;
15594        }
15595        #endif
15596    #endif
15597#endif /* HAVE_ECC */
15598
15599#ifndef HAVE_FIPS
15600    #if defined(HAVE_CURVE448) && ECC_MIN_KEY_SZ <= 448
15601        ret = TLSX_UseSupportedCurve(extensions,
15602                                            WOLFSSL_ECC_X448, ssl->heap);
15603        if (ret != WOLFSSL_SUCCESS) return ret;
15604    #endif
15605#endif /* HAVE_FIPS */
15606
15607#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_HAVE_MLKEM) && \
15608    !defined(WOLFSSL_NO_ML_KEM) && !defined(WOLFSSL_NO_ML_KEM_512) && \
15609    !defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE)
15610    if (IsAtLeastTLSv1_3(ssl->version)) {
15611        ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_ML_KEM_512,
15612                                     ssl->heap);
15613        if (ret != WOLFSSL_SUCCESS) return ret;
15614    }
15615#endif
15616
15617#if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES)
15618    #if (!defined(NO_ECC256)  || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 256
15619        #ifndef NO_ECC_SECP
15620        ret = TLSX_UseSupportedCurve(extensions,
15621                                        WOLFSSL_ECC_SECP256R1, ssl->heap);
15622        if (ret != WOLFSSL_SUCCESS) return ret;
15623        #endif
15624        #ifdef HAVE_ECC_KOBLITZ
15625        ret = TLSX_UseSupportedCurve(extensions,
15626                                        WOLFSSL_ECC_SECP256K1, ssl->heap);
15627        if (ret != WOLFSSL_SUCCESS) return ret;
15628        #endif
15629        #ifdef HAVE_ECC_BRAINPOOL
15630        if (IsAtLeastTLSv1_3(ssl->version)) {
15631            /* TLS 1.3 BrainpoolP256 curve */
15632            ret = TLSX_UseSupportedCurve(extensions,
15633                                    WOLFSSL_ECC_BRAINPOOLP256R1TLS13, ssl->heap);
15634            if (ret != WOLFSSL_SUCCESS) return ret;
15635
15636            /* If TLS 1.2 is allowed, also add the TLS 1.2 curve */
15637            if (ssl->options.downgrade &&
15638                (ssl->options.minDowngrade <= TLSv1_2_MINOR ||
15639                    ssl->options.minDowngrade <= DTLSv1_2_MINOR)) {
15640                ret = TLSX_UseSupportedCurve(extensions,
15641                            WOLFSSL_ECC_BRAINPOOLP256R1, ssl->heap);
15642                if (ret != WOLFSSL_SUCCESS) return ret;
15643            }
15644        }
15645        else {
15646            /* TLS 1.2 only */
15647            ret = TLSX_UseSupportedCurve(extensions,
15648                WOLFSSL_ECC_BRAINPOOLP256R1, ssl->heap);
15649            if (ret != WOLFSSL_SUCCESS) return ret;
15650        }
15651        #endif
15652        #ifdef WOLFSSL_SM2
15653        ret = TLSX_UseSupportedCurve(extensions,
15654                                        WOLFSSL_ECC_SM2P256V1, ssl->heap);
15655        if (ret != WOLFSSL_SUCCESS) return ret;
15656        #endif
15657    #endif
15658#endif /* HAVE_ECC */
15659
15660#ifndef HAVE_FIPS
15661    #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256
15662        ret = TLSX_UseSupportedCurve(extensions,
15663                                            WOLFSSL_ECC_X25519, ssl->heap);
15664        if (ret != WOLFSSL_SUCCESS) return ret;
15665    #endif
15666#endif /* HAVE_FIPS */
15667
15668#if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES)
15669    #if (defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 224
15670        #ifndef NO_ECC_SECP
15671        ret = TLSX_UseSupportedCurve(extensions,
15672                                        WOLFSSL_ECC_SECP224R1, ssl->heap);
15673        if (ret != WOLFSSL_SUCCESS) return ret;
15674        #endif
15675        #ifdef HAVE_ECC_KOBLITZ
15676        ret = TLSX_UseSupportedCurve(extensions,
15677                                        WOLFSSL_ECC_SECP224K1, ssl->heap);
15678        if (ret != WOLFSSL_SUCCESS) return ret;
15679        #endif
15680    #endif
15681
15682    #ifndef HAVE_FIPS
15683        #if (defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 192
15684            #ifndef NO_ECC_SECP
15685                ret = TLSX_UseSupportedCurve(extensions,
15686                                              WOLFSSL_ECC_SECP192R1, ssl->heap);
15687                if (ret != WOLFSSL_SUCCESS) return ret;
15688            #endif
15689            #ifdef HAVE_ECC_KOBLITZ
15690                ret = TLSX_UseSupportedCurve(extensions,
15691                                              WOLFSSL_ECC_SECP192K1, ssl->heap);
15692                if (ret != WOLFSSL_SUCCESS) return ret;
15693            #endif
15694        #endif
15695        #if (defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 160
15696            #ifndef NO_ECC_SECP
15697                ret = TLSX_UseSupportedCurve(extensions,
15698                                              WOLFSSL_ECC_SECP160R1, ssl->heap);
15699                if (ret != WOLFSSL_SUCCESS) return ret;
15700            #endif
15701            #ifdef HAVE_ECC_SECPR2
15702                ret = TLSX_UseSupportedCurve(extensions,
15703                                              WOLFSSL_ECC_SECP160R2, ssl->heap);
15704                if (ret != WOLFSSL_SUCCESS) return ret;
15705            #endif
15706            #ifdef HAVE_ECC_KOBLITZ
15707                ret = TLSX_UseSupportedCurve(extensions,
15708                                              WOLFSSL_ECC_SECP160K1, ssl->heap);
15709                if (ret != WOLFSSL_SUCCESS) return ret;
15710            #endif
15711        #endif
15712    #endif /* HAVE_FIPS */
15713#endif /* HAVE_ECC */
15714
15715#ifndef NO_DH
15716        /* Add FFDHE supported groups. */
15717    #ifdef HAVE_FFDHE_8192
15718        if (8192/8 >= ssl->options.minDhKeySz &&
15719                                        8192/8 <= ssl->options.maxDhKeySz) {
15720            ret = TLSX_UseSupportedCurve(extensions,
15721                                            WOLFSSL_FFDHE_8192, ssl->heap);
15722            if (ret != WOLFSSL_SUCCESS)
15723                return ret;
15724        }
15725    #endif
15726    #ifdef HAVE_FFDHE_6144
15727        if (6144/8 >= ssl->options.minDhKeySz &&
15728                                        6144/8 <= ssl->options.maxDhKeySz) {
15729            ret = TLSX_UseSupportedCurve(extensions,
15730                                            WOLFSSL_FFDHE_6144, ssl->heap);
15731            if (ret != WOLFSSL_SUCCESS)
15732                return ret;
15733        }
15734    #endif
15735    #ifdef HAVE_FFDHE_4096
15736        if (4096/8 >= ssl->options.minDhKeySz &&
15737                                        4096/8 <= ssl->options.maxDhKeySz) {
15738            ret = TLSX_UseSupportedCurve(extensions,
15739                                            WOLFSSL_FFDHE_4096, ssl->heap);
15740            if (ret != WOLFSSL_SUCCESS)
15741                return ret;
15742        }
15743    #endif
15744    #ifdef HAVE_FFDHE_3072
15745        if (3072/8 >= ssl->options.minDhKeySz &&
15746                                        3072/8 <= ssl->options.maxDhKeySz) {
15747            ret = TLSX_UseSupportedCurve(extensions,
15748                                            WOLFSSL_FFDHE_3072, ssl->heap);
15749            if (ret != WOLFSSL_SUCCESS)
15750                return ret;
15751        }
15752    #endif
15753    #ifdef HAVE_FFDHE_2048
15754        if (2048/8 >= ssl->options.minDhKeySz &&
15755                                        2048/8 <= ssl->options.maxDhKeySz) {
15756            ret = TLSX_UseSupportedCurve(extensions,
15757                                            WOLFSSL_FFDHE_2048, ssl->heap);
15758            if (ret != WOLFSSL_SUCCESS)
15759                return ret;
15760        }
15761    #endif
15762#endif
15763
15764#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_HAVE_MLKEM) && \
15765    !defined(WOLFSSL_NO_ML_KEM) && defined(WOLFSSL_EXTRA_PQC_HYBRIDS)
15766    if (IsAtLeastTLSv1_3(ssl->version)) {
15767#if !defined(WOLFSSL_NO_ML_KEM_1024) && defined(HAVE_ECC) && \
15768    (defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 521
15769        ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_SECP521R1MLKEM1024,
15770                                     ssl->heap);
15771        if (ret != WOLFSSL_SUCCESS) return ret;
15772#endif
15773#if !defined(WOLFSSL_NO_ML_KEM_768) && defined(HAVE_ECC) && \
15774    (defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 384
15775        ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_SECP384R1MLKEM768,
15776                                     ssl->heap);
15777        if (ret != WOLFSSL_SUCCESS) return ret;
15778#endif
15779#if !defined(WOLFSSL_NO_ML_KEM_768) && defined(HAVE_CURVE448) && \
15780    ECC_MIN_KEY_SZ <= 448
15781        ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_X448MLKEM768,
15782                                     ssl->heap);
15783        if (ret != WOLFSSL_SUCCESS) return ret;
15784#endif
15785#if !defined(WOLFSSL_NO_ML_KEM_512) && defined(HAVE_ECC) && \
15786    (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 256
15787        ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_SECP256R1MLKEM512,
15788                                     ssl->heap);
15789        if (ret != WOLFSSL_SUCCESS) return ret;
15790#endif
15791#if !defined(WOLFSSL_NO_ML_KEM_512) && defined(HAVE_CURVE25519) && \
15792    ECC_MIN_KEY_SZ <= 256
15793        ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_X25519MLKEM512,
15794                                     ssl->heap);
15795        if (ret != WOLFSSL_SUCCESS) return ret;
15796#endif
15797    }
15798#endif
15799
15800#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_HAVE_MLKEM) && \
15801    defined(WOLFSSL_MLKEM_KYBER)
15802    if (IsAtLeastTLSv1_3(ssl->version)) {
15803#ifdef WOLFSSL_KYBER1024
15804        ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_KYBER_LEVEL5,
15805                                     ssl->heap);
15806        if (ret != WOLFSSL_SUCCESS) return ret;
15807#if defined(HAVE_ECC) && (defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)) && \
15808    ECC_MIN_KEY_SZ <= 521
15809        ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P521_KYBER_LEVEL5,
15810                                     ssl->heap);
15811        if (ret != WOLFSSL_SUCCESS) return ret;
15812#endif
15813#endif
15814#ifdef WOLFSSL_KYBER768
15815        ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_KYBER_LEVEL3,
15816                                     ssl->heap);
15817        if (ret != WOLFSSL_SUCCESS) return ret;
15818#if defined(HAVE_ECC) && (defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)) && \
15819        ECC_MIN_KEY_SZ <= 384
15820        ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P384_KYBER_LEVEL3,
15821                                     ssl->heap);
15822        if (ret != WOLFSSL_SUCCESS) return ret;
15823#endif
15824#if defined(HAVE_ECC) && (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && \
15825    ECC_MIN_KEY_SZ <= 256
15826        ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P256_KYBER_LEVEL3,
15827                                     ssl->heap);
15828        if (ret != WOLFSSL_SUCCESS) return ret;
15829#endif
15830#if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256
15831        ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_X25519_KYBER_LEVEL3,
15832                                     ssl->heap);
15833        if (ret != WOLFSSL_SUCCESS) return ret;
15834#endif
15835#if defined(HAVE_CURVE448) && ECC_MIN_KEY_SZ <= 448
15836        ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_X448_KYBER_LEVEL3,
15837                                     ssl->heap);
15838        if (ret != WOLFSSL_SUCCESS) return ret;
15839#endif
15840#endif
15841#ifdef WOLFSSL_KYBER512
15842        ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_KYBER_LEVEL1,
15843                                     ssl->heap);
15844        if (ret != WOLFSSL_SUCCESS) return ret;
15845#if defined(HAVE_ECC) && (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && \
15846    ECC_MIN_KEY_SZ <= 256
15847        ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P256_KYBER_LEVEL1,
15848                                     ssl->heap);
15849        if (ret != WOLFSSL_SUCCESS) return ret;
15850#endif
15851#if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256
15852        ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_X25519_KYBER_LEVEL1,
15853                                     ssl->heap);
15854        if (ret != WOLFSSL_SUCCESS) return ret;
15855#endif
15856#endif
15857    }
15858#endif
15859
15860    (void)ssl;
15861    (void)extensions;
15862
15863    return ret;
15864}
15865
15866#endif /* HAVE_SUPPORTED_CURVES */
15867
15868int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer)
15869{
15870    int ret = 0;
15871    byte* public_key      = NULL;
15872    word16 public_key_len = 0;
15873#if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK))
15874    int usingPSK = 0;
15875#endif
15876#if defined(HAVE_SUPPORTED_CURVES) && defined(WOLFSSL_TLS13)
15877    TLSX* extension = NULL;
15878    word16 namedGroup = WOLFSSL_NAMED_GROUP_INVALID;
15879#endif
15880
15881    /* server will add extension depending on what is parsed from client */
15882    if (!isServer) {
15883#if defined(HAVE_RPK)
15884        ret = TLSX_ClientCertificateType_Use(ssl, isServer);
15885        if (ret != 0)
15886            return ret;
15887
15888        ret = TLSX_ServerCertificateType_Use(ssl, isServer);
15889        if (ret != 0)
15890            return ret;
15891#endif /* HAVE_RPK */
15892
15893#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) && \
15894    !defined(WOLFSSL_NO_TLS12)
15895        if (!ssl->options.disallowEncThenMac) {
15896            ret = TLSX_EncryptThenMac_Use(ssl);
15897            if (ret != 0)
15898                return ret;
15899        }
15900#endif
15901
15902#if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
15903                       defined(HAVE_CURVE448)) && defined(HAVE_SUPPORTED_CURVES)
15904        if (!ssl->options.userCurves && !ssl->ctx->userCurves) {
15905            if (TLSX_Find(ssl->ctx->extensions,
15906                                               TLSX_SUPPORTED_GROUPS) == NULL) {
15907                ret = TLSX_PopulateSupportedGroups(ssl, &ssl->extensions);
15908                if (ret != WOLFSSL_SUCCESS)
15909                    return ret;
15910            }
15911        }
15912        if ((!IsAtLeastTLSv1_3(ssl->version) || ssl->options.downgrade) &&
15913               TLSX_Find(ssl->ctx->extensions, TLSX_EC_POINT_FORMATS) == NULL &&
15914               TLSX_Find(ssl->extensions, TLSX_EC_POINT_FORMATS) == NULL) {
15915             ret = TLSX_UsePointFormat(&ssl->extensions,
15916                                         WOLFSSL_EC_PF_UNCOMPRESSED, ssl->heap);
15917             if (ret != WOLFSSL_SUCCESS)
15918                 return ret;
15919        }
15920#endif /* (HAVE_ECC || CURVE25519 || CURVE448) && HAVE_SUPPORTED_CURVES */
15921
15922#ifdef WOLFSSL_SRTP
15923        if (ssl->options.dtls && ssl->dtlsSrtpProfiles != 0) {
15924            WOLFSSL_MSG("Adding DTLS SRTP extension");
15925            if ((ret = TLSX_UseSRTP(&ssl->extensions, ssl->dtlsSrtpProfiles,
15926                                                                ssl->heap)) != 0) {
15927                return ret;
15928            }
15929        }
15930#endif
15931#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_DUAL_ALG_CERTS)
15932        if ((IsAtLeastTLSv1_3(ssl->version)) && (ssl->sigSpec != NULL)) {
15933            WOLFSSL_MSG("Adding CKS extension");
15934            if ((ret = TLSX_UseCKS(&ssl->extensions, ssl, ssl->heap)) != 0) {
15935                return ret;
15936            }
15937        }
15938#endif
15939    } /* is not server */
15940
15941#if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
15942    WOLFSSL_MSG("Adding signature algorithms extension");
15943    if ((ret = TLSX_SetSignatureAlgorithms(&ssl->extensions, ssl, ssl->heap))
15944                                                                         != 0) {
15945            return ret;
15946    }
15947#else
15948    ret = 0;
15949#endif
15950#ifdef WOLFSSL_TLS13
15951    #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES)
15952        if (IsAtLeastTLSv1_3(ssl->version) &&
15953                SSL_PRIORITY_CA_NAMES(ssl) != NULL) {
15954            WOLFSSL_MSG("Adding certificate authorities extension");
15955            if ((ret = TLSX_Push(&ssl->extensions,
15956                    TLSX_CERTIFICATE_AUTHORITIES, ssl, ssl->heap)) != 0) {
15957                    return ret;
15958            }
15959        }
15960    #endif
15961        if (!isServer && IsAtLeastTLSv1_3(ssl->version)) {
15962            /* Add mandatory TLS v1.3 extension: supported version */
15963            WOLFSSL_MSG("Adding supported versions extension");
15964            if ((ret = TLSX_SetSupportedVersions(&ssl->extensions, ssl,
15965                                                             ssl->heap)) != 0) {
15966                return ret;
15967            }
15968
15969    #if !defined(HAVE_ECC) && !defined(HAVE_CURVE25519) && \
15970                       !defined(HAVE_CURVE448) && defined(HAVE_SUPPORTED_CURVES)
15971        if (TLSX_Find(ssl->ctx->extensions, TLSX_SUPPORTED_GROUPS) == NULL) {
15972            /* Put in DH groups for TLS 1.3 only. */
15973            ret = TLSX_PopulateSupportedGroups(ssl, &ssl->extensions);
15974            if (ret != WOLFSSL_SUCCESS)
15975                return ret;
15976        /* ret value will be overwritten in !NO_PSK case */
15977        #ifdef NO_PSK
15978            ret = 0;
15979        #endif
15980        }
15981    #endif /* !(HAVE_ECC || CURVE25519 || CURVE448) && HAVE_SUPPORTED_CURVES */
15982
15983        #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
15984            if (ssl->certHashSigAlgoSz > 0) {
15985                WOLFSSL_MSG("Adding signature algorithms cert extension");
15986                if ((ret = TLSX_SetSignatureAlgorithmsCert(&ssl->extensions,
15987                                                        ssl, ssl->heap)) != 0) {
15988                    return ret;
15989                }
15990            }
15991        #endif
15992
15993        #if defined(HAVE_SUPPORTED_CURVES)
15994            extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
15995            if (extension == NULL) {
15996            #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
15997                if (ssl->options.resuming && ssl->session->namedGroup != 0)
15998                    namedGroup = ssl->session->namedGroup;
15999                else
16000            #endif
16001                if (ssl->numGroups > 0) {
16002                    int set = 0;
16003                    int i, j;
16004
16005                    /* try to find the highest element in ssl->group[]
16006                     * that is contained in preferredGroup[].
16007                     */
16008                    namedGroup = preferredGroup[0];
16009                    for (i = 0; i < ssl->numGroups && !set; i++) {
16010                        for (j = 0; preferredGroup[j] != WOLFSSL_NAMED_GROUP_INVALID; j++) {
16011                            if (preferredGroup[j] == ssl->group[i]) {
16012                                namedGroup = ssl->group[i];
16013                                set = 1;
16014                                break;
16015                            }
16016                        }
16017                    }
16018                    if (!set)
16019                        namedGroup = WOLFSSL_NAMED_GROUP_INVALID;
16020                }
16021                else {
16022                    /* Choose the most preferred group. */
16023                    namedGroup = preferredGroup[0];
16024                }
16025            }
16026            else {
16027                KeyShareEntry* kse = (KeyShareEntry*)extension->data;
16028                if (kse)
16029                    namedGroup = kse->group;
16030            }
16031            if (namedGroup != WOLFSSL_NAMED_GROUP_INVALID) {
16032                ret = TLSX_KeyShare_Use(ssl, namedGroup, 0, NULL, NULL,
16033                        &ssl->extensions);
16034                if (ret != 0)
16035                    return ret;
16036            }
16037        #endif /* HAVE_SUPPORTED_CURVES */
16038
16039        #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
16040            TLSX_Remove(&ssl->extensions, TLSX_PRE_SHARED_KEY, ssl->heap);
16041        #endif
16042        #if defined(HAVE_SESSION_TICKET)
16043            if (ssl->options.resuming && ssl->session->ticketLen > 0
16044        #if defined(WOLFSSL_CERT_WITH_EXTERN_PSK)
16045                && !ssl->options.certWithExternPsk
16046        #endif
16047            ) {
16048                WOLFSSL_SESSION* sess = ssl->session;
16049            #ifdef WOLFSSL_32BIT_MILLI_TIME
16050                word32 now, milli;
16051            #else
16052                word64 now, milli;
16053            #endif
16054
16055                /* Determine the MAC algorithm for the cipher suite used. */
16056                ssl->options.cipherSuite0 = sess->cipherSuite0;
16057                ssl->options.cipherSuite  = sess->cipherSuite;
16058                ret = SetCipherSpecs(ssl);
16059                if (ret != 0)
16060                    return ret;
16061                now = (word64)TimeNowInMilliseconds();
16062                if (now == 0)
16063                    return GETTIME_ERROR;
16064            #ifdef WOLFSSL_32BIT_MILLI_TIME
16065                if (now < sess->ticketSeen)
16066                    milli = (0xFFFFFFFFU - sess->ticketSeen) + 1 + now;
16067                else
16068                    milli = now - sess->ticketSeen;
16069                milli += sess->ticketAdd;
16070
16071                /* Pre-shared key is mandatory extension for resumption. */
16072                ret = TLSX_PreSharedKey_Use(&ssl->extensions, sess->ticket,
16073                    sess->ticketLen, milli, ssl->specs.mac_algorithm,
16074                    ssl->options.cipherSuite0, ssl->options.cipherSuite, 1,
16075                    NULL, ssl->heap);
16076            #else
16077                milli = now - sess->ticketSeen + sess->ticketAdd;
16078
16079                /* Pre-shared key is mandatory extension for resumption. */
16080                ret = TLSX_PreSharedKey_Use(&ssl->extensions, sess->ticket,
16081                    sess->ticketLen, (word32)milli, ssl->specs.mac_algorithm,
16082                    ssl->options.cipherSuite0, ssl->options.cipherSuite, 1,
16083                    NULL, ssl->heap);
16084            #endif
16085                if (ret != 0)
16086                    return ret;
16087
16088                usingPSK = 1;
16089            }
16090        #endif
16091    #ifndef NO_PSK
16092        #ifndef WOLFSSL_PSK_ONE_ID
16093            if (ssl->options.client_psk_cs_cb != NULL) {
16094                int i;
16095                const Suites* suites = WOLFSSL_SUITES(ssl);
16096                for (i = 0; i < suites->suiteSz; i += 2) {
16097                    byte cipherSuite0 = suites->suites[i + 0];
16098                    byte cipherSuite = suites->suites[i + 1];
16099                    unsigned int keySz;
16100                #ifdef WOLFSSL_PSK_MULTI_ID_PER_CS
16101                    int cnt = 0;
16102                #endif
16103
16104                #ifdef HAVE_NULL_CIPHER
16105                    if (cipherSuite0 == ECC_BYTE ||
16106                        cipherSuite0 == ECDHE_PSK_BYTE) {
16107                        if (cipherSuite != TLS_SHA256_SHA256 &&
16108                                             cipherSuite != TLS_SHA384_SHA384) {
16109                            continue;
16110                        }
16111                    }
16112                    else
16113                #endif
16114                #if (defined(WOLFSSL_SM4_GCM) || defined(WOLFSSL_SM4_CCM)) && \
16115                    defined(WOLFSSL_SM3)
16116                    if (cipherSuite0 == CIPHER_BYTE) {
16117                        if ((cipherSuite != TLS_SM4_GCM_SM3) &&
16118                            (cipherSuite != TLS_SM4_CCM_SM3)) {
16119                            continue;
16120                        }
16121                    }
16122                    else
16123                #endif
16124                    if (cipherSuite0 != TLS13_BYTE)
16125                        continue;
16126
16127                #ifdef WOLFSSL_PSK_MULTI_ID_PER_CS
16128                    do {
16129                        ssl->arrays->client_identity[0] = cnt;
16130                #endif
16131
16132                        ssl->arrays->client_identity[MAX_PSK_ID_LEN] = '\0';
16133                        keySz = ssl->options.client_psk_cs_cb(
16134                            ssl, ssl->arrays->server_hint,
16135                            ssl->arrays->client_identity, MAX_PSK_ID_LEN,
16136                            ssl->arrays->psk_key, MAX_PSK_KEY_LEN,
16137                            GetCipherNameInternal(cipherSuite0, cipherSuite));
16138                        if (keySz > 0) {
16139                            ssl->arrays->psk_keySz = keySz;
16140                            ret = TLSX_PreSharedKey_Use(&ssl->extensions,
16141                                (byte*)ssl->arrays->client_identity,
16142                                (word16)XSTRLEN(ssl->arrays->client_identity),
16143                                0, SuiteMac(WOLFSSL_SUITES(ssl)->suites + i),
16144                                cipherSuite0, cipherSuite, 0, NULL, ssl->heap);
16145                            if (ret != 0)
16146                                return ret;
16147                #ifdef WOLFSSL_PSK_MULTI_ID_PER_CS
16148                            cnt++;
16149                #endif
16150                        }
16151                #ifdef WOLFSSL_PSK_MULTI_ID_PER_CS
16152                    }
16153                    while (keySz > 0);
16154                #endif
16155                }
16156
16157                usingPSK = 1;
16158            }
16159            else
16160        #endif
16161            if (ssl->options.client_psk_cb != NULL ||
16162                ssl->options.client_psk_tls13_cb != NULL) {
16163                /* Default cipher suite. */
16164                byte cipherSuite0 = TLS13_BYTE;
16165                byte cipherSuite = WOLFSSL_DEF_PSK_CIPHER;
16166                int cipherSuiteFlags = WOLFSSL_CIPHER_SUITE_FLAG_NONE;
16167                const char* cipherName = NULL;
16168
16169                if (ssl->options.client_psk_tls13_cb != NULL) {
16170                    ssl->arrays->psk_keySz = ssl->options.client_psk_tls13_cb(
16171                        ssl, ssl->arrays->server_hint,
16172                        ssl->arrays->client_identity, MAX_PSK_ID_LEN,
16173                        ssl->arrays->psk_key, MAX_PSK_KEY_LEN, &cipherName);
16174                    if (GetCipherSuiteFromName(cipherName, &cipherSuite0,
16175                            &cipherSuite, NULL, NULL, &cipherSuiteFlags) != 0) {
16176                        return PSK_KEY_ERROR;
16177                    }
16178                }
16179                else {
16180                    ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl,
16181                        ssl->arrays->server_hint, ssl->arrays->client_identity,
16182                        MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN);
16183                }
16184                if (
16185                #ifdef OPENSSL_EXTRA
16186                    /* OpenSSL treats a PSK key length of 0
16187                     * to indicate no PSK available.
16188                     */
16189                    ssl->arrays->psk_keySz == 0 ||
16190                #endif
16191                         (ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN &&
16192                     (int)ssl->arrays->psk_keySz != WC_NO_ERR_TRACE(USE_HW_PSK))) {
16193                #ifndef OPENSSL_EXTRA
16194                    ret = PSK_KEY_ERROR;
16195                #endif
16196                }
16197                else {
16198                    ssl->arrays->client_identity[MAX_PSK_ID_LEN] = '\0';
16199
16200                    ssl->options.cipherSuite0 = cipherSuite0;
16201                    ssl->options.cipherSuite  = cipherSuite;
16202                    (void)cipherSuiteFlags;
16203                    ret = SetCipherSpecs(ssl);
16204                    if (ret == 0) {
16205                        ret = TLSX_PreSharedKey_Use(
16206                            &ssl->extensions,
16207                                     (byte*)ssl->arrays->client_identity,
16208                            (word16)XSTRLEN(ssl->arrays->client_identity),
16209                            0, ssl->specs.mac_algorithm,
16210                            cipherSuite0, cipherSuite, 0,
16211                            NULL, ssl->heap);
16212                    }
16213                    if (ret == 0)
16214                        usingPSK = 1;
16215                }
16216                if (ret != 0)
16217                    return ret;
16218            }
16219    #endif /* !NO_PSK */
16220        #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
16221
16222            /* Some servers do not generate session tickets unless
16223             * the extension is seen in a non-resume client hello.
16224             * We used to send it only if we were otherwise using PSK.
16225             * Now always send it. Define NO_TLSX_PSKKEM_PLAIN_ANNOUNCE
16226             * to revert to the old behaviour. */
16227            #ifdef NO_TLSX_PSKKEM_PLAIN_ANNOUNCE
16228            if (usingPSK)
16229            #endif
16230            {
16231                byte modes = 0;
16232
16233                (void)usingPSK;
16234                /* Pre-shared key modes: mandatory extension for resumption. */
16235            #ifdef HAVE_SUPPORTED_CURVES
16236                if (!ssl->options.onlyPskDheKe)
16237            #endif
16238                {
16239                    modes = 1 << PSK_KE;
16240                }
16241            #if !defined(NO_DH) || defined(HAVE_ECC) || \
16242                          defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
16243                if (!ssl->options.noPskDheKe) {
16244                    modes |= 1 << PSK_DHE_KE;
16245                }
16246            #endif
16247            #if defined(WOLFSSL_CERT_WITH_EXTERN_PSK)
16248                if (ssl->options.certWithExternPsk) {
16249                    /* RFC8773bis requires psk_dhe_ke with cert_with_extern_psk. */
16250                    modes |= 1 << PSK_DHE_KE;
16251                }
16252            #endif
16253                ret = TLSX_PskKeyModes_Use(ssl, modes);
16254                if (ret != 0)
16255                    return ret;
16256            }
16257
16258        #if defined(WOLFSSL_CERT_WITH_EXTERN_PSK)
16259            if (usingPSK && ssl->options.certWithExternPsk) {
16260                ret = TLSX_CertWithExternPsk_Use(ssl);
16261                if (ret != 0)
16262                    return ret;
16263                /* Require server confirmation before using cert-with-PSK path. */
16264                ssl->options.certWithExternPsk = 0;
16265            }
16266        #endif
16267        #endif
16268        #if defined(WOLFSSL_POST_HANDSHAKE_AUTH)
16269            if (!isServer && ssl->options.postHandshakeAuth) {
16270                ret = TLSX_PostHandAuth_Use(ssl);
16271                if (ret != 0)
16272                    return ret;
16273            }
16274        #endif
16275#if defined(HAVE_ECH)
16276            /* GREASE ECH */
16277            if (!ssl->options.disableECH) {
16278                if (ssl->echConfigs == NULL) {
16279                    ret = GREASE_ECH_USE(&(ssl->extensions), ssl->heap,
16280                            ssl->rng);
16281                }
16282                else if (ssl->echConfigs != NULL) {
16283                    ret = ECH_USE(ssl->echConfigs, &(ssl->extensions),
16284                            ssl->heap, ssl->rng);
16285                }
16286            }
16287#endif
16288        }
16289#if defined(HAVE_ECH)
16290        else if (IsAtLeastTLSv1_3(ssl->version)) {
16291            if (ssl->ctx->echConfigs != NULL && !ssl->options.disableECH) {
16292                ret = SERVER_ECH_USE(&(ssl->extensions), ssl->heap,
16293                    ssl->ctx->echConfigs);
16294
16295                if (ret == 0)
16296                    TLSX_SetResponse(ssl, TLSX_ECH);
16297            }
16298        }
16299#endif
16300
16301#endif
16302
16303    (void)isServer;
16304    (void)public_key;
16305    (void)public_key_len;
16306    (void)ssl;
16307
16308    return ret;
16309}
16310
16311
16312#if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_CLIENT)
16313
16314#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
16315static int TLSX_EchChangeSNI(WOLFSSL* ssl, TLSX** pEchX,
16316                             char* serverName, TLSX** pServerNameX,
16317                             TLSX*** pExtensions)
16318{
16319    int ret = 0;
16320    TLSX* echX = NULL;
16321    TLSX* serverNameX = NULL;
16322    TLSX** extensions = NULL;
16323
16324    /* calculate the rest of the extensions length with inner ech */
16325    if (ssl->extensions)
16326        echX = TLSX_Find(ssl->extensions, TLSX_ECH);
16327
16328    if (echX == NULL && ssl->ctx && ssl->ctx->extensions)
16329        /* if not NULL the semaphore will stop it from being counted */
16330        echX = TLSX_Find(ssl->ctx->extensions, TLSX_ECH);
16331
16332    /* if type is outer change sni to public name */
16333    if (echX != NULL &&
16334        ((WOLFSSL_ECH*)echX->data)->type == ECH_TYPE_OUTER &&
16335        (ssl->options.echAccepted ||
16336        ((WOLFSSL_ECH*)echX->data)->innerCount == 0)) {
16337        if (ssl->extensions) {
16338            serverNameX = TLSX_Find(ssl->extensions, TLSX_SERVER_NAME);
16339
16340            if (serverNameX != NULL)
16341                extensions = &ssl->extensions;
16342        }
16343
16344        if (serverNameX == NULL && ssl->ctx && ssl->ctx->extensions) {
16345            serverNameX = TLSX_Find(ssl->ctx->extensions, TLSX_SERVER_NAME);
16346            if (serverNameX != NULL)
16347                extensions = &ssl->ctx->extensions;
16348        }
16349
16350        /* ECH requires an inner SNI to be present for ClientHelloInner.
16351         * Without it, fail instead of mutating extension lists. */
16352        if (serverNameX == NULL) {
16353            ret = BAD_FUNC_ARG;
16354        }
16355
16356        /* store the inner server name */
16357        if (ret == 0 && serverNameX != NULL) {
16358            char* hostName = ((SNI*)serverNameX->data)->data.host_name;
16359            word32 hostNameSz = (word32)XSTRLEN(hostName) + 1;
16360
16361            if (hostNameSz > WOLFSSL_HOST_NAME_MAX)
16362                ret = BAD_LENGTH_E;
16363            else
16364                XMEMCPY(serverName, hostName, hostNameSz);
16365        }
16366
16367        /* only swap the SNI if one was found; extensions is non-NULL if an
16368         * SNI entry was found on ssl->extensions or ctx->extensions */
16369        if (ret == 0 && extensions != NULL) {
16370            /* remove the inner server name */
16371            TLSX_Remove(extensions, TLSX_SERVER_NAME, ssl->heap);
16372
16373            /* set the public name as the server name */
16374            if ((ret = TLSX_UseSNI(extensions, WOLFSSL_SNI_HOST_NAME,
16375                    ((WOLFSSL_ECH*)echX->data)->echConfig->publicName,
16376                    XSTRLEN(((WOLFSSL_ECH*)echX->data)->echConfig->publicName),
16377                    ssl->heap)) == WOLFSSL_SUCCESS)
16378                ret = 0;
16379        }
16380    }
16381    *pServerNameX = serverNameX;
16382    *pExtensions = extensions;
16383    *pEchX = echX;
16384    return ret;
16385}
16386
16387static int TLSX_EchRestoreSNI(WOLFSSL* ssl, char* serverName,
16388                              TLSX* serverNameX, TLSX** extensions)
16389{
16390    int ret = 0;
16391
16392    /* always remove the publicName SNI we injected, regardless of whether
16393     * there was a prior inner SNI to restore */
16394    if (extensions != NULL)
16395        TLSX_Remove(extensions, TLSX_SERVER_NAME, ssl->heap);
16396
16397    if (serverNameX != NULL) {
16398        /* restore the inner server name */
16399        ret = TLSX_UseSNI(extensions, WOLFSSL_SNI_HOST_NAME,
16400            serverName, XSTRLEN(serverName), ssl->heap);
16401
16402        if (ret == WOLFSSL_SUCCESS)
16403            ret = 0;
16404    }
16405    return ret;
16406}
16407
16408/* Returns 1 if the extension may be encoded into ech_outer_extensions,
16409 * 0 otherwise */
16410static int TLSX_ECH_IsEncodable(word16 type)
16411{
16412    /* supported_versions being here prevents the inner hello from advertising
16413     * a version less than TLS1.3 */
16414    switch (type) {
16415        case TLSX_SERVER_NAME:
16416        case TLSX_APPLICATION_LAYER_PROTOCOL:
16417        case TLSX_SUPPORTED_VERSIONS:
16418        case TLSX_ECH:
16419#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
16420        case TLSX_PRE_SHARED_KEY:
16421#endif
16422#ifdef WOLFSSL_EARLY_DATA
16423        case TLSX_EARLY_DATA:
16424#endif
16425            return 0;
16426        default:
16427            return 1;
16428    }
16429}
16430
16431/* find extensions that can be encoded into ech_outer_extensions.
16432 * If output is non-NULL, then write the encoded form.
16433 *
16434 * Layout of OuterExtensions (RFC 9849, S5.1):
16435 *   2-byte extension_type + 2-byte extension_data length +
16436 *   1-byte list length    + 2*count bytes of extension types
16437 */
16438static int TLSX_ECH_BuildOuterExtensions(WOLFSSL* ssl, const byte* semaphore,
16439    byte msgType, byte* output, word16* pOffset, word16* outCount,
16440    byte* encodeMask)
16441{
16442    TLSX* list;
16443    TLSX* extension;
16444    byte* typesStart = NULL;
16445    int listIdx;
16446    word16 count = 0;
16447    byte isRequest = (msgType == client_hello ||
16448                      msgType == certificate_request);
16449    byte seen[SEMAPHORE_SIZE];
16450
16451    /* backup semaphore so it can be aliased by encodeMask */
16452    XMEMCPY(seen, semaphore, SEMAPHORE_SIZE);
16453
16454    if (output != NULL && pOffset != NULL) {
16455        typesStart = output + *pOffset
16456                     + HELLO_EXT_TYPE_SZ + OPAQUE16_LEN + OPAQUE8_LEN;
16457    }
16458
16459    for (listIdx = 0; listIdx < 2; listIdx++) {
16460        list = (listIdx == 0) ? ssl->extensions :
16461            (ssl->ctx != NULL ? ssl->ctx->extensions : NULL);
16462        for (extension = list; extension != NULL; extension = extension->next) {
16463            word16 type = (word16)extension->type;
16464            word16 semIdx = TLSX_ToSemaphore(type);
16465
16466            /* OuterExtensions is <2..254>, so reference at most 127 types */
16467            if (count >= 127) {
16468                WOLFSSL_MSG("ECH: cannot encode more than 127 extensions");
16469                break;
16470            }
16471
16472            if (!isRequest && !extension->resp)
16473                continue;
16474            if (!IS_OFF(seen, semIdx))
16475                continue;
16476            TURN_ON(seen, semIdx);
16477            if (!TLSX_ECH_IsEncodable(type))
16478                continue;
16479
16480            if (typesStart != NULL)
16481                c16toa(type, typesStart + count * OPAQUE16_LEN);
16482            count++;
16483            TURN_ON(encodeMask, semIdx);
16484        }
16485    }
16486
16487    if (count > 0 && pOffset != NULL) {
16488        word16 listLen = (word16)(OPAQUE16_LEN * count);
16489        word16 blockSz = (word16)(HELLO_EXT_TYPE_SZ + OPAQUE16_LEN
16490                                + OPAQUE8_LEN + listLen);
16491        if ((word32)*pOffset + blockSz > WOLFSSL_MAX_16BIT) {
16492            WOLFSSL_MSG("ECH OuterExtensions overflows extensions length");
16493            return BUFFER_E;
16494        }
16495        if (output != NULL) {
16496            byte* hdr = output + *pOffset;
16497            c16toa(TLSXT_ECH_OUTER_EXTENSIONS, hdr);
16498            c16toa((word16)(OPAQUE8_LEN + listLen), hdr + OPAQUE16_LEN);
16499            hdr[OPAQUE16_LEN + OPAQUE16_LEN] = (byte)listLen;
16500        }
16501
16502        /* accumulate offset even if nothing is written */
16503        *pOffset += blockSz;
16504    }
16505
16506    *outCount = count;
16507    return 0;
16508}
16509
16510/* because the size of ech depends on the size of other extensions we need to
16511 * get the size with ech special and process ech last, return status */
16512static int TLSX_GetSizeWithEch(WOLFSSL* ssl, byte* semaphore, byte msgType,
16513    word16* pLength)
16514{
16515    int ret = 0, r = 0;
16516    TLSX* echX = NULL;
16517    TLSX* serverNameX = NULL;
16518    TLSX** extensions = NULL;
16519    WOLFSSL_ECH* ech = NULL;
16520    word16 count = 0;
16521    WC_DECLARE_VAR(serverName, char, WOLFSSL_HOST_NAME_MAX, 0);
16522
16523    WC_ALLOC_VAR_EX(serverName, char, WOLFSSL_HOST_NAME_MAX, NULL,
16524                    DYNAMIC_TYPE_TMP_BUFFER, return MEMORY_E);
16525
16526    r = TLSX_EchChangeSNI(ssl, &echX, serverName, &serverNameX, &extensions);
16527
16528    if (echX != NULL)
16529        ech = (WOLFSSL_ECH*)echX->data;
16530
16531    /* If ECH won't be written exclude it from the size calculation */
16532    if (r == 0 && !ssl->options.echAccepted && ech != NULL &&
16533            ech->innerCount != 0) {
16534        TURN_ON(semaphore, TLSX_ToSemaphore(echX->type));
16535    }
16536
16537    /* if encoding, then count encoded form of inner ClientHello.
16538     * `semaphore` is in/out so encodable extensions will later be ignored */
16539    if (r == 0 && ech != NULL && ech->type == ECH_TYPE_INNER &&
16540            ech->writeEncoded) {
16541        ret = TLSX_ECH_BuildOuterExtensions(ssl, semaphore, msgType,
16542            NULL, pLength, &count, semaphore);
16543    }
16544    if (r == 0 && ret == 0 && ssl->extensions)
16545        ret = TLSX_GetSize(ssl->extensions, semaphore, msgType, pLength);
16546    if (r == 0 && ret == 0 && ssl->ctx && ssl->ctx->extensions)
16547        ret = TLSX_GetSize(ssl->ctx->extensions, semaphore, msgType, pLength);
16548    if (r == 0)
16549        r = TLSX_EchRestoreSNI(ssl, serverName, serverNameX, extensions);
16550
16551    WC_FREE_VAR_EX(serverName, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
16552    if (ret == 0 && r != 0)
16553        ret = r;
16554    return ret;
16555}
16556#endif
16557
16558/** Tells the buffered size of extensions to be sent into the client hello. */
16559int TLSX_GetRequestSize(WOLFSSL* ssl, byte msgType, word32* pLength)
16560{
16561    int ret = 0;
16562    word16 length = 0;
16563    byte semaphore[SEMAPHORE_SIZE] = {0};
16564
16565    if (!TLSX_SupportExtensions(ssl))
16566        return 0;
16567    if (msgType == client_hello) {
16568        EC_VALIDATE_REQUEST(ssl, semaphore);
16569        PF_VALIDATE_REQUEST(ssl, semaphore);
16570#if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
16571        if (WOLFSSL_SUITES(ssl)->hashSigAlgoSz == 0)
16572            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS));
16573#endif
16574#if defined(WOLFSSL_TLS13)
16575        if (!IsAtLeastTLSv1_2(ssl)) {
16576            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS));
16577        }
16578    #if !defined(WOLFSSL_NO_TLS12) || !defined(NO_OLD_TLS)
16579        if (!IsAtLeastTLSv1_3(ssl->version)) {
16580            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
16581        #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
16582            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
16583            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PSK_KEY_EXCHANGE_MODES));
16584        #endif
16585        #ifdef WOLFSSL_EARLY_DATA
16586            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EARLY_DATA));
16587        #endif
16588        #ifdef WOLFSSL_SEND_HRR_COOKIE
16589            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_COOKIE));
16590        #endif
16591        #ifdef WOLFSSL_POST_HANDSHAKE_AUTH
16592            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_POST_HANDSHAKE_AUTH));
16593        #endif
16594        }
16595    #endif
16596    #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES)
16597        if (!IsAtLeastTLSv1_3(ssl->version) ||
16598                SSL_CA_NAMES(ssl) == NULL) {
16599            TURN_ON(semaphore,
16600                    TLSX_ToSemaphore(TLSX_CERTIFICATE_AUTHORITIES));
16601        }
16602    #endif
16603#endif /* WOLFSSL_TLS13 */
16604    #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
16605     || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
16606        if (!SSL_CM(ssl)->ocspStaplingEnabled) {
16607            /* mark already sent, so it won't send it */
16608            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST));
16609            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST_V2));
16610        }
16611    #endif
16612    }
16613
16614#ifdef WOLFSSL_TLS13
16615    #ifndef NO_CERTS
16616    else if (msgType == certificate_request) {
16617        /* Don't send out any extension except those that are turned off. */
16618        XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
16619#if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
16620        TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS));
16621#endif
16622#if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES)
16623        if (SSL_PRIORITY_CA_NAMES(ssl) != NULL) {
16624            TURN_OFF(semaphore,
16625                    TLSX_ToSemaphore(TLSX_CERTIFICATE_AUTHORITIES));
16626        }
16627#endif
16628        /* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP, OID_FILTERS
16629         *       TLSX_STATUS_REQUEST
16630         */
16631    }
16632    #endif
16633#if defined(HAVE_ECH)
16634    if (ssl->echConfigs != NULL && !ssl->options.disableECH
16635            && msgType == client_hello) {
16636        ret = TLSX_GetSizeWithEch(ssl, semaphore, msgType, &length);
16637        if (ret != 0)
16638            return ret;
16639    }
16640    else
16641#endif /* HAVE_ECH */
16642#endif /* WOLFSSL_TLS13 */
16643    {
16644        if (ssl->extensions) {
16645            ret = TLSX_GetSize(ssl->extensions, semaphore, msgType, &length);
16646            if (ret != 0)
16647                return ret;
16648        }
16649        if (ssl->ctx && ssl->ctx->extensions) {
16650            ret = TLSX_GetSize(ssl->ctx->extensions, semaphore, msgType,
16651                &length);
16652            if (ret != 0)
16653                return ret;
16654        }
16655    }
16656
16657#ifdef HAVE_EXTENDED_MASTER
16658    if (msgType == client_hello && ssl->options.haveEMS &&
16659                  (!IsAtLeastTLSv1_3(ssl->version) || ssl->options.downgrade)) {
16660        length += HELLO_EXT_SZ;
16661    }
16662#endif
16663
16664    /* The TLS extensions block length prefix is a 2-byte field, so any
16665     * accumulated total above 0xFFFF must be rejected rather than silently
16666     * truncating and producing a short, malformed handshake message. */
16667    if (length > (word16)(WOLFSSL_MAX_16BIT - OPAQUE16_LEN)) {
16668        WOLFSSL_MSG("TLSX_GetRequestSize extensions exceed word16");
16669        return BUFFER_E;
16670    }
16671    if (length)
16672        length += OPAQUE16_LEN; /* for total length storage. */
16673
16674    *pLength += length;
16675
16676    return ret;
16677}
16678
16679#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
16680/* return status after writing the extensions with ech written last */
16681static int TLSX_WriteWithEch(WOLFSSL* ssl, byte* output, byte* semaphore,
16682    byte msgType, word16* pOffset)
16683{
16684    int r = 0, ret = 0;
16685    TLSX* echX = NULL;
16686    TLSX* serverNameX = NULL;
16687    TLSX** extensions = NULL;
16688    WOLFSSL_ECH* ech = NULL;
16689    WC_DECLARE_VAR(serverName, char, WOLFSSL_HOST_NAME_MAX, 0);
16690
16691    WC_ALLOC_VAR_EX(serverName, char, WOLFSSL_HOST_NAME_MAX, NULL,
16692                    DYNAMIC_TYPE_TMP_BUFFER, return MEMORY_E);
16693    r = TLSX_EchChangeSNI(ssl, &echX, serverName, &serverNameX, &extensions);
16694    ret = r;
16695    if (ret == 0 && echX != NULL) {
16696        ech = (WOLFSSL_ECH*)echX->data;
16697        /* turn ech on so it doesn't write, then write it last */
16698        TURN_ON(semaphore, TLSX_ToSemaphore(echX->type));
16699    }
16700
16701    /* for ECH inner, print the encodable block first, then the non-encodables.
16702     * This allows the same transcript to be produced on either side
16703     * (the transcript is over the expanded form). */
16704    if (ret == 0 && ech != NULL && ech->type == ECH_TYPE_INNER) {
16705        byte encodeMask[SEMAPHORE_SIZE];
16706        byte* mask = ech->writeEncoded ? semaphore : encodeMask;
16707        word16 count = 0;
16708        int i;
16709
16710        XMEMSET(encodeMask, 0, SEMAPHORE_SIZE);
16711
16712        ret = TLSX_ECH_BuildOuterExtensions(ssl, semaphore, msgType,
16713            ech->writeEncoded ? output : NULL,
16714            ech->writeEncoded ? pOffset : NULL,
16715            &count, mask);
16716        if (ret == 0 && count >= 1 && !ech->writeEncoded) {
16717            /* expanded: print encodable block normally */
16718            for (i = 0; i < SEMAPHORE_SIZE; i++) {
16719                semaphore[i] |= encodeMask[i];
16720                encodeMask[i] = (byte)~encodeMask[i];
16721            }
16722            if (ssl->extensions) {
16723                ret = TLSX_Write(ssl->extensions, output + *pOffset,
16724                        encodeMask, msgType, pOffset);
16725            }
16726            if (ret == 0 && ssl->ctx && ssl->ctx->extensions) {
16727                ret = TLSX_Write(ssl->ctx->extensions, output + *pOffset,
16728                        encodeMask, msgType, pOffset);
16729            }
16730        }
16731    }
16732
16733    /* print non-encodable block */
16734    if (ret == 0 && ssl->extensions) {
16735        ret = TLSX_Write(ssl->extensions, output + *pOffset, semaphore,
16736                         msgType, pOffset);
16737    }
16738    if (ret == 0 && ssl->ctx && ssl->ctx->extensions) {
16739        ret = TLSX_Write(ssl->ctx->extensions, output + *pOffset, semaphore,
16740                         msgType, pOffset);
16741    }
16742
16743    /* only write ECH if there is a shot at acceptance */
16744    if (ret == 0 && echX != NULL &&
16745        (ssl->options.echAccepted ||
16746        ((WOLFSSL_ECH*)echX->data)->innerCount == 0)) {
16747        if (echX != NULL) {
16748            /* turn off and write it last */
16749            TURN_OFF(semaphore, TLSX_ToSemaphore(echX->type));
16750        }
16751
16752        if (ret == 0 && ssl->extensions) {
16753            ret = TLSX_Write(ssl->extensions, output + *pOffset, semaphore,
16754                msgType, pOffset);
16755        }
16756
16757        if (ret == 0 && ssl->ctx && ssl->ctx->extensions) {
16758            ret = TLSX_Write(ssl->ctx->extensions, output + *pOffset, semaphore,
16759                msgType, pOffset);
16760        }
16761    }
16762
16763    if (r == 0)
16764        r = TLSX_EchRestoreSNI(ssl, serverName, serverNameX, extensions);
16765    WC_FREE_VAR_EX(serverName, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
16766
16767    if (ret == 0 && r != 0)
16768        ret = r;
16769    return ret;
16770}
16771#endif
16772
16773/** Writes the extensions to be sent into the client hello. */
16774int TLSX_WriteRequest(WOLFSSL* ssl, byte* output, byte msgType, word32* pOffset)
16775{
16776    int ret = 0;
16777    word16 offset = 0;
16778    byte semaphore[SEMAPHORE_SIZE] = {0};
16779
16780    if (!TLSX_SupportExtensions(ssl) || output == NULL)
16781        return 0;
16782
16783    offset += OPAQUE16_LEN; /* extensions length */
16784
16785    if (msgType == client_hello) {
16786        EC_VALIDATE_REQUEST(ssl, semaphore);
16787        PF_VALIDATE_REQUEST(ssl, semaphore);
16788#if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
16789        if (WOLFSSL_SUITES(ssl)->hashSigAlgoSz == 0)
16790            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS));
16791#endif
16792#ifdef WOLFSSL_TLS13
16793        if (!IsAtLeastTLSv1_2(ssl)) {
16794            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS));
16795        }
16796    #if !defined(WOLFSSL_NO_TLS12) || !defined(NO_OLD_TLS)
16797        if (!IsAtLeastTLSv1_3(ssl->version)) {
16798            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
16799        #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
16800            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PSK_KEY_EXCHANGE_MODES));
16801        #endif
16802        #ifdef WOLFSSL_EARLY_DATA
16803            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EARLY_DATA));
16804        #endif
16805        #ifdef WOLFSSL_SEND_HRR_COOKIE
16806            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_COOKIE));
16807        #endif
16808        #ifdef WOLFSSL_POST_HANDSHAKE_AUTH
16809            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_POST_HANDSHAKE_AUTH));
16810        #endif
16811        #ifdef WOLFSSL_DUAL_ALG_CERTS
16812            TURN_ON(semaphore,
16813                    TLSX_ToSemaphore(TLSX_CKS));
16814        #endif
16815        }
16816    #endif
16817    #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES)
16818        if (!IsAtLeastTLSv1_3(ssl->version) || SSL_CA_NAMES(ssl) == NULL) {
16819            TURN_ON(semaphore,
16820                    TLSX_ToSemaphore(TLSX_CERTIFICATE_AUTHORITIES));
16821        }
16822    #endif
16823    #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
16824        /* Must write Pre-shared Key extension at the end in TLS v1.3.
16825         * Must not write out Pre-shared Key extension in earlier versions of
16826         * protocol.
16827         */
16828        TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
16829    #endif
16830#endif /* WOLFSSL_TLS13 */
16831    #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
16832     || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
16833         /* mark already sent, so it won't send it */
16834        if (!SSL_CM(ssl)->ocspStaplingEnabled) {
16835            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST));
16836            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST_V2));
16837        }
16838    #endif
16839    }
16840#ifdef WOLFSSL_TLS13
16841    #ifndef NO_CERTS
16842    else if (msgType == certificate_request) {
16843        /* Don't send out any extension except those that are turned off. */
16844        XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
16845#if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
16846        TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS));
16847#endif
16848#if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES)
16849        if (SSL_PRIORITY_CA_NAMES(ssl) != NULL) {
16850            TURN_OFF(semaphore,
16851                    TLSX_ToSemaphore(TLSX_CERTIFICATE_AUTHORITIES));
16852        }
16853#endif
16854        /* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP, TLSX_OID_FILTERS
16855         *       TLSX_STATUS_REQUEST
16856         */
16857    }
16858    #endif
16859#endif
16860#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
16861    if (ssl->echConfigs != NULL && !ssl->options.disableECH
16862            && msgType == client_hello) {
16863        ret = TLSX_WriteWithEch(ssl, output, semaphore,
16864                         msgType, &offset);
16865        if (ret != 0)
16866            return ret;
16867    }
16868    else
16869#endif
16870    {
16871        if (ssl->extensions) {
16872            ret = TLSX_Write(ssl->extensions, output + offset, semaphore,
16873                             msgType, &offset);
16874            if (ret != 0)
16875                return ret;
16876        }
16877        if (ssl->ctx && ssl->ctx->extensions) {
16878            ret = TLSX_Write(ssl->ctx->extensions, output + offset, semaphore,
16879                             msgType, &offset);
16880            if (ret != 0)
16881                return ret;
16882        }
16883    }
16884
16885#ifdef HAVE_EXTENDED_MASTER
16886    if (msgType == client_hello && ssl->options.haveEMS &&
16887                  (!IsAtLeastTLSv1_3(ssl->version) || ssl->options.downgrade)) {
16888        WOLFSSL_MSG("EMS extension to write");
16889        c16toa(HELLO_EXT_EXTMS, output + offset);
16890        offset += HELLO_EXT_TYPE_SZ;
16891        c16toa(0, output + offset);
16892        offset += HELLO_EXT_SZ_SZ;
16893    }
16894#endif
16895
16896#ifdef WOLFSSL_TLS13
16897    #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
16898    if (msgType == client_hello && IsAtLeastTLSv1_3(ssl->version)) {
16899        /* Write out what we can of Pre-shared key extension.  */
16900        TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
16901        ret = TLSX_Write(ssl->extensions, output + offset, semaphore,
16902                         client_hello, &offset);
16903        if (ret != 0)
16904            return ret;
16905    }
16906    #endif
16907#endif
16908
16909    /* Wrap detection for the TLSX_Write calls above is handled inside
16910     * TLSX_Write itself: any iteration that would push the local word16
16911     * offset past 0xFFFF returns BUFFER_E so we never reach here with a
16912     * truncated value. The TLS extensions block length prefix on the
16913     * wire is a 2-byte field, matching this invariant. */
16914
16915    if (offset > OPAQUE16_LEN || msgType != client_hello)
16916        c16toa(offset - OPAQUE16_LEN, output); /* extensions length */
16917
16918     *pOffset += offset;
16919
16920    return ret;
16921}
16922#endif /* WOLFSSL_TLS13 || !NO_WOLFSSL_CLIENT */
16923
16924#if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_SERVER)
16925
16926/** Tells the buffered size of extensions to be sent into the server hello. */
16927int TLSX_GetResponseSize(WOLFSSL* ssl, byte msgType, word16* pLength)
16928{
16929    int ret = 0;
16930    word16 length = 0;
16931    byte semaphore[SEMAPHORE_SIZE] = {0};
16932
16933    switch (msgType) {
16934#ifndef NO_WOLFSSL_SERVER
16935        case server_hello:
16936            PF_VALIDATE_RESPONSE(ssl, semaphore);
16937        #ifdef WOLFSSL_TLS13
16938                if (IsAtLeastTLSv1_3(ssl->version)) {
16939                    XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
16940                    TURN_OFF(semaphore,
16941                                     TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS));
16942                #if defined(HAVE_SUPPORTED_CURVES)
16943                #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
16944                    if (!ssl->options.noPskDheKe)
16945                #endif
16946                    {
16947                        /* Expect KeyShare extension in ServerHello. */
16948                        TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
16949                    }
16950                #endif
16951                #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
16952                    TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
16953                #ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
16954                    TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_CERT_WITH_EXTERN_PSK));
16955                #endif
16956                #endif
16957                }
16958            #if !defined(WOLFSSL_NO_TLS12) || !defined(NO_OLD_TLS)
16959                else {
16960                #ifdef HAVE_SUPPORTED_CURVES
16961                    TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
16962                #endif
16963                #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
16964                    TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
16965                #endif
16966                }
16967            #endif
16968            #ifdef WOLFSSL_DTLS_CID
16969                TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_CONNECTION_ID));
16970            #endif
16971        #endif /* WOLFSSL_TLS13 */
16972            break;
16973
16974    #ifdef WOLFSSL_TLS13
16975        case hello_retry_request:
16976            XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
16977            TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS));
16978        #ifdef HAVE_SUPPORTED_CURVES
16979        #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
16980            if (!ssl->options.noPskDheKe)
16981        #endif
16982            {
16983                /* Expect KeyShare extension in HelloRetryRequest. */
16984                TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
16985            }
16986        #endif
16987        #ifdef WOLFSSL_SEND_HRR_COOKIE
16988            TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_COOKIE));
16989        #endif
16990#ifdef HAVE_ECH
16991            /* send the special confirmation */
16992            TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_ECH));
16993#endif
16994            break;
16995    #endif
16996
16997    #ifdef WOLFSSL_TLS13
16998        case encrypted_extensions:
16999            /* Send out all extension except those that are turned on. */
17000        #ifdef HAVE_ECC
17001            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EC_POINT_FORMATS));
17002        #endif
17003            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS));
17004        #ifdef HAVE_SESSION_TICKET
17005            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SESSION_TICKET));
17006        #endif
17007        #ifdef HAVE_SUPPORTED_CURVES
17008            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
17009        #endif
17010        #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
17011            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
17012        #ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
17013            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_CERT_WITH_EXTERN_PSK));
17014        #endif
17015        #endif
17016        #ifdef HAVE_CERTIFICATE_STATUS_REQUEST
17017            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST));
17018        #endif
17019        #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
17020            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST_V2));
17021        #endif
17022        #if defined(HAVE_SERVER_RENEGOTIATION_INFO)
17023            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_RENEGOTIATION_INFO));
17024        #endif
17025        #ifdef WOLFSSL_DTLS_CID
17026            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_CONNECTION_ID));
17027        #endif /* WOLFSSL_DTLS_CID */
17028            break;
17029
17030        #ifdef WOLFSSL_EARLY_DATA
17031        case session_ticket:
17032            if (ssl->options.tls1_3) {
17033                XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
17034                TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_EARLY_DATA));
17035            }
17036            break;
17037        #endif
17038    #endif
17039#endif
17040
17041#ifdef WOLFSSL_TLS13
17042    #ifndef NO_CERTS
17043        case certificate:
17044            /* Don't send out any extension except those that are turned off. */
17045            XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
17046            TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST));
17047            /* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP,
17048             *       TLSX_SERVER_CERTIFICATE_TYPE
17049             */
17050            break;
17051    #endif
17052#endif
17053    }
17054
17055#ifdef HAVE_EXTENDED_MASTER
17056    if (ssl->options.haveEMS && msgType == server_hello &&
17057                                              !IsAtLeastTLSv1_3(ssl->version)) {
17058        length += HELLO_EXT_SZ;
17059    }
17060#endif
17061
17062    if (TLSX_SupportExtensions(ssl)) {
17063        ret = TLSX_GetSize(ssl->extensions, semaphore, msgType, &length);
17064        if (ret != 0)
17065            return ret;
17066    }
17067
17068    /* All the response data is set at the ssl object only, so no ctx here. */
17069
17070    if (length || msgType != server_hello)
17071        length += OPAQUE16_LEN; /* for total length storage. */
17072
17073    *pLength += length;
17074
17075    return ret;
17076}
17077
17078/** Writes the server hello extensions into a buffer. */
17079int TLSX_WriteResponse(WOLFSSL *ssl, byte* output, byte msgType, word16* pOffset)
17080{
17081    int ret = 0;
17082    word16 offset = 0;
17083
17084    if (TLSX_SupportExtensions(ssl) && output) {
17085        byte semaphore[SEMAPHORE_SIZE] = {0};
17086
17087        switch (msgType) {
17088#ifndef NO_WOLFSSL_SERVER
17089            case server_hello:
17090                PF_VALIDATE_RESPONSE(ssl, semaphore);
17091        #ifdef WOLFSSL_TLS13
17092                if (IsAtLeastTLSv1_3(ssl->version)) {
17093                    XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
17094                    TURN_OFF(semaphore,
17095                                     TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS));
17096            #ifdef HAVE_SUPPORTED_CURVES
17097                #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
17098                    if (!ssl->options.noPskDheKe)
17099                #endif
17100                    {
17101                        /* Write out KeyShare in ServerHello. */
17102                        TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
17103                    }
17104            #endif
17105            #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
17106                    TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
17107            #ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
17108                    TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_CERT_WITH_EXTERN_PSK));
17109            #endif
17110            #endif
17111                }
17112                else
17113        #endif /* WOLFSSL_TLS13 */
17114                {
17115        #if !defined(WOLFSSL_NO_TLS12) || !defined(NO_OLD_TLS)
17116            #ifdef HAVE_SUPPORTED_CURVES
17117                    TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
17118            #endif
17119            #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
17120                    TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
17121            #endif
17122        #endif
17123                    WC_DO_NOTHING; /* avoid empty brackets */
17124                }
17125        #ifdef WOLFSSL_DTLS_CID
17126                TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_CONNECTION_ID));
17127        #endif /* WOLFSSL_DTLS_CID */
17128                break;
17129
17130    #ifdef WOLFSSL_TLS13
17131            case hello_retry_request:
17132                XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
17133                TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS));
17134        #ifdef HAVE_SUPPORTED_CURVES
17135            #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
17136                if (!ssl->options.noPskDheKe)
17137            #endif
17138                {
17139                    /* Write out KeyShare in HelloRetryRequest. */
17140                    TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
17141                }
17142        #endif
17143                break;
17144    #endif
17145
17146    #ifdef WOLFSSL_TLS13
17147            case encrypted_extensions:
17148                /* Send out all extension except those that are turned on. */
17149        #ifdef HAVE_ECC
17150                TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EC_POINT_FORMATS));
17151        #endif
17152                TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS));
17153        #ifdef HAVE_SESSION_TICKET
17154                TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SESSION_TICKET));
17155        #endif
17156        #ifdef HAVE_SUPPORTED_CURVES
17157                TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
17158        #endif
17159        #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
17160                TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
17161        #ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
17162                TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_CERT_WITH_EXTERN_PSK));
17163        #endif
17164        #endif
17165        #ifdef HAVE_CERTIFICATE_STATUS_REQUEST
17166                TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST));
17167        #endif
17168        #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
17169            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST_V2));
17170        #endif
17171        #if defined(HAVE_SERVER_RENEGOTIATION_INFO)
17172            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_RENEGOTIATION_INFO));
17173        #endif
17174        #ifdef WOLFSSL_DTLS_CID
17175            TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_CONNECTION_ID));
17176        #endif /* WOLFSSL_DTLS_CID */
17177                break;
17178
17179        #ifdef WOLFSSL_EARLY_DATA
17180            case session_ticket:
17181                if (ssl->options.tls1_3) {
17182                    XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
17183                    TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_EARLY_DATA));
17184                }
17185                break;
17186        #endif
17187    #endif
17188#endif
17189
17190    #ifdef WOLFSSL_TLS13
17191        #ifndef NO_CERTS
17192            case certificate:
17193                /* Don't send out any extension except those that are turned
17194                 * off. */
17195                XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
17196                TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST));
17197                /* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP,
17198                 *       TLSX_SERVER_CERTIFICATE_TYPE
17199                 */
17200                break;
17201        #endif
17202    #endif
17203
17204            default:
17205                break;
17206        }
17207
17208        offset += OPAQUE16_LEN; /* extensions length */
17209
17210        ret = TLSX_Write(ssl->extensions, output + offset, semaphore,
17211                         msgType, &offset);
17212        if (ret != 0)
17213            return ret;
17214
17215#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_SEND_HRR_COOKIE)
17216        if (msgType == hello_retry_request) {
17217            XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
17218            TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_COOKIE));
17219            ret = TLSX_Write(ssl->extensions, output + offset, semaphore,
17220                             msgType, &offset);
17221            if (ret != 0)
17222                return ret;
17223        }
17224#endif
17225
17226#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
17227        /* write ECH last to promote interop with other implementations */
17228        if (msgType == hello_retry_request) {
17229            XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
17230            TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_ECH));
17231            ret = TLSX_Write(ssl->extensions, output + offset, semaphore,
17232                             msgType, &offset);
17233            if (ret != 0)
17234                return ret;
17235        }
17236#endif
17237
17238#ifdef HAVE_EXTENDED_MASTER
17239        if (ssl->options.haveEMS && msgType == server_hello &&
17240                                              !IsAtLeastTLSv1_3(ssl->version)) {
17241            WOLFSSL_MSG("EMS extension to write");
17242            c16toa(HELLO_EXT_EXTMS, output + offset);
17243            offset += HELLO_EXT_TYPE_SZ;
17244            c16toa(0, output + offset);
17245            offset += HELLO_EXT_SZ_SZ;
17246        }
17247#endif
17248
17249        if (offset > OPAQUE16_LEN || msgType != server_hello)
17250            c16toa(offset - OPAQUE16_LEN, output); /* extensions length */
17251    }
17252
17253    if (pOffset)
17254        *pOffset += offset;
17255
17256    return ret;
17257}
17258
17259#endif /* WOLFSSL_TLS13 || !NO_WOLFSSL_SERVER */
17260
17261#ifdef WOLFSSL_TLS13
17262int TLSX_ParseVersion(WOLFSSL* ssl, const byte* input, word16 length,
17263                      byte msgType, int* found)
17264{
17265    int ret = 0;
17266    int offset = 0;
17267
17268    *found = 0;
17269    while (offset < (int)length) {
17270        word16 type;
17271        word16 size;
17272
17273        if (offset + (2 * OPAQUE16_LEN) > length) {
17274            ret = BUFFER_ERROR;
17275            break;
17276        }
17277
17278        ato16(input + offset, &type);
17279        offset += HELLO_EXT_TYPE_SZ;
17280
17281        ato16(input + offset, &size);
17282        offset += OPAQUE16_LEN;
17283
17284        if (offset + size > length) {
17285            ret = BUFFER_ERROR;
17286            break;
17287        }
17288
17289        if (type == TLSX_SUPPORTED_VERSIONS) {
17290            *found = 1;
17291
17292            WOLFSSL_MSG("Supported Versions extension received");
17293
17294            ret = SV_PARSE(ssl, input + offset, size, msgType, &ssl->version,
17295                           &ssl->options, &ssl->extensions);
17296            break;
17297        }
17298
17299        offset += size;
17300    }
17301
17302    return ret;
17303}
17304#endif
17305/* Jump Table to check minimum size values for client case in TLSX_Parse */
17306#ifndef NO_WOLFSSL_SERVER
17307static word16 TLSX_GetMinSize_Client(word16* type)
17308{
17309    switch (*type) {
17310        case TLSXT_SERVER_NAME:
17311            return WOLFSSL_SNI_MIN_SIZE_CLIENT;
17312        case TLSXT_EARLY_DATA:
17313            return WOLFSSL_EDI_MIN_SIZE_CLIENT;
17314        case TLSXT_MAX_FRAGMENT_LENGTH:
17315            return WOLFSSL_MFL_MIN_SIZE_CLIENT;
17316        case TLSXT_TRUSTED_CA_KEYS:
17317            return WOLFSSL_TCA_MIN_SIZE_CLIENT;
17318        case TLSXT_TRUNCATED_HMAC:
17319            return WOLFSSL_THM_MIN_SIZE_CLIENT;
17320        case TLSXT_STATUS_REQUEST:
17321            return WOLFSSL_CSR_MIN_SIZE_CLIENT;
17322        case TLSXT_SUPPORTED_GROUPS:
17323            return WOLFSSL_EC_MIN_SIZE_CLIENT;
17324        case TLSXT_EC_POINT_FORMATS:
17325            return WOLFSSL_PF_MIN_SIZE_CLIENT;
17326        case TLSXT_SIGNATURE_ALGORITHMS:
17327            return WOLFSSL_SA_MIN_SIZE_CLIENT;
17328        case TLSXT_USE_SRTP:
17329            return WOLFSSL_SRTP_MIN_SIZE_CLIENT;
17330        case TLSXT_APPLICATION_LAYER_PROTOCOL:
17331            return WOLFSSL_ALPN_MIN_SIZE_CLIENT;
17332        case TLSXT_STATUS_REQUEST_V2:
17333            return WOLFSSL_CSR2_MIN_SIZE_CLIENT;
17334        case TLSXT_CLIENT_CERTIFICATE:
17335            return WOLFSSL_CCT_MIN_SIZE_CLIENT;
17336        case TLSXT_SERVER_CERTIFICATE:
17337            return WOLFSSL_SCT_MIN_SIZE_CLIENT;
17338        case TLSXT_ENCRYPT_THEN_MAC:
17339            return WOLFSSL_ETM_MIN_SIZE_CLIENT;
17340        case TLSXT_SESSION_TICKET:
17341            return WOLFSSL_STK_MIN_SIZE_CLIENT;
17342        case TLSXT_PRE_SHARED_KEY:
17343            return WOLFSSL_PSK_MIN_SIZE_CLIENT;
17344        case TLSXT_COOKIE:
17345            return WOLFSSL_CKE_MIN_SIZE_CLIENT;
17346        case TLSXT_PSK_KEY_EXCHANGE_MODES:
17347            return WOLFSSL_PKM_MIN_SIZE_CLIENT;
17348        case TLSXT_CERT_WITH_EXTERN_PSK:
17349            return WOLFSSL_CWEP_MIN_SIZE_CLIENT;
17350        case TLSXT_CERTIFICATE_AUTHORITIES:
17351            return WOLFSSL_CAN_MIN_SIZE_CLIENT;
17352        case TLSXT_POST_HANDSHAKE_AUTH:
17353            return WOLFSSL_PHA_MIN_SIZE_CLIENT;
17354        case TLSXT_SIGNATURE_ALGORITHMS_CERT:
17355            return WOLFSSL_SA_MIN_SIZE_CLIENT;
17356        case TLSXT_KEY_SHARE:
17357            return WOLFSSL_KS_MIN_SIZE_CLIENT;
17358        case TLSXT_CONNECTION_ID:
17359            return WOLFSSL_CID_MIN_SIZE_CLIENT;
17360        case TLSXT_RENEGOTIATION_INFO:
17361            return WOLFSSL_SCR_MIN_SIZE_CLIENT;
17362        case TLSXT_KEY_QUIC_TP_PARAMS_DRAFT:
17363            return WOLFSSL_QTP_MIN_SIZE_CLIENT;
17364        case TLSXT_ECH:
17365            return WOLFSSL_ECH_MIN_SIZE_CLIENT;
17366        default:
17367            return 0;
17368    }
17369}
17370    #define TLSX_GET_MIN_SIZE_CLIENT(type) TLSX_GetMinSize_Client(type)
17371#else
17372    #define TLSX_GET_MIN_SIZE_CLIENT(type) 0
17373#endif
17374
17375
17376#ifndef NO_WOLFSSL_CLIENT
17377/* Jump Table to check minimum size values for server case in TLSX_Parse */
17378static word16 TLSX_GetMinSize_Server(const word16 *type)
17379{
17380    switch (*type) {
17381        case TLSXT_SERVER_NAME:
17382            return WOLFSSL_SNI_MIN_SIZE_SERVER;
17383        case TLSXT_EARLY_DATA:
17384            return WOLFSSL_EDI_MIN_SIZE_SERVER;
17385        case TLSXT_MAX_FRAGMENT_LENGTH:
17386            return WOLFSSL_MFL_MIN_SIZE_SERVER;
17387        case TLSXT_TRUSTED_CA_KEYS:
17388            return WOLFSSL_TCA_MIN_SIZE_SERVER;
17389        case TLSXT_TRUNCATED_HMAC:
17390            return WOLFSSL_THM_MIN_SIZE_SERVER;
17391        case TLSXT_STATUS_REQUEST:
17392            return WOLFSSL_CSR_MIN_SIZE_SERVER;
17393        case TLSXT_SUPPORTED_GROUPS:
17394            return WOLFSSL_EC_MIN_SIZE_SERVER;
17395        case TLSXT_EC_POINT_FORMATS:
17396            return WOLFSSL_PF_MIN_SIZE_SERVER;
17397        case TLSXT_SIGNATURE_ALGORITHMS:
17398            return WOLFSSL_SA_MIN_SIZE_SERVER;
17399        case TLSXT_USE_SRTP:
17400            return WOLFSSL_SRTP_MIN_SIZE_SERVER;
17401        case TLSXT_APPLICATION_LAYER_PROTOCOL:
17402            return WOLFSSL_ALPN_MIN_SIZE_SERVER;
17403        case TLSXT_STATUS_REQUEST_V2:
17404            return WOLFSSL_CSR2_MIN_SIZE_SERVER;
17405        case TLSXT_CLIENT_CERTIFICATE:
17406            return WOLFSSL_CCT_MIN_SIZE_SERVER;
17407        case TLSXT_SERVER_CERTIFICATE:
17408            return WOLFSSL_SCT_MIN_SIZE_SERVER;
17409        case TLSXT_ENCRYPT_THEN_MAC:
17410            return WOLFSSL_ETM_MIN_SIZE_SERVER;
17411        case TLSXT_SESSION_TICKET:
17412            return WOLFSSL_STK_MIN_SIZE_SERVER;
17413        case TLSXT_PRE_SHARED_KEY:
17414            return WOLFSSL_PSK_MIN_SIZE_SERVER;
17415        case TLSXT_COOKIE:
17416            return WOLFSSL_CKE_MIN_SIZE_SERVER;
17417        case TLSXT_PSK_KEY_EXCHANGE_MODES:
17418            return WOLFSSL_PKM_MIN_SIZE_SERVER;
17419        case TLSXT_CERT_WITH_EXTERN_PSK:
17420            return WOLFSSL_CWEP_MIN_SIZE_SERVER;
17421        case TLSXT_CERTIFICATE_AUTHORITIES:
17422            return WOLFSSL_CAN_MIN_SIZE_SERVER;
17423        case TLSXT_POST_HANDSHAKE_AUTH:
17424            return WOLFSSL_PHA_MIN_SIZE_SERVER;
17425        case TLSXT_SIGNATURE_ALGORITHMS_CERT:
17426            return WOLFSSL_SA_MIN_SIZE_SERVER;
17427        case TLSXT_KEY_SHARE:
17428            return WOLFSSL_KS_MIN_SIZE_SERVER;
17429        case TLSXT_CONNECTION_ID:
17430            return WOLFSSL_CID_MIN_SIZE_SERVER;
17431        case TLSXT_RENEGOTIATION_INFO:
17432            return WOLFSSL_SCR_MIN_SIZE_SERVER;
17433        case TLSXT_KEY_QUIC_TP_PARAMS_DRAFT:
17434            return WOLFSSL_QTP_MIN_SIZE_SERVER;
17435        case TLSXT_ECH:
17436            return WOLFSSL_ECH_MIN_SIZE_SERVER;
17437        default:
17438            return 0;
17439    }
17440}
17441    #define TLSX_GET_MIN_SIZE_SERVER(type) TLSX_GetMinSize_Server(type)
17442#else
17443    #define TLSX_GET_MIN_SIZE_SERVER(type) 0
17444#endif
17445
17446
17447/** Parses a buffer of TLS extensions. */
17448WOLFSSL_TEST_VIS int TLSX_Parse(WOLFSSL* ssl, const byte* input, word16 length,
17449                                byte msgType, Suites *suites)
17450{
17451    int ret = 0;
17452    word16 offset = 0;
17453    byte isRequest = (msgType == client_hello ||
17454                      msgType == certificate_request);
17455
17456#ifdef HAVE_EXTENDED_MASTER
17457    byte pendingEMS = 0;
17458#endif
17459#if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK))
17460    int pskDone = 0;
17461#endif
17462#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_CERT_WITH_EXTERN_PSK) && \
17463    !defined(NO_PSK)
17464    int secondClientHello = 0;
17465    int prevHasPskWithCert = 0;
17466#endif
17467    byte seenType[SEMAPHORE_SIZE];  /* Seen known extensions. */
17468
17469    if (!ssl || !input || (isRequest && !suites))
17470        return BAD_FUNC_ARG;
17471
17472    /* No known extensions seen yet. */
17473    XMEMSET(seenType, 0, sizeof(seenType));
17474#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_CERT_WITH_EXTERN_PSK) && \
17475    !defined(NO_PSK)
17476    if (IsAtLeastTLSv1_3(ssl->version) && msgType == client_hello &&
17477            ssl->msgsReceived.got_client_hello == 2) {
17478        secondClientHello = 1;
17479        prevHasPskWithCert =
17480            TLSX_Find(ssl->extensions, TLSX_CERT_WITH_EXTERN_PSK) != NULL;
17481    }
17482#endif
17483
17484    while (ret == 0 && offset < length) {
17485        word16 type;
17486        word16 size;
17487
17488#if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK))
17489        if (msgType == client_hello && pskDone) {
17490            WOLFSSL_ERROR_VERBOSE(PSK_KEY_ERROR);
17491            return PSK_KEY_ERROR;
17492        }
17493#endif
17494
17495        if (length - offset < HELLO_EXT_TYPE_SZ + OPAQUE16_LEN)
17496            return BUFFER_ERROR;
17497
17498        ato16(input + offset, &type);
17499        offset += HELLO_EXT_TYPE_SZ;
17500
17501        ato16(input + offset, &size);
17502        offset += OPAQUE16_LEN;
17503
17504        /* Check we have a bit for extension type. */
17505        if ((type <= 62) || (type == TLSX_RENEGOTIATION_INFO)
17506        #ifdef WOLFSSL_QUIC
17507            || (type == TLSX_KEY_QUIC_TP_PARAMS_DRAFT)
17508        #endif
17509        #if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
17510            || (type == TLSX_ECH)
17511        #endif
17512        #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_DUAL_ALG_CERTS)
17513            || (type == TLSX_CKS)
17514        #endif
17515            )
17516        {
17517            /* Detect duplicate recognized extensions. */
17518            if (IS_OFF(seenType, TLSX_ToSemaphore(type))) {
17519                TURN_ON(seenType, TLSX_ToSemaphore(type));
17520            }
17521            else {
17522                return DUPLICATE_TLS_EXT_E;
17523            }
17524        }
17525
17526        if (length - offset < size)
17527            return BUFFER_ERROR;
17528
17529        /* Check minimum size required for TLSX, even if disabled */
17530        switch (msgType) {
17531            #ifndef NO_WOLFSSL_SERVER
17532            case client_hello:
17533                if (size < TLSX_GET_MIN_SIZE_CLIENT(&type)){
17534                    WOLFSSL_MSG("Minimum TLSX Size Requirement not Satisfied");
17535                    return BUFFER_ERROR;
17536                }
17537            break;
17538            #endif
17539            #ifndef NO_WOLFSSL_CLIENT
17540            case server_hello:
17541            case hello_retry_request:
17542                if (size < TLSX_GET_MIN_SIZE_SERVER(&type)){
17543                    WOLFSSL_MSG("Minimum TLSX Size Requirement not Satisfied");
17544                    return BUFFER_ERROR;
17545                }
17546            break;
17547            #endif
17548            default:
17549            break;
17550        }
17551
17552#ifdef WOLFSSL_TLS13
17553        /* RFC 8446 4.4.2: extensions in a Certificate message MUST
17554         * correspond to ones offered in our prior ClientHello (client) or
17555         * CertificateRequest (server). Reject anything we did not offer. */
17556        if (msgType == certificate &&
17557            IsAtLeastTLSv1_3(ssl->version) &&
17558            TLSX_Find(ssl->extensions, (TLSX_Type)type) == NULL) {
17559            WOLFSSL_MSG("Cert-msg extension not offered in CH/CR");
17560            SendAlert(ssl, alert_fatal, unsupported_extension);
17561            WOLFSSL_ERROR_VERBOSE(UNSUPPORTED_EXTENSION);
17562            return UNSUPPORTED_EXTENSION;
17563        }
17564#endif
17565
17566        switch (type) {
17567#ifdef HAVE_SNI
17568            case TLSX_SERVER_NAME:
17569                WOLFSSL_MSG("SNI extension received");
17570            #ifdef WOLFSSL_DEBUG_TLS
17571                WOLFSSL_BUFFER(input + offset, size);
17572            #endif
17573
17574#ifdef WOLFSSL_TLS13
17575                if (IsAtLeastTLSv1_3(ssl->version)) {
17576                    if (msgType != client_hello &&
17577                        msgType != encrypted_extensions)
17578                        return EXT_NOT_ALLOWED;
17579                }
17580                else
17581#endif
17582                {
17583                    if (msgType != client_hello &&
17584                        msgType != server_hello)
17585                        return EXT_NOT_ALLOWED;
17586                }
17587                ret = SNI_PARSE(ssl, input + offset, size, isRequest);
17588                break;
17589#endif
17590
17591            case TLSX_TRUSTED_CA_KEYS:
17592                WOLFSSL_MSG("Trusted CA extension received");
17593            #ifdef WOLFSSL_DEBUG_TLS
17594                WOLFSSL_BUFFER(input + offset, size);
17595            #endif
17596
17597#ifdef WOLFSSL_TLS13
17598                /* RFC 8446 4.2.4 states trusted_ca_keys is not used
17599                   in TLS 1.3. */
17600                if (IsAtLeastTLSv1_3(ssl->version)) {
17601                    break;
17602                }
17603                else
17604#endif
17605                {
17606                    if (msgType != client_hello &&
17607                        msgType != server_hello)
17608                        return EXT_NOT_ALLOWED;
17609                }
17610                ret = TCA_PARSE(ssl, input + offset, size, isRequest);
17611                break;
17612
17613            case TLSX_MAX_FRAGMENT_LENGTH:
17614                WOLFSSL_MSG("Max Fragment Length extension received");
17615            #ifdef WOLFSSL_DEBUG_TLS
17616                WOLFSSL_BUFFER(input + offset, size);
17617            #endif
17618
17619#ifdef WOLFSSL_TLS13
17620                if (IsAtLeastTLSv1_3(ssl->version)) {
17621                    if (msgType != client_hello &&
17622                        msgType != encrypted_extensions) {
17623                        WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
17624                        return EXT_NOT_ALLOWED;
17625                    }
17626                }
17627                else
17628#endif
17629                {
17630                    if (msgType != client_hello &&
17631                        msgType != server_hello) {
17632                        WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
17633                        return EXT_NOT_ALLOWED;
17634                    }
17635                }
17636                ret = MFL_PARSE(ssl, input + offset, size, isRequest);
17637                break;
17638
17639            case TLSX_TRUNCATED_HMAC:
17640                WOLFSSL_MSG("Truncated HMAC extension received");
17641            #ifdef WOLFSSL_DEBUG_TLS
17642                WOLFSSL_BUFFER(input + offset, size);
17643            #endif
17644
17645#ifdef WOLFSSL_TLS13
17646                if (IsAtLeastTLSv1_3(ssl->version))
17647                    break;
17648#endif
17649                if (msgType != client_hello)
17650                    return EXT_NOT_ALLOWED;
17651                ret = THM_PARSE(ssl, input + offset, size, isRequest);
17652                break;
17653
17654            case TLSX_SUPPORTED_GROUPS:
17655                WOLFSSL_MSG("Supported Groups extension received");
17656            #ifdef WOLFSSL_DEBUG_TLS
17657                WOLFSSL_BUFFER(input + offset, size);
17658            #endif
17659
17660#ifdef WOLFSSL_TLS13
17661                if (IsAtLeastTLSv1_3(ssl->version)) {
17662                    if (msgType != client_hello &&
17663                        msgType != encrypted_extensions) {
17664                        WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
17665                        return EXT_NOT_ALLOWED;
17666                    }
17667                }
17668                else
17669#endif
17670                {
17671                    if (msgType != client_hello) {
17672                        WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
17673                        return EXT_NOT_ALLOWED;
17674                    }
17675                }
17676                ret = EC_PARSE(ssl, input + offset, size, isRequest,
17677                        &ssl->extensions);
17678                break;
17679#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_DUAL_ALG_CERTS)
17680            case TLSX_CKS:
17681                WOLFSSL_MSG("CKS extension received");
17682                if (msgType != client_hello &&
17683                     msgType != encrypted_extensions) {
17684                        WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
17685                        return EXT_NOT_ALLOWED;
17686                }
17687                ret = TLSX_CKS_Parse(ssl, (byte *)(input + offset), size,
17688                                     &ssl->extensions);
17689            break;
17690#endif /* WOLFSSL_DUAL_ALG_CERTS */
17691            case TLSX_EC_POINT_FORMATS:
17692                WOLFSSL_MSG("Point Formats extension received");
17693            #ifdef WOLFSSL_DEBUG_TLS
17694                WOLFSSL_BUFFER(input + offset, size);
17695            #endif
17696
17697#ifdef WOLFSSL_TLS13
17698                if (IsAtLeastTLSv1_3(ssl->version))
17699                    break;
17700#endif
17701                if (msgType != client_hello &&
17702                    msgType != server_hello) {
17703                    WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
17704                    return EXT_NOT_ALLOWED;
17705                }
17706
17707                ret = PF_PARSE(ssl, input + offset, size, isRequest);
17708                break;
17709
17710            case TLSX_STATUS_REQUEST:
17711                WOLFSSL_MSG("Certificate Status Request extension received");
17712            #ifdef WOLFSSL_DEBUG_TLS
17713                WOLFSSL_BUFFER(input + offset, size);
17714            #endif
17715
17716#ifdef WOLFSSL_TLS13
17717                if (IsAtLeastTLSv1_3(ssl->version)) {
17718                    if (msgType != client_hello &&
17719                        msgType != certificate_request &&
17720                        msgType != certificate)
17721                        return EXT_NOT_ALLOWED;
17722                }
17723                else
17724 #endif
17725                {
17726                    if (msgType != client_hello &&
17727                        msgType != server_hello)
17728                        return EXT_NOT_ALLOWED;
17729                }
17730                ret = CSR_PARSE(ssl, input + offset, size, isRequest);
17731                break;
17732
17733            case TLSX_STATUS_REQUEST_V2:
17734                WOLFSSL_MSG("Certificate Status Request v2 extension received");
17735            #ifdef WOLFSSL_DEBUG_TLS
17736                WOLFSSL_BUFFER(input + offset, size);
17737            #endif
17738
17739#if defined(WOLFSSL_TLS13) && defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
17740                if (IsAtLeastTLSv1_3(ssl->version)) {
17741                    if (msgType != client_hello &&
17742                        msgType != certificate_request &&
17743                        msgType != certificate)
17744                        return EXT_NOT_ALLOWED;
17745                }
17746                else
17747#endif
17748                {
17749                    if (msgType != client_hello &&
17750                        msgType != server_hello)
17751                        return EXT_NOT_ALLOWED;
17752                }
17753                ret = CSR2_PARSE(ssl, input + offset, size, isRequest);
17754                break;
17755
17756#ifdef HAVE_EXTENDED_MASTER
17757            case HELLO_EXT_EXTMS:
17758                WOLFSSL_MSG("Extended Master Secret extension received");
17759            #ifdef WOLFSSL_DEBUG_TLS
17760                WOLFSSL_BUFFER(input + offset, size);
17761            #endif
17762
17763#if defined(WOLFSSL_TLS13)
17764                if (IsAtLeastTLSv1_3(ssl->version))
17765                    break;
17766#endif
17767                if (msgType != client_hello &&
17768                    msgType != server_hello)
17769                    return EXT_NOT_ALLOWED;
17770                if (size != 0)
17771                    return BUFFER_ERROR;
17772
17773#ifndef NO_WOLFSSL_SERVER
17774                if (isRequest)
17775                    ssl->options.haveEMS = 1;
17776#endif
17777                pendingEMS = 1;
17778                break;
17779#endif
17780
17781            case TLSX_RENEGOTIATION_INFO:
17782                WOLFSSL_MSG("Secure Renegotiation extension received");
17783            #ifdef WOLFSSL_DEBUG_TLS
17784                WOLFSSL_BUFFER(input + offset, size);
17785            #endif
17786
17787#ifdef WOLFSSL_TLS13
17788                if (IsAtLeastTLSv1_3(ssl->version))
17789                    break;
17790#endif
17791                if (msgType != client_hello &&
17792                    msgType != server_hello)
17793                    return EXT_NOT_ALLOWED;
17794                ret = SCR_PARSE(ssl, input + offset, size, isRequest);
17795                break;
17796
17797            case TLSX_SESSION_TICKET:
17798                WOLFSSL_MSG("Session Ticket extension received");
17799            #ifdef WOLFSSL_DEBUG_TLS
17800                WOLFSSL_BUFFER(input + offset, size);
17801            #endif
17802
17803#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)
17804                if (IsAtLeastTLSv1_3(ssl->version)) {
17805                    if (msgType != client_hello)
17806                        return EXT_NOT_ALLOWED;
17807                }
17808                else
17809#endif
17810                {
17811                    if (msgType != client_hello &&
17812                        msgType != server_hello)
17813                        return EXT_NOT_ALLOWED;
17814                }
17815                ret = WOLF_STK_PARSE(ssl, input + offset, size, isRequest);
17816                break;
17817
17818            case TLSX_APPLICATION_LAYER_PROTOCOL:
17819                WOLFSSL_MSG("ALPN extension received");
17820
17821            #ifdef WOLFSSL_DEBUG_TLS
17822                WOLFSSL_BUFFER(input + offset, size);
17823            #endif
17824
17825#if defined(WOLFSSL_TLS13) && defined(HAVE_ALPN)
17826                if (IsAtLeastTLSv1_3(ssl->version)) {
17827                    if (msgType != client_hello &&
17828                        msgType != encrypted_extensions)
17829                        return EXT_NOT_ALLOWED;
17830                }
17831                else
17832#endif
17833                {
17834                    if (msgType != client_hello &&
17835                        msgType != server_hello)
17836                        return EXT_NOT_ALLOWED;
17837                }
17838                ret = ALPN_PARSE(ssl, input + offset, size, isRequest);
17839                break;
17840#if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
17841            case TLSX_SIGNATURE_ALGORITHMS:
17842                WOLFSSL_MSG("Signature Algorithms extension received");
17843            #ifdef WOLFSSL_DEBUG_TLS
17844                WOLFSSL_BUFFER(input + offset, size);
17845            #endif
17846
17847                if (!IsAtLeastTLSv1_2(ssl))
17848                    break;
17849            #ifdef WOLFSSL_TLS13
17850                if (IsAtLeastTLSv1_3(ssl->version)) {
17851                    if (msgType != client_hello &&
17852                        msgType != certificate_request)
17853                        return EXT_NOT_ALLOWED;
17854                }
17855                else
17856            #endif
17857                {
17858                    if (msgType != client_hello)
17859                        return EXT_NOT_ALLOWED;
17860                }
17861                ret = SA_PARSE(ssl, input + offset, size, isRequest, suites);
17862                break;
17863#endif
17864
17865#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
17866            case TLSX_ENCRYPT_THEN_MAC:
17867                WOLFSSL_MSG("Encrypt-Then-Mac extension received");
17868
17869                /* Ignore for TLS 1.3+ */
17870                if (IsAtLeastTLSv1_3(ssl->version))
17871                    break;
17872                if (msgType != client_hello &&
17873                    msgType != server_hello)
17874                    return EXT_NOT_ALLOWED;
17875
17876                ret = ETM_PARSE(ssl, input + offset, size, msgType);
17877                break;
17878#endif /* HAVE_ENCRYPT_THEN_MAC */
17879
17880#ifdef WOLFSSL_TLS13
17881            case TLSX_SUPPORTED_VERSIONS:
17882                WOLFSSL_MSG("Skipping Supported Versions - already processed");
17883            #ifdef WOLFSSL_DEBUG_TLS
17884                WOLFSSL_BUFFER(input + offset, size);
17885            #endif
17886                if (msgType != client_hello &&
17887                    msgType != server_hello &&
17888                    msgType != hello_retry_request)
17889                    return EXT_NOT_ALLOWED;
17890
17891                break;
17892
17893            case TLSX_COOKIE:
17894                WOLFSSL_MSG("Cookie extension received");
17895            #ifdef WOLFSSL_DEBUG_TLS
17896                WOLFSSL_BUFFER(input + offset, size);
17897            #endif
17898                if (!IsAtLeastTLSv1_3(ssl->version))
17899                    break;
17900
17901                if (msgType != client_hello &&
17902                    msgType != hello_retry_request) {
17903                    return EXT_NOT_ALLOWED;
17904                }
17905
17906                ret = CKE_PARSE(ssl, input + offset, size, msgType);
17907                break;
17908
17909    #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
17910            case TLSX_PRE_SHARED_KEY:
17911                WOLFSSL_MSG("Pre-Shared Key extension received");
17912            #ifdef WOLFSSL_DEBUG_TLS
17913                WOLFSSL_BUFFER(input + offset, size);
17914            #endif
17915
17916                if (!IsAtLeastTLSv1_3(ssl->version))
17917                    break;
17918
17919                if (msgType != client_hello &&
17920                    msgType != server_hello) {
17921                    WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
17922                    return EXT_NOT_ALLOWED;
17923                }
17924
17925                ret = PSK_PARSE(ssl, input + offset, size, msgType);
17926                pskDone = 1;
17927                break;
17928
17929            case TLSX_PSK_KEY_EXCHANGE_MODES:
17930                WOLFSSL_MSG("PSK Key Exchange Modes extension received");
17931            #ifdef WOLFSSL_DEBUG_TLS
17932                WOLFSSL_BUFFER(input + offset, size);
17933            #endif
17934
17935                if (!IsAtLeastTLSv1_3(ssl->version))
17936                    break;
17937
17938                if (msgType != client_hello) {
17939                    WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
17940                    return EXT_NOT_ALLOWED;
17941                }
17942
17943                ret = PKM_PARSE(ssl, input + offset, size, msgType);
17944                break;
17945
17946    #ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
17947            case TLSX_CERT_WITH_EXTERN_PSK:
17948                WOLFSSL_MSG("Cert with external PSK extension received");
17949            #ifdef WOLFSSL_DEBUG_TLS
17950                WOLFSSL_BUFFER(input + offset, size);
17951            #endif
17952
17953                if (!IsAtLeastTLSv1_3(ssl->version))
17954                    break;
17955
17956                if (msgType != client_hello && msgType != server_hello) {
17957                    WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
17958                    return EXT_NOT_ALLOWED;
17959                }
17960                if (size != 0) {
17961                    WOLFSSL_ERROR_VERBOSE(BUFFER_ERROR);
17962                    return BUFFER_ERROR;
17963                }
17964
17965                ret = PSK_WITH_CERT_PARSE(ssl, msgType);
17966                break;
17967    #endif
17968    #endif
17969
17970    #ifdef WOLFSSL_EARLY_DATA
17971            case TLSX_EARLY_DATA:
17972                WOLFSSL_MSG("Early Data extension received");
17973            #ifdef WOLFSSL_DEBUG_TLS
17974                WOLFSSL_BUFFER(input + offset, size);
17975            #endif
17976
17977                if (!IsAtLeastTLSv1_3(ssl->version))
17978                    break;
17979
17980                if (msgType != client_hello && msgType != session_ticket &&
17981                    msgType != encrypted_extensions) {
17982                    WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
17983                    return EXT_NOT_ALLOWED;
17984                }
17985                ret = EDI_PARSE(ssl, input + offset, size, msgType);
17986                break;
17987    #endif
17988
17989    #ifdef WOLFSSL_POST_HANDSHAKE_AUTH
17990            case TLSX_POST_HANDSHAKE_AUTH:
17991                WOLFSSL_MSG("Post Handshake Authentication extension received");
17992            #ifdef WOLFSSL_DEBUG_TLS
17993                WOLFSSL_BUFFER(input + offset, size);
17994            #endif
17995
17996                if (!IsAtLeastTLSv1_3(ssl->version))
17997                    break;
17998
17999                if (msgType != client_hello) {
18000                    WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
18001                    return EXT_NOT_ALLOWED;
18002                }
18003
18004                ret = PHA_PARSE(ssl, input + offset, size, msgType);
18005                break;
18006    #endif
18007
18008    #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG)
18009            case TLSX_SIGNATURE_ALGORITHMS_CERT:
18010                WOLFSSL_MSG("Signature Algorithms extension received");
18011            #ifdef WOLFSSL_DEBUG_TLS
18012                WOLFSSL_BUFFER(input + offset, size);
18013            #endif
18014
18015                if (!IsAtLeastTLSv1_3(ssl->version))
18016                    break;
18017
18018                if (msgType != client_hello &&
18019                        msgType != certificate_request) {
18020                    WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
18021                    return EXT_NOT_ALLOWED;
18022                }
18023
18024                ret = SAC_PARSE(ssl, input + offset, size, isRequest);
18025                break;
18026    #endif
18027
18028    #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES)
18029            case TLSX_CERTIFICATE_AUTHORITIES:
18030                WOLFSSL_MSG("Certificate Authorities extension received");
18031            #ifdef WOLFSSL_DEBUG_TLS
18032                WOLFSSL_BUFFER(input + offset, size);
18033            #endif
18034
18035                if (!IsAtLeastTLSv1_3(ssl->version))
18036                    break;
18037
18038                if (msgType != client_hello &&
18039                        msgType != certificate_request) {
18040                    WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
18041                    return EXT_NOT_ALLOWED;
18042                }
18043
18044                ret = CAN_PARSE(ssl, input + offset, size, isRequest);
18045                break;
18046    #endif
18047
18048            case TLSX_KEY_SHARE:
18049                WOLFSSL_MSG("Key Share extension received");
18050            #ifdef WOLFSSL_DEBUG_TLS
18051                WOLFSSL_BUFFER(input + offset, size);
18052            #endif
18053
18054    #ifdef HAVE_SUPPORTED_CURVES
18055                if (!IsAtLeastTLSv1_3(ssl->version))
18056                    break;
18057
18058                if (msgType != client_hello && msgType != server_hello &&
18059                        msgType != hello_retry_request) {
18060                    WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
18061                    return EXT_NOT_ALLOWED;
18062                }
18063    #endif
18064
18065                ret = KS_PARSE(ssl, input + offset, size, msgType);
18066                break;
18067#endif
18068#ifdef WOLFSSL_SRTP
18069            case TLSX_USE_SRTP:
18070                WOLFSSL_MSG("Use SRTP extension received");
18071
18072#if defined(WOLFSSL_TLS13)
18073                if (IsAtLeastTLSv1_3(ssl->version)) {
18074                    if (msgType != client_hello &&
18075                        msgType != encrypted_extensions)
18076                        return EXT_NOT_ALLOWED;
18077                }
18078                else
18079#endif
18080                {
18081                    if (msgType != client_hello &&
18082                        msgType != server_hello)
18083                        return EXT_NOT_ALLOWED;
18084                }
18085                ret = SRTP_PARSE(ssl, input + offset, size, isRequest);
18086                break;
18087#endif
18088#ifdef WOLFSSL_QUIC
18089            case TLSX_KEY_QUIC_TP_PARAMS:
18090                FALL_THROUGH;
18091            case TLSX_KEY_QUIC_TP_PARAMS_DRAFT:
18092                WOLFSSL_MSG("QUIC transport parameter received");
18093            #ifdef WOLFSSL_DEBUG_TLS
18094                WOLFSSL_BUFFER(input + offset, size);
18095            #endif
18096
18097                if (IsAtLeastTLSv1_3(ssl->version) &&
18098                        msgType != client_hello &&
18099                        msgType != encrypted_extensions) {
18100                    return EXT_NOT_ALLOWED;
18101                }
18102                else if (!IsAtLeastTLSv1_3(ssl->version) &&
18103                         msgType == encrypted_extensions) {
18104                    return EXT_NOT_ALLOWED;
18105                }
18106                else if (WOLFSSL_IS_QUIC(ssl)) {
18107                    ret = QTP_PARSE(ssl, input + offset, size, type, msgType);
18108                }
18109                else {
18110                    WOLFSSL_MSG("QUIC transport param TLS extension type, but no QUIC");
18111                    return EXT_NOT_ALLOWED; /* be safe, this should not happen */
18112                }
18113                break;
18114#endif /* WOLFSSL_QUIC */
18115#if defined(WOLFSSL_DTLS_CID)
18116            case TLSX_CONNECTION_ID:
18117                if (msgType != client_hello && msgType != server_hello)
18118                    return EXT_NOT_ALLOWED;
18119
18120                WOLFSSL_MSG("ConnectionID extension received");
18121                ret = CID_PARSE(ssl, input + offset, size, isRequest);
18122                break;
18123
18124#endif /* defined(WOLFSSL_DTLS_CID) */
18125#if defined(HAVE_RPK)
18126            case TLSX_CLIENT_CERTIFICATE_TYPE:
18127                WOLFSSL_MSG("Client Certificate Type extension received");
18128#if defined(WOLFSSL_TLS13)
18129                /* RFC 8446, Section 4.2 (Extensions), client_certificate_type
18130                   and server_certificate_type MUST be sent in ClientHello(CH)
18131                   or EncryptedExtensions(EE) */
18132                if (IsAtLeastTLSv1_3(ssl->version)) {
18133                    if (msgType != client_hello &&
18134                        msgType != encrypted_extensions) {
18135                        WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
18136                        return EXT_NOT_ALLOWED;
18137                    }
18138                }
18139                else
18140#endif
18141                {
18142                    /* TLS 1.2: allowed in CH and SH (RFC 7250) */
18143                    if (msgType != client_hello &&
18144                        msgType != server_hello) {
18145                        WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
18146                        return EXT_NOT_ALLOWED;
18147                    }
18148                }
18149                ret = CCT_PARSE(ssl, input + offset, size, msgType);
18150                break;
18151
18152            case TLSX_SERVER_CERTIFICATE_TYPE:
18153                WOLFSSL_MSG("Server Certificate Type extension received");
18154#if defined(WOLFSSL_TLS13)
18155                /* RFC 8446, Section 4.2 (Extensions) */
18156                if (IsAtLeastTLSv1_3(ssl->version)) {
18157                    if (msgType != client_hello &&
18158                        msgType != encrypted_extensions) {
18159                        WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
18160                        return EXT_NOT_ALLOWED;
18161                    }
18162                }
18163                else
18164#endif
18165                {
18166                    /* TLS 1.2: allowed in CH and SH (RFC 7250) */
18167                    if (msgType != client_hello &&
18168                        msgType != server_hello) {
18169                        WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
18170                        return EXT_NOT_ALLOWED;
18171                    }
18172                }
18173                ret = SCT_PARSE(ssl, input + offset, size, msgType);
18174                break;
18175#endif /* HAVE_RPK */
18176#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
18177            case TLSX_ECH:
18178                WOLFSSL_MSG("ECH extension received");
18179                if (!IsAtLeastTLSv1_3(ssl->version))
18180                    break;
18181
18182                if (msgType != client_hello &&
18183                    msgType != encrypted_extensions &&
18184                    msgType != hello_retry_request) {
18185                    return EXT_NOT_ALLOWED;
18186                }
18187
18188                ret = ECH_PARSE(ssl, input + offset, size, msgType);
18189                break;
18190            case TLSXT_ECH_OUTER_EXTENSIONS:
18191                /* RFC 9849 s5.1: ech_outer_extensions MUST only appear in
18192                 * the EncodedClientHelloInner */
18193                WOLFSSL_MSG("ech_outer_extensions in plaintext message");
18194                WOLFSSL_ERROR_VERBOSE(INVALID_PARAMETER);
18195                return INVALID_PARAMETER;
18196#endif
18197            default:
18198                WOLFSSL_MSG("Unknown TLS extension type");
18199#if defined(WOLFSSL_TLS13)
18200                /* RFC 8446 Sec. 4.2: a TLS 1.3 client MUST abort with an
18201                 * unsupported_extension alert when it receives an extension
18202                 * "response" that was not advertised in the ClientHello. The
18203                 * rule applies only to messages whose extensions are responses
18204                 * to the ClientHello: ServerHello, HelloRetryRequest,
18205                 * EncryptedExtensions and Certificate.
18206                 *
18207                 * Extensions in CertificateRequest and NewSessionTicket are
18208                 * independent server-initiated payloads, not responses, and
18209                 * per RFC 8701 (GREASE) the server MAY include unknown
18210                 * (GREASE) extension types there which the client MUST treat
18211                 * like any other unknown value (i.e. ignore them). */
18212                if (IsAtLeastTLSv1_3(ssl->version) &&
18213                        (msgType == server_hello ||
18214                         msgType == hello_retry_request ||
18215                         msgType == encrypted_extensions ||
18216                         msgType == certificate)) {
18217                    SendAlert((WOLFSSL*)ssl, alert_fatal, unsupported_extension);
18218                    WOLFSSL_ERROR_VERBOSE(UNSUPPORTED_EXTENSION);
18219                    return UNSUPPORTED_EXTENSION;
18220                }
18221#endif
18222        }
18223
18224        /* offset should be updated here! */
18225        offset += size;
18226    }
18227
18228#ifdef HAVE_EXTENDED_MASTER
18229    if (IsAtLeastTLSv1_3(ssl->version) &&
18230        (msgType == hello_retry_request || msgType == hello_verify_request)) {
18231        /* Don't change EMS status until server_hello received.
18232         * Second ClientHello must have same extensions.
18233         */
18234    }
18235    else if (!isRequest && ssl->options.haveEMS && !pendingEMS)
18236        ssl->options.haveEMS = 0;
18237#endif
18238#if defined(WOLFSSL_TLS13) && !defined(NO_PSK)
18239    if (IsAtLeastTLSv1_3(ssl->version) && msgType == server_hello &&
18240        IS_OFF(seenType, TLSX_ToSemaphore(TLSX_KEY_SHARE))) {
18241        ssl->options.noPskDheKe = 1;
18242    }
18243#endif
18244#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_CERT_WITH_EXTERN_PSK) && \
18245    !defined(NO_PSK)
18246    if (IsAtLeastTLSv1_3(ssl->version)) {
18247        int hasPskWithCert = !IS_OFF(seenType,
18248            TLSX_ToSemaphore(TLSX_CERT_WITH_EXTERN_PSK));
18249        if (hasPskWithCert && ssl->options.certWithExternPsk) {
18250            int hasPsk = !IS_OFF(seenType, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
18251            int hasPskModes = !IS_OFF(seenType,
18252                TLSX_ToSemaphore(TLSX_PSK_KEY_EXCHANGE_MODES));
18253            int hasKeyShare = !IS_OFF(seenType, TLSX_ToSemaphore(TLSX_KEY_SHARE));
18254            int hasSg = !IS_OFF(seenType,
18255                TLSX_ToSemaphore(TLSX_SUPPORTED_GROUPS));
18256            int hasSigAlg = !IS_OFF(seenType,
18257                TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS));
18258#ifdef WOLFSSL_EARLY_DATA
18259            int hasEarlyData = !IS_OFF(seenType, TLSX_ToSemaphore(TLSX_EARLY_DATA));
18260#endif
18261
18262            if (msgType == client_hello && isRequest) {
18263                TLSX* pskm;
18264                /* RFC8773bis: CH2 after HRR must keep CH1's extension set. */
18265                if (secondClientHello && !prevHasPskWithCert) {
18266                    WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
18267                    return EXT_NOT_ALLOWED;
18268                }
18269                /* RFC8773bis: cert_with_extern_psk depends on these extensions. */
18270                if (!hasPsk || !hasPskModes || !hasKeyShare || !hasSg ||
18271                    !hasSigAlg) {
18272                    WOLFSSL_ERROR_VERBOSE(EXT_MISSING);
18273                    return EXT_MISSING;
18274                }
18275#ifdef WOLFSSL_EARLY_DATA
18276                /* External PSK + certificate mode forbids 0-RTT in CH.
18277                 * When WOLFSSL_EARLY_DATA is not defined there is no parser
18278                 * case for TLSX_EARLY_DATA, so an incoming early_data
18279                 * extension is treated as unknown and ignored per RFC 8446
18280                 * Sect. 4.2 - no additional check is needed in that case. */
18281                if (hasEarlyData) {
18282                    WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
18283                    return EXT_NOT_ALLOWED;
18284                }
18285#endif
18286                pskm = TLSX_Find(ssl->extensions, TLSX_PSK_KEY_EXCHANGE_MODES);
18287                /* RFC8773bis requires client support for psk_dhe_ke mode. */
18288                if (pskm == NULL || (pskm->val & (1 << PSK_DHE_KE)) == 0) {
18289                    WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
18290                    return EXT_NOT_ALLOWED;
18291                }
18292            }
18293            else if (msgType == server_hello && !isRequest) {
18294                /* SH confirming cert_with_extern_psk must also confirm PSK and KSE. */
18295                if (!hasPsk || !hasKeyShare) {
18296                    WOLFSSL_ERROR_VERBOSE(EXT_MISSING);
18297                    return EXT_MISSING;
18298                }
18299            }
18300        }
18301        else if (msgType == client_hello && isRequest && secondClientHello &&
18302                prevHasPskWithCert) {
18303            /* RFC8773bis: reject dropping the extension in CH2 after HRR. */
18304            WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
18305            return EXT_NOT_ALLOWED;
18306        }
18307    }
18308#endif
18309#if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES)
18310    /* RFC 8446 Section 9.2: ClientHello with KeyShare must
18311     * contain SupportedGroups and vice-versa. */
18312    if (IsAtLeastTLSv1_3(ssl->version) && msgType == client_hello && isRequest) {
18313        int hasKeyShare = !IS_OFF(seenType, TLSX_ToSemaphore(TLSX_KEY_SHARE));
18314        int hasSupportedGroups = !IS_OFF(seenType,
18315            TLSX_ToSemaphore(TLSX_SUPPORTED_GROUPS));
18316
18317        if (hasKeyShare && !hasSupportedGroups) {
18318            WOLFSSL_MSG("ClientHello with KeyShare extension missing required "
18319                        "SupportedGroups extension");
18320            return INCOMPLETE_DATA;
18321        }
18322        if (hasSupportedGroups && !hasKeyShare) {
18323            WOLFSSL_MSG("ClientHello with SupportedGroups extension missing "
18324                        "required KeyShare extension");
18325            return INCOMPLETE_DATA;
18326        }
18327    }
18328#endif
18329
18330    if (ret == 0)
18331        ret = SNI_VERIFY_PARSE(ssl, isRequest);
18332    if (ret == 0)
18333        ret = TCA_VERIFY_PARSE(ssl, isRequest);
18334
18335    WOLFSSL_LEAVE("Leaving TLSX_Parse", ret);
18336    return ret;
18337}
18338
18339/* undefining semaphore macros */
18340#undef IS_OFF
18341#undef TURN_ON
18342#undef SEMAPHORE_SIZE
18343
18344#endif /* HAVE_TLS_EXTENSIONS */
18345
18346#ifndef NO_WOLFSSL_CLIENT
18347
18348    WOLFSSL_METHOD* wolfTLS_client_method(void)
18349    {
18350        return wolfTLS_client_method_ex(NULL);
18351    }
18352    WOLFSSL_METHOD* wolfTLS_client_method_ex(void* heap)
18353    {
18354        WOLFSSL_METHOD* method =
18355                              (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
18356                                                     heap, DYNAMIC_TYPE_METHOD);
18357        (void)heap;
18358        WOLFSSL_ENTER("TLS_client_method_ex");
18359        if (method) {
18360        #if defined(WOLFSSL_TLS13)
18361            InitSSL_Method(method, MakeTLSv1_3());
18362        #elif !defined(WOLFSSL_NO_TLS12)
18363            InitSSL_Method(method, MakeTLSv1_2());
18364        #elif !defined(NO_OLD_TLS)
18365            InitSSL_Method(method, MakeTLSv1_1());
18366        #elif defined(WOLFSSL_ALLOW_TLSV10)
18367            InitSSL_Method(method, MakeTLSv1());
18368        #else
18369        #error No TLS version enabled! Consider using NO_TLS or WOLFCRYPT_ONLY.
18370        #endif
18371
18372            method->downgrade = 1;
18373            method->side      = WOLFSSL_CLIENT_END;
18374        }
18375        return method;
18376    }
18377
18378#ifndef NO_OLD_TLS
18379    #ifdef WOLFSSL_ALLOW_TLSV10
18380    WOLFSSL_METHOD* wolfTLSv1_client_method(void)
18381    {
18382        return wolfTLSv1_client_method_ex(NULL);
18383    }
18384    WOLFSSL_METHOD* wolfTLSv1_client_method_ex(void* heap)
18385    {
18386        WOLFSSL_METHOD* method =
18387                             (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
18388                                                     heap, DYNAMIC_TYPE_METHOD);
18389        (void)heap;
18390        WOLFSSL_ENTER("TLSv1_client_method_ex");
18391        if (method)
18392            InitSSL_Method(method, MakeTLSv1());
18393        return method;
18394    }
18395    #endif /* WOLFSSL_ALLOW_TLSV10 */
18396
18397    WOLFSSL_METHOD* wolfTLSv1_1_client_method(void)
18398    {
18399        return wolfTLSv1_1_client_method_ex(NULL);
18400    }
18401    WOLFSSL_METHOD* wolfTLSv1_1_client_method_ex(void* heap)
18402    {
18403        WOLFSSL_METHOD* method =
18404                              (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
18405                                                     heap, DYNAMIC_TYPE_METHOD);
18406        (void)heap;
18407        WOLFSSL_ENTER("TLSv1_1_client_method_ex");
18408        if (method)
18409            InitSSL_Method(method, MakeTLSv1_1());
18410        return method;
18411    }
18412#endif /* !NO_OLD_TLS */
18413
18414#ifndef WOLFSSL_NO_TLS12
18415    WOLFSSL_ABI
18416    WOLFSSL_METHOD* wolfTLSv1_2_client_method(void)
18417    {
18418        return wolfTLSv1_2_client_method_ex(NULL);
18419    }
18420    WOLFSSL_METHOD* wolfTLSv1_2_client_method_ex(void* heap)
18421    {
18422        WOLFSSL_METHOD* method =
18423                              (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
18424                                                     heap, DYNAMIC_TYPE_METHOD);
18425        (void)heap;
18426        WOLFSSL_ENTER("TLSv1_2_client_method_ex");
18427        if (method)
18428            InitSSL_Method(method, MakeTLSv1_2());
18429        return method;
18430    }
18431#endif /* WOLFSSL_NO_TLS12 */
18432
18433#ifdef WOLFSSL_TLS13
18434    /* The TLS v1.3 client method data.
18435     *
18436     * returns the method data for a TLS v1.3 client.
18437     */
18438    WOLFSSL_ABI
18439    WOLFSSL_METHOD* wolfTLSv1_3_client_method(void)
18440    {
18441        return wolfTLSv1_3_client_method_ex(NULL);
18442    }
18443
18444    /* The TLS v1.3 client method data.
18445     *
18446     * heap  The heap used for allocation.
18447     * returns the method data for a TLS v1.3 client.
18448     */
18449    WOLFSSL_METHOD* wolfTLSv1_3_client_method_ex(void* heap)
18450    {
18451        WOLFSSL_METHOD* method = (WOLFSSL_METHOD*)
18452                                 XMALLOC(sizeof(WOLFSSL_METHOD), heap,
18453                                         DYNAMIC_TYPE_METHOD);
18454        (void)heap;
18455        WOLFSSL_ENTER("TLSv1_3_client_method_ex");
18456        if (method)
18457            InitSSL_Method(method, MakeTLSv1_3());
18458        return method;
18459    }
18460#endif /* WOLFSSL_TLS13 */
18461
18462#ifdef WOLFSSL_DTLS
18463
18464    WOLFSSL_METHOD* wolfDTLS_client_method(void)
18465    {
18466        return wolfDTLS_client_method_ex(NULL);
18467    }
18468    WOLFSSL_METHOD* wolfDTLS_client_method_ex(void* heap)
18469    {
18470        WOLFSSL_METHOD* method =
18471                              (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
18472                                                     heap, DYNAMIC_TYPE_METHOD);
18473        (void)heap;
18474        WOLFSSL_ENTER("DTLS_client_method_ex");
18475        if (method) {
18476        #if defined(WOLFSSL_DTLS13)
18477            InitSSL_Method(method, MakeDTLSv1_3());
18478        #elif !defined(WOLFSSL_NO_TLS12)
18479            InitSSL_Method(method, MakeDTLSv1_2());
18480        #elif !defined(NO_OLD_TLS)
18481            InitSSL_Method(method, MakeDTLSv1());
18482        #else
18483            #error No DTLS version enabled!
18484        #endif
18485
18486            method->downgrade = 1;
18487            method->side      = WOLFSSL_CLIENT_END;
18488        }
18489        return method;
18490    }
18491
18492    #ifndef NO_OLD_TLS
18493    WOLFSSL_METHOD* wolfDTLSv1_client_method(void)
18494    {
18495        return wolfDTLSv1_client_method_ex(NULL);
18496    }
18497    WOLFSSL_METHOD* wolfDTLSv1_client_method_ex(void* heap)
18498    {
18499        WOLFSSL_METHOD* method =
18500                          (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
18501                                                 heap, DYNAMIC_TYPE_METHOD);
18502        (void)heap;
18503        WOLFSSL_ENTER("DTLSv1_client_method_ex");
18504        if (method)
18505            InitSSL_Method(method, MakeDTLSv1());
18506        return method;
18507    }
18508    #endif  /* NO_OLD_TLS */
18509
18510    #ifndef WOLFSSL_NO_TLS12
18511    WOLFSSL_METHOD* wolfDTLSv1_2_client_method(void)
18512    {
18513        return wolfDTLSv1_2_client_method_ex(NULL);
18514    }
18515    WOLFSSL_METHOD* wolfDTLSv1_2_client_method_ex(void* heap)
18516    {
18517        WOLFSSL_METHOD* method =
18518                          (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
18519                                                 heap, DYNAMIC_TYPE_METHOD);
18520        (void)heap;
18521        WOLFSSL_ENTER("DTLSv1_2_client_method_ex");
18522        if (method)
18523            InitSSL_Method(method, MakeDTLSv1_2());
18524        (void)heap;
18525        return method;
18526    }
18527    #endif /* !WOLFSSL_NO_TLS12 */
18528#endif /* WOLFSSL_DTLS */
18529
18530#endif /* NO_WOLFSSL_CLIENT */
18531
18532
18533/* EITHER SIDE METHODS */
18534#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE)
18535    #ifndef NO_OLD_TLS
18536    #ifdef WOLFSSL_ALLOW_TLSV10
18537    /* Gets a WOLFSSL_METHOD type that is not set as client or server
18538     *
18539     * Returns a pointer to a WOLFSSL_METHOD struct
18540     */
18541    WOLFSSL_METHOD* wolfTLSv1_method(void)
18542    {
18543        return wolfTLSv1_method_ex(NULL);
18544    }
18545    WOLFSSL_METHOD* wolfTLSv1_method_ex(void* heap)
18546    {
18547        WOLFSSL_METHOD* m;
18548        WOLFSSL_ENTER("TLSv1_method");
18549    #ifndef NO_WOLFSSL_CLIENT
18550        m = wolfTLSv1_client_method_ex(heap);
18551    #else
18552        m = wolfTLSv1_server_method_ex(heap);
18553    #endif
18554        if (m != NULL) {
18555            m->side = WOLFSSL_NEITHER_END;
18556        }
18557
18558        return m;
18559    }
18560    #endif /* WOLFSSL_ALLOW_TLSV10 */
18561
18562    /* Gets a WOLFSSL_METHOD type that is not set as client or server
18563     *
18564     * Returns a pointer to a WOLFSSL_METHOD struct
18565     */
18566    WOLFSSL_METHOD* wolfTLSv1_1_method(void)
18567    {
18568        return wolfTLSv1_1_method_ex(NULL);
18569    }
18570    WOLFSSL_METHOD* wolfTLSv1_1_method_ex(void* heap)
18571    {
18572        WOLFSSL_METHOD* m;
18573        WOLFSSL_ENTER("TLSv1_1_method");
18574    #ifndef NO_WOLFSSL_CLIENT
18575        m = wolfTLSv1_1_client_method_ex(heap);
18576    #else
18577        m = wolfTLSv1_1_server_method_ex(heap);
18578    #endif
18579        if (m != NULL) {
18580            m->side = WOLFSSL_NEITHER_END;
18581        }
18582        return m;
18583    }
18584    #endif /* !NO_OLD_TLS */
18585
18586    #ifndef WOLFSSL_NO_TLS12
18587    /* Gets a WOLFSSL_METHOD type that is not set as client or server
18588     *
18589     * Returns a pointer to a WOLFSSL_METHOD struct
18590     */
18591    WOLFSSL_METHOD* wolfTLSv1_2_method(void)
18592    {
18593        return wolfTLSv1_2_method_ex(NULL);
18594    }
18595    WOLFSSL_METHOD* wolfTLSv1_2_method_ex(void* heap)
18596    {
18597        WOLFSSL_METHOD* m;
18598        WOLFSSL_ENTER("TLSv1_2_method");
18599    #ifndef NO_WOLFSSL_CLIENT
18600        m = wolfTLSv1_2_client_method_ex(heap);
18601    #else
18602        m = wolfTLSv1_2_server_method_ex(heap);
18603    #endif
18604        if (m != NULL) {
18605            m->side = WOLFSSL_NEITHER_END;
18606        }
18607        return m;
18608    }
18609    #endif /* !WOLFSSL_NO_TLS12 */
18610
18611    #ifdef WOLFSSL_TLS13
18612    /* Gets a WOLFSSL_METHOD type that is not set as client or server
18613     *
18614     * Returns a pointer to a WOLFSSL_METHOD struct
18615     */
18616    WOLFSSL_METHOD* wolfTLSv1_3_method(void)
18617    {
18618        return wolfTLSv1_3_method_ex(NULL);
18619    }
18620    WOLFSSL_METHOD* wolfTLSv1_3_method_ex(void* heap)
18621    {
18622        WOLFSSL_METHOD* m;
18623        WOLFSSL_ENTER("TLSv1_3_method");
18624    #ifndef NO_WOLFSSL_CLIENT
18625        m = wolfTLSv1_3_client_method_ex(heap);
18626    #else
18627        m = wolfTLSv1_3_server_method_ex(heap);
18628    #endif
18629        if (m != NULL) {
18630            m->side = WOLFSSL_NEITHER_END;
18631        }
18632        return m;
18633    }
18634    #endif /* WOLFSSL_TLS13 */
18635
18636#ifdef WOLFSSL_DTLS
18637    WOLFSSL_METHOD* wolfDTLS_method(void)
18638    {
18639        return wolfDTLS_method_ex(NULL);
18640    }
18641    WOLFSSL_METHOD* wolfDTLS_method_ex(void* heap)
18642    {
18643        WOLFSSL_METHOD* m;
18644        WOLFSSL_ENTER("DTLS_method_ex");
18645    #ifndef NO_WOLFSSL_CLIENT
18646        m = wolfDTLS_client_method_ex(heap);
18647    #else
18648        m = wolfDTLS_server_method_ex(heap);
18649    #endif
18650        if (m != NULL) {
18651            m->side = WOLFSSL_NEITHER_END;
18652        }
18653        return m;
18654    }
18655
18656    #ifndef NO_OLD_TLS
18657    WOLFSSL_METHOD* wolfDTLSv1_method(void)
18658    {
18659        return wolfDTLSv1_method_ex(NULL);
18660    }
18661    WOLFSSL_METHOD* wolfDTLSv1_method_ex(void* heap)
18662    {
18663        WOLFSSL_METHOD* m;
18664        WOLFSSL_ENTER("DTLSv1_method_ex");
18665    #ifndef NO_WOLFSSL_CLIENT
18666        m = wolfDTLSv1_client_method_ex(heap);
18667    #else
18668        m = wolfDTLSv1_server_method_ex(heap);
18669    #endif
18670        if (m != NULL) {
18671            m->side = WOLFSSL_NEITHER_END;
18672        }
18673        return m;
18674    }
18675    #endif /* !NO_OLD_TLS */
18676    #ifndef WOLFSSL_NO_TLS12
18677    WOLFSSL_METHOD* wolfDTLSv1_2_method(void)
18678    {
18679        return wolfDTLSv1_2_method_ex(NULL);
18680    }
18681    WOLFSSL_METHOD* wolfDTLSv1_2_method_ex(void* heap)
18682    {
18683        WOLFSSL_METHOD* m;
18684        WOLFSSL_ENTER("DTLSv1_2_method");
18685    #ifndef NO_WOLFSSL_CLIENT
18686        m = wolfDTLSv1_2_client_method_ex(heap);
18687    #else
18688        m = wolfDTLSv1_2_server_method_ex(heap);
18689    #endif
18690        if (m != NULL) {
18691            m->side = WOLFSSL_NEITHER_END;
18692        }
18693        return m;
18694    }
18695    #endif /* !WOLFSSL_NO_TLS12 */
18696    #ifdef WOLFSSL_DTLS13
18697    WOLFSSL_METHOD* wolfDTLSv1_3_method(void)
18698    {
18699        return wolfDTLSv1_3_method_ex(NULL);
18700    }
18701    WOLFSSL_METHOD* wolfDTLSv1_3_method_ex(void* heap)
18702    {
18703        WOLFSSL_METHOD* m;
18704        WOLFSSL_ENTER("DTLSv1_3_method");
18705    #ifndef NO_WOLFSSL_CLIENT
18706        m = wolfDTLSv1_3_client_method_ex(heap);
18707    #else
18708        m = wolfDTLSv1_3_server_method_ex(heap);
18709    #endif
18710        if (m != NULL) {
18711            m->side = WOLFSSL_NEITHER_END;
18712        }
18713        return m;
18714    }
18715    #endif /* WOLFSSL_DTLS13 */
18716#endif /* WOLFSSL_DTLS */
18717#endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */
18718
18719
18720#ifndef NO_WOLFSSL_SERVER
18721
18722    WOLFSSL_METHOD* wolfTLS_server_method(void)
18723    {
18724        return wolfTLS_server_method_ex(NULL);
18725    }
18726
18727    WOLFSSL_METHOD* wolfTLS_server_method_ex(void* heap)
18728    {
18729        WOLFSSL_METHOD* method =
18730                              (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
18731                                                     heap, DYNAMIC_TYPE_METHOD);
18732        (void)heap;
18733        WOLFSSL_ENTER("TLS_server_method_ex");
18734        if (method) {
18735        #if defined(WOLFSSL_TLS13)
18736            InitSSL_Method(method, MakeTLSv1_3());
18737        #elif !defined(WOLFSSL_NO_TLS12)
18738            InitSSL_Method(method, MakeTLSv1_2());
18739        #elif !defined(NO_OLD_TLS)
18740            InitSSL_Method(method, MakeTLSv1_1());
18741        #elif defined(WOLFSSL_ALLOW_TLSV10)
18742            InitSSL_Method(method, MakeTLSv1());
18743        #else
18744        #error No TLS version enabled! Consider using NO_TLS or WOLFCRYPT_ONLY.
18745        #endif
18746
18747            method->downgrade = 1;
18748            method->side      = WOLFSSL_SERVER_END;
18749        }
18750        return method;
18751    }
18752
18753#ifndef NO_OLD_TLS
18754    #ifdef WOLFSSL_ALLOW_TLSV10
18755    WOLFSSL_METHOD* wolfTLSv1_server_method(void)
18756    {
18757        return wolfTLSv1_server_method_ex(NULL);
18758    }
18759    WOLFSSL_METHOD* wolfTLSv1_server_method_ex(void* heap)
18760    {
18761        WOLFSSL_METHOD* method =
18762                              (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
18763                                                     heap, DYNAMIC_TYPE_METHOD);
18764        (void)heap;
18765        WOLFSSL_ENTER("TLSv1_server_method_ex");
18766        if (method) {
18767            InitSSL_Method(method, MakeTLSv1());
18768            method->side = WOLFSSL_SERVER_END;
18769        }
18770        return method;
18771    }
18772    #endif /* WOLFSSL_ALLOW_TLSV10 */
18773
18774    WOLFSSL_METHOD* wolfTLSv1_1_server_method(void)
18775    {
18776        return wolfTLSv1_1_server_method_ex(NULL);
18777    }
18778    WOLFSSL_METHOD* wolfTLSv1_1_server_method_ex(void* heap)
18779    {
18780        WOLFSSL_METHOD* method =
18781                              (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
18782                                                     heap, DYNAMIC_TYPE_METHOD);
18783        (void)heap;
18784        WOLFSSL_ENTER("TLSv1_1_server_method_ex");
18785        if (method) {
18786            InitSSL_Method(method, MakeTLSv1_1());
18787            method->side = WOLFSSL_SERVER_END;
18788        }
18789        return method;
18790    }
18791#endif /* !NO_OLD_TLS */
18792
18793
18794#ifndef WOLFSSL_NO_TLS12
18795    WOLFSSL_ABI
18796    WOLFSSL_METHOD* wolfTLSv1_2_server_method(void)
18797    {
18798        return wolfTLSv1_2_server_method_ex(NULL);
18799    }
18800    WOLFSSL_METHOD* wolfTLSv1_2_server_method_ex(void* heap)
18801    {
18802        WOLFSSL_METHOD* method =
18803                              (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
18804                                                     heap, DYNAMIC_TYPE_METHOD);
18805        (void)heap;
18806        WOLFSSL_ENTER("TLSv1_2_server_method_ex");
18807        if (method) {
18808            InitSSL_Method(method, MakeTLSv1_2());
18809            method->side = WOLFSSL_SERVER_END;
18810        }
18811        return method;
18812    }
18813#endif /* !WOLFSSL_NO_TLS12 */
18814
18815#ifdef WOLFSSL_TLS13
18816    /* The TLS v1.3 server method data.
18817     *
18818     * returns the method data for a TLS v1.3 server.
18819     */
18820    WOLFSSL_ABI
18821    WOLFSSL_METHOD* wolfTLSv1_3_server_method(void)
18822    {
18823        return wolfTLSv1_3_server_method_ex(NULL);
18824    }
18825
18826    /* The TLS v1.3 server method data.
18827     *
18828     * heap  The heap used for allocation.
18829     * returns the method data for a TLS v1.3 server.
18830     */
18831    WOLFSSL_METHOD* wolfTLSv1_3_server_method_ex(void* heap)
18832    {
18833        WOLFSSL_METHOD* method =
18834                              (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
18835                                                     heap, DYNAMIC_TYPE_METHOD);
18836        (void)heap;
18837        WOLFSSL_ENTER("TLSv1_3_server_method_ex");
18838        if (method) {
18839            InitSSL_Method(method, MakeTLSv1_3());
18840            method->side = WOLFSSL_SERVER_END;
18841        }
18842        return method;
18843    }
18844#endif /* WOLFSSL_TLS13 */
18845
18846#ifdef WOLFSSL_DTLS
18847    WOLFSSL_METHOD* wolfDTLS_server_method(void)
18848    {
18849        return wolfDTLS_server_method_ex(NULL);
18850    }
18851    WOLFSSL_METHOD* wolfDTLS_server_method_ex(void* heap)
18852    {
18853        WOLFSSL_METHOD* method =
18854                              (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
18855                                                     heap, DYNAMIC_TYPE_METHOD);
18856        (void)heap;
18857        WOLFSSL_ENTER("DTLS_server_method_ex");
18858        if (method) {
18859        #if defined(WOLFSSL_DTLS13)
18860            InitSSL_Method(method, MakeDTLSv1_3());
18861        #elif !defined(WOLFSSL_NO_TLS12)
18862            InitSSL_Method(method, MakeDTLSv1_2());
18863        #elif !defined(NO_OLD_TLS)
18864            InitSSL_Method(method, MakeDTLSv1());
18865        #else
18866            #error No DTLS version enabled!
18867        #endif
18868
18869            method->downgrade = 1;
18870            method->side      = WOLFSSL_SERVER_END;
18871        }
18872        return method;
18873    }
18874
18875    #ifndef NO_OLD_TLS
18876    WOLFSSL_METHOD* wolfDTLSv1_server_method(void)
18877    {
18878        return wolfDTLSv1_server_method_ex(NULL);
18879    }
18880    WOLFSSL_METHOD* wolfDTLSv1_server_method_ex(void* heap)
18881    {
18882        WOLFSSL_METHOD* method =
18883                          (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
18884                                                 heap, DYNAMIC_TYPE_METHOD);
18885        (void)heap;
18886        WOLFSSL_ENTER("DTLSv1_server_method_ex");
18887        if (method) {
18888            InitSSL_Method(method, MakeDTLSv1());
18889            method->side = WOLFSSL_SERVER_END;
18890        }
18891        return method;
18892    }
18893    #endif /* !NO_OLD_TLS */
18894
18895    #ifndef WOLFSSL_NO_TLS12
18896    WOLFSSL_METHOD* wolfDTLSv1_2_server_method(void)
18897    {
18898        return wolfDTLSv1_2_server_method_ex(NULL);
18899    }
18900    WOLFSSL_METHOD* wolfDTLSv1_2_server_method_ex(void* heap)
18901    {
18902        WOLFSSL_METHOD* method =
18903                          (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD),
18904                                                 heap, DYNAMIC_TYPE_METHOD);
18905        WOLFSSL_ENTER("DTLSv1_2_server_method_ex");
18906        (void)heap;
18907        if (method) {
18908            InitSSL_Method(method, MakeDTLSv1_2());
18909            method->side = WOLFSSL_SERVER_END;
18910        }
18911        (void)heap;
18912        return method;
18913    }
18914    #endif /* !WOLFSSL_NO_TLS12 */
18915#endif /* WOLFSSL_DTLS */
18916
18917#endif /* NO_WOLFSSL_SERVER */
18918
18919#endif /* NO_TLS */
18920
18921#endif /* WOLFCRYPT_ONLY */