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/wolfcrypt/src/wc_mlkem_poly.c raw
   1/* wc_mlkem_poly.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/* Implementation based on FIPS 203:
  23 *   https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.203.pdf
  24 *
  25 * Original implementation based on NIST 3rd Round submission package.
  26 * See link at:
  27 *   https://csrc.nist.gov/Projects/post-quantum-cryptography/
  28 *   post-quantum-cryptography-standardization/round-3-submissions
  29 */
  30
  31/* Implementation of the functions that operate on polynomials or vectors of
  32 * polynomials.
  33 */
  34
  35/* Possible ML-KEM options:
  36 *
  37 * WOLFSSL_HAVE_MLKEM                                         Default: OFF
  38 *   Enables this code, wolfSSL implementation, to be built.
  39 *
  40 * WOLFSSL_WC_ML_KEM_512                                      Default: OFF
  41 *   Enables the ML-KEM 512 parameter implementations.
  42 * WOLFSSL_WC_ML_KEM_768                                      Default: OFF
  43 *   Enables the ML-KEM 768 parameter implementations.
  44 * WOLFSSL_WC_ML_KEM_1024                                     Default: OFF
  45 *   Enables the ML-KEM 1024 parameter implementations.
  46 * WOLFSSL_KYBER512                                           Default: OFF
  47 *   Enables the KYBER512 parameter implementations.
  48 * WOLFSSL_KYBER768                                           Default: OFF
  49 *   Enables the KYBER768 parameter implementations.
  50 * WOLFSSL_KYBER1024                                          Default: OFF
  51 *   Enables the KYBER1024 parameter implementations.
  52 *
  53 * USE_INTEL_SPEEDUP                                          Default: OFF
  54 *   Compiles in Intel x64 specific implementations that are faster.
  55 * WOLFSSL_MLKEM_NO_LARGE_CODE                                Default: OFF
  56 *   Compiles smaller, fast code size with a speed trade-off.
  57 * WOLFSSL_MLKEM_SMALL                                        Default: OFF
  58 *   Compiles to small code size with a speed trade-off.
  59 * WOLFSSL_SMALL_STACK                                        Default: OFF
  60 *   Use less stack by dynamically allocating local variables.
  61 *
  62 * WOLFSSL_MLKEM_NTT_UNROLL                                   Default: OFF
  63 *   Enable an alternative NTT implementation that may be faster on some
  64 *   platforms and is smaller in code size.
  65 * WOLFSSL_MLKEM_INVNTT_UNROLL                                Default: OFF
  66 *   Enables an alternative inverse NTT implementation that may be faster on
  67 *   some platforms and is smaller in code size.
  68 */
  69
  70#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
  71
  72#ifdef WC_MLKEM_NO_ASM
  73    #undef USE_INTEL_SPEEDUP
  74    #undef WOLFSSL_ARMASM
  75    #undef WOLFSSL_RISCV_ASM
  76#endif
  77
  78#include <wolfssl/wolfcrypt/wc_mlkem.h>
  79#include <wolfssl/wolfcrypt/sha3.h>
  80#include <wolfssl/wolfcrypt/cpuid.h>
  81
  82#ifdef WOLFSSL_HAVE_MLKEM
  83
  84#ifdef NO_INLINE
  85    #include <wolfssl/wolfcrypt/misc.h>
  86#else
  87    #define WOLFSSL_MISC_INCLUDED
  88    #include <wolfcrypt/src/misc.c>
  89#endif
  90
  91#if defined(WOLFSSL_MLKEM_MAKEKEY_SMALL_MEM) || \
  92    defined(WOLFSSL_MLKEM_ENCAPSULATE_SMALL_MEM)
  93static int mlkem_gen_matrix_i(MLKEM_PRF_T* prf, sword16* a, int k, byte* seed,
  94    int i, int transposed);
  95static int mlkem_get_noise_i(MLKEM_PRF_T* prf, int k, sword16* vec2,
  96    byte* seed, int i, int make);
  97static int mlkem_get_noise_eta2_c(MLKEM_PRF_T* prf, sword16* p,
  98    const byte* seed);
  99#endif
 100
 101/* Declared in wc_mlkem.c to stop compiler optimizer from simplifying. */
 102extern sword16 wc_mlkem_opt_blocker(void);
 103
 104#if defined(USE_INTEL_SPEEDUP) || (defined(__aarch64__) && \
 105    defined(WOLFSSL_ARMASM))
 106static cpuid_flags_t cpuid_flags = WC_CPUID_INITIALIZER;
 107#endif
 108
 109/* Half of Q plus one. Converted message bit value of 1. */
 110#define MLKEM_Q_1_HALF      ((MLKEM_Q + 1) / 2)
 111/* Half of Q */
 112#define MLKEM_Q_HALF        (MLKEM_Q / 2)
 113
 114
 115/* q^-1 mod 2^16 (inverse of 3329 mod 65536) */
 116#define MLKEM_QINV       62209
 117
 118/* Used in Barrett Reduction:
 119 *    r = a mod q
 120 * => r = a - ((V * a) >> 26) * q), as V based on 2^26
 121 * V is the multiplier that gets the quotient after shifting.
 122 */
 123#define MLKEM_V          (((1U << 26) + (MLKEM_Q / 2)) / MLKEM_Q)
 124
 125/* Used in converting to Montgomery form.
 126 * f is the normalizer = 2^k % m.
 127 * 16-bit value cast to sword32 in use.
 128 */
 129#define MLKEM_F          (((word64)1 << 32) % MLKEM_Q)
 130
 131/* Number of bytes in an output block of SHA-3-128 */
 132#define SHA3_128_BYTES   (WC_SHA3_128_COUNT * 8)
 133/* Number of bytes in an output block of SHA-3-256 */
 134#define SHA3_256_BYTES   (WC_SHA3_256_COUNT * 8)
 135
 136/* Number of blocks to generate for matrix. */
 137#define GEN_MATRIX_NBLOCKS \
 138    ((12 * MLKEM_N / 8 * (1 << 12) / MLKEM_Q + XOF_BLOCK_SIZE) / XOF_BLOCK_SIZE)
 139/* Number of bytes to generate for matrix. */
 140#define GEN_MATRIX_SIZE     GEN_MATRIX_NBLOCKS * XOF_BLOCK_SIZE
 141
 142
 143/* Number of random bytes to generate for ETA3. */
 144#define ETA3_RAND_SIZE     ((3 * MLKEM_N) / 4)
 145/* Number of random bytes to generate for ETA2. */
 146#define ETA2_RAND_SIZE     ((2 * MLKEM_N) / 4)
 147
 148
 149/* Montgomery reduce a.
 150 *
 151 * @param  [in]  a  32-bit value to be reduced.
 152 * @return  Montgomery reduction result.
 153 */
 154#define MLKEM_MONT_RED(a) \
 155    (sword16)(((a) - (sword32)(((sword16)((sword16)(a) * \
 156                                (sword16)MLKEM_QINV)) * \
 157                               (sword32)MLKEM_Q)) >> 16)
 158
 159/* Barrett reduce a. r = a mod q.
 160 *
 161 * Converted division to multiplication.
 162 *
 163 * @param  [in]  a  16-bit value to be reduced to range of q.
 164 * @return  Modulo result.
 165 */
 166#define MLKEM_BARRETT_RED(a) \
 167    (sword16)((sword16)(a) - (sword16)((sword16)( \
 168        ((sword32)((sword32)MLKEM_V * (sword16)(a))) >> 26) * (word16)MLKEM_Q))
 169
 170
 171/* Zetas for NTT. */
 172const sword16 zetas[MLKEM_N / 2] = {
 173    2285, 2571, 2970, 1812, 1493, 1422,  287,  202,
 174    3158,  622, 1577,  182,  962, 2127, 1855, 1468,
 175     573, 2004,  264,  383, 2500, 1458, 1727, 3199,
 176    2648, 1017,  732,  608, 1787,  411, 3124, 1758,
 177    1223,  652, 2777, 1015, 2036, 1491, 3047, 1785,
 178     516, 3321, 3009, 2663, 1711, 2167,  126, 1469,
 179    2476, 3239, 3058,  830,  107, 1908, 3082, 2378,
 180    2931,  961, 1821, 2604,  448, 2264,  677, 2054,
 181    2226,  430,  555,  843, 2078,  871, 1550,  105,
 182     422,  587,  177, 3094, 3038, 2869, 1574, 1653,
 183    3083,  778, 1159, 3182, 2552, 1483, 2727, 1119,
 184    1739,  644, 2457,  349,  418,  329, 3173, 3254,
 185     817, 1097,  603,  610, 1322, 2044, 1864,  384,
 186    2114, 3193, 1218, 1994, 2455,  220, 2142, 1670,
 187    2144, 1799, 2051,  794, 1819, 2475, 2459,  478,
 188    3221, 3021,  996,  991,  958, 1869, 1522, 1628
 189};
 190
 191
 192#if !defined(WOLFSSL_ARMASM)
 193/* Number-Theoretic Transform.
 194 *
 195 * FIPS 203, Algorithm 9: NTT(f)
 196 * Computes the NTT representation f_hat of the given polynomial f element of
 197 * R_q.
 198 *   1: f_hat <- f
 199 *   2: i <- 1
 200 *   3: for (len <- 128; len >= 2; len <- len/2)
 201 *   4:     for (start <- 0; start < 256; start <- start + 2.len)
 202 *   5:         zeta <- zetas^BitRev_7(i) mod q
 203 *   6:         i <- i + 1
 204 *   7:         for (j <- start; j < start + len; j++)
 205 *   8:             t <- zeta.f[j+len]
 206 *   9:             f_hat[j+len] <- f_hat[j] - t
 207 *  10:             f_hat[j] <- f_hat[j] + t
 208 *  11:         end for
 209 *  12:     end for
 210 *  13: end for
 211 *  14: return f_hat
 212 *
 213 * @param  [in, out]  r  Polynomial to transform.
 214 */
 215static void mlkem_ntt(sword16* r)
 216{
 217#ifdef WOLFSSL_MLKEM_SMALL
 218    unsigned int len;
 219    unsigned int k;
 220    unsigned int j;
 221
 222    /* Step 2 */
 223    k = 1;
 224    /* Step 3 */
 225    for (len = MLKEM_N / 2; len >= 2; len >>= 1) {
 226        unsigned int start;
 227        /* Step 4 */
 228        for (start = 0; start < MLKEM_N; start = j + len) {
 229            /* Step 5, 6*/
 230            sword16 zeta = zetas[k++];
 231            /* Step 7 */
 232            for (j = start; j < start + len; ++j) {
 233                /* Step 8 */
 234                sword32 p = (sword32)zeta * r[j + len];
 235                sword16 t = MLKEM_MONT_RED(p);
 236                sword16 rj = r[j];
 237                /* Step 9 */
 238                r[j + len] = (sword16)(rj - t);
 239                /* Step 10 */
 240                r[j] = (sword16)(rj + t);
 241            }
 242        }
 243    }
 244
 245    /* Reduce coefficients with quick algorithm. */
 246    for (j = 0; j < MLKEM_N; ++j) {
 247        r[j] = MLKEM_BARRETT_RED(r[j]);
 248    }
 249#elif defined(WOLFSSL_MLKEM_NO_LARGE_CODE)
 250    /* Take out the first iteration. */
 251    unsigned int len;
 252    unsigned int k = 1;
 253    unsigned int j;
 254    unsigned int start;
 255    sword16 zeta = zetas[k++];
 256
 257    for (j = 0; j < MLKEM_N / 2; ++j) {
 258        sword32 p = (sword32)zeta * r[j + MLKEM_N / 2];
 259        sword16 t = MLKEM_MONT_RED(p);
 260        sword16 rj = r[j];
 261        r[j + MLKEM_N / 2] = (sword16)(rj - t);
 262        r[j] = (sword16)(rj + t);
 263    }
 264    for (len = MLKEM_N / 4; len >= 2; len >>= 1) {
 265        for (start = 0; start < MLKEM_N; start = j + len) {
 266            zeta = zetas[k++];
 267            for (j = start; j < start + len; ++j) {
 268                sword32 p = (sword32)zeta * r[j + len];
 269                sword16 t = MLKEM_MONT_RED(p);
 270                sword16 rj = r[j];
 271                r[j + len] = (sword16)(rj - t);
 272                r[j] = (sword16)(rj + t);
 273            }
 274        }
 275    }
 276
 277    /* Reduce coefficients with quick algorithm. */
 278    for (j = 0; j < MLKEM_N; ++j) {
 279        r[j] = MLKEM_BARRETT_RED(r[j]);
 280    }
 281#elif defined(WOLFSSL_MLKEM_NTT_UNROLL)
 282    /* Unroll len loop (Step 3). */
 283    unsigned int k = 1;
 284    unsigned int j;
 285    unsigned int start;
 286    sword16 zeta = zetas[k++];
 287
 288    /* len = 128 */
 289    for (j = 0; j < MLKEM_N / 2; ++j) {
 290        sword32 p = (sword32)zeta * r[j + MLKEM_N / 2];
 291        sword16 t = MLKEM_MONT_RED(p);
 292        sword16 rj = r[j];
 293        r[j + MLKEM_N / 2] = rj - t;
 294        r[j] = rj + t;
 295    }
 296    /* len = 64 */
 297    for (start = 0; start < MLKEM_N; start += 2 * 64) {
 298        zeta = zetas[k++];
 299        for (j = 0; j < 64; ++j) {
 300            sword32 p = (sword32)zeta * r[start + j + 64];
 301            sword16 t = MLKEM_MONT_RED(p);
 302            sword16 rj = r[start + j];
 303            r[start + j + 64] = rj - t;
 304            r[start + j] = rj + t;
 305        }
 306    }
 307    /* len = 32 */
 308    for (start = 0; start < MLKEM_N; start += 2 * 32) {
 309        zeta = zetas[k++];
 310        for (j = 0; j < 32; ++j) {
 311            sword32 p = (sword32)zeta * r[start + j + 32];
 312            sword16 t = MLKEM_MONT_RED(p);
 313            sword16 rj = r[start + j];
 314            r[start + j + 32] = rj - t;
 315            r[start + j] = rj + t;
 316        }
 317    }
 318    /* len = 16 */
 319    for (start = 0; start < MLKEM_N; start += 2 * 16) {
 320        zeta = zetas[k++];
 321        for (j = 0; j < 16; ++j) {
 322            sword32 p = (sword32)zeta * r[start + j + 16];
 323            sword16 t = MLKEM_MONT_RED(p);
 324            sword16 rj = r[start + j];
 325            r[start + j + 16] = rj - t;
 326            r[start + j] = rj + t;
 327        }
 328    }
 329    /* len = 8 */
 330    for (start = 0; start < MLKEM_N; start += 2 * 8) {
 331        zeta = zetas[k++];
 332        for (j = 0; j < 8; ++j) {
 333            sword32 p = (sword32)zeta * r[start + j + 8];
 334            sword16 t = MLKEM_MONT_RED(p);
 335            sword16 rj = r[start + j];
 336            r[start + j + 8] = rj - t;
 337            r[start + j] = rj + t;
 338        }
 339    }
 340    /* len = 4 */
 341    for (start = 0; start < MLKEM_N; start += 2 * 4) {
 342        zeta = zetas[k++];
 343        for (j = 0; j < 4; ++j) {
 344            sword32 p = (sword32)zeta * r[start + j + 4];
 345            sword16 t = MLKEM_MONT_RED(p);
 346            sword16 rj = r[start + j];
 347            r[start + j + 4] = rj - t;
 348            r[start + j] = rj + t;
 349        }
 350    }
 351    /* len = 2 */
 352    for (start = 0; start < MLKEM_N; start += 2 * 2) {
 353        zeta = zetas[k++];
 354        for (j = 0; j < 2; ++j) {
 355            sword32 p = (sword32)zeta * r[start + j + 2];
 356            sword16 t = MLKEM_MONT_RED(p);
 357            sword16 rj = r[start + j];
 358            r[start + j + 2] = rj - t;
 359            r[start + j] = rj + t;
 360        }
 361    }
 362    /* Reduce coefficients with quick algorithm. */
 363    for (j = 0; j < MLKEM_N; ++j) {
 364        r[j] = MLKEM_BARRETT_RED(r[j]);
 365    }
 366#else
 367    /* Unroll len (2, 3, 2) and start loops. */
 368    unsigned int j;
 369    sword16 t0;
 370    sword16 t1;
 371    sword16 t2;
 372    sword16 t3;
 373
 374    /* len = 128,64 */
 375    sword16 zeta128 = zetas[1];
 376    sword16 zeta64_0 = zetas[2];
 377    sword16 zeta64_1 = zetas[3];
 378    for (j = 0; j < MLKEM_N / 8; j++) {
 379        sword16 r0 = r[j +   0];
 380        sword16 r1 = r[j +  32];
 381        sword16 r2 = r[j +  64];
 382        sword16 r3 = r[j +  96];
 383        sword16 r4 = r[j + 128];
 384        sword16 r5 = r[j + 160];
 385        sword16 r6 = r[j + 192];
 386        sword16 r7 = r[j + 224];
 387
 388        t0 = MLKEM_MONT_RED((sword32)zeta128 * r4);
 389        t1 = MLKEM_MONT_RED((sword32)zeta128 * r5);
 390        t2 = MLKEM_MONT_RED((sword32)zeta128 * r6);
 391        t3 = MLKEM_MONT_RED((sword32)zeta128 * r7);
 392        r4 = (sword16)(r0 - t0);
 393        r5 = (sword16)(r1 - t1);
 394        r6 = (sword16)(r2 - t2);
 395        r7 = (sword16)(r3 - t3);
 396        r0 = (sword16)(r0 + t0);
 397        r1 = (sword16)(r1 + t1);
 398        r2 = (sword16)(r2 + t2);
 399        r3 = (sword16)(r3 + t3);
 400
 401        t0 = MLKEM_MONT_RED((sword32)zeta64_0 * r2);
 402        t1 = MLKEM_MONT_RED((sword32)zeta64_0 * r3);
 403        t2 = MLKEM_MONT_RED((sword32)zeta64_1 * r6);
 404        t3 = MLKEM_MONT_RED((sword32)zeta64_1 * r7);
 405        r2 = (sword16)(r0 - t0);
 406        r3 = (sword16)(r1 - t1);
 407        r6 = (sword16)(r4 - t2);
 408        r7 = (sword16)(r5 - t3);
 409        r0 = (sword16)(r0 + t0);
 410        r1 = (sword16)(r1 + t1);
 411        r4 = (sword16)(r4 + t2);
 412        r5 = (sword16)(r5 + t3);
 413
 414        r[j +   0] = r0;
 415        r[j +  32] = r1;
 416        r[j +  64] = r2;
 417        r[j +  96] = r3;
 418        r[j + 128] = r4;
 419        r[j + 160] = r5;
 420        r[j + 192] = r6;
 421        r[j + 224] = r7;
 422    }
 423
 424    /* len = 32,16,8 */
 425    for (j = 0; j < MLKEM_N; j += 64) {
 426        unsigned int i;
 427        sword16 zeta32   = zetas[ 4 + j / 64 + 0];
 428        sword16 zeta16_0 = zetas[ 8 + j / 32 + 0];
 429        sword16 zeta16_1 = zetas[ 8 + j / 32 + 1];
 430        sword16 zeta8_0  = zetas[16 + j / 16 + 0];
 431        sword16 zeta8_1  = zetas[16 + j / 16 + 1];
 432        sword16 zeta8_2  = zetas[16 + j / 16 + 2];
 433        sword16 zeta8_3  = zetas[16 + j / 16 + 3];
 434        for (i = 0; i < 8; i++) {
 435            sword16 r0 = r[j + i +  0];
 436            sword16 r1 = r[j + i +  8];
 437            sword16 r2 = r[j + i + 16];
 438            sword16 r3 = r[j + i + 24];
 439            sword16 r4 = r[j + i + 32];
 440            sword16 r5 = r[j + i + 40];
 441            sword16 r6 = r[j + i + 48];
 442            sword16 r7 = r[j + i + 56];
 443
 444            t0 = MLKEM_MONT_RED((sword32)zeta32 * r4);
 445            t1 = MLKEM_MONT_RED((sword32)zeta32 * r5);
 446            t2 = MLKEM_MONT_RED((sword32)zeta32 * r6);
 447            t3 = MLKEM_MONT_RED((sword32)zeta32 * r7);
 448            r4 = (sword16)(r0 - t0);
 449            r5 = (sword16)(r1 - t1);
 450            r6 = (sword16)(r2 - t2);
 451            r7 = (sword16)(r3 - t3);
 452            r0 = (sword16)(r0 + t0);
 453            r1 = (sword16)(r1 + t1);
 454            r2 = (sword16)(r2 + t2);
 455            r3 = (sword16)(r3 + t3);
 456
 457            t0 = MLKEM_MONT_RED((sword32)zeta16_0 * r2);
 458            t1 = MLKEM_MONT_RED((sword32)zeta16_0 * r3);
 459            t2 = MLKEM_MONT_RED((sword32)zeta16_1 * r6);
 460            t3 = MLKEM_MONT_RED((sword32)zeta16_1 * r7);
 461            r2 = (sword16)(r0 - t0);
 462            r3 = (sword16)(r1 - t1);
 463            r6 = (sword16)(r4 - t2);
 464            r7 = (sword16)(r5 - t3);
 465            r0 = (sword16)(r0 + t0);
 466            r1 = (sword16)(r1 + t1);
 467            r4 = (sword16)(r4 + t2);
 468            r5 = (sword16)(r5 + t3);
 469
 470            t0 = MLKEM_MONT_RED((sword32)zeta8_0 * r1);
 471            t1 = MLKEM_MONT_RED((sword32)zeta8_1 * r3);
 472            t2 = MLKEM_MONT_RED((sword32)zeta8_2 * r5);
 473            t3 = MLKEM_MONT_RED((sword32)zeta8_3 * r7);
 474            r1 = (sword16)(r0 - t0);
 475            r3 = (sword16)(r2 - t1);
 476            r5 = (sword16)(r4 - t2);
 477            r7 = (sword16)(r6 - t3);
 478            r0 = (sword16)(r0 + t0);
 479            r2 = (sword16)(r2 + t1);
 480            r4 = (sword16)(r4 + t2);
 481            r6 = (sword16)(r6 + t3);
 482
 483            r[j + i +  0] = r0;
 484            r[j + i +  8] = r1;
 485            r[j + i + 16] = r2;
 486            r[j + i + 24] = r3;
 487            r[j + i + 32] = r4;
 488            r[j + i + 40] = r5;
 489            r[j + i + 48] = r6;
 490            r[j + i + 56] = r7;
 491        }
 492    }
 493
 494    /* len = 4,2 and Final reduction */
 495    for (j = 0; j < MLKEM_N; j += 8) {
 496        sword16 zeta4  = zetas[32 + j / 8 + 0];
 497        sword16 zeta2_0 = zetas[64 + j / 4 + 0];
 498        sword16 zeta2_1 = zetas[64 + j / 4 + 1];
 499        sword16 r0 = r[j + 0];
 500        sword16 r1 = r[j + 1];
 501        sword16 r2 = r[j + 2];
 502        sword16 r3 = r[j + 3];
 503        sword16 r4 = r[j + 4];
 504        sword16 r5 = r[j + 5];
 505        sword16 r6 = r[j + 6];
 506        sword16 r7 = r[j + 7];
 507
 508        t0 = MLKEM_MONT_RED((sword32)zeta4 * r4);
 509        t1 = MLKEM_MONT_RED((sword32)zeta4 * r5);
 510        t2 = MLKEM_MONT_RED((sword32)zeta4 * r6);
 511        t3 = MLKEM_MONT_RED((sword32)zeta4 * r7);
 512        r4 = (sword16)(r0 - t0);
 513        r5 = (sword16)(r1 - t1);
 514        r6 = (sword16)(r2 - t2);
 515        r7 = (sword16)(r3 - t3);
 516        r0 = (sword16)(r0 + t0);
 517        r1 = (sword16)(r1 + t1);
 518        r2 = (sword16)(r2 + t2);
 519        r3 = (sword16)(r3 + t3);
 520
 521        t0 = MLKEM_MONT_RED((sword32)zeta2_0 * r2);
 522        t1 = MLKEM_MONT_RED((sword32)zeta2_0 * r3);
 523        t2 = MLKEM_MONT_RED((sword32)zeta2_1 * r6);
 524        t3 = MLKEM_MONT_RED((sword32)zeta2_1 * r7);
 525        r2 = (sword16)(r0 - t0);
 526        r3 = (sword16)(r1 - t1);
 527        r6 = (sword16)(r4 - t2);
 528        r7 = (sword16)(r5 - t3);
 529        r0 = (sword16)(r0 + t0);
 530        r1 = (sword16)(r1 + t1);
 531        r4 = (sword16)(r4 + t2);
 532        r5 = (sword16)(r5 + t3);
 533
 534        r[j + 0] = MLKEM_BARRETT_RED(r0);
 535        r[j + 1] = MLKEM_BARRETT_RED(r1);
 536        r[j + 2] = MLKEM_BARRETT_RED(r2);
 537        r[j + 3] = MLKEM_BARRETT_RED(r3);
 538        r[j + 4] = MLKEM_BARRETT_RED(r4);
 539        r[j + 5] = MLKEM_BARRETT_RED(r5);
 540        r[j + 6] = MLKEM_BARRETT_RED(r6);
 541        r[j + 7] = MLKEM_BARRETT_RED(r7);
 542    }
 543#endif
 544}
 545
 546#if !defined(WOLFSSL_MLKEM_NO_ENCAPSULATE) || \
 547    !defined(WOLFSSL_MLKEM_NO_DECAPSULATE)
 548/* Zetas for inverse NTT. */
 549const sword16 zetas_inv[MLKEM_N / 2] = {
 550    1701, 1807, 1460, 2371, 2338, 2333,  308,  108,
 551    2851,  870,  854, 1510, 2535, 1278, 1530, 1185,
 552    1659, 1187, 3109,  874, 1335, 2111,  136, 1215,
 553    2945, 1465, 1285, 2007, 2719, 2726, 2232, 2512,
 554      75,  156, 3000, 2911, 2980,  872, 2685, 1590,
 555    2210,  602, 1846,  777,  147, 2170, 2551,  246,
 556    1676, 1755,  460,  291,  235, 3152, 2742, 2907,
 557    3224, 1779, 2458, 1251, 2486, 2774, 2899, 1103,
 558    1275, 2652, 1065, 2881,  725, 1508, 2368,  398,
 559     951,  247, 1421, 3222, 2499,  271,   90,  853,
 560    1860, 3203, 1162, 1618,  666,  320,    8, 2813,
 561    1544,  282, 1838, 1293, 2314,  552, 2677, 2106,
 562    1571,  205, 2918, 1542, 2721, 2597, 2312,  681,
 563     130, 1602, 1871,  829, 2946, 3065, 1325, 2756,
 564    1861, 1474, 1202, 2367, 3147, 1752, 2707,  171,
 565    3127, 3042, 1907, 1836, 1517,  359,  758, 1441
 566};
 567
 568/* Inverse Number-Theoretic Transform.
 569 *
 570 * FIPS 203, Algorithm 10: NTT^-1(f_hat)
 571 * Computes the polynomial f element of R_q that corresponds to the given NTT
 572 * representation f element of T_q.
 573 *   1: f <- f_hat
 574 *   2: i <- 127
 575 *   3: for (len <- 2; len <= 128 ; len <- 2.len)
 576 *   4:     for (start <- 0; start < 256; start <- start + 2.len)
 577 *   5:         zeta <- zetas^BitRev_7(i) mod q
 578 *   6:         i <- i - 1
 579 *   7:         for (j <- start; j < start + len; j++)
 580 *   8:             t <- f[j]
 581 *   9:             f[j] <- t + f[j + len]
 582 *  10:             f[j + len] <- zeta.(f[j+len] - t)
 583 *  11:         end for
 584 *  12:     end for
 585 *  13: end for
 586 *  14: f <- f.3303 mod q
 587 *  15: return f
 588 *
 589 * @param  [in, out]  r  Polynomial to transform.
 590 */
 591static void mlkem_invntt(sword16* r)
 592{
 593#ifdef WOLFSSL_MLKEM_SMALL
 594    unsigned int len;
 595    unsigned int k;
 596    unsigned int j;
 597    sword16 zeta;
 598
 599    /* Step 2 - table reversed */
 600    k = 0;
 601    /* Step 3 */
 602    for (len = 2; len <= MLKEM_N / 2; len <<= 1) {
 603        unsigned int start;
 604        /* Step 4 */
 605        for (start = 0; start < MLKEM_N; start = j + len) {
 606            /* Step 5, 6 */
 607            zeta = zetas_inv[k++];
 608            /* Step 7 */
 609            for (j = start; j < start + len; ++j) {
 610                sword32 p;
 611                /* Step 8 */
 612                sword16 rj = r[j];
 613                sword16 rjl = r[j + len];
 614                /* Step 9 */
 615                sword16 t = (sword16)(rj + rjl);
 616                r[j] = MLKEM_BARRETT_RED(t);
 617                /* Step 10 */
 618                rjl = (sword16)(rj - rjl);
 619                p = (sword32)zeta * rjl;
 620                r[j + len] = MLKEM_MONT_RED(p);
 621            }
 622        }
 623    }
 624
 625    /* Step 14 */
 626    zeta = zetas_inv[127];
 627    for (j = 0; j < MLKEM_N; ++j) {
 628        sword32 p = (sword32)zeta * r[j];
 629        r[j] = MLKEM_MONT_RED(p);
 630    }
 631#elif defined(WOLFSSL_MLKEM_NO_LARGE_CODE)
 632    /* Take out last iteration. */
 633    unsigned int len;
 634    unsigned int k;
 635    unsigned int j;
 636    sword16 zeta;
 637    sword16 zeta2;
 638
 639    k = 0;
 640    for (len = 2; len <= MLKEM_N / 4; len <<= 1) {
 641        unsigned int start;
 642        for (start = 0; start < MLKEM_N; start = j + len) {
 643            zeta = zetas_inv[k++];
 644            for (j = start; j < start + len; ++j) {
 645                sword32 p;
 646                sword16 rj = r[j];
 647                sword16 rjl = r[j + len];
 648                sword16 t = (sword16)(rj + rjl);
 649                r[j] = MLKEM_BARRETT_RED(t);
 650                rjl = (sword16)(rj - rjl);
 651                p = (sword32)zeta * rjl;
 652                r[j + len] = MLKEM_MONT_RED(p);
 653            }
 654        }
 655    }
 656
 657    zeta = zetas_inv[126];
 658    zeta2 = zetas_inv[127];
 659    for (j = 0; j < MLKEM_N / 2; ++j) {
 660        sword32 p;
 661        sword16 rj = r[j];
 662        sword16 rjl = r[j + MLKEM_N / 2];
 663        sword16 t = (sword16)(rj + rjl);
 664        rjl = (sword16)(rj - rjl);
 665        p = (sword32)zeta * rjl;
 666        r[j] = (sword16)t;
 667        r[j + MLKEM_N / 2] = MLKEM_MONT_RED(p);
 668
 669        p = (sword32)zeta2 * r[j];
 670        r[j] = MLKEM_MONT_RED(p);
 671        p = (sword32)zeta2 * r[j + MLKEM_N / 2];
 672        r[j + MLKEM_N / 2] = MLKEM_MONT_RED(p);
 673    }
 674#elif defined(WOLFSSL_MLKEM_INVNTT_UNROLL)
 675    /* Unroll len loop (Step 3). */
 676    unsigned int k;
 677    unsigned int j;
 678    unsigned int start;
 679    sword16 zeta;
 680    sword16 zeta2;
 681
 682    k = 0;
 683    /* len = 2 */
 684    for (start = 0; start < MLKEM_N; start += 2 * 2) {
 685        zeta = zetas_inv[k++];
 686        for (j = 0; j < 2; ++j) {
 687            sword32 p;
 688            sword16 rj = r[start + j];
 689            sword16 rjl = r[start + j + 2];
 690            sword16 t = rj + rjl;
 691            r[start + j] = t;
 692            rjl = rj - rjl;
 693            p = (sword32)zeta * rjl;
 694            r[start + j + 2] = MLKEM_MONT_RED(p);
 695        }
 696    }
 697    /* len = 4 */
 698    for (start = 0; start < MLKEM_N; start += 2 * 4) {
 699        zeta = zetas_inv[k++];
 700        for (j = 0; j < 4; ++j) {
 701            sword32 p;
 702            sword16 rj = r[start + j];
 703            sword16 rjl = r[start + j + 4];
 704            sword16 t = rj + rjl;
 705            r[start + j] = t;
 706            rjl = rj - rjl;
 707            p = (sword32)zeta * rjl;
 708            r[start + j + 4] = MLKEM_MONT_RED(p);
 709        }
 710    }
 711    /* len = 8 */
 712    for (start = 0; start < MLKEM_N; start += 2 * 8) {
 713        zeta = zetas_inv[k++];
 714        for (j = 0; j < 8; ++j) {
 715            sword32 p;
 716            sword16 rj = r[start + j];
 717            sword16 rjl = r[start + j + 8];
 718            sword16 t = rj + rjl;
 719            /* Reduce. */
 720            r[start + j] = MLKEM_BARRETT_RED(t);
 721            rjl = rj - rjl;
 722            p = (sword32)zeta * rjl;
 723            r[start + j + 8] = MLKEM_MONT_RED(p);
 724        }
 725    }
 726    /* len = 16 */
 727    for (start = 0; start < MLKEM_N; start += 2 * 16) {
 728        zeta = zetas_inv[k++];
 729        for (j = 0; j < 16; ++j) {
 730            sword32 p;
 731            sword16 rj = r[start + j];
 732            sword16 rjl = r[start + j + 16];
 733            sword16 t = rj + rjl;
 734            r[start + j] = t;
 735            rjl = rj - rjl;
 736            p = (sword32)zeta * rjl;
 737            r[start + j + 16] = MLKEM_MONT_RED(p);
 738        }
 739    }
 740    /* len = 32 */
 741    for (start = 0; start < MLKEM_N; start += 2 * 32) {
 742        zeta = zetas_inv[k++];
 743        for (j = 0; j < 32; ++j) {
 744            sword32 p;
 745            sword16 rj = r[start + j];
 746            sword16 rjl = r[start + j + 32];
 747            sword16 t = rj + rjl;
 748            r[start + j] = t;
 749            rjl = rj - rjl;
 750            p = (sword32)zeta * rjl;
 751            r[start + j + 32] = MLKEM_MONT_RED(p);
 752        }
 753    }
 754    /* len = 64 */
 755    for (start = 0; start < MLKEM_N; start += 2 * 64) {
 756        zeta = zetas_inv[k++];
 757        for (j = 0; j < 64; ++j) {
 758            sword32 p;
 759            sword16 rj = r[start + j];
 760            sword16 rjl = r[start + j + 64];
 761            sword16 t = rj + rjl;
 762            /* Reduce. */
 763            r[start + j] = MLKEM_BARRETT_RED(t);
 764            rjl = rj - rjl;
 765            p = (sword32)zeta * rjl;
 766            r[start + j + 64] = MLKEM_MONT_RED(p);
 767        }
 768    }
 769    /* len = 128, 256 */
 770    zeta = zetas_inv[126];
 771    zeta2 = zetas_inv[127];
 772    for (j = 0; j < MLKEM_N / 2; ++j) {
 773        sword32 p;
 774        sword16 rj = r[j];
 775        sword16 rjl = r[j + MLKEM_N / 2];
 776        sword16 t = rj + rjl;
 777        rjl = rj - rjl;
 778        p = (sword32)zeta * rjl;
 779        r[j] = t;
 780        r[j + MLKEM_N / 2] = MLKEM_MONT_RED(p);
 781
 782        p = (sword32)zeta2 * r[j];
 783        r[j] = MLKEM_MONT_RED(p);
 784        p = (sword32)zeta2 * r[j + MLKEM_N / 2];
 785        r[j + MLKEM_N / 2] = MLKEM_MONT_RED(p);
 786    }
 787#else
 788    /* Unroll len (2, 3, 3) and start loops. */
 789    unsigned int j;
 790    sword16 t0;
 791    sword16 t1;
 792    sword16 t2;
 793    sword16 t3;
 794    sword16 zeta64_0;
 795    sword16 zeta64_1;
 796    sword16 zeta128;
 797    sword16 zeta256;
 798    sword32 p;
 799
 800    for (j = 0; j < MLKEM_N; j += 8) {
 801        sword16 zeta2_0 = zetas_inv[ 0 + j / 4 + 0];
 802        sword16 zeta2_1 = zetas_inv[ 0 + j / 4 + 1];
 803        sword16 zeta4   = zetas_inv[64 + j / 8 + 0];
 804        sword16 r0 = r[j + 0];
 805        sword16 r1 = r[j + 1];
 806        sword16 r2 = r[j + 2];
 807        sword16 r3 = r[j + 3];
 808        sword16 r4 = r[j + 4];
 809        sword16 r5 = r[j + 5];
 810        sword16 r6 = r[j + 6];
 811        sword16 r7 = r[j + 7];
 812
 813        p = (sword32)zeta2_0 * (sword16)(r0 - r2);
 814        t0 = MLKEM_MONT_RED(p);
 815        p = (sword32)zeta2_0 * (sword16)(r1 - r3);
 816        t1 = MLKEM_MONT_RED(p);
 817        p = (sword32)zeta2_1 * (sword16)(r4 - r6);
 818        t2 = MLKEM_MONT_RED(p);
 819        p = (sword32)zeta2_1 * (sword16)(r5 - r7);
 820        t3 = MLKEM_MONT_RED(p);
 821        r0 = (sword16)(r0 + r2);
 822        r1 = (sword16)(r1 + r3);
 823        r4 = (sword16)(r4 + r6);
 824        r5 = (sword16)(r5 + r7);
 825        r2 = t0;
 826        r3 = t1;
 827        r6 = t2;
 828        r7 = t3;
 829
 830        p = (sword32)zeta4 * (sword16)(r0 - r4);
 831        t0 = MLKEM_MONT_RED(p);
 832        p = (sword32)zeta4 * (sword16)(r1 - r5);
 833        t1 = MLKEM_MONT_RED(p);
 834        p = (sword32)zeta4 * (sword16)(r2 - r6);
 835        t2 = MLKEM_MONT_RED(p);
 836        p = (sword32)zeta4 * (sword16)(r3 - r7);
 837        t3 = MLKEM_MONT_RED(p);
 838        r0 = (sword16)(r0 + r4);
 839        r1 = (sword16)(r1 + r5);
 840        r2 = (sword16)(r2 + r6);
 841        r3 = (sword16)(r3 + r7);
 842        r4 = t0;
 843        r5 = t1;
 844        r6 = t2;
 845        r7 = t3;
 846
 847        r[j + 0] = r0;
 848        r[j + 1] = r1;
 849        r[j + 2] = r2;
 850        r[j + 3] = r3;
 851        r[j + 4] = r4;
 852        r[j + 5] = r5;
 853        r[j + 6] = r6;
 854        r[j + 7] = r7;
 855    }
 856
 857    for (j = 0; j < MLKEM_N; j += 64) {
 858        unsigned int i;
 859        sword16 zeta8_0  = zetas_inv[ 96 + j / 16 + 0];
 860        sword16 zeta8_1  = zetas_inv[ 96 + j / 16 + 1];
 861        sword16 zeta8_2  = zetas_inv[ 96 + j / 16 + 2];
 862        sword16 zeta8_3  = zetas_inv[ 96 + j / 16 + 3];
 863        sword16 zeta16_0 = zetas_inv[112 + j / 32 + 0];
 864        sword16 zeta16_1 = zetas_inv[112 + j / 32 + 1];
 865        sword16 zeta32   = zetas_inv[120 + j / 64 + 0];
 866        for (i = 0; i < 8; i++) {
 867            sword16 r0 = r[j + i +  0];
 868            sword16 r1 = r[j + i +  8];
 869            sword16 r2 = r[j + i + 16];
 870            sword16 r3 = r[j + i + 24];
 871            sword16 r4 = r[j + i + 32];
 872            sword16 r5 = r[j + i + 40];
 873            sword16 r6 = r[j + i + 48];
 874            sword16 r7 = r[j + i + 56];
 875
 876            p = (sword32)zeta8_0 * (sword16)(r0 - r1);
 877            t0 = MLKEM_MONT_RED(p);
 878            p = (sword32)zeta8_1 * (sword16)(r2 - r3);
 879            t1 = MLKEM_MONT_RED(p);
 880            p = (sword32)zeta8_2 * (sword16)(r4 - r5);
 881            t2 = MLKEM_MONT_RED(p);
 882            p = (sword32)zeta8_3 * (sword16)(r6 - r7);
 883            t3 = MLKEM_MONT_RED(p);
 884            r0 = MLKEM_BARRETT_RED(r0 + r1);
 885            r2 = MLKEM_BARRETT_RED(r2 + r3);
 886            r4 = MLKEM_BARRETT_RED(r4 + r5);
 887            r6 = MLKEM_BARRETT_RED(r6 + r7);
 888            r1 = t0;
 889            r3 = t1;
 890            r5 = t2;
 891            r7 = t3;
 892
 893            p = (sword32)zeta16_0 * (sword16)(r0 - r2);
 894            t0 = MLKEM_MONT_RED(p);
 895            p = (sword32)zeta16_0 * (sword16)(r1 - r3);
 896            t1 = MLKEM_MONT_RED(p);
 897            p = (sword32)zeta16_1 * (sword16)(r4 - r6);
 898            t2 = MLKEM_MONT_RED(p);
 899            p = (sword32)zeta16_1 * (sword16)(r5 - r7);
 900            t3 = MLKEM_MONT_RED(p);
 901            r0 = (sword16)(r0 + r2);
 902            r1 = (sword16)(r1 + r3);
 903            r4 = (sword16)(r4 + r6);
 904            r5 = (sword16)(r5 + r7);
 905            r2 = t0;
 906            r3 = t1;
 907            r6 = t2;
 908            r7 = t3;
 909
 910            p = (sword32)zeta32 * (sword16)(r0 - r4);
 911            t0 = MLKEM_MONT_RED(p);
 912            p = (sword32)zeta32 * (sword16)(r1 - r5);
 913            t1 = MLKEM_MONT_RED(p);
 914            p = (sword32)zeta32 * (sword16)(r2 - r6);
 915            t2 = MLKEM_MONT_RED(p);
 916            p = (sword32)zeta32 * (sword16)(r3 - r7);
 917            t3 = MLKEM_MONT_RED(p);
 918            r0 = (sword16)(r0 + r4);
 919            r1 = (sword16)(r1 + r5);
 920            r2 = (sword16)(r2 + r6);
 921            r3 = (sword16)(r3 + r7);
 922            r4 = t0;
 923            r5 = t1;
 924            r6 = t2;
 925            r7 = t3;
 926
 927            r[j + i +  0] = r0;
 928            r[j + i +  8] = r1;
 929            r[j + i + 16] = r2;
 930            r[j + i + 24] = r3;
 931            r[j + i + 32] = r4;
 932            r[j + i + 40] = r5;
 933            r[j + i + 48] = r6;
 934            r[j + i + 56] = r7;
 935        }
 936    }
 937
 938    zeta64_0 = zetas_inv[124];
 939    zeta64_1 = zetas_inv[125];
 940    zeta128  = zetas_inv[126];
 941    zeta256  = zetas_inv[127];
 942    for (j = 0; j < MLKEM_N / 8; j++) {
 943        sword16 r0 = r[j +   0];
 944        sword16 r1 = r[j +  32];
 945        sword16 r2 = r[j +  64];
 946        sword16 r3 = r[j +  96];
 947        sword16 r4 = r[j + 128];
 948        sword16 r5 = r[j + 160];
 949        sword16 r6 = r[j + 192];
 950        sword16 r7 = r[j + 224];
 951
 952        p = (sword32)zeta64_0 * (sword16)(r0 - r2);
 953        t0 = MLKEM_MONT_RED(p);
 954        p = (sword32)zeta64_0 * (sword16)(r1 - r3);
 955        t1 = MLKEM_MONT_RED(p);
 956        p = (sword32)zeta64_1 * (sword16)(r4 - r6);
 957        t2 = MLKEM_MONT_RED(p);
 958        p = (sword32)zeta64_1 * (sword16)(r5 - r7);
 959        t3 = MLKEM_MONT_RED(p);
 960        r0 = MLKEM_BARRETT_RED(r0 + r2);
 961        r1 = MLKEM_BARRETT_RED(r1 + r3);
 962        r4 = MLKEM_BARRETT_RED(r4 + r6);
 963        r5 = MLKEM_BARRETT_RED(r5 + r7);
 964        r2 = t0;
 965        r3 = t1;
 966        r6 = t2;
 967        r7 = t3;
 968
 969        p = (sword32)zeta128 * (sword16)(r0 - r4);
 970        t0 = MLKEM_MONT_RED(p);
 971        p = (sword32)zeta128 * (sword16)(r1 - r5);
 972        t1 = MLKEM_MONT_RED(p);
 973        p = (sword32)zeta128 * (sword16)(r2 - r6);
 974        t2 = MLKEM_MONT_RED(p);
 975        p = (sword32)zeta128 * (sword16)(r3 - r7);
 976        t3 = MLKEM_MONT_RED(p);
 977        r0 = (sword16)(r0 + r4);
 978        r1 = (sword16)(r1 + r5);
 979        r2 = (sword16)(r2 + r6);
 980        r3 = (sword16)(r3 + r7);
 981        r4 = t0;
 982        r5 = t1;
 983        r6 = t2;
 984        r7 = t3;
 985
 986        p = (sword32)zeta256 * r0;
 987        r0 = MLKEM_MONT_RED(p);
 988        p = (sword32)zeta256 * r1;
 989        r1 = MLKEM_MONT_RED(p);
 990        p = (sword32)zeta256 * r2;
 991        r2 = MLKEM_MONT_RED(p);
 992        p = (sword32)zeta256 * r3;
 993        r3 = MLKEM_MONT_RED(p);
 994        p = (sword32)zeta256 * r4;
 995        r4 = MLKEM_MONT_RED(p);
 996        p = (sword32)zeta256 * r5;
 997        r5 = MLKEM_MONT_RED(p);
 998        p = (sword32)zeta256 * r6;
 999        r6 = MLKEM_MONT_RED(p);
1000        p = (sword32)zeta256 * r7;
1001        r7 = MLKEM_MONT_RED(p);
1002
1003        r[j +   0] = r0;
1004        r[j +  32] = r1;
1005        r[j +  64] = r2;
1006        r[j +  96] = r3;
1007        r[j + 128] = r4;
1008        r[j + 160] = r5;
1009        r[j + 192] = r6;
1010        r[j + 224] = r7;
1011    }
1012#endif
1013}
1014#endif
1015
1016/* Multiplication of polynomials in Zq[X]/(X^2-zeta).
1017 *
1018 * Used for multiplication of elements in Rq in NTT domain.
1019 *
1020 * FIPS 203, Algorithm 12: BaseCaseMultiply(a0, a1, b0, b1, zeta)
1021 * Computes the product of two degree-one polynomials with respect to a
1022 * quadratic modulus.
1023 *   1: c0 <- a0.b0 + a1.b1.zeta
1024 *   2: c1 <- a0.b1 + a1.b0
1025 *   3: return (c0, c1)
1026 *
1027 * @param  [out]  r     Result polynomial.
1028 * @param  [in]   a     First factor.
1029 * @param  [in]   b     Second factor.
1030 * @param  [in]   zeta  Integer defining the reduction polynomial.
1031 */
1032static void mlkem_basemul(sword16* r, const sword16* a, const sword16* b,
1033    sword16 zeta)
1034{
1035    sword16 r0;
1036    sword16 a0 = a[0];
1037    sword16 a1 = a[1];
1038    sword16 b0 = b[0];
1039    sword16 b1 = b[1];
1040    sword32 p1;
1041    sword32 p2;
1042
1043    /* Step 1 */
1044    p1   = (sword32)a0 * b0;
1045    p2   = (sword32)a1 * b1;
1046    r0   = MLKEM_MONT_RED(p2);
1047    p2   = (sword32)zeta * r0;
1048    p2  += p1;
1049    r[0] = MLKEM_MONT_RED(p2);
1050
1051    /* Step 2 */
1052    p1   = (sword32)a0 * b1;
1053    p2   = (sword32)a1 * b0;
1054    p1  += p2;
1055    r[1] = MLKEM_MONT_RED(p1);
1056}
1057
1058/* Multiply two polynomials in NTT domain. r = a * b.
1059 *
1060 * FIPS 203, Algorithm 11: MultiplyNTTs(f_hat, g_hat)
1061 * Computes the product (in the ring T_q) of two NTT representations.
1062 *   1: for (i <- 0; i < 128; i++)
1063 *   2:     (h_hat[2i],h_hat[2i+1]) <-
1064 *              BaseCaseMultiply(f_hat[2i],f_hat[2i+1],g_hat[2i],g_hat[2i+1],
1065 *                               zetas^(BitRev_7(i)+1))
1066 *   3: end for
1067 *   4: return h_hat
1068 *
1069 * @param  [out]  r  Result polynomial.
1070 * @param  [in]   a  First polynomial multiplier.
1071 * @param  [in]   b  Second polynomial multiplier.
1072 */
1073static void mlkem_basemul_mont(sword16* r, const sword16* a, const sword16* b)
1074{
1075    const sword16* zeta = zetas + 64;
1076
1077#if defined(WOLFSSL_MLKEM_SMALL)
1078    /* Two multiplications per loop. */
1079    unsigned int i;
1080    /* Step 1 */
1081    for (i = 0; i < MLKEM_N; i += 4, zeta++) {
1082        /* Step 2 */
1083        mlkem_basemul(r + i + 0, a + i + 0, b + i + 0, zeta[0]);
1084        mlkem_basemul(r + i + 2, a + i + 2, b + i + 2, (sword16)(-zeta[0]));
1085    }
1086#elif defined(WOLFSSL_MLKEM_NO_LARGE_CODE)
1087    /* Four multiplications per loop. */
1088    unsigned int i;
1089    for (i = 0; i < MLKEM_N; i += 8, zeta += 2) {
1090        mlkem_basemul(r + i + 0, a + i + 0, b + i + 0, zeta[0]);
1091        mlkem_basemul(r + i + 2, a + i + 2, b + i + 2, (sword16)(-zeta[0]));
1092        mlkem_basemul(r + i + 4, a + i + 4, b + i + 4, zeta[1]);
1093        mlkem_basemul(r + i + 6, a + i + 6, b + i + 6, (sword16)(-zeta[1]));
1094    }
1095#else
1096    /* Eight multiplications per loop. */
1097    unsigned int i;
1098    for (i = 0; i < MLKEM_N; i += 16, zeta += 4) {
1099        mlkem_basemul(r + i +  0, a + i +  0, b + i +  0, zeta[0]);
1100        mlkem_basemul(r + i +  2, a + i +  2, b + i +  2, (sword16)(-zeta[0]));
1101        mlkem_basemul(r + i +  4, a + i +  4, b + i +  4, zeta[1]);
1102        mlkem_basemul(r + i +  6, a + i +  6, b + i +  6, (sword16)(-zeta[1]));
1103        mlkem_basemul(r + i +  8, a + i +  8, b + i +  8, zeta[2]);
1104        mlkem_basemul(r + i + 10, a + i + 10, b + i + 10, (sword16)(-zeta[2]));
1105        mlkem_basemul(r + i + 12, a + i + 12, b + i + 12, zeta[3]);
1106        mlkem_basemul(r + i + 14, a + i + 14, b + i + 14, (sword16)(-zeta[3]));
1107    }
1108#endif
1109}
1110
1111/* Multiply two polynomials in NTT domain and add to result. r += a * b.
1112 *
1113 * FIPS 203, Algorithm 11: MultiplyNTTs(f_hat, g_hat)
1114 * Computes the product (in the ring T_q) of two NTT representations.
1115 *   1: for (i <- 0; i < 128; i++)
1116 *   2:     (h_hat[2i],h_hat[2i+1]) <-
1117 *              BaseCaseMultiply(f_hat[2i],f_hat[2i+1],g_hat[2i],g_hat[2i+1],
1118 *                               zetas^(BitRev_7(i)+1))
1119 *   3: end for
1120 *   4: return h_hat
1121 * Add h_hat to r.
1122 *
1123 * @param  [in, out]  r  Result polynomial.
1124 * @param  [in]       a  First polynomial multiplier.
1125 * @param  [in]       b  Second polynomial multiplier.
1126 */
1127static void mlkem_basemul_mont_add(sword16* r, const sword16* a,
1128    const sword16* b)
1129{
1130    const sword16* zeta = zetas + 64;
1131
1132#if defined(WOLFSSL_MLKEM_SMALL)
1133    /* Two multiplications per loop. */
1134    unsigned int i;
1135    for (i = 0; i < MLKEM_N; i += 4, zeta++) {
1136        sword16 t0[2];
1137        sword16 t2[2];
1138
1139        mlkem_basemul(t0, a + i + 0, b + i + 0, zeta[0]);
1140        mlkem_basemul(t2, a + i + 2, b + i + 2, (sword16)(-zeta[0]));
1141
1142        r[i + 0] = (sword16)(r[i + 0] + t0[0]);
1143        r[i + 1] = (sword16)(r[i + 1] + t0[1]);
1144        r[i + 2] = (sword16)(r[i + 2] + t2[0]);
1145        r[i + 3] = (sword16)(r[i + 3] + t2[1]);
1146    }
1147#elif defined(WOLFSSL_MLKEM_NO_LARGE_CODE)
1148    /* Four multiplications per loop. */
1149    unsigned int i;
1150    for (i = 0; i < MLKEM_N; i += 8, zeta += 2) {
1151        sword16 t0[2];
1152        sword16 t2[2];
1153        sword16 t4[2];
1154        sword16 t6[2];
1155
1156        mlkem_basemul(t0, a + i + 0, b + i + 0, zeta[0]);
1157        mlkem_basemul(t2, a + i + 2, b + i + 2, (sword16)(-zeta[0]));
1158        mlkem_basemul(t4, a + i + 4, b + i + 4, zeta[1]);
1159        mlkem_basemul(t6, a + i + 6, b + i + 6, (sword16)(-zeta[1]));
1160
1161        r[i + 0] = (sword16)(r[i + 0] + t0[0]);
1162        r[i + 1] = (sword16)(r[i + 1] + t0[1]);
1163        r[i + 2] = (sword16)(r[i + 2] + t2[0]);
1164        r[i + 3] = (sword16)(r[i + 3] + t2[1]);
1165        r[i + 4] = (sword16)(r[i + 4] + t4[0]);
1166        r[i + 5] = (sword16)(r[i + 5] + t4[1]);
1167        r[i + 6] = (sword16)(r[i + 6] + t6[0]);
1168        r[i + 7] = (sword16)(r[i + 7] + t6[1]);
1169    }
1170#else
1171    /* Eight multiplications per loop. */
1172    unsigned int i;
1173    for (i = 0; i < MLKEM_N; i += 16, zeta += 4) {
1174        sword16 t0[2];
1175        sword16 t2[2];
1176        sword16 t4[2];
1177        sword16 t6[2];
1178        sword16 t8[2];
1179        sword16 t10[2];
1180        sword16 t12[2];
1181        sword16 t14[2];
1182
1183        mlkem_basemul(t0, a + i + 0, b + i + 0, zeta[0]);
1184        mlkem_basemul(t2, a + i + 2, b + i + 2, (sword16)(-zeta[0]));
1185        mlkem_basemul(t4, a + i + 4, b + i + 4, zeta[1]);
1186        mlkem_basemul(t6, a + i + 6, b + i + 6, (sword16)(-zeta[1]));
1187        mlkem_basemul(t8, a + i + 8, b + i + 8, zeta[2]);
1188        mlkem_basemul(t10, a + i + 10, b + i + 10, (sword16)(-zeta[2]));
1189        mlkem_basemul(t12, a + i + 12, b + i + 12, zeta[3]);
1190        mlkem_basemul(t14, a + i + 14, b + i + 14, (sword16)(-zeta[3]));
1191
1192        r[i + 0] = (sword16)(r[i + 0] + t0[0]);
1193        r[i + 1] = (sword16)(r[i + 1] + t0[1]);
1194        r[i + 2] = (sword16)(r[i + 2] + t2[0]);
1195        r[i + 3] = (sword16)(r[i + 3] + t2[1]);
1196        r[i + 4] = (sword16)(r[i + 4] + t4[0]);
1197        r[i + 5] = (sword16)(r[i + 5] + t4[1]);
1198        r[i + 6] = (sword16)(r[i + 6] + t6[0]);
1199        r[i + 7] = (sword16)(r[i + 7] + t6[1]);
1200        r[i + 8] = (sword16)(r[i + 8] + t8[0]);
1201        r[i + 9] = (sword16)(r[i + 9] + t8[1]);
1202        r[i + 10] = (sword16)(r[i + 10] + t10[0]);
1203        r[i + 11] = (sword16)(r[i + 11] + t10[1]);
1204        r[i + 12] = (sword16)(r[i + 12] + t12[0]);
1205        r[i + 13] = (sword16)(r[i + 13] + t12[1]);
1206        r[i + 14] = (sword16)(r[i + 14] + t14[0]);
1207        r[i + 15] = (sword16)(r[i + 15] + t14[1]);
1208    }
1209#endif
1210}
1211#endif
1212
1213/* Pointwise multiply elements of a and b, into r, and multiply by 2^-16.
1214 *
1215 * @param  [out]  r  Result polynomial.
1216 * @param  [in]   a  First vector polynomial to multiply with.
1217 * @param  [in]   b  Second vector polynomial to multiply with.
1218 * @param  [in]   k  Number of polynomials in vector.
1219 */
1220static void mlkem_pointwise_acc_mont(sword16* r, const sword16* a,
1221    const sword16* b, unsigned int k)
1222{
1223    unsigned int i;
1224
1225    mlkem_basemul_mont(r, a, b);
1226#ifdef WOLFSSL_MLKEM_SMALL
1227    for (i = 1; i < k; ++i) {
1228        mlkem_basemul_mont_add(r, a + i * MLKEM_N, b + i * MLKEM_N);
1229    }
1230#else
1231    for (i = 1; i < k - 1; ++i) {
1232        mlkem_basemul_mont_add(r, a + i * MLKEM_N, b + i * MLKEM_N);
1233    }
1234    mlkem_basemul_mont_add(r, a + (k - 1) * MLKEM_N, b + (k - 1) * MLKEM_N);
1235#endif
1236}
1237
1238/******************************************************************************/
1239
1240/* Initialize ML-KEM implementation.
1241 */
1242void mlkem_init(void)
1243{
1244#if defined(USE_INTEL_SPEEDUP) || (defined(__aarch64__) && \
1245    defined(WOLFSSL_ARMASM))
1246    cpuid_get_flags_ex(&cpuid_flags);
1247#endif
1248}
1249
1250/******************************************************************************/
1251
1252#if defined(__aarch64__) && defined(WOLFSSL_ARMASM)
1253
1254#ifndef WOLFSSL_MLKEM_NO_MAKE_KEY
1255/* Generate a public-private key pair from randomly generated data.
1256 *
1257 * FIPS 203, Algorithm 13: K-PKE.KeyGen(d)
1258 *   ...
1259 *   16: s_hat <- NTT(s)
1260 *   17: e_hat <- NTT(e)
1261 *   18: t_hat <- A_hat o s_hat + e_hat
1262 *   ...
1263 *
1264 * @param  [in, out]  s  Private key vector of polynomials.
1265 * @param  [out]      t  Public key vector of polynomials.
1266 * @param  [in, out]  e  Error values as a vector of polynomials. Modified.
1267 * @param  [in]       a  Random values in an array of vectors of polynomials.
1268 * @param  [in]       k  Number of polynomials in vector.
1269 */
1270void mlkem_keygen(sword16* s, sword16* t, sword16* e, const sword16* a, int k)
1271{
1272    int i;
1273
1274#ifndef WOLFSSL_AARCH64_NO_SQRDMLSH
1275    if (IS_AARCH64_RDM(cpuid_flags)) {
1276        /* Transform private key. All of result used in public key calculation.
1277         * Step 16: s_hat = NTT(s) */
1278        for (i = 0; i < k; ++i) {
1279            mlkem_ntt_sqrdmlsh(s + i * MLKEM_N);
1280        }
1281
1282        /* For each polynomial in the vectors.
1283         * Step 17, Step 18: Calculate public from A_hat, s_hat and e_hat. */
1284        for (i = 0; i < k; ++i) {
1285            /* Multiply a by private into public polynomial.
1286             * Step 18: ... A_hat o s_hat ... */
1287            mlkem_pointwise_acc_mont(t + i * MLKEM_N, a + i * k * MLKEM_N, s,
1288                (unsigned int)k);
1289            /* Convert public polynomial to Montgomery form.
1290             * Step 18: ... MontRed(A_hat o s_hat) ... */
1291            mlkem_to_mont_sqrdmlsh(t + i * MLKEM_N);
1292            /* Transform error values polynomial.
1293             * Step 17: e_hat = NTT(e) */
1294            mlkem_ntt_sqrdmlsh(e + i * MLKEM_N);
1295            /* Add errors to public key and reduce.
1296             * Step 18: t_hat = BarrettRed(MontRed(A_hat o s_hat) + e_hat) */
1297            mlkem_add_reduce(t + i * MLKEM_N, e + i * MLKEM_N);
1298        }
1299    }
1300    else
1301#endif
1302    {
1303        /* Transform private key. All of result used in public key calculation.
1304         * Step 16: s_hat = NTT(s) */
1305        for (i = 0; i < k; ++i) {
1306            mlkem_ntt(s + i * MLKEM_N);
1307        }
1308
1309        /* For each polynomial in the vectors.
1310         * Step 17, Step 18: Calculate public from A_hat, s_hat and e_hat. */
1311        for (i = 0; i < k; ++i) {
1312            /* Multiply a by private into public polynomial.
1313             * Step 18: ... A_hat o s_hat ... */
1314            mlkem_pointwise_acc_mont(t + i * MLKEM_N, a + i * k * MLKEM_N, s,
1315                (unsigned int)k);
1316            /* Convert public polynomial to Montgomery form.
1317             * Step 18: ... MontRed(A_hat o s_hat) ... */
1318            mlkem_to_mont(t + i * MLKEM_N);
1319            /* Transform error values polynomial.
1320             * Step 17: e_hat = NTT(e) */
1321            mlkem_ntt(e + i * MLKEM_N);
1322            /* Add errors to public key and reduce.
1323             * Step 18: t_hat = BarrettRed(MontRed(A_hat o s_hat) + e_hat) */
1324            mlkem_add_reduce(t + i * MLKEM_N, e + i * MLKEM_N);
1325        }
1326    }
1327}
1328#endif /* WOLFSSL_MLKEM_NO_MAKE_KEY */
1329
1330#if !defined(WOLFSSL_MLKEM_NO_ENCAPSULATE) || \
1331    !defined(WOLFSSL_MLKEM_NO_DECAPSULATE)
1332/* Encapsulate message.
1333 *
1334 * FIPS 203, Algorithm 14: K-PKE.Encrypt(ek_PKE, m, r)
1335 *   ...
1336 *   Step 18: y_hat <- NTT(y)
1337 *   Step 19: u <- InvNTT(A_hat_trans o y_hat) + e_1
1338 *   ...
1339 *   Step 21: v <- InvNTT(t_hat_trans o y_hat) + e_2 + mu
1340 *   ...
1341 *
1342 * @param  [in]       t   Public key vector of polynomials.
1343 * @param  [out]      u   Vector of polynomials.
1344 * @param  [out]      v   Polynomial.
1345 * @param  [in]       a   Array of vector of polynomials.
1346 * @param  [in, out]  y   Vector of polynomials.
1347 * @param  [in]       e1  Error Vector of polynomials.
1348 * @param  [in]       e2  Error polynomial.
1349 * @param  [in]       m   Message polynomial.
1350 * @param  [in]       k   Number of polynomials in vector.
1351 */
1352void mlkem_encapsulate(const sword16* t, sword16* u, sword16* v,
1353    const sword16* a, sword16* y, const sword16* e1, const sword16* e2,
1354    const sword16* m, int k)
1355{
1356    int i;
1357
1358#ifndef WOLFSSL_AARCH64_NO_SQRDMLSH
1359    if (IS_AARCH64_RDM(cpuid_flags)) {
1360        /* Transform y. All of result used in calculation of u and v.
1361         * Step 18: y_hat <- NTT(y) */
1362        for (i = 0; i < k; ++i) {
1363            mlkem_ntt_sqrdmlsh(y + i * MLKEM_N);
1364        }
1365
1366        /* For each polynomial in the vectors.
1367         * Step 19: u <- InvNTT(A_hat_trans o y_hat) + e_1 */
1368        for (i = 0; i < k; ++i) {
1369            /* Multiply at by y into u polynomial.
1370             * Step 19: ... A_hat_trans o y_hat ... */
1371            mlkem_pointwise_acc_mont(u + i * MLKEM_N, a + i * k * MLKEM_N, y,
1372                (unsigned int)k);
1373            /* Inverse transform u polynomial.
1374             * Step 19: ... InvNTT(A_hat_trans o y_hat) ... */
1375            mlkem_invntt_sqrdmlsh(u + i * MLKEM_N);
1376            /* Add errors to u and reduce.
1377             * Step 19: u <- InvNTT(A_hat_trans o y_hat) + e_1 */
1378            mlkem_add_reduce(u + i * MLKEM_N, e1 + i * MLKEM_N);
1379        }
1380
1381        /* Multiply public key by y into v polynomial.
1382         * Step 21: ... t_hat_trans o y_hat ... */
1383        mlkem_pointwise_acc_mont(v, t, y, (unsigned int)k);
1384        /* Inverse transform v.
1385         * Step 21: ... InvNTT(t_hat_trans o y_hat) ... */
1386        mlkem_invntt_sqrdmlsh(v);
1387    }
1388    else
1389#endif
1390    {
1391        /* Transform y. All of result used in calculation of u and v.
1392         * Step 18: y_hat <- NTT(y) */
1393        for (i = 0; i < k; ++i) {
1394            mlkem_ntt(y + i * MLKEM_N);
1395        }
1396
1397        /* For each polynomial in the vectors.
1398         * Step 19: u <- InvNTT(A_hat_trans o y_hat) + e_1 */
1399        for (i = 0; i < k; ++i) {
1400            /* Multiply at by y into u polynomial.
1401             * Step 19: ... A_hat_trans o y_hat ... */
1402            mlkem_pointwise_acc_mont(u + i * MLKEM_N, a + i * k * MLKEM_N, y,
1403                (unsigned int)k);
1404            /* Inverse transform u polynomial.
1405             * Step 19: ... InvNTT(A_hat_trans o y_hat) ... */
1406            mlkem_invntt(u + i * MLKEM_N);
1407            /* Add errors to u and reduce.
1408             * Step 19: u <- InvNTT(A_hat_trans o y_hat) + e_1 */
1409            mlkem_add_reduce(u + i * MLKEM_N, e1 + i * MLKEM_N);
1410        }
1411
1412        /* Multiply public key by y into v polynomial.
1413         * Step 21: ... t_hat_trans o y_hat ... */
1414        mlkem_pointwise_acc_mont(v, t, y, (unsigned int)k);
1415        /* Inverse transform v.
1416         * Step 21: ... InvNTT(t_hat_trans o y_hat) ... */
1417        mlkem_invntt(v);
1418    }
1419    /* Add errors and message to v and reduce.
1420     * Step 21: v <- InvNTT(t_hat_trans o y_hat) + e_2 + mu */
1421    mlkem_add3_reduce(v, e2, m);
1422}
1423#endif /* !WOLFSSL_MLKEM_NO_ENCAPSULATE || !WOLFSSL_MLKEM_NO_DECAPSULATE */
1424
1425#ifndef WOLFSSL_MLKEM_NO_DECAPSULATE
1426/* Decapsulate message.
1427 *
1428 * FIPS 203, Algorithm 15: K-PKE.Decrypt(dk_PKE,c)
1429 * Uses the decryption key to decrypt a ciphertext.
1430 *   ...
1431 *   6: w <- v' - InvNTT(s_hat_trans o NTT(u'))
1432 *   ...
1433 *
1434 * @param  [in]       s  Decryption key as vector of polynomials.
1435 * @param  [out]      w  Message polynomial.
1436 * @param  [in, out]  u  Vector of polynomials containing error.
1437 * @param  [in]       v  Encapsulated message polynomial.
1438 * @param  [in]       k  Number of polynomials in vector.
1439 */
1440void mlkem_decapsulate(const sword16* s, sword16* w, sword16* u,
1441    const sword16* v, int k)
1442{
1443    int i;
1444
1445#ifndef WOLFSSL_AARCH64_NO_SQRDMLSH
1446    if (IS_AARCH64_RDM(cpuid_flags)) {
1447        /* Transform u. All of result used in calculation of w.
1448         * Step 6: ... NTT(u') */
1449        for (i = 0; i < k; ++i) {
1450            mlkem_ntt_sqrdmlsh(u + i * MLKEM_N);
1451        }
1452
1453        /* Multiply private key by u into w polynomial.
1454         * Step 6: ... s_hat_trans o NTT(u') */
1455        mlkem_pointwise_acc_mont(w, s, u, (unsigned int)k);
1456        /* Inverse transform w.
1457         * Step 6: ... InvNTT(s_hat_trans o NTT(u')) */
1458        mlkem_invntt_sqrdmlsh(w);
1459    }
1460    else
1461#endif
1462    {
1463        /* Transform u. All of result used in calculation of w.
1464         * Step 6: ... NTT(u') */
1465        for (i = 0; i < k; ++i) {
1466            mlkem_ntt(u + i * MLKEM_N);
1467        }
1468
1469        /* Multiply private key by u into w polynomial.
1470         * Step 6: ... s_hat_trans o NTT(u') */
1471        mlkem_pointwise_acc_mont(w, s, u, (unsigned int)k);
1472        /* Inverse transform w.
1473         * Step 6: ... InvNTT(s_hat_trans o NTT(u')) */
1474        mlkem_invntt(w);
1475    }
1476    /* Subtract errors (in w) out of v and reduce into w.
1477     * Step 6: w <- v' - InvNTT(s_hat_trans o NTT(u')) */
1478    mlkem_rsub_reduce(w, v);
1479}
1480#endif /* !WOLFSSL_MLKEM_NO_DECAPSULATE */
1481
1482#else
1483
1484#ifndef WOLFSSL_MLKEM_NO_MAKE_KEY
1485
1486#if !defined(WOLFSSL_MLKEM_SMALL) && !defined(WOLFSSL_MLKEM_NO_LARGE_CODE)
1487/* Number-Theoretic Transform.
1488 *
1489 * FIPS 203, Algorithm 9: NTT(f)
1490 * Computes the NTT representation f_hat of the given polynomial f element of
1491 * R_q.
1492 *   1: f_hat <- f
1493 *   2: i <- 1
1494 *   3: for (len <- 128; len >= 2; len <- len/2)
1495 *   4:     for (start <- 0; start < 256; start <- start + 2.len)
1496 *   5:         zeta <- zetas^BitRev_7(i) mod q
1497 *   6:         i <- i + 1
1498 *   7:         for (j <- start; j < start + len; j++)
1499 *   8:             t <- zeta.f[j+len]
1500 *   9:             f_hat[j+len] <- f_hat[j] - t
1501 *  10:             f_hat[j] <- f_hat[j] + t
1502 *  11:         end for
1503 *  12:     end for
1504 *  13: end for
1505 *  14: return f_hat
1506 *
1507 * @param [in, out]  r  Polynomial to transform.
1508 * @param [in, out]  a  Polynomial to add NTT result to.
1509 */
1510static void mlkem_ntt_add_to(sword16* r, sword16* a)
1511{
1512#if defined(WOLFSSL_MLKEM_NTT_UNROLL)
1513    /* Unroll len loop (Step 3). */
1514    unsigned int k = 1;
1515    unsigned int j;
1516    unsigned int start;
1517    sword16 zeta = zetas[k++];
1518
1519    /* len = 128 */
1520    for (j = 0; j < MLKEM_N / 2; ++j) {
1521        sword32 p = (sword32)zeta * r[j + MLKEM_N / 2];
1522        sword16 t = MLKEM_MONT_RED(p);
1523        sword16 rj = r[j];
1524        r[j + MLKEM_N / 2] = rj - t;
1525        r[j] = rj + t;
1526    }
1527    /* len = 64 */
1528    for (start = 0; start < MLKEM_N; start += 2 * 64) {
1529        zeta = zetas[k++];
1530        for (j = 0; j < 64; ++j) {
1531            sword32 p = (sword32)zeta * r[start + j + 64];
1532            sword16 t = MLKEM_MONT_RED(p);
1533            sword16 rj = r[start + j];
1534            r[start + j + 64] = rj - t;
1535            r[start + j] = rj + t;
1536        }
1537    }
1538    /* len = 32 */
1539    for (start = 0; start < MLKEM_N; start += 2 * 32) {
1540        zeta = zetas[k++];
1541        for (j = 0; j < 32; ++j) {
1542            sword32 p = (sword32)zeta * r[start + j + 32];
1543            sword16 t = MLKEM_MONT_RED(p);
1544            sword16 rj = r[start + j];
1545            r[start + j + 32] = rj - t;
1546            r[start + j] = rj + t;
1547        }
1548    }
1549    /* len = 16 */
1550    for (start = 0; start < MLKEM_N; start += 2 * 16) {
1551        zeta = zetas[k++];
1552        for (j = 0; j < 16; ++j) {
1553            sword32 p = (sword32)zeta * r[start + j + 16];
1554            sword16 t = MLKEM_MONT_RED(p);
1555            sword16 rj = r[start + j];
1556            r[start + j + 16] = rj - t;
1557            r[start + j] = rj + t;
1558        }
1559    }
1560    /* len = 8 */
1561    for (start = 0; start < MLKEM_N; start += 2 * 8) {
1562        zeta = zetas[k++];
1563        for (j = 0; j < 8; ++j) {
1564            sword32 p = (sword32)zeta * r[start + j + 8];
1565            sword16 t = MLKEM_MONT_RED(p);
1566            sword16 rj = r[start + j];
1567            r[start + j + 8] = rj - t;
1568            r[start + j] = rj + t;
1569        }
1570    }
1571    /* len = 4 */
1572    for (start = 0; start < MLKEM_N; start += 2 * 4) {
1573        zeta = zetas[k++];
1574        for (j = 0; j < 4; ++j) {
1575            sword32 p = (sword32)zeta * r[start + j + 4];
1576            sword16 t = MLKEM_MONT_RED(p);
1577            sword16 rj = r[start + j];
1578            r[start + j + 4] = rj - t;
1579            r[start + j] = rj + t;
1580        }
1581    }
1582    /* len = 2 */
1583    for (start = 0; start < MLKEM_N; start += 2 * 2) {
1584        zeta = zetas[k++];
1585        for (j = 0; j < 2; ++j) {
1586            sword32 p = (sword32)zeta * r[start + j + 2];
1587            sword16 t = MLKEM_MONT_RED(p);
1588            sword16 rj = r[start + j];
1589            r[start + j + 2] = rj - t;
1590            r[start + j] = rj + t;
1591        }
1592    }
1593    /* Reduce coefficients with quick algorithm. */
1594    for (j = 0; j < MLKEM_N; ++j) {
1595        sword16 t = a[j] + r[j];
1596        a[j] = MLKEM_BARRETT_RED(t);
1597    }
1598#else /* !WOLFSSL_MLKEM_NTT_UNROLL */
1599    /* Unroll len (2, 3, 2) and start loops. */
1600    unsigned int j;
1601    sword16 t0;
1602    sword16 t1;
1603    sword16 t2;
1604    sword16 t3;
1605
1606    /* len = 128,64 */
1607    sword16 zeta128 = zetas[1];
1608    sword16 zeta64_0 = zetas[2];
1609    sword16 zeta64_1 = zetas[3];
1610    for (j = 0; j < MLKEM_N / 8; j++) {
1611        sword16 r0 = r[j +   0];
1612        sword16 r1 = r[j +  32];
1613        sword16 r2 = r[j +  64];
1614        sword16 r3 = r[j +  96];
1615        sword16 r4 = r[j + 128];
1616        sword16 r5 = r[j + 160];
1617        sword16 r6 = r[j + 192];
1618        sword16 r7 = r[j + 224];
1619
1620        t0 = MLKEM_MONT_RED((sword32)zeta128 * r4);
1621        t1 = MLKEM_MONT_RED((sword32)zeta128 * r5);
1622        t2 = MLKEM_MONT_RED((sword32)zeta128 * r6);
1623        t3 = MLKEM_MONT_RED((sword32)zeta128 * r7);
1624        r4 = (sword16)(r0 - t0);
1625        r5 = (sword16)(r1 - t1);
1626        r6 = (sword16)(r2 - t2);
1627        r7 = (sword16)(r3 - t3);
1628        r0 = (sword16)(r0 + t0);
1629        r1 = (sword16)(r1 + t1);
1630        r2 = (sword16)(r2 + t2);
1631        r3 = (sword16)(r3 + t3);
1632
1633        t0 = MLKEM_MONT_RED((sword32)zeta64_0 * r2);
1634        t1 = MLKEM_MONT_RED((sword32)zeta64_0 * r3);
1635        t2 = MLKEM_MONT_RED((sword32)zeta64_1 * r6);
1636        t3 = MLKEM_MONT_RED((sword32)zeta64_1 * r7);
1637        r2 = (sword16)(r0 - t0);
1638        r3 = (sword16)(r1 - t1);
1639        r6 = (sword16)(r4 - t2);
1640        r7 = (sword16)(r5 - t3);
1641        r0 = (sword16)(r0 + t0);
1642        r1 = (sword16)(r1 + t1);
1643        r4 = (sword16)(r4 + t2);
1644        r5 = (sword16)(r5 + t3);
1645
1646        r[j +   0] = r0;
1647        r[j +  32] = r1;
1648        r[j +  64] = r2;
1649        r[j +  96] = r3;
1650        r[j + 128] = r4;
1651        r[j + 160] = r5;
1652        r[j + 192] = r6;
1653        r[j + 224] = r7;
1654    }
1655
1656    /* len = 32,16,8 */
1657    for (j = 0; j < MLKEM_N; j += 64) {
1658        unsigned int i;
1659        sword16 zeta32   = zetas[ 4 + j / 64 + 0];
1660        sword16 zeta16_0 = zetas[ 8 + j / 32 + 0];
1661        sword16 zeta16_1 = zetas[ 8 + j / 32 + 1];
1662        sword16 zeta8_0  = zetas[16 + j / 16 + 0];
1663        sword16 zeta8_1  = zetas[16 + j / 16 + 1];
1664        sword16 zeta8_2  = zetas[16 + j / 16 + 2];
1665        sword16 zeta8_3  = zetas[16 + j / 16 + 3];
1666        for (i = 0; i < 8; i++) {
1667            sword16 r0 = r[j + i +  0];
1668            sword16 r1 = r[j + i +  8];
1669            sword16 r2 = r[j + i + 16];
1670            sword16 r3 = r[j + i + 24];
1671            sword16 r4 = r[j + i + 32];
1672            sword16 r5 = r[j + i + 40];
1673            sword16 r6 = r[j + i + 48];
1674            sword16 r7 = r[j + i + 56];
1675
1676            t0 = MLKEM_MONT_RED((sword32)zeta32 * r4);
1677            t1 = MLKEM_MONT_RED((sword32)zeta32 * r5);
1678            t2 = MLKEM_MONT_RED((sword32)zeta32 * r6);
1679            t3 = MLKEM_MONT_RED((sword32)zeta32 * r7);
1680            r4 = (sword16)(r0 - t0);
1681            r5 = (sword16)(r1 - t1);
1682            r6 = (sword16)(r2 - t2);
1683            r7 = (sword16)(r3 - t3);
1684            r0 = (sword16)(r0 + t0);
1685            r1 = (sword16)(r1 + t1);
1686            r2 = (sword16)(r2 + t2);
1687            r3 = (sword16)(r3 + t3);
1688
1689            t0 = MLKEM_MONT_RED((sword32)zeta16_0 * r2);
1690            t1 = MLKEM_MONT_RED((sword32)zeta16_0 * r3);
1691            t2 = MLKEM_MONT_RED((sword32)zeta16_1 * r6);
1692            t3 = MLKEM_MONT_RED((sword32)zeta16_1 * r7);
1693            r2 = (sword16)(r0 - t0);
1694            r3 = (sword16)(r1 - t1);
1695            r6 = (sword16)(r4 - t2);
1696            r7 = (sword16)(r5 - t3);
1697            r0 = (sword16)(r0 + t0);
1698            r1 = (sword16)(r1 + t1);
1699            r4 = (sword16)(r4 + t2);
1700            r5 = (sword16)(r5 + t3);
1701
1702            t0 = MLKEM_MONT_RED((sword32)zeta8_0 * r1);
1703            t1 = MLKEM_MONT_RED((sword32)zeta8_1 * r3);
1704            t2 = MLKEM_MONT_RED((sword32)zeta8_2 * r5);
1705            t3 = MLKEM_MONT_RED((sword32)zeta8_3 * r7);
1706            r1 = (sword16)(r0 - t0);
1707            r3 = (sword16)(r2 - t1);
1708            r5 = (sword16)(r4 - t2);
1709            r7 = (sword16)(r6 - t3);
1710            r0 = (sword16)(r0 + t0);
1711            r2 = (sword16)(r2 + t1);
1712            r4 = (sword16)(r4 + t2);
1713            r6 = (sword16)(r6 + t3);
1714
1715            r[j + i +  0] = r0;
1716            r[j + i +  8] = r1;
1717            r[j + i + 16] = r2;
1718            r[j + i + 24] = r3;
1719            r[j + i + 32] = r4;
1720            r[j + i + 40] = r5;
1721            r[j + i + 48] = r6;
1722            r[j + i + 56] = r7;
1723        }
1724    }
1725
1726    /* len = 4,2 and Final reduction */
1727    for (j = 0; j < MLKEM_N; j += 8) {
1728        sword16 zeta4  = zetas[32 + j / 8 + 0];
1729        sword16 zeta2_0 = zetas[64 + j / 4 + 0];
1730        sword16 zeta2_1 = zetas[64 + j / 4 + 1];
1731        sword16 r0 = r[j + 0];
1732        sword16 r1 = r[j + 1];
1733        sword16 r2 = r[j + 2];
1734        sword16 r3 = r[j + 3];
1735        sword16 r4 = r[j + 4];
1736        sword16 r5 = r[j + 5];
1737        sword16 r6 = r[j + 6];
1738        sword16 r7 = r[j + 7];
1739
1740        t0 = MLKEM_MONT_RED((sword32)zeta4 * r4);
1741        t1 = MLKEM_MONT_RED((sword32)zeta4 * r5);
1742        t2 = MLKEM_MONT_RED((sword32)zeta4 * r6);
1743        t3 = MLKEM_MONT_RED((sword32)zeta4 * r7);
1744        r4 = (sword16)(r0 - t0);
1745        r5 = (sword16)(r1 - t1);
1746        r6 = (sword16)(r2 - t2);
1747        r7 = (sword16)(r3 - t3);
1748        r0 = (sword16)(r0 + t0);
1749        r1 = (sword16)(r1 + t1);
1750        r2 = (sword16)(r2 + t2);
1751        r3 = (sword16)(r3 + t3);
1752
1753        t0 = MLKEM_MONT_RED((sword32)zeta2_0 * r2);
1754        t1 = MLKEM_MONT_RED((sword32)zeta2_0 * r3);
1755        t2 = MLKEM_MONT_RED((sword32)zeta2_1 * r6);
1756        t3 = MLKEM_MONT_RED((sword32)zeta2_1 * r7);
1757        r2 = (sword16)(r0 - t0);
1758        r3 = (sword16)(r1 - t1);
1759        r6 = (sword16)(r4 - t2);
1760        r7 = (sword16)(r5 - t3);
1761        r0 = (sword16)(r0 + t0);
1762        r1 = (sword16)(r1 + t1);
1763        r4 = (sword16)(r4 + t2);
1764        r5 = (sword16)(r5 + t3);
1765
1766        r0 = (sword16)(r0 + a[j + 0]);
1767        r1 = (sword16)(r1 + a[j + 1]);
1768        r2 = (sword16)(r2 + a[j + 2]);
1769        r3 = (sword16)(r3 + a[j + 3]);
1770        r4 = (sword16)(r4 + a[j + 4]);
1771        r5 = (sword16)(r5 + a[j + 5]);
1772        r6 = (sword16)(r6 + a[j + 6]);
1773        r7 = (sword16)(r7 + a[j + 7]);
1774
1775        a[j + 0] = MLKEM_BARRETT_RED(r0);
1776        a[j + 1] = MLKEM_BARRETT_RED(r1);
1777        a[j + 2] = MLKEM_BARRETT_RED(r2);
1778        a[j + 3] = MLKEM_BARRETT_RED(r3);
1779        a[j + 4] = MLKEM_BARRETT_RED(r4);
1780        a[j + 5] = MLKEM_BARRETT_RED(r5);
1781        a[j + 6] = MLKEM_BARRETT_RED(r6);
1782        a[j + 7] = MLKEM_BARRETT_RED(r7);
1783    }
1784#endif /* !WOLFSSL_MLKEM_NTT_UNROLL */
1785}
1786#endif /* !WOLFSSL_MLKEM_SMALL && !WOLFSSL_MLKEM_NO_LARGE_CODE */
1787
1788#ifndef WOLFSSL_MLKEM_MAKEKEY_SMALL_MEM
1789/* Generate a public-private key pair from randomly generated data.
1790 *
1791 * FIPS 203, Algorithm 13: K-PKE.KeyGen(d)
1792 *   ...
1793 *   16: s_hat <- NTT(s)
1794 *   17: e_hat <- NTT(e)
1795 *   18: t_hat <- A_hat o s_hat + e_hat
1796 *   ...
1797 *
1798 * @param  [in, out]  s  Private key vector of polynomials.
1799 * @param  [out]      t  Public key vector of polynomials.
1800 * @param  [in, out]  e  Error values as a vector of polynomials. Modified.
1801 * @param  [in]       a  Random values in an array of vectors of polynomials.
1802 * @param  [in]       k  Number of polynomials in vector.
1803 */
1804static void mlkem_keygen_c(sword16* s, sword16* t, sword16* e, const sword16* a,
1805    int k)
1806{
1807    int i;
1808
1809    /* Transform private key. All of result used in public key calculation
1810     * Step 16: s_hat = NTT(s) */
1811    for (i = 0; i < k; ++i) {
1812        mlkem_ntt(s + i * MLKEM_N);
1813    }
1814
1815    /* For each polynomial in the vectors.
1816     * Step 17, Step 18: Calculate public from A_hat, s_hat and e_hat. */
1817    for (i = 0; i < k; ++i) {
1818        int j;
1819
1820        /* Multiply a by private into public polynomial.
1821         * Step 18: ... A_hat o s_hat ... */
1822        mlkem_pointwise_acc_mont(t + i * MLKEM_N, a + i * k * MLKEM_N, s,
1823            (unsigned int)k);
1824        /* Convert public polynomial to Montgomery form.
1825         * Step 18: ... MontRed(A_hat o s_hat) ... */
1826        for (j = 0; j < MLKEM_N; ++j) {
1827            sword32 n = t[i * MLKEM_N + j] * (sword32)MLKEM_F;
1828            t[i * MLKEM_N + j] = MLKEM_MONT_RED(n);
1829        }
1830        /* Transform error values polynomial.
1831         * Step 17: e_hat = NTT(e) */
1832#if defined(WOLFSSL_MLKEM_SMALL) || defined(WOLFSSL_MLKEM_NO_LARGE_CODE)
1833        mlkem_ntt(e + i * MLKEM_N);
1834        /* Add errors to public key and reduce.
1835         * Step 18: t_hat = BarrettRed(MontRed(A_hat o s_hat) + e_hat) */
1836        for (j = 0; j < MLKEM_N; ++j) {
1837            sword16 n = (sword16)(t[i * MLKEM_N + j] + e[i * MLKEM_N + j]);
1838            t[i * MLKEM_N + j] = MLKEM_BARRETT_RED(n);
1839        }
1840#else
1841        /* Add errors to public key and reduce.
1842         * Step 18: t_hat = BarrettRed(MontRed(A_hat o s_hat) + e_hat) */
1843        mlkem_ntt_add_to(e + i * MLKEM_N, t + i * MLKEM_N);
1844#endif
1845    }
1846}
1847
1848/* Generate a public-private key pair from randomly generated data.
1849 *
1850 * FIPS 203, Algorithm 13: K-PKE.KeyGen(d)
1851 *   ...
1852 *   16: s_hat <- NTT(s)
1853 *   17: e_hat <- NTT(e)
1854 *   18: t_hat <- A_hat o s_hat + e_hat
1855 *   ...
1856 *
1857 * @param  [in, out]  s  Private key vector of polynomials.
1858 * @param  [out]      t  Public key vector of polynomials.
1859 * @param  [in, out]  e  Error values as a vector of polynomials. Modified.
1860 * @param  [in]       a  Random values in an array of vectors of polynomials.
1861 * @param  [in]       k  Number of polynomials in vector.
1862 */
1863void mlkem_keygen(sword16* s, sword16* t, sword16* e, const sword16* a, int k)
1864{
1865#ifdef USE_INTEL_SPEEDUP
1866    if (IS_INTEL_AVX2(cpuid_flags) && (SAVE_VECTOR_REGISTERS2() == 0)) {
1867        /* Alg 13: Steps 16-18 */
1868        mlkem_keygen_avx2(s, t, e, a, k);
1869        RESTORE_VECTOR_REGISTERS();
1870    }
1871    else
1872#endif
1873    {
1874        /* Alg 13: Steps 16-18 */
1875        mlkem_keygen_c(s, t, e, a, k);
1876    }
1877}
1878
1879#else /* WOLFSSL_MLKEM_MAKEKEY_SMALL_MEM */
1880
1881/* Generate a public-private key pair from randomly generated data.
1882 *
1883 * FIPS 203, Algorithm 13: K-PKE.KeyGen(d)
1884 *   3: for (i <- 0; i < k; i++)                         > generate matrix A_hat
1885 *   ... (generate A[i])
1886 *   7: end for
1887 *   ...
1888 *  13:      e[i] <- SamplePolyCBD_eta_1(PRF_eta_1(sigma, N))
1889 *   ...
1890 *  16: s_hat <- NTT(s)
1891 *  17: e_hat <- NTT(e)
1892 *  18: t_hat <- A_hat o s_hat + e_hat
1893 *   ...
1894 *
1895 * @param  [in, out]  s      Private key vector of polynomials.
1896 * @param  [out]      t      Public key vector of polynomials.
1897 * @param  [in, out]  prf    XOF object.
1898 * @param  [in]       tv     Temporary vector of polynomials.
1899 * @param  [in]       k      Number of polynomials in vector.
1900 * @param  [in]       rho    Random seed to generate matrix A from.
1901 * @param  [in, out]  sigma  Random seed to generate noise from.
1902 * @return  0 on success.
1903 * @return  MEMORY_E when dynamic memory allocation fails. Only possible when
1904 *          WOLFSSL_SMALL_STACK is defined.
1905 * @return  Other negative value when a hash error occurred.
1906 */
1907int mlkem_keygen_seeds(sword16* s, sword16* t, MLKEM_PRF_T* prf,
1908    sword16* tv, int k, byte* rho, byte* sigma)
1909{
1910    int i;
1911    int ret = 0;
1912    sword16* ai = tv;
1913    sword16* e = tv;
1914
1915    /* Transform private key. All of result used in public key calculation
1916     * Step 16: s_hat = NTT(s) */
1917    for (i = 0; i < k; ++i) {
1918        mlkem_ntt(s + i * MLKEM_N);
1919    }
1920
1921    /* For each polynomial in the vectors.
1922     * Step 17, Step 18: Calculate public from A_hat, s_hat and e_hat. */
1923    for (i = 0; i < k; ++i) {
1924        int j;
1925
1926        /* Generate a vector of matrix A.
1927         * Steps 4-6: generate A[i] */
1928        ret = mlkem_gen_matrix_i(prf, ai, k, rho, i, 0);
1929        if (ret != 0) {
1930           break;
1931        }
1932
1933        /* Multiply a by private into public polynomial.
1934         * Step 18: ... A_hat o s_hat ... */
1935        mlkem_pointwise_acc_mont(t + i * MLKEM_N, ai, s, (unsigned int)k);
1936        /* Convert public polynomial to Montgomery form.
1937         * Step 18: ... MontRed(A_hat o s_hat) ... */
1938        for (j = 0; j < MLKEM_N; ++j) {
1939            sword32 n = t[i * MLKEM_N + j] * (sword32)MLKEM_F;
1940            t[i * MLKEM_N + j] = MLKEM_MONT_RED(n);
1941        }
1942
1943        /* Generate noise using PRF.
1944         * Step 13: e[i] <- SamplePolyCBD_eta_1(PRF_eta_1(sigma, N)) */
1945        ret = mlkem_get_noise_i(prf, k, e, sigma, i, 1);
1946        if (ret != 0) {
1947           break;
1948        }
1949        /* Transform error values polynomial.
1950         * Step 17: e_hat = NTT(e) */
1951#if defined(WOLFSSL_MLKEM_SMALL) || defined(WOLFSSL_MLKEM_NO_LARGE_CODE)
1952        mlkem_ntt(e);
1953        /* Add errors to public key and reduce.
1954         * Step 18: t_hat = BarrettRed(MontRed(A_hat o s_hat) + e_hat) */
1955        for (j = 0; j < MLKEM_N; ++j) {
1956            sword16 n = (sword16)(t[i * MLKEM_N + j] + e[j]);
1957            t[i * MLKEM_N + j] = MLKEM_BARRETT_RED(n);
1958        }
1959#else
1960        /* Add errors to public key and reduce.
1961         * Step 18: t_hat = BarrettRed(MontRed(A_hat o s_hat) + e_hat) */
1962        mlkem_ntt_add_to(e, t + i * MLKEM_N);
1963#endif
1964    }
1965
1966    return ret;
1967}
1968
1969#endif /* WOLFSSL_MLKEM_MAKEKEY_SMALL_MEM */
1970#endif /* !WOLFSSL_MLKEM_NO_MAKE_KEY */
1971
1972#if !defined(WOLFSSL_MLKEM_NO_ENCAPSULATE) || \
1973    !defined(WOLFSSL_MLKEM_NO_DECAPSULATE)
1974#ifndef WOLFSSL_MLKEM_ENCAPSULATE_SMALL_MEM
1975/* Encapsulate message.
1976 *
1977 * @param  [in]       pub  Public key vector of polynomials.
1978 * @param  [out]      u    Vector of polynomials.
1979 * @param  [out]      v    Polynomial.
1980 * @param  [in]       a    Array of vector of polynomials.
1981 * @param  [in, out]  y    Vector of polynomials.
1982 * @param  [in]       e1   Error Vector of polynomials.
1983 * @param  [in]       e2   Error polynomial.
1984 * @param  [in]       m    Message polynomial.
1985 * @param  [in]       k    Number of polynomials in vector.
1986 */
1987static void mlkem_encapsulate_c(const sword16* pub, sword16* u, sword16* v,
1988    const sword16* a, sword16* y, const sword16* e1, const sword16* e2,
1989    const sword16* m, int k)
1990{
1991    int i;
1992
1993    /* Transform y. All of result used in calculation of u and v. */
1994    for (i = 0; i < k; ++i) {
1995        mlkem_ntt(y + i * MLKEM_N);
1996    }
1997
1998    /* For each polynomial in the vectors. */
1999    for (i = 0; i < k; ++i) {
2000        int j;
2001
2002        /* Multiply at by y into u polynomial. */
2003        mlkem_pointwise_acc_mont(u + i * MLKEM_N, a + i * k * MLKEM_N, y,
2004            (unsigned int)k);
2005        /* Inverse transform u polynomial. */
2006        mlkem_invntt(u + i * MLKEM_N);
2007        /* Add errors to u and reduce. */
2008#if defined(WOLFSSL_MLKEM_SMALL) || defined(WOLFSSL_MLKEM_NO_LARGE_CODE)
2009        for (j = 0; j < MLKEM_N; ++j) {
2010            sword16 t = (sword16)(u[i * MLKEM_N + j] + e1[i * MLKEM_N + j]);
2011            u[i * MLKEM_N + j] = MLKEM_BARRETT_RED(t);
2012        }
2013#else
2014        for (j = 0; j < MLKEM_N; j += 8) {
2015            sword16 t0 = (sword16)(u[i * MLKEM_N + j + 0] +
2016                                   e1[i * MLKEM_N + j + 0]);
2017            sword16 t1 = (sword16)(u[i * MLKEM_N + j + 1] +
2018                                   e1[i * MLKEM_N + j + 1]);
2019            sword16 t2 = (sword16)(u[i * MLKEM_N + j + 2] +
2020                                   e1[i * MLKEM_N + j + 2]);
2021            sword16 t3 = (sword16)(u[i * MLKEM_N + j + 3] +
2022                                   e1[i * MLKEM_N + j + 3]);
2023            sword16 t4 = (sword16)(u[i * MLKEM_N + j + 4] +
2024                                   e1[i * MLKEM_N + j + 4]);
2025            sword16 t5 = (sword16)(u[i * MLKEM_N + j + 5] +
2026                                   e1[i * MLKEM_N + j + 5]);
2027            sword16 t6 = (sword16)(u[i * MLKEM_N + j + 6] +
2028                                   e1[i * MLKEM_N + j + 6]);
2029            sword16 t7 = (sword16)(u[i * MLKEM_N + j + 7] +
2030                                   e1[i * MLKEM_N + j + 7]);
2031            u[i * MLKEM_N + j + 0] = MLKEM_BARRETT_RED(t0);
2032            u[i * MLKEM_N + j + 1] = MLKEM_BARRETT_RED(t1);
2033            u[i * MLKEM_N + j + 2] = MLKEM_BARRETT_RED(t2);
2034            u[i * MLKEM_N + j + 3] = MLKEM_BARRETT_RED(t3);
2035            u[i * MLKEM_N + j + 4] = MLKEM_BARRETT_RED(t4);
2036            u[i * MLKEM_N + j + 5] = MLKEM_BARRETT_RED(t5);
2037            u[i * MLKEM_N + j + 6] = MLKEM_BARRETT_RED(t6);
2038            u[i * MLKEM_N + j + 7] = MLKEM_BARRETT_RED(t7);
2039        }
2040#endif
2041    }
2042
2043    /* Multiply public key by y into v polynomial. */
2044    mlkem_pointwise_acc_mont(v, pub, y, (unsigned int)k);
2045    /* Inverse transform v. */
2046    mlkem_invntt(v);
2047    /* Add errors and message to v and reduce. */
2048    for (i = 0; i < MLKEM_N; ++i) {
2049        sword16 t = (sword16)(v[i] + e2[i] + m[i]);
2050        v[i] = MLKEM_BARRETT_RED(t);
2051    }
2052}
2053
2054/* Encapsulate message.
2055 *
2056 * @param  [in]       pub  Public key vector of polynomials.
2057 * @param  [out]      u    Vector of polynomials.
2058 * @param  [out]      v    Polynomial.
2059 * @param  [in]       a    Array of vector of polynomials.
2060 * @param  [in, out]  y    Vector of polynomials.
2061 * @param  [in]       e1   Error Vector of polynomials.
2062 * @param  [in]       e2   Error polynomial.
2063 * @param  [in]       m    Message polynomial.
2064 * @param  [in]       k    Number of polynomials in vector.
2065 */
2066void mlkem_encapsulate(const sword16* pub, sword16* u, sword16* v,
2067    const sword16* a, sword16* y, const sword16* e1, const sword16* e2,
2068    const sword16* m, int k)
2069{
2070#ifdef USE_INTEL_SPEEDUP
2071    if (IS_INTEL_AVX2(cpuid_flags) && (SAVE_VECTOR_REGISTERS2() == 0)) {
2072        mlkem_encapsulate_avx2(pub, u, v, a, y, e1, e2, m, k);
2073        RESTORE_VECTOR_REGISTERS();
2074    }
2075    else
2076#endif
2077    {
2078        mlkem_encapsulate_c(pub, u, v, a, y, e1, e2, m, k);
2079    }
2080}
2081
2082#else
2083
2084/* Encapsulate message.
2085 *
2086 * @param  [in]       pub    Public key vector of polynomials.
2087 * @param  [in, out]  prf    XOF object.
2088 * @param  [out]      u      Vector of polynomials.
2089 * @param  [in, out]  tp     Polynomial.
2090 * @param  [in, out]  y      Vector of polynomials.
2091 * @param  [in]       k      Number of polynomials in vector.
2092 * @param  [in]       msg    Message to encapsulate.
2093 * @param  [in]       seed   Random seed to generate matrix A from.
2094 * @param  [in, out]  coins  Random seed to generate noise from.
2095 * @return  0 on success.
2096 * @return  MEMORY_E when dynamic memory allocation fails. Only possible when
2097 *          WOLFSSL_SMALL_STACK is defined.
2098 * @return  Other negative value when a hash error occurred.
2099 */
2100int mlkem_encapsulate_seeds(const sword16* pub, MLKEM_PRF_T* prf, sword16* u,
2101    sword16* tp, sword16* y, int k, const byte* msg, byte* seed, byte* coins)
2102{
2103    int ret = 0;
2104    int i;
2105    sword16* a = tp;
2106    sword16* e1 = tp;
2107    sword16* v = tp;
2108    sword16* e2 = tp + MLKEM_N;
2109    sword16* m = y;
2110
2111    /* Transform y. All of result used in calculation of u and v. */
2112    for (i = 0; i < k; ++i) {
2113        mlkem_ntt(y + i * MLKEM_N);
2114    }
2115
2116    /* For each polynomial in the vectors. */
2117    for (i = 0; i < k; ++i) {
2118        int j;
2119
2120        /* Generate a vector of matrix A. */
2121        ret = mlkem_gen_matrix_i(prf, a, k, seed, i, 1);
2122        if (ret != 0) {
2123           break;
2124        }
2125
2126        /* Multiply at by y into u polynomial. */
2127        mlkem_pointwise_acc_mont(u + i * MLKEM_N, a, y, (unsigned int)k);
2128        /* Inverse transform u polynomial. */
2129        mlkem_invntt(u + i * MLKEM_N);
2130
2131        /* Generate noise using PRF. */
2132        ret = mlkem_get_noise_i(prf, k, e1, coins, i, 0);
2133        if (ret != 0) {
2134           break;
2135        }
2136        /* Add errors to u and reduce. */
2137#if defined(WOLFSSL_MLKEM_SMALL) || defined(WOLFSSL_MLKEM_NO_LARGE_CODE)
2138        for (j = 0; j < MLKEM_N; ++j) {
2139            sword16 t = (sword16)(u[i * MLKEM_N + j] + e1[j]);
2140            u[i * MLKEM_N + j] = MLKEM_BARRETT_RED(t);
2141        }
2142#else
2143        for (j = 0; j < MLKEM_N; j += 8) {
2144            sword16 t0 = (sword16)(u[i * MLKEM_N + j + 0] + e1[j + 0]);
2145            sword16 t1 = (sword16)(u[i * MLKEM_N + j + 1] + e1[j + 1]);
2146            sword16 t2 = (sword16)(u[i * MLKEM_N + j + 2] + e1[j + 2]);
2147            sword16 t3 = (sword16)(u[i * MLKEM_N + j + 3] + e1[j + 3]);
2148            sword16 t4 = (sword16)(u[i * MLKEM_N + j + 4] + e1[j + 4]);
2149            sword16 t5 = (sword16)(u[i * MLKEM_N + j + 5] + e1[j + 5]);
2150            sword16 t6 = (sword16)(u[i * MLKEM_N + j + 6] + e1[j + 6]);
2151            sword16 t7 = (sword16)(u[i * MLKEM_N + j + 7] + e1[j + 7]);
2152            u[i * MLKEM_N + j + 0] = MLKEM_BARRETT_RED(t0);
2153            u[i * MLKEM_N + j + 1] = MLKEM_BARRETT_RED(t1);
2154            u[i * MLKEM_N + j + 2] = MLKEM_BARRETT_RED(t2);
2155            u[i * MLKEM_N + j + 3] = MLKEM_BARRETT_RED(t3);
2156            u[i * MLKEM_N + j + 4] = MLKEM_BARRETT_RED(t4);
2157            u[i * MLKEM_N + j + 5] = MLKEM_BARRETT_RED(t5);
2158            u[i * MLKEM_N + j + 6] = MLKEM_BARRETT_RED(t6);
2159            u[i * MLKEM_N + j + 7] = MLKEM_BARRETT_RED(t7);
2160        }
2161#endif
2162    }
2163
2164    /* Multiply public key by y into v polynomial. */
2165    mlkem_pointwise_acc_mont(v, pub, y, (unsigned int)k);
2166    /* Inverse transform v. */
2167    mlkem_invntt(v);
2168
2169    mlkem_from_msg(m, msg);
2170
2171    /* Generate noise using PRF. */
2172    coins[WC_ML_KEM_SYM_SZ] = (byte)(2 * k);
2173    ret = mlkem_get_noise_eta2_c(prf, e2, coins);
2174    if (ret == 0) {
2175        /* Add errors and message to v and reduce. */
2176    #if defined(WOLFSSL_MLKEM_SMALL) || defined(WOLFSSL_MLKEM_NO_LARGE_CODE)
2177        for (i = 0; i < MLKEM_N; ++i) {
2178            sword16 t = (sword16)(v[i] + e2[i] + m[i]);
2179            v[i] = MLKEM_BARRETT_RED(t);
2180        }
2181    #else
2182        for (i = 0; i < MLKEM_N; i += 8) {
2183            sword16 t0 = (sword16)(v[i + 0] + e2[i + 0] + m[i + 0]);
2184            sword16 t1 = (sword16)(v[i + 1] + e2[i + 1] + m[i + 1]);
2185            sword16 t2 = (sword16)(v[i + 2] + e2[i + 2] + m[i + 2]);
2186            sword16 t3 = (sword16)(v[i + 3] + e2[i + 3] + m[i + 3]);
2187            sword16 t4 = (sword16)(v[i + 4] + e2[i + 4] + m[i + 4]);
2188            sword16 t5 = (sword16)(v[i + 5] + e2[i + 5] + m[i + 5]);
2189            sword16 t6 = (sword16)(v[i + 6] + e2[i + 6] + m[i + 6]);
2190            sword16 t7 = (sword16)(v[i + 7] + e2[i + 7] + m[i + 7]);
2191            v[i + 0] = MLKEM_BARRETT_RED(t0);
2192            v[i + 1] = MLKEM_BARRETT_RED(t1);
2193            v[i + 2] = MLKEM_BARRETT_RED(t2);
2194            v[i + 3] = MLKEM_BARRETT_RED(t3);
2195            v[i + 4] = MLKEM_BARRETT_RED(t4);
2196            v[i + 5] = MLKEM_BARRETT_RED(t5);
2197            v[i + 6] = MLKEM_BARRETT_RED(t6);
2198            v[i + 7] = MLKEM_BARRETT_RED(t7);
2199        }
2200    #endif
2201    }
2202
2203    return ret;
2204}
2205#endif
2206#endif /* !WOLFSSL_MLKEM_NO_ENCAPSULATE || !WOLFSSL_MLKEM_NO_DECAPSULATE */
2207
2208#ifndef WOLFSSL_MLKEM_NO_DECAPSULATE
2209
2210/* Decapsulate message.
2211 *
2212 * FIPS 203, Algorithm 15: K-PKE.Decrypt(dk_PKE,c)
2213 * Uses the decryption key to decrypt a ciphertext.
2214 *   ...
2215 *   6: w <- v' - InvNTT(s_hat_trans o NTT(u'))
2216 *   ...
2217 *
2218 * @param  [in]       s  Private key vector of polynomials.
2219 * @param  [out]      w  Message polynomial.
2220 * @param  [in, out]  u  Vector of polynomials containing error.
2221 * @param  [in]       v  Encapsulated message polynomial.
2222 * @param  [in]       k  Number of polynomials in vector.
2223 */
2224static void mlkem_decapsulate_c(const sword16* s, sword16* w, sword16* u,
2225    const sword16* v, int k)
2226{
2227    int i;
2228
2229    /* Transform u. All of result used in calculation of w.
2230     * Step 6: ... NTT(u') */
2231    for (i = 0; i < k; ++i) {
2232        mlkem_ntt(u + i * MLKEM_N);
2233    }
2234
2235    /* Multiply private key by u into w polynomial.
2236     * Step 6: ... s_hat_trans o NTT(u') */
2237    mlkem_pointwise_acc_mont(w, s, u, (unsigned int)k);
2238    /* Inverse transform w.
2239     * Step 6: ... InvNTT(s_hat_trans o NTT(u')) */
2240    mlkem_invntt(w);
2241    /* Subtract errors (in w) out of v and reduce into w.
2242     * Step 6: w <- v' - InvNTT(s_hat_trans o NTT(u')) */
2243    for (i = 0; i < MLKEM_N; ++i) {
2244        sword16 t = (sword16)(v[i] - w[i]);
2245        w[i] = MLKEM_BARRETT_RED(t);
2246    }
2247}
2248
2249/* Decapsulate message.
2250 *
2251 * FIPS 203, Algorithm 15: K-PKE.Decrypt(dk_PKE,c)
2252 * Uses the decryption key to decrypt a ciphertext.
2253 *   ...
2254 *   6: w <- v' - InvNTT(s_hat_trans o NTT(u'))
2255 *   ...
2256 *
2257 * @param  [in]       s  Private key vector of polynomials.
2258 * @param  [out]      w  Message polynomial.
2259 * @param  [in, out]  u  Vector of polynomials containing error.
2260 * @param  [in]       v  Encapsulated message polynomial.
2261 * @param  [in]       k  Number of polynomials in vector.
2262 */
2263void mlkem_decapsulate(const sword16* s, sword16* w, sword16* u,
2264    const sword16* v, int k)
2265{
2266#ifdef USE_INTEL_SPEEDUP
2267    if (IS_INTEL_AVX2(cpuid_flags) && (SAVE_VECTOR_REGISTERS2() == 0)) {
2268        mlkem_decapsulate_avx2(s, w, u, v, k);
2269        RESTORE_VECTOR_REGISTERS();
2270    }
2271    else
2272#endif
2273    {
2274        mlkem_decapsulate_c(s, w, u, v, k);
2275    }
2276}
2277
2278#endif /* !WOLFSSL_MLKEM_NO_DECAPSULATE */
2279#endif
2280
2281/******************************************************************************/
2282
2283#if defined(USE_INTEL_SPEEDUP) && !defined(WC_SHA3_NO_ASM)
2284#if defined(WOLFSSL_KYBER512) || defined(WOLFSSL_WC_ML_KEM_512)
2285/* Deterministically generate a matrix (or transpose) of uniform integers mod q.
2286 *
2287 * Seed used with XOF to generate random bytes.
2288 *
2289 * @param  [out]  a           Matrix of uniform integers.
2290 * @param  [in]   seed        Bytes to seed XOF generation.
2291 * @param  [in]   transposed  Whether A or A^T is generated.
2292 * @return  0 on success.
2293 * @return  MEMORY_E when dynamic memory allocation fails. Only possible when
2294 *          WOLFSSL_SMALL_STACK is defined.
2295 */
2296static int mlkem_gen_matrix_k2_avx2(sword16* a, byte* seed, int transposed)
2297{
2298    int i;
2299#ifdef WOLFSSL_SMALL_STACK
2300    byte *rand = NULL;
2301    word64 *state = NULL;
2302#else
2303    byte rand[4 * GEN_MATRIX_SIZE + 4];
2304    word64 state[25 * 4];
2305#endif
2306    unsigned int ctr0;
2307    unsigned int ctr1;
2308    unsigned int ctr2;
2309    unsigned int ctr3;
2310    byte* p;
2311
2312#ifdef WOLFSSL_SMALL_STACK
2313    rand = (byte*)XMALLOC(4 * GEN_MATRIX_SIZE + 4, NULL,
2314                          DYNAMIC_TYPE_TMP_BUFFER);
2315    state = (word64*)XMALLOC(sizeof(word64) * 25 * 4, NULL,
2316                          DYNAMIC_TYPE_TMP_BUFFER);
2317    if ((rand == NULL) || (state == NULL)) {
2318        XFREE(rand, NULL, DYNAMIC_TYPE_TMP_BUFFER);
2319        XFREE(state, NULL, DYNAMIC_TYPE_TMP_BUFFER);
2320        return MEMORY_E;
2321    }
2322#endif
2323
2324    /* Loading 64 bits, only using 48 bits. Loading 4 bytes more than used. */
2325    rand[4 * GEN_MATRIX_SIZE + 0] = 0xff;
2326    rand[4 * GEN_MATRIX_SIZE + 1] = 0xff;
2327    rand[4 * GEN_MATRIX_SIZE + 2] = 0xff;
2328    rand[4 * GEN_MATRIX_SIZE + 3] = 0xff;
2329
2330    if (!transposed) {
2331        state[4*4 + 0] = 0x1f0000 + 0x000;
2332        state[4*4 + 1] = 0x1f0000 + 0x001;
2333        state[4*4 + 2] = 0x1f0000 + 0x100;
2334        state[4*4 + 3] = 0x1f0000 + 0x101;
2335    }
2336    else {
2337        state[4*4 + 0] = 0x1f0000 + 0x000;
2338        state[4*4 + 1] = 0x1f0000 + 0x100;
2339        state[4*4 + 2] = 0x1f0000 + 0x001;
2340        state[4*4 + 3] = 0x1f0000 + 0x101;
2341    }
2342
2343    sha3_128_blocksx4_seed_avx2(state, seed);
2344    mlkem_redistribute_21_rand_avx2(state, rand + 0 * GEN_MATRIX_SIZE,
2345        rand + 1 * GEN_MATRIX_SIZE, rand + 2 * GEN_MATRIX_SIZE,
2346        rand + 3 * GEN_MATRIX_SIZE);
2347    for (i = SHA3_128_BYTES; i < GEN_MATRIX_SIZE; i += SHA3_128_BYTES) {
2348        sha3_blocksx4_avx2(state);
2349        mlkem_redistribute_21_rand_avx2(state, rand + i + 0 * GEN_MATRIX_SIZE,
2350            rand + i + 1 * GEN_MATRIX_SIZE, rand + i + 2 * GEN_MATRIX_SIZE,
2351            rand + i + 3 * GEN_MATRIX_SIZE);
2352    }
2353
2354    /* Sample random bytes to create a polynomial. */
2355    p = rand;
2356    ctr0 = mlkem_rej_uniform_n_avx2(a + 0 * MLKEM_N, MLKEM_N, p,
2357        GEN_MATRIX_SIZE);
2358    p += GEN_MATRIX_SIZE;
2359    ctr1 = mlkem_rej_uniform_n_avx2(a + 1 * MLKEM_N, MLKEM_N, p,
2360        GEN_MATRIX_SIZE);
2361    p += GEN_MATRIX_SIZE;
2362    ctr2 = mlkem_rej_uniform_n_avx2(a + 2 * MLKEM_N, MLKEM_N, p,
2363        GEN_MATRIX_SIZE);
2364    p += GEN_MATRIX_SIZE;
2365    ctr3 = mlkem_rej_uniform_n_avx2(a + 3 * MLKEM_N, MLKEM_N, p,
2366        GEN_MATRIX_SIZE);
2367    /* Create more blocks if too many rejected. */
2368    while ((ctr0 < MLKEM_N) || (ctr1 < MLKEM_N) || (ctr2 < MLKEM_N) ||
2369           (ctr3 < MLKEM_N)) {
2370        sha3_blocksx4_avx2(state);
2371        mlkem_redistribute_21_rand_avx2(state, rand + 0 * GEN_MATRIX_SIZE,
2372            rand + 1 * GEN_MATRIX_SIZE, rand + 2 * GEN_MATRIX_SIZE,
2373            rand + 3 * GEN_MATRIX_SIZE);
2374
2375        p = rand;
2376        ctr0 += mlkem_rej_uniform_avx2(a + 0 * MLKEM_N + ctr0, MLKEM_N - ctr0,
2377            p, XOF_BLOCK_SIZE);
2378        p += GEN_MATRIX_SIZE;
2379        ctr1 += mlkem_rej_uniform_avx2(a + 1 * MLKEM_N + ctr1, MLKEM_N - ctr1,
2380            p, XOF_BLOCK_SIZE);
2381        p += GEN_MATRIX_SIZE;
2382        ctr2 += mlkem_rej_uniform_avx2(a + 2 * MLKEM_N + ctr2, MLKEM_N - ctr2,
2383            p, XOF_BLOCK_SIZE);
2384        p += GEN_MATRIX_SIZE;
2385        ctr3 += mlkem_rej_uniform_avx2(a + 3 * MLKEM_N + ctr3, MLKEM_N - ctr3,
2386            p, XOF_BLOCK_SIZE);
2387    }
2388
2389    WC_FREE_VAR_EX(rand, NULL, DYNAMIC_TYPE_TMP_BUFFER);
2390    WC_FREE_VAR_EX(state, NULL, DYNAMIC_TYPE_TMP_BUFFER);
2391
2392    return 0;
2393}
2394#endif
2395
2396#if defined(WOLFSSL_KYBER768) || defined(WOLFSSL_WC_ML_KEM_768)
2397/* Deterministically generate a matrix (or transpose) of uniform integers mod q.
2398 *
2399 * Seed used with XOF to generate random bytes.
2400 *
2401 * @param  [out]  a           Matrix of uniform integers.
2402 * @param  [in]   seed        Bytes to seed XOF generation.
2403 * @param  [in]   transposed  Whether A or A^T is generated.
2404 * @return  0 on success.
2405 * @return  MEMORY_E when dynamic memory allocation fails. Only possible when
2406 *          WOLFSSL_SMALL_STACK is defined.
2407 */
2408static int mlkem_gen_matrix_k3_avx2(sword16* a, byte* seed, int transposed)
2409{
2410    int i;
2411    int k;
2412#ifdef WOLFSSL_SMALL_STACK
2413    byte *rand = NULL;
2414    word64 *state = NULL;
2415#else
2416    byte rand[4 * GEN_MATRIX_SIZE + 4];
2417    word64 state[25 * 4];
2418#endif
2419    unsigned int ctr0;
2420    unsigned int ctr1;
2421    unsigned int ctr2;
2422    unsigned int ctr3;
2423    byte* p;
2424
2425#ifdef WOLFSSL_SMALL_STACK
2426    rand = (byte*)XMALLOC(4 * GEN_MATRIX_SIZE + 4, NULL,
2427                          DYNAMIC_TYPE_TMP_BUFFER);
2428    state = (word64*)XMALLOC(sizeof(word64) * 25 * 4, NULL,
2429                          DYNAMIC_TYPE_TMP_BUFFER);
2430    if ((rand == NULL) || (state == NULL)) {
2431        XFREE(rand, NULL, DYNAMIC_TYPE_TMP_BUFFER);
2432        XFREE(state, NULL, DYNAMIC_TYPE_TMP_BUFFER);
2433        return MEMORY_E;
2434    }
2435#endif
2436
2437    /* Loading 64 bits, only using 48 bits. Loading 4 bytes more than used. */
2438    rand[4 * GEN_MATRIX_SIZE + 0] = 0xff;
2439    rand[4 * GEN_MATRIX_SIZE + 1] = 0xff;
2440    rand[4 * GEN_MATRIX_SIZE + 2] = 0xff;
2441    rand[4 * GEN_MATRIX_SIZE + 3] = 0xff;
2442
2443    for (k = 0; k < 2; k++) {
2444        for (i = 0; i < 4; i++) {
2445            if (!transposed) {
2446                state[4*4 + i] = (word32)(0x1f0000 + (((k*4+i)/3) << 8) +
2447                                          ((k*4+i)%3));
2448            }
2449            else {
2450                state[4*4 + i] = (word32)(0x1f0000 + (((k*4+i)%3) << 8) +
2451                                          ((k*4+i)/3));
2452
2453            }
2454        }
2455
2456        sha3_128_blocksx4_seed_avx2(state, seed);
2457        mlkem_redistribute_21_rand_avx2(state,
2458            rand + 0 * GEN_MATRIX_SIZE, rand + 1 * GEN_MATRIX_SIZE,
2459            rand + 2 * GEN_MATRIX_SIZE, rand + 3 * GEN_MATRIX_SIZE);
2460        for (i = SHA3_128_BYTES; i < GEN_MATRIX_SIZE; i += SHA3_128_BYTES) {
2461            sha3_blocksx4_avx2(state);
2462            mlkem_redistribute_21_rand_avx2(state,
2463                rand + i + 0 * GEN_MATRIX_SIZE, rand + i + 1 * GEN_MATRIX_SIZE,
2464                rand + i + 2 * GEN_MATRIX_SIZE, rand + i + 3 * GEN_MATRIX_SIZE);
2465        }
2466
2467        /* Sample random bytes to create a polynomial. */
2468        p = rand;
2469        ctr0 = mlkem_rej_uniform_n_avx2(a + 0 * MLKEM_N, MLKEM_N, p,
2470            GEN_MATRIX_SIZE);
2471        p += GEN_MATRIX_SIZE;
2472        ctr1 = mlkem_rej_uniform_n_avx2(a + 1 * MLKEM_N, MLKEM_N, p,
2473            GEN_MATRIX_SIZE);
2474        p += GEN_MATRIX_SIZE;
2475        ctr2 = mlkem_rej_uniform_n_avx2(a + 2 * MLKEM_N, MLKEM_N, p,
2476            GEN_MATRIX_SIZE);
2477        p += GEN_MATRIX_SIZE;
2478        ctr3 = mlkem_rej_uniform_n_avx2(a + 3 * MLKEM_N, MLKEM_N, p,
2479            GEN_MATRIX_SIZE);
2480        /* Create more blocks if too many rejected. */
2481        while ((ctr0 < MLKEM_N) || (ctr1 < MLKEM_N) || (ctr2 < MLKEM_N) ||
2482               (ctr3 < MLKEM_N)) {
2483            sha3_blocksx4_avx2(state);
2484            mlkem_redistribute_21_rand_avx2(state, rand + 0 * GEN_MATRIX_SIZE,
2485                rand + 1 * GEN_MATRIX_SIZE, rand + 2 * GEN_MATRIX_SIZE,
2486                rand + 3 * GEN_MATRIX_SIZE);
2487
2488            p = rand;
2489            ctr0 += mlkem_rej_uniform_avx2(a + 0 * MLKEM_N + ctr0,
2490                MLKEM_N - ctr0, p, XOF_BLOCK_SIZE);
2491            p += GEN_MATRIX_SIZE;
2492            ctr1 += mlkem_rej_uniform_avx2(a + 1 * MLKEM_N + ctr1,
2493                MLKEM_N - ctr1, p, XOF_BLOCK_SIZE);
2494            p += GEN_MATRIX_SIZE;
2495            ctr2 += mlkem_rej_uniform_avx2(a + 2 * MLKEM_N + ctr2,
2496                MLKEM_N - ctr2, p, XOF_BLOCK_SIZE);
2497            p += GEN_MATRIX_SIZE;
2498            ctr3 += mlkem_rej_uniform_avx2(a + 3 * MLKEM_N + ctr3,
2499                MLKEM_N - ctr3, p, XOF_BLOCK_SIZE);
2500        }
2501
2502        a += 4 * MLKEM_N;
2503    }
2504
2505    readUnalignedWords64(state, seed, 4);
2506    /* Transposed value same as not. */
2507    state[4] = 0x1f0000 + (2 << 8) + 2;
2508    XMEMSET(state + 5, 0, sizeof(*state) * (25 - 5));
2509    state[20] = W64LIT(0x8000000000000000);
2510    for (i = 0; i < GEN_MATRIX_SIZE; i += SHA3_128_BYTES) {
2511#ifndef WC_SHA3_NO_ASM
2512        if (IS_INTEL_BMI2(cpuid_flags)) {
2513            sha3_block_bmi2(state);
2514        }
2515        else if (IS_INTEL_AVX2(cpuid_flags) && (SAVE_VECTOR_REGISTERS2() == 0))
2516        {
2517            sha3_block_avx2(state);
2518            RESTORE_VECTOR_REGISTERS();
2519        }
2520        else
2521#endif /* !WC_SHA3_NO_ASM */
2522        {
2523            BlockSha3(state);
2524        }
2525        XMEMCPY(rand + i, state, SHA3_128_BYTES);
2526    }
2527    ctr0 = mlkem_rej_uniform_n_avx2(a, MLKEM_N, rand, GEN_MATRIX_SIZE);
2528    while (ctr0 < MLKEM_N) {
2529#ifndef WC_SHA3_NO_ASM
2530        if (IS_INTEL_BMI2(cpuid_flags)) {
2531            sha3_block_bmi2(state);
2532        }
2533        else if (IS_INTEL_AVX2(cpuid_flags) && (SAVE_VECTOR_REGISTERS2() == 0))
2534        {
2535            sha3_block_avx2(state);
2536            RESTORE_VECTOR_REGISTERS();
2537        }
2538        else
2539#endif /* !WC_SHA3_NO_ASM */
2540        {
2541            BlockSha3(state);
2542        }
2543        XMEMCPY(rand, state, SHA3_128_BYTES);
2544        ctr0 += mlkem_rej_uniform_avx2(a + ctr0, MLKEM_N - ctr0, rand,
2545            XOF_BLOCK_SIZE);
2546    }
2547
2548    WC_FREE_VAR_EX(rand, NULL, DYNAMIC_TYPE_TMP_BUFFER);
2549    WC_FREE_VAR_EX(state, NULL, DYNAMIC_TYPE_TMP_BUFFER);
2550
2551    return 0;
2552}
2553#endif
2554#if defined(WOLFSSL_KYBER1024) || defined(WOLFSSL_WC_ML_KEM_1024)
2555/* Deterministically generate a matrix (or transpose) of uniform integers mod q.
2556 *
2557 * Seed used with XOF to generate random bytes.
2558 *
2559 * @param  [out]  a           Matrix of uniform integers.
2560 * @param  [in]   seed        Bytes to seed XOF generation.
2561 * @param  [in]   transposed  Whether A or A^T is generated.
2562 * @return  0 on success.
2563 * @return  MEMORY_E when dynamic memory allocation fails. Only possible when
2564 *          WOLFSSL_SMALL_STACK is defined.
2565 */
2566static int mlkem_gen_matrix_k4_avx2(sword16* a, byte* seed, int transposed)
2567{
2568    int i;
2569    int k;
2570#ifdef WOLFSSL_SMALL_STACK
2571    byte *rand = NULL;
2572    word64 *state = NULL;
2573#else
2574    byte rand[4 * GEN_MATRIX_SIZE + 4];
2575    word64 state[25 * 4];
2576#endif
2577    unsigned int ctr0;
2578    unsigned int ctr1;
2579    unsigned int ctr2;
2580    unsigned int ctr3;
2581    byte* p;
2582
2583#ifdef WOLFSSL_SMALL_STACK
2584    rand = (byte*)XMALLOC(4 * GEN_MATRIX_SIZE + 4, NULL,
2585                          DYNAMIC_TYPE_TMP_BUFFER);
2586    state = (word64*)XMALLOC(sizeof(word64) * 25 * 4, NULL,
2587                          DYNAMIC_TYPE_TMP_BUFFER);
2588    if ((rand == NULL) || (state == NULL)) {
2589        XFREE(rand, NULL, DYNAMIC_TYPE_TMP_BUFFER);
2590        XFREE(state, NULL, DYNAMIC_TYPE_TMP_BUFFER);
2591        return MEMORY_E;
2592    }
2593#endif
2594
2595    /* Loading 64 bits, only using 48 bits. Loading 4 bytes more than used. */
2596    rand[4 * GEN_MATRIX_SIZE + 0] = 0xff;
2597    rand[4 * GEN_MATRIX_SIZE + 1] = 0xff;
2598    rand[4 * GEN_MATRIX_SIZE + 2] = 0xff;
2599    rand[4 * GEN_MATRIX_SIZE + 3] = 0xff;
2600
2601    for (k = 0; k < 4; k++) {
2602        for (i = 0; i < 4; i++) {
2603            if (!transposed) {
2604                state[4*4 + i] = (word32)(0x1f0000 + (k << 8) + i);
2605            }
2606            else {
2607                state[4*4 + i] = (word32)(0x1f0000 + (i << 8) + k);
2608            }
2609        }
2610
2611        sha3_128_blocksx4_seed_avx2(state, seed);
2612        mlkem_redistribute_21_rand_avx2(state,
2613            rand + 0 * GEN_MATRIX_SIZE, rand + 1 * GEN_MATRIX_SIZE,
2614            rand + 2 * GEN_MATRIX_SIZE, rand + 3 * GEN_MATRIX_SIZE);
2615        for (i = SHA3_128_BYTES; i < GEN_MATRIX_SIZE; i += SHA3_128_BYTES) {
2616            sha3_blocksx4_avx2(state);
2617            mlkem_redistribute_21_rand_avx2(state,
2618                rand + i + 0 * GEN_MATRIX_SIZE, rand + i + 1 * GEN_MATRIX_SIZE,
2619                rand + i + 2 * GEN_MATRIX_SIZE, rand + i + 3 * GEN_MATRIX_SIZE);
2620        }
2621
2622        /* Sample random bytes to create a polynomial. */
2623        p = rand;
2624        ctr0 = mlkem_rej_uniform_n_avx2(a + 0 * MLKEM_N, MLKEM_N, p,
2625            GEN_MATRIX_SIZE);
2626        p += GEN_MATRIX_SIZE;
2627        ctr1 = mlkem_rej_uniform_n_avx2(a + 1 * MLKEM_N, MLKEM_N, p,
2628            GEN_MATRIX_SIZE);
2629        p += GEN_MATRIX_SIZE;
2630        ctr2 = mlkem_rej_uniform_n_avx2(a + 2 * MLKEM_N, MLKEM_N, p,
2631            GEN_MATRIX_SIZE);
2632        p += GEN_MATRIX_SIZE;
2633        ctr3 = mlkem_rej_uniform_n_avx2(a + 3 * MLKEM_N, MLKEM_N, p,
2634            GEN_MATRIX_SIZE);
2635        /* Create more blocks if too many rejected. */
2636        while ((ctr0 < MLKEM_N) || (ctr1 < MLKEM_N) || (ctr2 < MLKEM_N) ||
2637               (ctr3 < MLKEM_N)) {
2638            sha3_blocksx4_avx2(state);
2639            mlkem_redistribute_21_rand_avx2(state, rand + 0 * GEN_MATRIX_SIZE,
2640                rand + 1 * GEN_MATRIX_SIZE, rand + 2 * GEN_MATRIX_SIZE,
2641                rand + 3 * GEN_MATRIX_SIZE);
2642
2643            p = rand;
2644            ctr0 += mlkem_rej_uniform_avx2(a + 0 * MLKEM_N + ctr0,
2645                MLKEM_N - ctr0, p, XOF_BLOCK_SIZE);
2646            p += GEN_MATRIX_SIZE;
2647            ctr1 += mlkem_rej_uniform_avx2(a + 1 * MLKEM_N + ctr1,
2648                MLKEM_N - ctr1, p, XOF_BLOCK_SIZE);
2649            p += GEN_MATRIX_SIZE;
2650            ctr2 += mlkem_rej_uniform_avx2(a + 2 * MLKEM_N + ctr2,
2651                MLKEM_N - ctr2, p, XOF_BLOCK_SIZE);
2652            p += GEN_MATRIX_SIZE;
2653            ctr3 += mlkem_rej_uniform_avx2(a + 3 * MLKEM_N + ctr3,
2654                MLKEM_N - ctr3, p, XOF_BLOCK_SIZE);
2655        }
2656
2657        a += 4 * MLKEM_N;
2658    }
2659
2660    WC_FREE_VAR_EX(rand, NULL, DYNAMIC_TYPE_TMP_BUFFER);
2661    WC_FREE_VAR_EX(state, NULL, DYNAMIC_TYPE_TMP_BUFFER);
2662
2663    return 0;
2664}
2665#endif /* WOLFSSL_KYBER1024 || WOLFSSL_WC_ML_KEM_1024 */
2666#elif defined(WOLFSSL_ARMASM) && defined(__aarch64__)
2667#if defined(WOLFSSL_KYBER512) || defined(WOLFSSL_WC_ML_KEM_512)
2668/* Deterministically generate a matrix (or transpose) of uniform integers mod q.
2669 *
2670 * Seed used with XOF to generate random bytes.
2671 *
2672 * @param  [out]  a           Matrix of uniform integers.
2673 * @param  [in]   seed        Bytes to seed XOF generation.
2674 * @param  [in]   transposed  Whether A or A^T is generated.
2675 * @return  0 on success.
2676 */
2677static int mlkem_gen_matrix_k2_aarch64(sword16* a, byte* seed, int transposed)
2678{
2679    word64 state[3 * 25];
2680    word64* st = (word64*)state;
2681    unsigned int ctr0;
2682    unsigned int ctr1;
2683    unsigned int ctr2;
2684    byte* p;
2685
2686    if (!transposed) {
2687        state[0*25 + 4] = 0x1f0000 + (0 << 8) + 0;
2688        state[1*25 + 4] = 0x1f0000 + (0 << 8) + 1;
2689        state[2*25 + 4] = 0x1f0000 + (1 << 8) + 0;
2690    }
2691    else {
2692        state[0*25 + 4] = 0x1f0000 + (0 << 8) + 0;
2693        state[1*25 + 4] = 0x1f0000 + (1 << 8) + 0;
2694        state[2*25 + 4] = 0x1f0000 + (0 << 8) + 1;
2695    }
2696
2697    mlkem_shake128_blocksx3_seed_neon(state, seed);
2698    /* Sample random bytes to create a polynomial. */
2699    p = (byte*)st;
2700    ctr0 = mlkem_rej_uniform_neon(a + 0 * MLKEM_N, MLKEM_N, p, XOF_BLOCK_SIZE);
2701    p += 25 * 8;
2702    ctr1 = mlkem_rej_uniform_neon(a + 1 * MLKEM_N, MLKEM_N, p, XOF_BLOCK_SIZE);
2703    p += 25 * 8;
2704    ctr2 = mlkem_rej_uniform_neon(a + 2 * MLKEM_N, MLKEM_N, p, XOF_BLOCK_SIZE);
2705    while ((ctr0 < MLKEM_N) || (ctr1 < MLKEM_N) || (ctr2 < MLKEM_N)) {
2706        mlkem_sha3_blocksx3_neon(st);
2707
2708        p = (byte*)st;
2709        ctr0 += mlkem_rej_uniform_neon(a + 0 * MLKEM_N + ctr0, MLKEM_N - ctr0,
2710            p, XOF_BLOCK_SIZE);
2711        p += 25 * 8;
2712        ctr1 += mlkem_rej_uniform_neon(a + 1 * MLKEM_N + ctr1, MLKEM_N - ctr1,
2713            p, XOF_BLOCK_SIZE);
2714        p += 25 * 8;
2715        ctr2 += mlkem_rej_uniform_neon(a + 2 * MLKEM_N + ctr2, MLKEM_N - ctr2,
2716            p, XOF_BLOCK_SIZE);
2717    }
2718
2719    a += 3 * MLKEM_N;
2720
2721    readUnalignedWords64(state, seed, 4);
2722    /* Transposed value same as not. */
2723    state[4] = 0x1f0000 + (1 << 8) + 1;
2724    XMEMSET(state + 5, 0, sizeof(*state) * (25 - 5));
2725    state[20] = W64LIT(0x8000000000000000);
2726    BlockSha3(state);
2727    p = (byte*)state;
2728    ctr0 = mlkem_rej_uniform_neon(a, MLKEM_N, p, XOF_BLOCK_SIZE);
2729    while (ctr0 < MLKEM_N) {
2730        BlockSha3(state);
2731        ctr0 += mlkem_rej_uniform_neon(a + ctr0, MLKEM_N - ctr0, p,
2732            XOF_BLOCK_SIZE);
2733    }
2734
2735    return 0;
2736}
2737#endif
2738
2739#if defined(WOLFSSL_KYBER768) || defined(WOLFSSL_WC_ML_KEM_768)
2740/* Deterministically generate a matrix (or transpose) of uniform integers mod q.
2741 *
2742 * Seed used with XOF to generate random bytes.
2743 *
2744 * @param  [out]  a           Matrix of uniform integers.
2745 * @param  [in]   seed        Bytes to seed XOF generation.
2746 * @param  [in]   transposed  Whether A or A^T is generated.
2747 * @return  0 on success.
2748 */
2749static int mlkem_gen_matrix_k3_aarch64(sword16* a, byte* seed, int transposed)
2750{
2751    int i;
2752    int k;
2753    word64 state[3 * 25];
2754    word64* st = (word64*)state;
2755    unsigned int ctr0;
2756    unsigned int ctr1;
2757    unsigned int ctr2;
2758    byte* p;
2759
2760    for (k = 0; k < 3; k++) {
2761        for (i = 0; i < 3; i++) {
2762            if (!transposed) {
2763                state[i*25 + 4] = 0x1f0000 + ((k << 8) + i);
2764            }
2765            else {
2766                state[i*25 + 4] = 0x1f0000 + ((i << 8) + k);
2767            }
2768        }
2769
2770        mlkem_shake128_blocksx3_seed_neon(state, seed);
2771        /* Sample random bytes to create a polynomial. */
2772        p = (byte*)st;
2773        ctr0 = mlkem_rej_uniform_neon(a + 0 * MLKEM_N, MLKEM_N, p,
2774            XOF_BLOCK_SIZE);
2775        p += 25 * 8;
2776        ctr1 = mlkem_rej_uniform_neon(a + 1 * MLKEM_N, MLKEM_N, p,
2777            XOF_BLOCK_SIZE);
2778        p += 25 * 8;
2779        ctr2 = mlkem_rej_uniform_neon(a + 2 * MLKEM_N, MLKEM_N, p,
2780            XOF_BLOCK_SIZE);
2781        /* Create more blocks if too many rejected. */
2782        while ((ctr0 < MLKEM_N) || (ctr1 < MLKEM_N) || (ctr2 < MLKEM_N)) {
2783            mlkem_sha3_blocksx3_neon(st);
2784
2785            p = (byte*)st;
2786            ctr0 += mlkem_rej_uniform_neon(a + 0 * MLKEM_N + ctr0,
2787                MLKEM_N - ctr0, p, XOF_BLOCK_SIZE);
2788            p += 25 * 8;
2789            ctr1 += mlkem_rej_uniform_neon(a + 1 * MLKEM_N + ctr1,
2790                MLKEM_N - ctr1, p, XOF_BLOCK_SIZE);
2791            p += 25 * 8;
2792            ctr2 += mlkem_rej_uniform_neon(a + 2 * MLKEM_N + ctr2,
2793                MLKEM_N - ctr2, p, XOF_BLOCK_SIZE);
2794        }
2795
2796        a += 3 * MLKEM_N;
2797    }
2798
2799    return 0;
2800}
2801#endif
2802
2803#if defined(WOLFSSL_KYBER1024) || defined(WOLFSSL_WC_ML_KEM_1024)
2804/* Deterministically generate a matrix (or transpose) of uniform integers mod q.
2805 *
2806 * Seed used with XOF to generate random bytes.
2807 *
2808 * @param  [out]  a           Matrix of uniform integers.
2809 * @param  [in]   seed        Bytes to seed XOF generation.
2810 * @param  [in]   transposed  Whether A or A^T is generated.
2811 * @return  0 on success.
2812 */
2813static int mlkem_gen_matrix_k4_aarch64(sword16* a, byte* seed, int transposed)
2814{
2815    int i;
2816    int k;
2817    word64 state[3 * 25];
2818    word64* st = (word64*)state;
2819    unsigned int ctr0;
2820    unsigned int ctr1;
2821    unsigned int ctr2;
2822    byte* p;
2823
2824    for (k = 0; k < 5; k++) {
2825        for (i = 0; i < 3; i++) {
2826            byte bi = ((k * 3) + i) / 4;
2827            byte bj = ((k * 3) + i) % 4;
2828            if (!transposed) {
2829                state[i*25 + 4] = 0x1f0000 + (bi << 8) + bj;
2830            }
2831            else {
2832                state[i*25 + 4] = 0x1f0000 + (bj << 8) + bi;
2833            }
2834        }
2835
2836        mlkem_shake128_blocksx3_seed_neon(state, seed);
2837        /* Sample random bytes to create a polynomial. */
2838        p = (byte*)st;
2839        ctr0 = mlkem_rej_uniform_neon(a + 0 * MLKEM_N, MLKEM_N, p,
2840            XOF_BLOCK_SIZE);
2841        p += 25 * 8;
2842        ctr1 = mlkem_rej_uniform_neon(a + 1 * MLKEM_N, MLKEM_N, p,
2843            XOF_BLOCK_SIZE);
2844        p += 25 * 8;
2845        ctr2 = mlkem_rej_uniform_neon(a + 2 * MLKEM_N, MLKEM_N, p,
2846            XOF_BLOCK_SIZE);
2847        /* Create more blocks if too many rejected. */
2848        while ((ctr0 < MLKEM_N) || (ctr1 < MLKEM_N) || (ctr2 < MLKEM_N)) {
2849            mlkem_sha3_blocksx3_neon(st);
2850
2851            p = (byte*)st;
2852            ctr0 += mlkem_rej_uniform_neon(a + 0 * MLKEM_N + ctr0,
2853                MLKEM_N - ctr0, p, XOF_BLOCK_SIZE);
2854            p += 25 * 8;
2855            ctr1 += mlkem_rej_uniform_neon(a + 1 * MLKEM_N + ctr1,
2856                MLKEM_N - ctr1, p, XOF_BLOCK_SIZE);
2857            p += 25 * 8;
2858            ctr2 += mlkem_rej_uniform_neon(a + 2 * MLKEM_N + ctr2,
2859                MLKEM_N - ctr2, p, XOF_BLOCK_SIZE);
2860        }
2861
2862        a += 3 * MLKEM_N;
2863    }
2864
2865    readUnalignedWords64(state, seed, 4);
2866    /* Transposed value same as not. */
2867    state[4] = 0x1f0000 + (3 << 8) + 3;
2868    XMEMSET(state + 5, 0, sizeof(*state) * (25 - 5));
2869    state[20] = W64LIT(0x8000000000000000);
2870    BlockSha3(state);
2871    p = (byte*)state;
2872    ctr0 = mlkem_rej_uniform_neon(a, MLKEM_N, p, XOF_BLOCK_SIZE);
2873    while (ctr0 < MLKEM_N) {
2874        BlockSha3(state);
2875        ctr0 += mlkem_rej_uniform_neon(a + ctr0, MLKEM_N - ctr0, p,
2876            XOF_BLOCK_SIZE);
2877    }
2878
2879    return 0;
2880}
2881#endif
2882#endif /* USE_INTEL_SPEEDUP */
2883
2884#if !(defined(WOLFSSL_ARMASM) && defined(__aarch64__))
2885/* Absorb the seed data for squeezing out pseudo-random data.
2886 *
2887 * FIPS 203, Section 4.1:
2888 * 1. XOF.init() = SHAKE128.Init().
2889 * 2. XOF.Absorb(ctx,str) = SHAKE128.Absorb(ctx,str).
2890 *
2891 * @param  [in, out]  shake128  SHAKE-128 object.
2892 * @param  [in]       seed      Data to absorb.
2893 * @param  [in]       len       Length of data to absorb in bytes.
2894 * @return  0 on success always.
2895 */
2896static int mlkem_xof_absorb(wc_Shake* shake128, const byte* seed, int len)
2897{
2898    int ret;
2899
2900    ret = wc_InitShake128(shake128, NULL, INVALID_DEVID);
2901    if (ret == 0) {
2902        ret = wc_Shake128_Absorb(shake128, seed, (word32)len);
2903    }
2904
2905    return ret;
2906}
2907
2908/* Squeeze the state to produce pseudo-random data.
2909 *
2910 * FIPS 203, Section 4.1:
2911 * 3. XOF.Squeeze(ctx,l) = SHAKE128.Squeeze(ctx,8.l).
2912 *
2913 * @param  [in, out]  shake128  SHAKE-128 object.
2914 * @param  [out]      out       Buffer to write to.
2915 * @param  [in]       blocks    Number of blocks to write.
2916 * @return  0 on success always.
2917 */
2918static int mlkem_xof_squeezeblocks(wc_Shake* shake128, byte* out, int blocks)
2919{
2920    return wc_Shake128_SqueezeBlocks(shake128, out, (word32)blocks);
2921}
2922#endif
2923
2924/* New/Initialize SHA-3 object.
2925 *
2926 * FIPS 203, Section 4.1:
2927 * H(s) := SHA3-256(s)
2928 *
2929 * @param  [in, out]  hash    SHA-3 object.
2930 * @param  [in]       heap    Dynamic memory allocator hint.
2931 * @param  [in]       devId   Device id.
2932 * @return  0 on success always.
2933 */
2934int mlkem_hash_new(wc_Sha3* hash, void* heap, int devId)
2935{
2936    return wc_InitSha3_256(hash, heap, devId);
2937}
2938
2939/* Free SHA-3 object.
2940 *
2941 * FIPS 203, Section 4.1:
2942 * H(s) := SHA3-256(s)
2943 *
2944 * @param  [in, out]  hash  SHA-3 object.
2945 */
2946void mlkem_hash_free(wc_Sha3* hash)
2947{
2948    wc_Sha3_256_Free(hash);
2949}
2950
2951/* Hash data using SHA3-256 with SHA-3 object.
2952 *
2953 * FIPS 203, Section 4.1:
2954 * H(s) := SHA3-256(s)
2955 *
2956 * @param  [in, out]  hash     SHA-3 object.
2957 * @param  [in]       data     Data to be hashed.
2958 * @param  [in]       dataLen  Length of data in bytes.
2959 * @param  [out]      out      Hash of data.
2960 * @return  0 on success.
2961 */
2962int mlkem_hash256(wc_Sha3* hash, const byte* data, word32 dataLen, byte* out)
2963{
2964    int ret;
2965
2966    /* Process all data. */
2967    ret = wc_Sha3_256_Update(hash, data, dataLen);
2968    if (ret == 0) {
2969        /* Calculate Hash of data passed in and re-initialize. */
2970        ret = wc_Sha3_256_Final(hash, out);
2971    }
2972
2973    return ret;
2974}
2975
2976/* Hash one or two blocks of data using SHA3-512 with SHA-3 object.
2977 *
2978 * FIPS 203, Section 4.1:
2979 * G(s) := SHA3-512(s)
2980 *
2981 * @param  [in, out]  hash      SHA-3 object.
2982 * @param  [in]       data1     First block of data to be hashed.
2983 * @param  [in]       data1Len  Length of first block of data in bytes.
2984 * @param  [in]       data2     Second block of data to be hashed. May be NULL.
2985 * @param  [in]       data2Len  Length of second block of data in bytes.
2986 * @param  [out]      out       Hash of all data.
2987 * @return  0 on success.
2988 */
2989int mlkem_hash512(wc_Sha3* hash, const byte* data1, word32 data1Len,
2990    const byte* data2, word32 data2Len, byte* out)
2991{
2992    int ret;
2993
2994    /* Process first block of data. */
2995    ret = wc_Sha3_512_Update(hash, data1, data1Len);
2996    /* Check if there is a second block of data. */
2997    if ((ret == 0) && (data2 != NULL) && (data2Len > 0)) {
2998        /* Process second block of data. */
2999        ret = wc_Sha3_512_Update(hash, data2, data2Len);
3000    }
3001    if (ret == 0) {
3002        /* Calculate Hash of data passed in and re-initialize. */
3003        ret = wc_Sha3_512_Final(hash, out);
3004    }
3005
3006    return ret;
3007}
3008
3009/* Initialize SHAKE-256 object.
3010 *
3011 * @param  [in, out]  prf  SHAKE-256 object.
3012 */
3013void mlkem_prf_init(wc_Shake* prf)
3014{
3015    wc_InitShake256(prf, NULL, 0);
3016}
3017
3018/* New/Initialize SHAKE-256 object.
3019 *
3020 * FIPS 203, Section 4.1, 4.3:
3021 * PRF_eta(s,b) := SHAKE256(s||b,8.64.eta)
3022 *
3023 * @param  [in, out]  prf    SHAKE-256 object.
3024 * @param  [in]       heap   Dynamic memory allocator hint.
3025 * @param  [in]       devId  Device id.
3026 * @return  0 on success always.
3027 */
3028int mlkem_prf_new(wc_Shake* prf, void* heap, int devId)
3029{
3030    return wc_InitShake256(prf, heap, devId);
3031}
3032
3033/* Free SHAKE-256 object.
3034 *
3035 * FIPS 203, Section 4.1, 4.3:
3036 * PRF_eta(s,b) := SHAKE256(s||b,8.64.eta)
3037 *
3038 * @param  [in, out]  prf  SHAKE-256 object.
3039 */
3040void mlkem_prf_free(wc_Shake* prf)
3041{
3042    wc_Shake256_Free(prf);
3043}
3044
3045#if !(defined(WOLFSSL_ARMASM) && defined(__aarch64__))
3046/* Create pseudo-random data from the key using SHAKE-256.
3047 *
3048 * FIPS 203, Section 4.1, 4.3:
3049 * PRF_eta(s,b) := SHAKE256(s||b,8.64.eta)
3050 *
3051 * @param  [in, out]  shake256  SHAKE-256 object.
3052 * @param  [out]      out       Buffer to write to.
3053 * @param  [in]       outLen    Number of bytes to write.
3054 * @param  [in]       key       Data to derive from. Must be:
3055 *                                WC_ML_KEM_SYM_SZ + 1 bytes in length.
3056 * @return  0 on success always.
3057 */
3058static int mlkem_prf(wc_Shake* shake256, byte* out, unsigned int outLen,
3059    const byte* key)
3060{
3061#ifdef USE_INTEL_SPEEDUP
3062    word64 state[25];
3063
3064    (void)shake256;
3065
3066    /* Put first WC_ML_KEM_SYM_SZ bytes of key into blank state. */
3067    readUnalignedWords64(state, key, WC_ML_KEM_SYM_SZ / sizeof(word64));
3068    /* Last byte in with end of content marker. */
3069    state[WC_ML_KEM_SYM_SZ / 8] = 0x1f00 | key[WC_ML_KEM_SYM_SZ];
3070    /* Set rest of state to 0. */
3071    XMEMSET(state + WC_ML_KEM_SYM_SZ / 8 + 1, 0,
3072        (25 - WC_ML_KEM_SYM_SZ / 8 - 1) * sizeof(word64));
3073    /* ... except for rate marker. */
3074    state[WC_SHA3_256_COUNT - 1] = W64LIT(0x8000000000000000);
3075
3076    /* Generate as much output as is required. */
3077    while (outLen > 0) {
3078        /* Get as much of an output block as is needed. */
3079        unsigned int len = min(outLen, WC_SHA3_256_BLOCK_SIZE);
3080
3081        /* Perform a block operation on the state for next block of output. */
3082#ifndef WC_SHA3_NO_ASM
3083        if (IS_INTEL_BMI2(cpuid_flags)) {
3084            sha3_block_bmi2(state);
3085        }
3086        else if (IS_INTEL_AVX2(cpuid_flags) &&
3087                 (SAVE_VECTOR_REGISTERS2() == 0)) {
3088            sha3_block_avx2(state);
3089            RESTORE_VECTOR_REGISTERS();
3090        }
3091        else
3092#endif /* !WC_SHA3_NO_ASM */
3093        {
3094            BlockSha3(state);
3095        }
3096
3097        /* Copy the state as output. */
3098        XMEMCPY(out, state, len);
3099        /* Update output pointer and length. */
3100        out += len;
3101        outLen -= len;
3102    }
3103
3104    return 0;
3105#else
3106    int ret;
3107
3108    /* Process all data. */
3109    ret = wc_Shake256_Update(shake256, key, WC_ML_KEM_SYM_SZ + 1);
3110    if (ret == 0) {
3111        /* Calculate Hash of data passed in and re-initialize. */
3112        ret = wc_Shake256_Final(shake256, out, outLen);
3113    }
3114
3115    return ret;
3116#endif
3117}
3118#endif
3119
3120#ifdef WOLFSSL_MLKEM_KYBER
3121#ifdef USE_INTEL_SPEEDUP
3122/* Create pseudo-random key from the seed using SHAKE-256.
3123 *
3124 * @param  [in]  seed      Data to derive from.
3125 * @param  [in]  seedLen   Length of data to derive from in bytes.
3126 * @param  [out] out       Buffer to write to.
3127 * @param  [in]  outLen    Number of bytes to derive.
3128 * @return  0 on success always.
3129 */
3130int mlkem_kdf(const byte* seed, int seedLen, byte* out, int outLen)
3131{
3132    word64 state[25];
3133    word32 len64 = seedLen / 8;
3134
3135    readUnalignedWords64(state, seed, len64);
3136    state[len64] = 0x1f;
3137    XMEMSET(state + len64 + 1, 0, (25 - len64 - 1) * sizeof(word64));
3138    state[WC_SHA3_256_COUNT - 1] = W64LIT(0x8000000000000000);
3139
3140#ifndef WC_SHA3_NO_ASM
3141    if (IS_INTEL_BMI2(cpuid_flags)) {
3142        sha3_block_bmi2(state);
3143    }
3144    else if (IS_INTEL_AVX2(cpuid_flags) && (SAVE_VECTOR_REGISTERS2() == 0)) {
3145        sha3_block_avx2(state);
3146        RESTORE_VECTOR_REGISTERS();
3147    }
3148    else
3149#endif
3150    {
3151        BlockSha3(state);
3152    }
3153    XMEMCPY(out, state, outLen);
3154
3155    return 0;
3156}
3157#endif
3158
3159#if defined(WOLFSSL_ARMASM) && defined(__aarch64__)
3160/* Create pseudo-random key from the seed using SHAKE-256.
3161 *
3162 * @param  [in]  seed      Data to derive from.
3163 * @param  [in]  seedLen   Length of data to derive from in bytes.
3164 * @param  [out] out       Buffer to write to.
3165 * @param  [in]  outLen    Number of bytes to derive.
3166 * @return  0 on success always.
3167 */
3168int mlkem_kdf(const byte* seed, int seedLen, byte* out, int outLen)
3169{
3170    word64 state[25];
3171    word32 len64 = seedLen / 8;
3172
3173    readUnalignedWords64(state, seed, len64);
3174    state[len64] = 0x1f;
3175    XMEMSET(state + len64 + 1, 0, (25 - len64 - 1) * sizeof(word64));
3176    state[WC_SHA3_256_COUNT - 1] = W64LIT(0x8000000000000000);
3177
3178    BlockSha3(state);
3179    XMEMCPY(out, state, outLen);
3180
3181    return 0;
3182}
3183#endif
3184#endif
3185
3186#ifndef WOLFSSL_NO_ML_KEM
3187/* Derive the secret from z and cipher text.
3188 *
3189 * @param [in, out]  prf   SHAKE-256 object.
3190 * @param [in]       z     Implicit rejection value.
3191 * @param [in]       ct    Cipher text.
3192 * @param [in]       ctSz  Length of cipher text in bytes.
3193 * @param [out]      ss    Shared secret.
3194 * @return  0 on success.
3195 * @return  MEMORY_E when dynamic memory allocation failed.
3196 * @return  Other negative value when a hash error occurred.
3197 */
3198int mlkem_derive_secret(wc_Shake* prf, const byte* z, const byte* ct,
3199    word32 ctSz, byte* ss)
3200{
3201    int ret;
3202
3203#ifdef USE_INTEL_SPEEDUP
3204    XMEMCPY(prf->t, z, WC_ML_KEM_SYM_SZ);
3205    XMEMCPY(prf->t + WC_ML_KEM_SYM_SZ, ct,
3206        WC_SHA3_256_COUNT * 8 - WC_ML_KEM_SYM_SZ);
3207    prf->i = WC_ML_KEM_SYM_SZ + WC_SHA3_256_COUNT * 8 - WC_ML_KEM_SYM_SZ;
3208    ct += WC_SHA3_256_COUNT * 8 - WC_ML_KEM_SYM_SZ;
3209    ctSz -= WC_SHA3_256_COUNT * 8 - WC_ML_KEM_SYM_SZ;
3210    ret = wc_Shake256_Update(prf, ct, ctSz);
3211    if (ret == 0) {
3212        ret = wc_Shake256_Final(prf, ss, WC_ML_KEM_SS_SZ);
3213    }
3214#else
3215    ret = wc_InitShake256(prf, NULL, INVALID_DEVID);
3216    if (ret == 0) {
3217        ret = wc_Shake256_Update(prf, z, WC_ML_KEM_SYM_SZ);
3218    }
3219    if (ret == 0) {
3220        ret = wc_Shake256_Update(prf, ct, ctSz);
3221    }
3222    if (ret == 0) {
3223        ret = wc_Shake256_Final(prf, ss, WC_ML_KEM_SS_SZ);
3224    }
3225#endif
3226
3227    return ret;
3228}
3229#endif
3230
3231#if !defined(WOLFSSL_ARMASM)
3232/* Rejection sampling on uniform random bytes to generate uniform random
3233 * integers mod q.
3234 *
3235 * FIPS 203, Algorithm 7: SampleNTT(B)
3236 * Takes a 32-byte seed and two indices as input and outputs a pseudorandom
3237 * element of T_q.
3238 *   ...
3239 *   4: while j < 256 do
3240 *   5:     (ctx,C) <- XOF.Squeeze(ctx,3)
3241 *   6:     d1 <- C[0] + 256.(C[1] mod 16)
3242 *   7:     d2 <- lower(C[1] / 16) + 16.C[2]
3243 *   8:     if d1 < q then
3244 *   9:         a_hat[j] <- d1
3245 *  10:         j <- j + 1
3246 *  11:     end if
3247 *  12:     if d2 < q and j < 256 then
3248 *  13:         a_hat[j] <- d2
3249 *  14:         j <- j + 1
3250 *  15:     end if
3251 *  16: end while
3252 *  ...
3253 *
3254 * @param  [out]  p     Uniform random integers mod q.
3255 * @param  [in]   len   Maximum number of integers.
3256 * @param  [in]   r     Uniform random bytes buffer.
3257 * @param  [in]   rLen  Length of random data in buffer.
3258 * @return  Number of integers sampled.
3259 */
3260static unsigned int mlkem_rej_uniform_c(sword16* p, unsigned int len,
3261    const byte* r, unsigned int rLen)
3262{
3263    unsigned int i;
3264    unsigned int j;
3265
3266#if defined(WOLFSSL_MLKEM_SMALL) || !defined(WC_64BIT_CPU) || \
3267    defined(BIG_ENDIAN_ORDER)
3268    /* Keep sampling until max number of integers reached or buffer is used up.
3269     * Step 4. */
3270    for (i = 0, j = 0; (i < len) && (j <= rLen - 3); j += 3) {
3271        /* Step 5 - Now using 3 bytes of what the caller generated. */
3272        /* Use 24 bits (3 bytes) as two 12 bits integers. */
3273        /* Step 6. */
3274        sword16 v0 = ((r[0] >> 0) | ((word16)r[1] << 8)) & 0xFFF;
3275        /* Step 7. */
3276        sword16 v1 = ((r[1] >> 4) | ((word16)r[2] << 4)) & 0xFFF;
3277
3278        /* Reject first 12-bit integer if greater than or equal to q.
3279         * Step 8 */
3280        if (v0 < MLKEM_Q) {
3281            /* Steps 9-10 */
3282            p[i++] = v0;
3283        }
3284        /* Check second if we don't have enough integers yet.
3285         * Reject second 12-bit integer if greater than or equal to q.
3286         * Step 12 */
3287        if ((i < len) && (v1 < MLKEM_Q)) {
3288            /* Steps 13-14 */
3289            p[i++] = v1;
3290        }
3291
3292        /* Move over used bytes. */
3293        r += 3;
3294    }
3295#else
3296    /* Unroll loops. Minimal work per loop. */
3297    unsigned int minJ;
3298
3299    /* Calculate minimum number of 6 byte data blocks to get all required
3300     * numbers assuming no rejections. */
3301    minJ = len / 4 * 6;
3302    if (minJ > rLen)
3303        minJ = rLen;
3304    i = 0;
3305    for (j = 0; j < minJ; j += 6) {
3306        /* Use 48 bits (6 bytes) as four 12-bit integers. */
3307        word64 r_word = readUnalignedWord64(r);
3308        sword16 v0 =  r_word        & 0xfff;
3309        sword16 v1 = (r_word >> 12) & 0xfff;
3310        sword16 v2 = (r_word >> 24) & 0xfff;
3311        sword16 v3 = (r_word >> 36) & 0xfff;
3312
3313        p[i] = v0;
3314        i += (v0 < MLKEM_Q);
3315        p[i] = v1;
3316        i += (v1 < MLKEM_Q);
3317        p[i] = v2;
3318        i += (v2 < MLKEM_Q);
3319        p[i] = v3;
3320        i += (v3 < MLKEM_Q);
3321
3322        /* Move over used bytes. */
3323        r += 6;
3324    }
3325    /* Check whether we have all the numbers we need. */
3326    if (j < rLen) {
3327        /* Keep trying until we have fewer than 4 numbers to find or data is
3328         * used up. */
3329        for (; (i + 4 < len) && (j < rLen); j += 6) {
3330            /* Use 48 bits (6 bytes) as four 12-bit integers. */
3331            word64 r_word = readUnalignedWord64(r);
3332            sword16 v0 =  r_word        & 0xfff;
3333            sword16 v1 = (r_word >> 12) & 0xfff;
3334            sword16 v2 = (r_word >> 24) & 0xfff;
3335            sword16 v3 = (r_word >> 36) & 0xfff;
3336
3337            p[i] = v0;
3338            i += (v0 < MLKEM_Q);
3339            p[i] = v1;
3340            i += (v1 < MLKEM_Q);
3341            p[i] = v2;
3342            i += (v2 < MLKEM_Q);
3343            p[i] = v3;
3344            i += (v3 < MLKEM_Q);
3345
3346            /* Move over used bytes. */
3347            r += 6;
3348        }
3349        /* Keep trying until we have all the numbers we need or the data is used
3350         * up. */
3351        for (; (i < len) && (j < rLen); j += 6) {
3352            /* Use 48 bits (6 bytes) as four 12-bit integers. */
3353            word64 r_word = readUnalignedWord64(r);
3354            sword16 v0 =  r_word        & 0xfff;
3355            sword16 v1 = (r_word >> 12) & 0xfff;
3356            sword16 v2 = (r_word >> 24) & 0xfff;
3357            sword16 v3 = (r_word >> 36) & 0xfff;
3358
3359            /* Reject first 12-bit integer if greater than or equal to q. */
3360            if (v0 < MLKEM_Q) {
3361                p[i++] = v0;
3362            }
3363            /* Check second if we don't have enough integers yet.
3364             * Reject second 12-bit integer if greater than or equal to q. */
3365            if ((i < len) && (v1 < MLKEM_Q)) {
3366                p[i++] = v1;
3367            }
3368            /* Check third if we don't have enough integers yet.
3369             * Reject third 12-bit integer if greater than or equal to q. */
3370            if ((i < len) && (v2 < MLKEM_Q)) {
3371                p[i++] = v2;
3372            }
3373            /* Check fourth if we don't have enough integers yet.
3374             * Reject fourth 12-bit integer if greater than or equal to q. */
3375            if ((i < len) && (v3 < MLKEM_Q)) {
3376                p[i++] = v3;
3377            }
3378
3379            /* Move over used bytes. */
3380            r += 6;
3381        }
3382    }
3383#endif
3384
3385    return i;
3386}
3387#endif
3388
3389#if !defined(WOLFSSL_MLKEM_MAKEKEY_SMALL_MEM) || \
3390    !defined(WOLFSSL_MLKEM_ENCAPSULATE_SMALL_MEM)
3391
3392#if !(defined(WOLFSSL_ARMASM) && defined(__aarch64__))
3393/* Deterministically generate a matrix (or transpose) of uniform integers mod q.
3394 *
3395 * Seed used with XOF to generate random bytes.
3396 *
3397 * FIPS 203, Algorithm 13: K-PKE.KeyGen(d)
3398 *   ...
3399 *   3: for (i <- 0; i < k; i++)
3400 *   4:     for (j <- 0; j < k; j++)
3401 *   5:         A_hat[i,j] <- SampleNTT(rho||j||i)
3402 *   6:     end for
3403 *   7: end for
3404 *   ...
3405 * FIPS 203, Algorithm 14: K-PKE.Encrypt(ek_PKE,m,r)
3406 *   ...
3407 *   4: for (i <- 0; i < k; i++)
3408 *   5:     for (j <- 0; j < k; j++)
3409 *   6:         A_hat[i,j] <- SampleNTT(rho||j||i)  (Transposed is rho||i||j)
3410 *   7:     end for
3411 *   8: end for
3412 *   ...
3413 * FIPS 203, Algorithm 7: SampleNTT(B)
3414 * Takes a 32-byte seed and two indices as input and outputs a pseudorandom
3415 * element of T_q.
3416 *   1: ctx <- XOF.init()
3417 *   2: ctx <- XOF.Absorb(ctx,B)
3418 *   3: j <- 0
3419 *   4: while j < 256 do
3420 *   5:     (ctx,C) <- XOF.Squeeze(ctx,3)
3421 *   ...
3422 *  16: end while
3423 *  17: return a_hat
3424 *
3425 * @param  [in, out]  prf         XOF object.
3426 * @param  [out]      a           Matrix of uniform integers.
3427 * @param  [in]       k           Number of dimensions. k x k polynomials.
3428 * @param  [in]       seed        Bytes to seed XOF generation.
3429 * @param  [in]       transposed  Whether A or A^T is generated.
3430 * @return  0 on success.
3431 * @return  MEMORY_E when dynamic memory allocation fails. Only possible when
3432 *          WOLFSSL_SMALL_STACK is defined.
3433 */
3434static int mlkem_gen_matrix_c(MLKEM_PRF_T* prf, sword16* a, int k, byte* seed,
3435    int transposed)
3436{
3437#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC)
3438    byte* rand;
3439#else
3440    byte rand[GEN_MATRIX_SIZE + 2];
3441#endif
3442    byte extSeed[WC_ML_KEM_SYM_SZ + 2];
3443    int ret = 0;
3444    int i;
3445
3446    /* Copy seed into buffer that has space for i and j to be appended. */
3447    XMEMCPY(extSeed, seed, WC_ML_KEM_SYM_SZ);
3448
3449#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC)
3450    /* Allocate large amount of memory to hold random bytes to be sampled. */
3451    rand = (byte*)XMALLOC(GEN_MATRIX_SIZE + 2, NULL, DYNAMIC_TYPE_TMP_BUFFER);
3452    if (rand == NULL) {
3453        ret = MEMORY_E;
3454    }
3455#endif
3456
3457#if !defined(WOLFSSL_MLKEM_SMALL) && defined(WC_64BIT_CPU)
3458    /* Loading 64 bits, only using 48 bits. Loading 2 bytes more than used. */
3459    if (ret == 0) {
3460        rand[GEN_MATRIX_SIZE+0] = 0xff;
3461        rand[GEN_MATRIX_SIZE+1] = 0xff;
3462    }
3463#endif
3464
3465    /* Generate each vector of polynomials.
3466     * Alg 13, Step 3. Alg 14, Step 4. */
3467    for (i = 0; (ret == 0) && (i < k); i++, a += k * MLKEM_N) {
3468        int j;
3469        /* Generate each polynomial in vector from seed with indices.
3470         * Alg 13, Step 4. Alg 14, Step 5. */
3471        for (j = 0; (ret == 0) && (j < k); j++) {
3472            if (transposed) {
3473                /* Alg 14, Step 6: .. rho||i||j ... */
3474                extSeed[WC_ML_KEM_SYM_SZ + 0] = (byte)i;
3475                extSeed[WC_ML_KEM_SYM_SZ + 1] = (byte)j;
3476            }
3477            else {
3478                /* Alg 13, Step 5: .. rho||j||i ... */
3479                extSeed[WC_ML_KEM_SYM_SZ + 0] = (byte)j;
3480                extSeed[WC_ML_KEM_SYM_SZ + 1] = (byte)i;
3481            }
3482            /* Absorb the index specific seed.
3483             * Alg 7, Step 1-2 */
3484            ret = mlkem_xof_absorb(prf, extSeed, sizeof(extSeed));
3485            if (ret == 0) {
3486                /* Create data based on the seed.
3487                 * Alg 7, Step 5. Generating enough to, on average, be able to
3488                 * get enough valid values. */
3489                ret = mlkem_xof_squeezeblocks(prf, rand, GEN_MATRIX_NBLOCKS);
3490            }
3491            if (ret == 0) {
3492                unsigned int ctr;
3493
3494                /* Sample random bytes to create a polynomial.
3495                 * Alg 7, Step 3 - implicitly counter is 0.
3496                 * Alg 7, Step 4-16. */
3497                ctr = mlkem_rej_uniform_c(a + j * MLKEM_N, MLKEM_N, rand,
3498                    GEN_MATRIX_SIZE);
3499                /* Create more blocks if too many rejected.
3500                 * Alg 7, Step 4. */
3501                while (ctr < MLKEM_N) {
3502                    /* Alg 7, Step 5. */
3503                    mlkem_xof_squeezeblocks(prf, rand, 1);
3504                    /* Alg 7, Step 4-16. */
3505                    ctr += mlkem_rej_uniform_c(a + j * MLKEM_N + ctr,
3506                        MLKEM_N - ctr, rand, XOF_BLOCK_SIZE);
3507                }
3508            }
3509        }
3510    }
3511
3512#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC)
3513    /* Dispose of temporary buffer. */
3514    XFREE(rand, NULL, DYNAMIC_TYPE_TMP_BUFFER);
3515#endif
3516
3517    return ret;
3518}
3519#endif
3520
3521/* Deterministically generate a matrix (or transpose) of uniform integers mod q.
3522 *
3523 * Seed used with XOF to generate random bytes.
3524 *
3525 * FIPS 203, Algorithm 13: K-PKE.KeyGen(d), Steps 3-7
3526 * FIPS 203, Algorithm 14: K-PKE.Encrypt(ek_PKE,m,r), Steps 4-8
3527 *
3528 * @param  [in, out]  prf         XOF object.
3529 * @param  [out]      a           Matrix of uniform integers.
3530 * @param  [in]       k           Number of dimensions. k x k polynomials.
3531 * @param  [in]       seed        Bytes to seed XOF generation.
3532 * @param  [in]       transposed  Whether A or A^T is generated.
3533 * @return  0 on success.
3534 * @return  MEMORY_E when dynamic memory allocation fails. Only possible when
3535 *          WOLFSSL_SMALL_STACK is defined.
3536 */
3537int mlkem_gen_matrix(MLKEM_PRF_T* prf, sword16* a, int k, byte* seed,
3538    int transposed)
3539{
3540    int ret;
3541
3542#if defined(WOLFSSL_KYBER512) || defined(WOLFSSL_WC_ML_KEM_512)
3543    if (k == WC_ML_KEM_512_K) {
3544#if defined(WOLFSSL_ARMASM) && defined(__aarch64__)
3545        ret = mlkem_gen_matrix_k2_aarch64(a, seed, transposed);
3546#else
3547    #if defined(USE_INTEL_SPEEDUP) && !defined(WC_SHA3_NO_ASM)
3548        if (IS_INTEL_AVX2(cpuid_flags) && (SAVE_VECTOR_REGISTERS2() == 0)) {
3549            ret = mlkem_gen_matrix_k2_avx2(a, seed, transposed);
3550            RESTORE_VECTOR_REGISTERS();
3551        }
3552        else
3553    #endif
3554        {
3555            ret = mlkem_gen_matrix_c(prf, a, WC_ML_KEM_512_K, seed, transposed);
3556        }
3557#endif
3558    }
3559    else
3560#endif
3561#if defined(WOLFSSL_KYBER768) || defined(WOLFSSL_WC_ML_KEM_768)
3562    if (k == WC_ML_KEM_768_K) {
3563#if defined(WOLFSSL_ARMASM) && defined(__aarch64__)
3564        ret = mlkem_gen_matrix_k3_aarch64(a, seed, transposed);
3565#else
3566    #if defined(USE_INTEL_SPEEDUP) && !defined(WC_SHA3_NO_ASM)
3567        if (IS_INTEL_AVX2(cpuid_flags) && (SAVE_VECTOR_REGISTERS2() == 0)) {
3568            ret = mlkem_gen_matrix_k3_avx2(a, seed, transposed);
3569            RESTORE_VECTOR_REGISTERS();
3570        }
3571        else
3572    #endif
3573        {
3574            ret = mlkem_gen_matrix_c(prf, a, WC_ML_KEM_768_K, seed, transposed);
3575        }
3576#endif
3577    }
3578    else
3579#endif
3580#if defined(WOLFSSL_KYBER1024) || defined(WOLFSSL_WC_ML_KEM_1024)
3581    if (k == WC_ML_KEM_1024_K) {
3582#if defined(WOLFSSL_ARMASM) && defined(__aarch64__)
3583        ret = mlkem_gen_matrix_k4_aarch64(a, seed, transposed);
3584#else
3585    #if defined(USE_INTEL_SPEEDUP) && !defined(WC_SHA3_NO_ASM)
3586        if (IS_INTEL_AVX2(cpuid_flags) && (SAVE_VECTOR_REGISTERS2() == 0)) {
3587            ret = mlkem_gen_matrix_k4_avx2(a, seed, transposed);
3588            RESTORE_VECTOR_REGISTERS();
3589        }
3590        else
3591    #endif
3592        {
3593            ret = mlkem_gen_matrix_c(prf, a, WC_ML_KEM_1024_K, seed,
3594                transposed);
3595        }
3596#endif
3597    }
3598    else
3599#endif
3600    {
3601        ret = BAD_STATE_E;
3602    }
3603
3604    (void)prf;
3605
3606    return ret;
3607}
3608
3609#endif
3610
3611#if defined(WOLFSSL_MLKEM_MAKEKEY_SMALL_MEM) || \
3612    defined(WOLFSSL_MLKEM_ENCAPSULATE_SMALL_MEM)
3613
3614/* Deterministically generate a matrix (or transpose) of uniform integers mod q.
3615 *
3616 * Seed used with XOF to generate random bytes.
3617 *
3618 * FIPS 203, Algorithm 13: K-PKE.KeyGen(d)
3619 * ...
3620 * 4:     for (j <- 0; j < k; j++)
3621 * 5:         A_hat[i,j] <- SampleNTT(rho||j||i)
3622 * 6:     end for
3623 * ...
3624 * FIPS 203, Algorithm 14: K-PKE.Encrypt(ek_PKE,m,r)
3625 * ...
3626 * 5:     for (j <- 0; j < k; j++)
3627 * 6:         A_hat[i,j] <- SampleNTT(rho||j||i)  (Transposed is rho||i||j)
3628 * 7:     end for
3629 * ...
3630 *
3631 * @param  [in, out]  prf         XOF object.
3632 * @param  [out]      a           Matrix of uniform integers.
3633 * @param  [in]       k           Number of dimensions. k x k polynomials.
3634 * @param  [in]       seed        Bytes to seed XOF generation.
3635 * @param  [in]       i           Index of vector to generate.
3636 * @param  [in]       transposed  Whether A or A^T is generated.
3637 * @return  0 on success.
3638 * @return  MEMORY_E when dynamic memory allocation fails. Only possible when
3639 *          WOLFSSL_SMALL_STACK is defined.
3640 */
3641static int mlkem_gen_matrix_i(MLKEM_PRF_T* prf, sword16* a, int k, byte* seed,
3642    int i, int transposed)
3643{
3644#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC)
3645    byte* rand;
3646#else
3647    byte rand[GEN_MATRIX_SIZE + 2];
3648#endif
3649    byte extSeed[WC_ML_KEM_SYM_SZ + 2];
3650    int ret = 0;
3651    int j;
3652
3653    XMEMCPY(extSeed, seed, WC_ML_KEM_SYM_SZ);
3654
3655#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC)
3656    /* Allocate large amount of memory to hold random bytes to be sampled. */
3657    rand = (byte*)XMALLOC(GEN_MATRIX_SIZE + 2, NULL, DYNAMIC_TYPE_TMP_BUFFER);
3658    if (rand == NULL) {
3659        ret = MEMORY_E;
3660    }
3661#endif
3662
3663#if !defined(WOLFSSL_MLKEM_SMALL) && defined(WC_64BIT_CPU)
3664    /* Loading 64 bits, only using 48 bits. Loading 2 bytes more than used. */
3665    if (ret == 0) {
3666        rand[GEN_MATRIX_SIZE+0] = 0xff;
3667        rand[GEN_MATRIX_SIZE+1] = 0xff;
3668    }
3669#endif
3670
3671    /* Generate each polynomial in vector from seed with indices.
3672     * Alg 13, Step 4. Alg 14, Step 5. */
3673    for (j = 0; (ret == 0) && (j < k); j++) {
3674        if (transposed) {
3675            /* Alg 14, Step 6: .. rho||i||j ... */
3676            extSeed[WC_ML_KEM_SYM_SZ + 0] = (byte)i;
3677            extSeed[WC_ML_KEM_SYM_SZ + 1] = (byte)j;
3678        }
3679        else {
3680            /* Alg 13, Step 5: .. rho||j||i ... */
3681            extSeed[WC_ML_KEM_SYM_SZ + 0] = (byte)j;
3682            extSeed[WC_ML_KEM_SYM_SZ + 1] = (byte)i;
3683        }
3684        /* Absorb the index specific seed.
3685         * Alg 7, Step 1-2 */
3686        ret = mlkem_xof_absorb(prf, extSeed, sizeof(extSeed));
3687        if (ret == 0) {
3688            /* Create data based on the seed.
3689             * Alg 7, Step 5. Generating enough to, on average, be able to get
3690             * enough valid values. */
3691            ret = mlkem_xof_squeezeblocks(prf, rand, GEN_MATRIX_NBLOCKS);
3692        }
3693        if (ret == 0) {
3694            unsigned int ctr;
3695
3696            /* Sample random bytes to create a polynomial.
3697             * Alg 7, Step 3 - implicitly counter is 0.
3698             * Alg 7, Step 4-16. */
3699            ctr = mlkem_rej_uniform_c(a + j * MLKEM_N, MLKEM_N, rand,
3700                GEN_MATRIX_SIZE);
3701            /* Create more blocks if too many rejected.
3702             * Alg 7, Step 4. */
3703            while (ctr < MLKEM_N) {
3704                /* Alg 7, Step 5. */
3705                mlkem_xof_squeezeblocks(prf, rand, 1);
3706                /* Alg 7, Step 4-16. */
3707                ctr += mlkem_rej_uniform_c(a + j * MLKEM_N + ctr,
3708                    MLKEM_N - ctr, rand, XOF_BLOCK_SIZE);
3709            }
3710        }
3711    }
3712
3713#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC)
3714    /* Dispose of temporary buffer. */
3715    XFREE(rand, NULL, DYNAMIC_TYPE_TMP_BUFFER);
3716#endif
3717
3718    return ret;
3719}
3720
3721#endif
3722
3723
3724/******************************************************************************/
3725
3726/* Subtract one 2 bit value from another out of a larger number.
3727 *
3728 * FIPS 203, Algorithm 8: SamplePolyCBD_eta(B)
3729 * Takes a seed as input and outputs a pseudorandom sample from the distribution
3730 * D_eta(R_q).
3731 *
3732 * @param  [in]  d  Value containing sequential 2 bit values.
3733 * @param  [in]  i  Start index of the two values in 2 bits each.
3734 * @return  Difference of the two values with range -2..2.
3735 */
3736#define ETA2_SUB(d, i) \
3737    (sword16)(((sword16)(((d) >> ((i) * 4 + 0)) & 0x3)) - \
3738              ((sword16)(((d) >> ((i) * 4 + 2)) & 0x3)))
3739
3740/* Compute polynomial with coefficients distributed according to a centered
3741 * binomial distribution with parameter eta2 from uniform random bytes.
3742 *
3743 * FIPS 203, Algorithm 8: SamplePolyCBD_eta(B)
3744 * Takes a seed as input and outputs a pseudorandom sample from the distribution
3745 * D_eta(R_q).
3746 *
3747 * @param [out]  p  Polynomial computed.
3748 * @param [in]   r  Random bytes.
3749 */
3750static void mlkem_cbd_eta2(sword16* p, const byte* r)
3751{
3752    unsigned int i;
3753
3754#ifndef WORD64_AVAILABLE
3755    /* Calculate eight integer coefficients at a time. */
3756    for (i = 0; i < MLKEM_N; i += 8) {
3757    #ifdef WOLFSSL_MLKEM_SMALL
3758        unsigned int j;
3759    #endif
3760        /* Take the next 4 bytes, little endian, as a 32 bit value. */
3761    #ifdef BIG_ENDIAN_ORDER
3762        word32 t = ByteReverseWord32(*(word32*)r);
3763    #else
3764        word32 t = *(word32*)r;
3765    #endif
3766        word32 d;
3767        /* Add second bits to first. */
3768        d  = (t >> 0) & 0x55555555;
3769        d += (t >> 1) & 0x55555555;
3770        /* Values 0, 1 or 2 in consecutive 2 bits.
3771         * 0 - 1/4, 1 - 2/4, 2 - 1/4. */
3772
3773    #ifdef WOLFSSL_MLKEM_SMALL
3774        for (j = 0; j < 8; j++) {
3775            p[i + j] = ETA2_SUB(d, j);
3776        }
3777    #else
3778        p[i + 0] = ETA2_SUB(d, 0);
3779        p[i + 1] = ETA2_SUB(d, 1);
3780        p[i + 2] = ETA2_SUB(d, 2);
3781        p[i + 3] = ETA2_SUB(d, 3);
3782        p[i + 4] = ETA2_SUB(d, 4);
3783        p[i + 5] = ETA2_SUB(d, 5);
3784        p[i + 6] = ETA2_SUB(d, 6);
3785        p[i + 7] = ETA2_SUB(d, 7);
3786    #endif
3787        /* -2 - 1/16, -1 - 4/16, 0 - 6/16, 1 - 4/16, 2 - 1/16  */
3788
3789        /* Move over used bytes. */
3790        r += 4;
3791    }
3792#else
3793    /* Calculate sixteen integer coefficients at a time. */
3794    for (i = 0; i < MLKEM_N; i += 16) {
3795    #ifdef WOLFSSL_MLKEM_SMALL
3796        unsigned int j;
3797    #endif
3798        /* Take the next 8 bytes, little endian, as a 64 bit value. */
3799    #ifdef BIG_ENDIAN_ORDER
3800        word64 t = ByteReverseWord64(readUnalignedWord64(r));
3801    #else
3802        word64 t = readUnalignedWord64(r);
3803    #endif
3804        word64 d;
3805        /* Add second bits to first. */
3806        d  = (t >> 0) & 0x5555555555555555L;
3807        d += (t >> 1) & 0x5555555555555555L;
3808        /* Values 0, 1 or 2 in consecutive 2 bits.
3809         * 0 - 1/4, 1 - 2/4, 2 - 1/4. */
3810
3811    #ifdef WOLFSSL_MLKEM_SMALL
3812        for (j = 0; j < 16; j++) {
3813            p[i + j] = ETA2_SUB(d, j);
3814        }
3815    #else
3816        p[i +  0] = ETA2_SUB(d,  0);
3817        p[i +  1] = ETA2_SUB(d,  1);
3818        p[i +  2] = ETA2_SUB(d,  2);
3819        p[i +  3] = ETA2_SUB(d,  3);
3820        p[i +  4] = ETA2_SUB(d,  4);
3821        p[i +  5] = ETA2_SUB(d,  5);
3822        p[i +  6] = ETA2_SUB(d,  6);
3823        p[i +  7] = ETA2_SUB(d,  7);
3824        p[i +  8] = ETA2_SUB(d,  8);
3825        p[i +  9] = ETA2_SUB(d,  9);
3826        p[i + 10] = ETA2_SUB(d, 10);
3827        p[i + 11] = ETA2_SUB(d, 11);
3828        p[i + 12] = ETA2_SUB(d, 12);
3829        p[i + 13] = ETA2_SUB(d, 13);
3830        p[i + 14] = ETA2_SUB(d, 14);
3831        p[i + 15] = ETA2_SUB(d, 15);
3832    #endif
3833        /* -2 - 1/16, -1 - 4/16, 0 - 6/16, 1 - 4/16, 2 - 1/16  */
3834
3835        /* Move over used bytes. */
3836        r += 8;
3837    }
3838#endif
3839}
3840
3841#if defined(WOLFSSL_KYBER512) || defined(WOLFSSL_WC_ML_KEM_512)
3842/* Subtract one 3 bit value from another out of a larger number.
3843 *
3844 * FIPS 203, Algorithm 8: SamplePolyCBD_eta(B)
3845 * Takes a seed as input and outputs a pseudorandom sample from the distribution
3846 * D_eta(R_q).
3847 *
3848 * @param  [in]  d  Value containing sequential 3 bit values.
3849 * @param  [in]  i  Start index of the two values in 3 bits each.
3850 * @return  Difference of the two values with range -3..3.
3851 */
3852#define ETA3_SUB(d, i) \
3853    (sword16)(((sword16)(((d) >> ((i) * 6 + 0)) & 0x7)) - \
3854              ((sword16)(((d) >> ((i) * 6 + 3)) & 0x7)))
3855
3856/* Compute polynomial with coefficients distributed according to a centered
3857 * binomial distribution with parameter eta3 from uniform random bytes.
3858 *
3859 * FIPS 203, Algorithm 8: SamplePolyCBD_eta(B)
3860 * Takes a seed as input and outputs a pseudorandom sample from the distribution
3861 * D_eta(R_q).
3862 *
3863 * @param [out]  p  Polynomial computed.
3864 * @param [in]   r  Random bytes.
3865 */
3866static void mlkem_cbd_eta3(sword16* p, const byte* r)
3867{
3868    unsigned int i;
3869
3870#if defined(WOLFSSL_SMALL_STACK) || defined(WOLFSSL_MLKEM_NO_LARGE_CODE) || \
3871    defined(BIG_ENDIAN_ORDER)
3872#ifndef WORD64_AVAILABLE
3873    /* Calculate four integer coefficients at a time. */
3874    for (i = 0; i < MLKEM_N; i += 4) {
3875    #ifdef WOLFSSL_MLKEM_SMALL
3876        unsigned int j;
3877    #endif
3878        /* Take the next 3 bytes, little endian, as a 24 bit value. */
3879        word32 t = (((word32)(r[0])) <<  0) |
3880                   (((word32)(r[1])) <<  8) |
3881                   (((word32)(r[2])) << 16);
3882        word32 d;
3883        /* Add second and third bits to first. */
3884        d  = (t >> 0) & 0x00249249;
3885        d += (t >> 1) & 0x00249249;
3886        d += (t >> 2) & 0x00249249;
3887        /* Values 0, 1, 2 or 3 in consecutive 3 bits.
3888         * 0 - 1/8, 1 - 3/8, 2 - 3/8, 3 - 1/8. */
3889
3890    #ifdef WOLFSSL_MLKEM_SMALL
3891        for (j = 0; j < 4; j++) {
3892            p[i + j] = ETA3_SUB(d, j);
3893        }
3894    #else
3895        p[i + 0] = ETA3_SUB(d, 0);
3896        p[i + 1] = ETA3_SUB(d, 1);
3897        p[i + 2] = ETA3_SUB(d, 2);
3898        p[i + 3] = ETA3_SUB(d, 3);
3899    #endif
3900        /* -3-1/64, -2-6/64, -1-15/64, 0-20/64, 1-15/64, 2-6/64, 3-1/64 */
3901
3902        /* Move over used bytes. */
3903        r += 3;
3904    }
3905#else
3906    /* Calculate eight integer coefficients at a time. */
3907    for (i = 0; i < MLKEM_N; i += 8) {
3908    #ifdef WOLFSSL_MLKEM_SMALL
3909        unsigned int j;
3910    #endif
3911        /* Take the next 6 bytes, little endian, as a 48 bit value. */
3912        word64 t = (((word64)(r[0])) <<  0) |
3913                   (((word64)(r[1])) <<  8) |
3914                   (((word64)(r[2])) << 16) |
3915                   (((word64)(r[3])) << 24) |
3916                   (((word64)(r[4])) << 32) |
3917                   (((word64)(r[5])) << 40);
3918        word64 d;
3919        /* Add second and third bits to first. */
3920        d  = (t >> 0) & 0x0000249249249249L;
3921        d += (t >> 1) & 0x0000249249249249L;
3922        d += (t >> 2) & 0x0000249249249249L;
3923        /* Values 0, 1, 2 or 3 in consecutive 3 bits.
3924         * 0 - 1/8, 1 - 3/8, 2 - 3/8, 3 - 1/8. */
3925
3926    #ifdef WOLFSSL_MLKEM_SMALL
3927        for (j = 0; j < 8; j++) {
3928            p[i + j] = ETA3_SUB(d, j);
3929        }
3930    #else
3931        p[i + 0] = ETA3_SUB(d, 0);
3932        p[i + 1] = ETA3_SUB(d, 1);
3933        p[i + 2] = ETA3_SUB(d, 2);
3934        p[i + 3] = ETA3_SUB(d, 3);
3935        p[i + 4] = ETA3_SUB(d, 4);
3936        p[i + 5] = ETA3_SUB(d, 5);
3937        p[i + 6] = ETA3_SUB(d, 6);
3938        p[i + 7] = ETA3_SUB(d, 7);
3939    #endif
3940        /* -3-1/64, -2-6/64, -1-15/64, 0-20/64, 1-15/64, 2-6/64, 3-1/64 */
3941
3942        /* Move over used bytes. */
3943        r += 6;
3944    }
3945#endif /* WORD64_AVAILABLE */
3946#else
3947    /* Calculate eight integer coefficients at a time. */
3948    for (i = 0; i < MLKEM_N; i += 16) {
3949        const word32* r32 = (const word32*)r;
3950        /* Take the next 12 bytes, little endian, as 24 bit values. */
3951        word32 t0 =   r32[0]                          & 0xffffff;
3952        word32 t1 = ((r32[0] >> 24) | (r32[1] <<  8)) & 0xffffff;
3953        word32 t2 = ((r32[1] >> 16) | (r32[2] << 16)) & 0xffffff;
3954        word32 t3 =   r32[2] >>  8                              ;
3955        word32 d0;
3956        word32 d1;
3957        word32 d2;
3958        word32 d3;
3959
3960        /* Add second and third bits to first. */
3961        d0  = (t0 >> 0) & 0x00249249;
3962        d0 += (t0 >> 1) & 0x00249249;
3963        d0 += (t0 >> 2) & 0x00249249;
3964        d1  = (t1 >> 0) & 0x00249249;
3965        d1 += (t1 >> 1) & 0x00249249;
3966        d1 += (t1 >> 2) & 0x00249249;
3967        d2  = (t2 >> 0) & 0x00249249;
3968        d2 += (t2 >> 1) & 0x00249249;
3969        d2 += (t2 >> 2) & 0x00249249;
3970        d3  = (t3 >> 0) & 0x00249249;
3971        d3 += (t3 >> 1) & 0x00249249;
3972        d3 += (t3 >> 2) & 0x00249249;
3973        /* Values 0, 1, 2 or 3 in consecutive 3 bits.
3974         * 0 - 1/8, 1 - 3/8, 2 - 3/8, 3 - 1/8. */
3975
3976        p[i +  0] = ETA3_SUB(d0, 0);
3977        p[i +  1] = ETA3_SUB(d0, 1);
3978        p[i +  2] = ETA3_SUB(d0, 2);
3979        p[i +  3] = ETA3_SUB(d0, 3);
3980        p[i +  4] = ETA3_SUB(d1, 0);
3981        p[i +  5] = ETA3_SUB(d1, 1);
3982        p[i +  6] = ETA3_SUB(d1, 2);
3983        p[i +  7] = ETA3_SUB(d1, 3);
3984        p[i +  8] = ETA3_SUB(d2, 0);
3985        p[i +  9] = ETA3_SUB(d2, 1);
3986        p[i + 10] = ETA3_SUB(d2, 2);
3987        p[i + 11] = ETA3_SUB(d2, 3);
3988        p[i + 12] = ETA3_SUB(d3, 0);
3989        p[i + 13] = ETA3_SUB(d3, 1);
3990        p[i + 14] = ETA3_SUB(d3, 2);
3991        p[i + 15] = ETA3_SUB(d3, 3);
3992        /* -3-1/64, -2-6/64, -1-15/64, 0-20/64, 1-15/64, 2-6/64, 3-1/64 */
3993
3994        /* Move over used bytes. */
3995        r += 12;
3996    }
3997#endif /* WOLFSSL_SMALL_STACK || WOLFSSL_MLKEM_NO_LARGE_CODE ||
3998        * BIG_ENDIAN_ORDER */
3999}
4000#endif
4001
4002#if !(defined(__aarch64__) && defined(WOLFSSL_ARMASM))
4003
4004/* Get noise/error by calculating random bytes and sampling to a binomial
4005 * distribution.
4006 *
4007 * FIPS 203, Algorithm 13: K-PKE.KeyGen(d)
4008 *   ...
4009 *   9:     s[i] <- SamplePolyCBD_eta_1(PRF_eta_1(sigma, N))
4010 *   ...
4011 *  13:     e[i] <- SamplePolyCBD_eta_1(PRF_eta_1(sigma, N))
4012 *   ...
4013 * FIPS 203, Algorithm 14: K-PKE.Encrypt(ek_PKE,m,r)
4014 *   ...
4015 *  10:     y[i] <- SamplePolyCBD_eta_1(PRF_eta_1(r, N))
4016 *   ...
4017 *
4018 * @param  [in, out]  prf   Pseudo-random function object.
4019 * @param  [out]      p     Polynomial.
4020 * @param  [in]       seed  Seed to use when calculating random.
4021 * @param  [in]       eta1  Size of noise/error integers.
4022 * @return  0 on success.
4023 */
4024static int mlkem_get_noise_eta1_c(MLKEM_PRF_T* prf, sword16* p,
4025    const byte* seed, byte eta1)
4026{
4027    int ret;
4028
4029    (void)eta1;
4030
4031#if defined(WOLFSSL_KYBER512) || defined(WOLFSSL_WC_ML_KEM_512)
4032    if (eta1 == MLKEM_CBD_ETA3) {
4033        byte rand[ETA3_RAND_SIZE];
4034
4035        /* Calculate random bytes from seed with PRF. */
4036        ret = mlkem_prf(prf, rand, sizeof(rand), seed);
4037        if (ret == 0) {
4038            /* Sample for values in range -3..3 from 3 bits of random. */
4039            mlkem_cbd_eta3(p, rand);
4040         }
4041    }
4042    else
4043#endif
4044    {
4045        byte rand[ETA2_RAND_SIZE];
4046
4047        /* Calculate random bytes from seed with PRF. */
4048        ret = mlkem_prf(prf, rand, sizeof(rand), seed);
4049        if (ret == 0) {
4050            /* Sample for values in range -2..2 from 2 bits of random. */
4051            mlkem_cbd_eta2(p, rand);
4052        }
4053    }
4054
4055    return ret;
4056}
4057
4058/* Get noise/error by calculating random bytes and sampling to a binomial
4059 * distribution. Values -2..2
4060 *
4061 * FIPS 203, Algorithm 14: K-PKE.Encrypt(ek_PKE,m,r)
4062 *   ...
4063 *  14:     e1[i] <- SamplePolyCBD_eta_2(PRF_eta_2(r, N))
4064 *   ...
4065 *  17:     e2 <- SamplePolyCBD_eta_2(PRF_eta_2(r, N))
4066 *   ...
4067 *
4068 * @param  [in, out]  prf   Pseudo-random function object.
4069 * @param  [out]      p     Polynomial.
4070 * @param  [in]       seed  Seed to use when calculating random.
4071 * @return  0 on success.
4072 */
4073static int mlkem_get_noise_eta2_c(MLKEM_PRF_T* prf, sword16* p,
4074    const byte* seed)
4075{
4076    int ret;
4077    byte rand[ETA2_RAND_SIZE];
4078
4079    /* Calculate random bytes from seed with PRF. */
4080    ret = mlkem_prf(prf, rand, sizeof(rand), seed);
4081    if (ret == 0) {
4082        mlkem_cbd_eta2(p, rand);
4083    }
4084
4085    return ret;
4086}
4087
4088#endif
4089
4090#if defined(USE_INTEL_SPEEDUP) && !defined(WC_SHA3_NO_ASM)
4091#define PRF_RAND_SZ   (2 * SHA3_256_BYTES)
4092
4093#if defined(WOLFSSL_KYBER768) || defined(WOLFSSL_WC_ML_KEM_768) || \
4094    defined(WOLFSSL_KYBER1024) || defined(WOLFSSL_WC_ML_KEM_1024)
4095/* Get the noise/error by calculating random bytes.
4096 *
4097 * FIPS 203, Algorithm 14: K-PKE.Encrypt(ek_PKE,m,r)
4098 *   ...
4099 *  14:     e1[i] <- SamplePolyCBD_eta_2(PRF_eta_2(r, N))
4100 *   ...
4101 *  17:     e2 <- SamplePolyCBD_eta_2(PRF_eta_2(r, N))
4102 *   ...
4103 *
4104 * @param  [out]  rand  Random number byte array.
4105 * @param  [in]   seed  Seed to generate random from.
4106 * @param  [in]   o     Offset of seed count.
4107 */
4108static void mlkem_get_noise_x4_eta2_avx2(byte* rand, byte* seed, byte o)
4109{
4110    int i;
4111    word64 state[25 * 4];
4112
4113    for (i = 0; i < 4; i++) {
4114        state[4*4 + i] = (word32)(0x1f00 + i + o);
4115    }
4116
4117    sha3_256_blocksx4_seed_avx2(state, seed);
4118    mlkem_redistribute_16_rand_avx2(state, rand + 0 * ETA2_RAND_SIZE,
4119        rand + 1 * ETA2_RAND_SIZE, rand + 2 * ETA2_RAND_SIZE,
4120        rand + 3 * ETA2_RAND_SIZE);
4121}
4122#endif
4123
4124#if defined(WOLFSSL_KYBER512) || defined(WOLFSSL_WC_ML_KEM_512) || \
4125    defined(WOLFSSL_KYBER1024) || defined(WOLFSSL_WC_ML_KEM_1024)
4126/* Get noise/error by calculating random bytes and sampling to a binomial
4127 * distribution. Values -2..2
4128 *
4129 * FIPS 203, Algorithm 14: K-PKE.Encrypt(ek_PKE,m,r)
4130 *   ...
4131 *  14:     e1[i] <- SamplePolyCBD_eta_2(PRF_eta_2(r, N))
4132 *   ...
4133 *  17:     e2 <- SamplePolyCBD_eta_2(PRF_eta_2(r, N))
4134 *   ...
4135 *
4136 * @param  [in, out]  prf   Pseudo-random function object.
4137 * @param  [out]      p     Polynomial.
4138 * @param  [in]       seed  Seed to use when calculating random.
4139 * @return  0 on success.
4140 */
4141static int mlkem_get_noise_eta2_avx2(MLKEM_PRF_T* prf, sword16* p,
4142    const byte* seed)
4143{
4144    word64 state[25];
4145
4146    (void)prf;
4147
4148    /* Put first WC_ML_KEM_SYM_SZ bytes of key into blank state. */
4149    readUnalignedWords64(state, seed, WC_ML_KEM_SYM_SZ / sizeof(word64));
4150    /* Last byte in with end of content marker. */
4151    state[WC_ML_KEM_SYM_SZ / 8] = 0x1f00 | seed[WC_ML_KEM_SYM_SZ];
4152    /* Set rest of state to 0. */
4153    XMEMSET(state + WC_ML_KEM_SYM_SZ / 8 + 1, 0,
4154        (25 - WC_ML_KEM_SYM_SZ / 8 - 1) * sizeof(word64));
4155    /* ... except for rate marker. */
4156    state[WC_SHA3_256_COUNT - 1] = W64LIT(0x8000000000000000);
4157
4158    /* Perform a block operation on the state for next block of output. */
4159#ifndef WC_SHA3_NO_ASM
4160    if (IS_INTEL_BMI2(cpuid_flags)) {
4161        sha3_block_bmi2(state);
4162    }
4163    else if (IS_INTEL_AVX2(cpuid_flags) && (SAVE_VECTOR_REGISTERS2() == 0)) {
4164        sha3_block_avx2(state);
4165        RESTORE_VECTOR_REGISTERS();
4166    }
4167    else
4168#endif /* !WC_SHA3_NO_ASM */
4169    {
4170        BlockSha3(state);
4171    }
4172    mlkem_cbd_eta2_avx2(p, (byte*)state);
4173
4174    return 0;
4175}
4176#endif
4177
4178#if defined(WOLFSSL_KYBER512) || defined(WOLFSSL_WC_ML_KEM_512)
4179/* Get the noise/error by calculating random bytes.
4180 *
4181 * FIPS 203, Algorithm 13: K-PKE.KeyGen(d)
4182 *   ...
4183 *   9:     s[i] <- SamplePolyCBD_eta_1(PRF_eta_1(sigma, N))
4184 *   ...
4185 *  13:     e[i] <- SamplePolyCBD_eta_1(PRF_eta_1(sigma, N))
4186 *   ...
4187 * FIPS 203, Algorithm 14: K-PKE.Encrypt(ek_PKE,m,r)
4188 *   ...
4189 *  10:     y[i] <- SamplePolyCBD_eta_1(PRF_eta_1(r, N))
4190 *   ...
4191 *
4192 * @param  [out]  rand  Random number byte array.
4193 * @param  [in]   seed  Seed to generate random from.
4194 */
4195static void mlkem_get_noise_x4_eta3_avx2(byte* rand, byte* seed)
4196{
4197    word64 state[25 * 4];
4198    int i;
4199
4200    state[4*4 + 0] = 0x1f00 + 0;
4201    state[4*4 + 1] = 0x1f00 + 1;
4202    state[4*4 + 2] = 0x1f00 + 2;
4203    state[4*4 + 3] = 0x1f00 + 3;
4204
4205    sha3_256_blocksx4_seed_avx2(state, seed);
4206    mlkem_redistribute_17_rand_avx2(state, rand + 0 * PRF_RAND_SZ,
4207        rand + 1 * PRF_RAND_SZ, rand + 2 * PRF_RAND_SZ,
4208        rand + 3 * PRF_RAND_SZ);
4209    i = SHA3_256_BYTES;
4210    sha3_blocksx4_avx2(state);
4211    mlkem_redistribute_8_rand_avx2(state, rand + i + 0 * PRF_RAND_SZ,
4212        rand + i + 1 * PRF_RAND_SZ, rand + i + 2 * PRF_RAND_SZ,
4213        rand + i + 3 * PRF_RAND_SZ);
4214}
4215
4216/* Get the noise/error by calculating random bytes and sampling to a binomial
4217 * distribution.
4218 *
4219 * @param  [in, out]  prf   Pseudo-random function object.
4220 * @param  [out]      vec1  First Vector of polynomials.
4221 * @param  [out]      vec2  Second Vector of polynomials.
4222 * @param  [out]      poly  Polynomial.
4223 * @param  [in, out]  seed  Seed to use when calculating random.
4224 * @return  0 on success.
4225 * @return  MEMORY_E when dynamic memory allocation fails. Only possible when
4226 *          WOLFSSL_SMALL_STACK is defined.
4227 */
4228static int mlkem_get_noise_k2_avx2(MLKEM_PRF_T* prf, sword16* vec1,
4229    sword16* vec2, sword16* poly, byte* seed)
4230{
4231    int ret = 0;
4232    WC_DECLARE_VAR(rand, byte, 4 * PRF_RAND_SZ, 0);
4233
4234    WC_ALLOC_VAR_EX(rand, byte, 4 * PRF_RAND_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER,
4235        return MEMORY_E);
4236
4237    mlkem_get_noise_x4_eta3_avx2(rand, seed);
4238    mlkem_cbd_eta3_avx2(vec1          , rand + 0 * PRF_RAND_SZ);
4239    mlkem_cbd_eta3_avx2(vec1 + MLKEM_N, rand + 1 * PRF_RAND_SZ);
4240    if (poly == NULL) {
4241        mlkem_cbd_eta3_avx2(vec2          , rand + 2 * PRF_RAND_SZ);
4242        mlkem_cbd_eta3_avx2(vec2 + MLKEM_N, rand + 3 * PRF_RAND_SZ);
4243    }
4244    else {
4245        mlkem_cbd_eta2_avx2(vec2          , rand + 2 * PRF_RAND_SZ);
4246        mlkem_cbd_eta2_avx2(vec2 + MLKEM_N, rand + 3 * PRF_RAND_SZ);
4247
4248        seed[WC_ML_KEM_SYM_SZ] = 4;
4249        ret = mlkem_get_noise_eta2_avx2(prf, poly, seed);
4250    }
4251
4252    WC_FREE_VAR_EX(rand, NULL, DYNAMIC_TYPE_TMP_BUFFER);
4253
4254    return ret;
4255}
4256#endif
4257
4258#if defined(WOLFSSL_KYBER768) || defined(WOLFSSL_WC_ML_KEM_768)
4259/* Get the noise/error by calculating random bytes and sampling to a binomial
4260 * distribution.
4261 *
4262 * @param  [out]      vec1  First Vector of polynomials.
4263 * @param  [out]      vec2  Second Vector of polynomials.
4264 * @param  [out]      poly  Polynomial.
4265 * @param  [in]       seed  Seed to use when calculating random.
4266 * @return  0 on success.
4267 */
4268static int mlkem_get_noise_k3_avx2(sword16* vec1, sword16* vec2, sword16* poly,
4269    byte* seed)
4270{
4271    byte rand[4 * ETA2_RAND_SIZE];
4272
4273    mlkem_get_noise_x4_eta2_avx2(rand, seed, 0);
4274    mlkem_cbd_eta2_avx2(vec1              , rand + 0 * ETA2_RAND_SIZE);
4275    mlkem_cbd_eta2_avx2(vec1 + 1 * MLKEM_N, rand + 1 * ETA2_RAND_SIZE);
4276    mlkem_cbd_eta2_avx2(vec1 + 2 * MLKEM_N, rand + 2 * ETA2_RAND_SIZE);
4277    mlkem_cbd_eta2_avx2(vec2              , rand + 3 * ETA2_RAND_SIZE);
4278    mlkem_get_noise_x4_eta2_avx2(rand, seed, 4);
4279    mlkem_cbd_eta2_avx2(vec2 + 1 * MLKEM_N, rand + 0 * ETA2_RAND_SIZE);
4280    mlkem_cbd_eta2_avx2(vec2 + 2 * MLKEM_N, rand + 1 * ETA2_RAND_SIZE);
4281    if (poly != NULL) {
4282        mlkem_cbd_eta2_avx2(poly, rand + 2 * ETA2_RAND_SIZE);
4283    }
4284
4285    return 0;
4286}
4287#endif
4288
4289#if defined(WOLFSSL_KYBER1024) || defined(WOLFSSL_WC_ML_KEM_1024)
4290/* Get the noise/error by calculating random bytes and sampling to a binomial
4291 * distribution.
4292 *
4293 * @param  [in, out]  prf   Pseudo-random function object.
4294 * @param  [out]      vec1  First Vector of polynomials.
4295 * @param  [out]      vec2  Second Vector of polynomials.
4296 * @param  [out]      poly  Polynomial.
4297 * @param  [in, out]  seed  Seed to use when calculating random.
4298 * @return  0 on success.
4299 */
4300static int mlkem_get_noise_k4_avx2(MLKEM_PRF_T* prf, sword16* vec1,
4301    sword16* vec2, sword16* poly, byte* seed)
4302{
4303    int ret = 0;
4304    byte rand[4 * ETA2_RAND_SIZE];
4305
4306    (void)prf;
4307
4308    mlkem_get_noise_x4_eta2_avx2(rand, seed, 0);
4309    mlkem_cbd_eta2_avx2(vec1              , rand + 0 * ETA2_RAND_SIZE);
4310    mlkem_cbd_eta2_avx2(vec1 + 1 * MLKEM_N, rand + 1 * ETA2_RAND_SIZE);
4311    mlkem_cbd_eta2_avx2(vec1 + 2 * MLKEM_N, rand + 2 * ETA2_RAND_SIZE);
4312    mlkem_cbd_eta2_avx2(vec1 + 3 * MLKEM_N, rand + 3 * ETA2_RAND_SIZE);
4313    mlkem_get_noise_x4_eta2_avx2(rand, seed, 4);
4314    mlkem_cbd_eta2_avx2(vec2              , rand + 0 * ETA2_RAND_SIZE);
4315    mlkem_cbd_eta2_avx2(vec2 + 1 * MLKEM_N, rand + 1 * ETA2_RAND_SIZE);
4316    mlkem_cbd_eta2_avx2(vec2 + 2 * MLKEM_N, rand + 2 * ETA2_RAND_SIZE);
4317    mlkem_cbd_eta2_avx2(vec2 + 3 * MLKEM_N, rand + 3 * ETA2_RAND_SIZE);
4318    if (poly != NULL) {
4319        seed[WC_ML_KEM_SYM_SZ] = 8;
4320        ret = mlkem_get_noise_eta2_avx2(prf, poly, seed);
4321    }
4322
4323    return ret;
4324}
4325#endif
4326#endif /* USE_INTEL_SPEEDUP */
4327
4328#if defined(__aarch64__) && defined(WOLFSSL_ARMASM)
4329
4330#define PRF_RAND_SZ   (2 * SHA3_256_BYTES)
4331
4332/* Get the noise/error by calculating random bytes.
4333 *
4334 * FIPS 203, Algorithm 14: K-PKE.Encrypt(ek_PKE,m,r)
4335 *   ...
4336 *  14:     e1[i] <- SamplePolyCBD_eta_2(PRF_eta_2(r, N))
4337 *   ...
4338 *  17:     e2 <- SamplePolyCBD_eta_2(PRF_eta_2(r, N))
4339 *   ...
4340 *
4341 * @param  [out]  rand  Random number byte array.
4342 * @param  [in]   seed  Seed to generate random from.
4343 * @param  [in]   o     Offset of seed count.
4344 */
4345static void mlkem_get_noise_x3_eta2_aarch64(byte* rand, byte* seed, byte o)
4346{
4347    word64* state = (word64*)rand;
4348
4349    state[0*25 + 4] = 0x1f00 + 0 + o;
4350    state[1*25 + 4] = 0x1f00 + 1 + o;
4351    state[2*25 + 4] = 0x1f00 + 2 + o;
4352
4353    mlkem_shake256_blocksx3_seed_neon(state, seed);
4354}
4355
4356#if defined(WOLFSSL_KYBER512) || defined(WOLFSSL_WC_ML_KEM_512)
4357/* Get the noise/error by calculating random bytes.
4358 *
4359 * FIPS 203, Algorithm 13: K-PKE.KeyGen(d)
4360 *   ...
4361 *   9:     s[i] <- SamplePolyCBD_eta_1(PRF_eta_1(sigma, N))
4362 *   ...
4363 *  13:     e[i] <- SamplePolyCBD_eta_1(PRF_eta_1(sigma, N))
4364 *   ...
4365 * FIPS 203, Algorithm 14: K-PKE.Encrypt(ek_PKE,m,r)
4366 *   ...
4367 *  10:     y[i] <- SamplePolyCBD_eta_1(PRF_eta_1(r, N))
4368 *   ...
4369 *
4370 * @param  [out]  rand  Random number byte array.
4371 * @param  [in]   seed  Seed to generate random from.
4372 * @param  [in]   o     Offset of seed count.
4373 */
4374static void mlkem_get_noise_x3_eta3_aarch64(byte* rand, byte* seed, byte o)
4375{
4376    word64 state[3 * 25];
4377
4378    state[0*25 + 4] = 0x1f00 + 0 + o;
4379    state[1*25 + 4] = 0x1f00 + 1 + o;
4380    state[2*25 + 4] = 0x1f00 + 2 + o;
4381
4382    mlkem_shake256_blocksx3_seed_neon(state, seed);
4383    XMEMCPY(rand + 0 * ETA3_RAND_SIZE, state + 0*25, SHA3_256_BYTES);
4384    XMEMCPY(rand + 1 * ETA3_RAND_SIZE, state + 1*25, SHA3_256_BYTES);
4385    XMEMCPY(rand + 2 * ETA3_RAND_SIZE, state + 2*25, SHA3_256_BYTES);
4386    mlkem_sha3_blocksx3_neon(state);
4387    rand += SHA3_256_BYTES;
4388    XMEMCPY(rand + 0 * ETA3_RAND_SIZE, state + 0*25,
4389        ETA3_RAND_SIZE - SHA3_256_BYTES);
4390    XMEMCPY(rand + 1 * ETA3_RAND_SIZE, state + 1*25,
4391        ETA3_RAND_SIZE - SHA3_256_BYTES);
4392    XMEMCPY(rand + 2 * ETA3_RAND_SIZE, state + 2*25,
4393        ETA3_RAND_SIZE - SHA3_256_BYTES);
4394}
4395
4396/* Get the noise/error by calculating random bytes.
4397 *
4398 * FIPS 203, Algorithm 13: K-PKE.KeyGen(d)
4399 *   ...
4400 *  13:     e[i] <- SamplePolyCBD_eta_1(PRF_eta_1(sigma, N))
4401 *   ...
4402 *
4403 * @param  [out]  rand  Random number byte array.
4404 * @param  [in]   seed  Seed to generate random from.
4405 * @param  [in]   o     Offset of seed count.
4406 */
4407static void mlkem_get_noise_eta3_aarch64(byte* rand, byte* seed, byte o)
4408{
4409    word64 state[25];
4410
4411    state[0] = ((word64*)seed)[0];
4412    state[1] = ((word64*)seed)[1];
4413    state[2] = ((word64*)seed)[2];
4414    state[3] = ((word64*)seed)[3];
4415    state[4] = 0x1f00 + o;
4416    XMEMSET(state + 5, 0, sizeof(*state) * (25 - 5));
4417    state[16] = W64LIT(0x8000000000000000);
4418    BlockSha3(state);
4419    XMEMCPY(rand                 , state, SHA3_256_BYTES);
4420    BlockSha3(state);
4421    XMEMCPY(rand + SHA3_256_BYTES, state, ETA3_RAND_SIZE - SHA3_256_BYTES);
4422}
4423
4424/* Get the noise/error by calculating random bytes and sampling to a binomial
4425 * distribution.
4426 *
4427 * @param  [out]      vec1  First Vector of polynomials.
4428 * @param  [out]      vec2  Second Vector of polynomials.
4429 * @param  [out]      poly  Polynomial.
4430 * @param  [in]       seed  Seed to use when calculating random.
4431 * @return  0 on success.
4432 */
4433static int mlkem_get_noise_k2_aarch64(sword16* vec1, sword16* vec2,
4434    sword16* poly, byte* seed)
4435{
4436    int ret = 0;
4437    byte rand[3 * 25 * 8];
4438
4439    mlkem_get_noise_x3_eta3_aarch64(rand, seed, 0);
4440    mlkem_cbd_eta3(vec1          , rand + 0 * ETA3_RAND_SIZE);
4441    mlkem_cbd_eta3(vec1 + MLKEM_N, rand + 1 * ETA3_RAND_SIZE);
4442    if (poly == NULL) {
4443        mlkem_cbd_eta3(vec2          , rand + 2 * ETA3_RAND_SIZE);
4444        mlkem_get_noise_eta3_aarch64(rand, seed, 3);
4445        mlkem_cbd_eta3(vec2 + MLKEM_N, rand                     );
4446    }
4447    else {
4448        mlkem_get_noise_x3_eta2_aarch64(rand, seed, 2);
4449        mlkem_cbd_eta2(vec2          , rand + 0 * 25 * 8);
4450        mlkem_cbd_eta2(vec2 + MLKEM_N, rand + 1 * 25 * 8);
4451        mlkem_cbd_eta2(poly          , rand + 2 * 25 * 8);
4452    }
4453
4454    return ret;
4455}
4456#endif
4457
4458#if defined(WOLFSSL_KYBER768) || defined(WOLFSSL_WC_ML_KEM_768)
4459/* Get the noise/error by calculating random bytes.
4460 *
4461 * FIPS 203, Algorithm 14: K-PKE.Encrypt(ek_PKE,m,r)
4462 *   ...
4463 *  14:     e1[i] <- SamplePolyCBD_eta_2(PRF_eta_2(r, N))
4464 *   ...
4465 *  17:     e2 <- SamplePolyCBD_eta_2(PRF_eta_2(r, N))
4466 *   ...
4467 *
4468 * @param  [out]  rand  Random number byte array.
4469 * @param  [in]   seed  Seed to generate random from.
4470 * @param  [in]   o     Offset of seed count.
4471 */
4472static void mlkem_get_noise_eta2_aarch64(byte* rand, byte* seed, byte o)
4473{
4474    word64* state = (word64*)rand;
4475
4476    state[0] = ((word64*)seed)[0];
4477    state[1] = ((word64*)seed)[1];
4478    state[2] = ((word64*)seed)[2];
4479    state[3] = ((word64*)seed)[3];
4480    /* Transposed value same as not. */
4481    state[4] = 0x1f00 + o;
4482    XMEMSET(state + 5, 0, sizeof(*state) * (25 - 5));
4483    state[16] = W64LIT(0x8000000000000000);
4484    BlockSha3(state);
4485}
4486
4487/* Get the noise/error by calculating random bytes and sampling to a binomial
4488 * distribution.
4489 *
4490 * @param  [out]      vec1  First Vector of polynomials.
4491 * @param  [out]      vec2  Second Vector of polynomials.
4492 * @param  [out]      poly  Polynomial.
4493 * @param  [in]       seed  Seed to use when calculating random.
4494 * @return  0 on success.
4495 */
4496static int mlkem_get_noise_k3_aarch64(sword16* vec1, sword16* vec2,
4497     sword16* poly, byte* seed)
4498{
4499    byte rand[3 * 25 * 8];
4500
4501    mlkem_get_noise_x3_eta2_aarch64(rand, seed, 0);
4502    mlkem_cbd_eta2(vec1              , rand + 0 * 25 * 8);
4503    mlkem_cbd_eta2(vec1 + 1 * MLKEM_N, rand + 1 * 25 * 8);
4504    mlkem_cbd_eta2(vec1 + 2 * MLKEM_N, rand + 2 * 25 * 8);
4505    mlkem_get_noise_x3_eta2_aarch64(rand, seed, 3);
4506    mlkem_cbd_eta2(vec2              , rand + 0 * 25 * 8);
4507    mlkem_cbd_eta2(vec2 + 1 * MLKEM_N, rand + 1 * 25 * 8);
4508    mlkem_cbd_eta2(vec2 + 2 * MLKEM_N, rand + 2 * 25 * 8);
4509    if (poly != NULL) {
4510        mlkem_get_noise_eta2_aarch64(rand, seed, 6);
4511        mlkem_cbd_eta2(poly              , rand + 0 * 25 * 8);
4512    }
4513
4514    return 0;
4515}
4516#endif
4517
4518#if defined(WOLFSSL_KYBER1024) || defined(WOLFSSL_WC_ML_KEM_1024)
4519/* Get the noise/error by calculating random bytes and sampling to a binomial
4520 * distribution.
4521 *
4522 * @param  [out]      vec1  First Vector of polynomials.
4523 * @param  [out]      vec2  Second Vector of polynomials.
4524 * @param  [out]      poly  Polynomial.
4525 * @param  [in]       seed  Seed to use when calculating random.
4526 * @return  0 on success.
4527 */
4528static int mlkem_get_noise_k4_aarch64(sword16* vec1, sword16* vec2,
4529    sword16* poly, byte* seed)
4530{
4531    int ret = 0;
4532    byte rand[3 * 25 * 8];
4533
4534    mlkem_get_noise_x3_eta2_aarch64(rand, seed, 0);
4535    mlkem_cbd_eta2(vec1              , rand + 0 * 25 * 8);
4536    mlkem_cbd_eta2(vec1 + 1 * MLKEM_N, rand + 1 * 25 * 8);
4537    mlkem_cbd_eta2(vec1 + 2 * MLKEM_N, rand + 2 * 25 * 8);
4538    mlkem_get_noise_x3_eta2_aarch64(rand, seed, 3);
4539    mlkem_cbd_eta2(vec1 + 3 * MLKEM_N, rand + 0 * 25 * 8);
4540    mlkem_cbd_eta2(vec2              , rand + 1 * 25 * 8);
4541    mlkem_cbd_eta2(vec2 + 1 * MLKEM_N, rand + 2 * 25 * 8);
4542    mlkem_get_noise_x3_eta2_aarch64(rand, seed, 6);
4543    mlkem_cbd_eta2(vec2 + 2 * MLKEM_N, rand + 0 * 25 * 8);
4544    mlkem_cbd_eta2(vec2 + 3 * MLKEM_N, rand + 1 * 25 * 8);
4545    if (poly != NULL) {
4546        mlkem_cbd_eta2(poly,               rand + 2 * 25 * 8);
4547    }
4548
4549    return ret;
4550}
4551#endif
4552#endif /* __aarch64__ && WOLFSSL_ARMASM */
4553
4554#if !(defined(__aarch64__) && defined(WOLFSSL_ARMASM))
4555
4556/* Get the noise/error by calculating random bytes and sampling to a binomial
4557 * distribution.
4558 *
4559 * @param  [in, out]  prf   Pseudo-random function object.
4560 * @param  [in]       k     Number of polynomials in vector.
4561 * @param  [out]      vec1  First Vector of polynomials.
4562 * @param  [in]       eta1  Size of noise/error integers with first vector.
4563 * @param  [out]      vec2  Second Vector of polynomials.
4564 * @param  [in]       eta2  Size of noise/error integers with second vector.
4565 * @param  [out]      poly  Polynomial.
4566 * @param  [in, out]  seed  Seed to use when calculating random.
4567 * @return  0 on success.
4568 */
4569static int mlkem_get_noise_c(MLKEM_PRF_T* prf, int k, sword16* vec1, int eta1,
4570    sword16* vec2, int eta2, sword16* poly, byte* seed)
4571{
4572    int ret = 0;
4573    int i;
4574
4575    /* First noise generation has a seed with 0x00 appended. */
4576    seed[WC_ML_KEM_SYM_SZ] = 0;
4577    /* Generate noise as private key. */
4578    for (i = 0; (ret == 0) && (i < k); i++) {
4579        /* Generate noise for each dimension of vector. */
4580        ret = mlkem_get_noise_eta1_c(prf, vec1 + i * MLKEM_N, seed, (byte)eta1);
4581        /* Increment value of appended byte. */
4582        seed[WC_ML_KEM_SYM_SZ]++;
4583    }
4584    if ((ret == 0) && (vec2 != NULL)) {
4585        /* Generate noise for error. */
4586        for (i = 0; (ret == 0) && (i < k); i++) {
4587            /* Generate noise for each dimension of vector. */
4588            ret = mlkem_get_noise_eta1_c(prf, vec2 + i * MLKEM_N, seed,
4589                (byte)eta2);
4590            /* Increment value of appended byte. */
4591            seed[WC_ML_KEM_SYM_SZ]++;
4592        }
4593    }
4594    else {
4595        seed[WC_ML_KEM_SYM_SZ] = (byte)(2 * k);
4596    }
4597    if ((ret == 0) && (poly != NULL)) {
4598        /* Generating random error polynomial. */
4599        ret = mlkem_get_noise_eta2_c(prf, poly, seed);
4600    }
4601
4602    return ret;
4603}
4604
4605#endif /* !(__aarch64__ && WOLFSSL_ARMASM) */
4606
4607/* Get the noise/error by calculating random bytes and sampling to a binomial
4608 * distribution.
4609 *
4610 * @param  [in, out]  prf   Pseudo-random function object.
4611 * @param  [in]       k     Number of polynomials in vector.
4612 * @param  [out]      vec1  First Vector of polynomials.
4613 * @param  [out]      vec2  Second Vector of polynomials.
4614 * @param  [out]      poly  Polynomial.
4615 * @param  [in, out]  seed  Seed to use when calculating random.
4616 * @return  0 on success.
4617 */
4618int mlkem_get_noise(MLKEM_PRF_T* prf, int k, sword16* vec1, sword16* vec2,
4619    sword16* poly, byte* seed)
4620{
4621    int ret;
4622
4623#if defined(WOLFSSL_KYBER512) || defined(WOLFSSL_WC_ML_KEM_512)
4624    if (k == WC_ML_KEM_512_K) {
4625#if defined(WOLFSSL_ARMASM) && defined(__aarch64__)
4626        ret = mlkem_get_noise_k2_aarch64(vec1, vec2, poly, seed);
4627#else
4628    #if defined(USE_INTEL_SPEEDUP) && !defined(WC_SHA3_NO_ASM)
4629        if (IS_INTEL_AVX2(cpuid_flags) && (SAVE_VECTOR_REGISTERS2() == 0)) {
4630            ret = mlkem_get_noise_k2_avx2(prf, vec1, vec2, poly, seed);
4631            RESTORE_VECTOR_REGISTERS();
4632        }
4633        else
4634    #endif
4635        if (poly == NULL) {
4636            ret = mlkem_get_noise_c(prf, k, vec1, MLKEM_CBD_ETA3, vec2,
4637                MLKEM_CBD_ETA3, NULL, seed);
4638        }
4639        else {
4640            ret = mlkem_get_noise_c(prf, k, vec1, MLKEM_CBD_ETA3, vec2,
4641                MLKEM_CBD_ETA2, poly, seed);
4642        }
4643#endif
4644    }
4645    else
4646#endif
4647#if defined(WOLFSSL_KYBER768) || defined(WOLFSSL_WC_ML_KEM_768)
4648    if (k == WC_ML_KEM_768_K) {
4649#if defined(WOLFSSL_ARMASM) && defined(__aarch64__)
4650        ret = mlkem_get_noise_k3_aarch64(vec1, vec2, poly, seed);
4651#else
4652    #if defined(USE_INTEL_SPEEDUP) && !defined(WC_SHA3_NO_ASM)
4653        if (IS_INTEL_AVX2(cpuid_flags) && (SAVE_VECTOR_REGISTERS2() == 0)) {
4654            ret = mlkem_get_noise_k3_avx2(vec1, vec2, poly, seed);
4655            RESTORE_VECTOR_REGISTERS();
4656        }
4657        else
4658    #endif
4659        {
4660            ret = mlkem_get_noise_c(prf, k, vec1, MLKEM_CBD_ETA2, vec2,
4661                MLKEM_CBD_ETA2, poly, seed);
4662        }
4663#endif
4664    }
4665    else
4666#endif
4667#if defined(WOLFSSL_KYBER1024) || defined(WOLFSSL_WC_ML_KEM_1024)
4668    if (k == WC_ML_KEM_1024_K) {
4669#if defined(WOLFSSL_ARMASM) && defined(__aarch64__)
4670        ret = mlkem_get_noise_k4_aarch64(vec1, vec2, poly, seed);
4671#else
4672    #if defined(USE_INTEL_SPEEDUP) && !defined(WC_SHA3_NO_ASM)
4673        if (IS_INTEL_AVX2(cpuid_flags) && (SAVE_VECTOR_REGISTERS2() == 0)) {
4674            ret = mlkem_get_noise_k4_avx2(prf, vec1, vec2, poly, seed);
4675            RESTORE_VECTOR_REGISTERS();
4676        }
4677        else
4678    #endif
4679        {
4680            ret = mlkem_get_noise_c(prf, k, vec1, MLKEM_CBD_ETA2, vec2,
4681                MLKEM_CBD_ETA2, poly, seed);
4682        }
4683#endif
4684    }
4685    else
4686#endif
4687    {
4688        ret = BAD_STATE_E;
4689    }
4690
4691    (void)prf;
4692
4693    return ret;
4694}
4695
4696#if defined(WOLFSSL_MLKEM_MAKEKEY_SMALL_MEM) || \
4697    defined(WOLFSSL_MLKEM_ENCAPSULATE_SMALL_MEM)
4698/* Get the noise/error by calculating random bytes and sampling to a binomial
4699 * distribution.
4700 *
4701 * @param  [in, out]  prf   Pseudo-random function object.
4702 * @param  [in]       k     Number of polynomials in vector.
4703 * @param  [out]      vec2  Second Vector of polynomials.
4704 * @param  [in, out]  seed  Seed to use when calculating random.
4705 * @param  [in]       i     Index of vector to generate.
4706 * @param  [in]       make  Indicates generation is for making a key.
4707 * @return  0 on success.
4708 */
4709static int mlkem_get_noise_i(MLKEM_PRF_T* prf, int k, sword16* vec2,
4710    byte* seed, int i, int make)
4711{
4712    int ret;
4713
4714    /* Initialize the PRF (generating matrix A leaves it in uninitialized
4715     * state). */
4716    mlkem_prf_init(prf);
4717
4718    /* Set index of polynomial of second vector into seed. */
4719    seed[WC_ML_KEM_SYM_SZ] = (byte)(k + i);
4720#if defined(WOLFSSL_KYBER512) || defined(WOLFSSL_WC_ML_KEM_512)
4721    if ((k == WC_ML_KEM_512_K) && make) {
4722        ret = mlkem_get_noise_eta1_c(prf, vec2, seed, MLKEM_CBD_ETA3);
4723    }
4724    else
4725#endif
4726    {
4727        ret = mlkem_get_noise_eta1_c(prf, vec2, seed, MLKEM_CBD_ETA2);
4728    }
4729
4730    (void)make;
4731    return ret;
4732}
4733#endif
4734
4735/******************************************************************************/
4736
4737#if !(defined(__aarch64__) && defined(WOLFSSL_ARMASM))
4738/* Compare two byte arrays of equal size.
4739 *
4740 * @param [in]  a   First array to compare.
4741 * @param [in]  b   Second array to compare.
4742 * @param [in]  sz  Size of arrays in bytes.
4743 * @return  0 on success.
4744 * @return  -1 on failure.
4745 */
4746static int mlkem_cmp_c(const byte* a, const byte* b, int sz)
4747{
4748    int i;
4749    byte r = 0;
4750
4751    /* Constant time comparison of the encapsulated message and cipher text. */
4752    for (i = 0; i < sz; i++) {
4753        r |= a[i] ^ b[i];
4754    }
4755    return (int)(0 - ((-(word32)r) >> 31));
4756}
4757#endif
4758
4759/* Compare two byte arrays of equal size.
4760 *
4761 * @param [in]  a   First array to compare.
4762 * @param [in]  b   Second array to compare.
4763 * @param [in]  sz  Size of arrays in bytes.
4764 * @return  0 on success.
4765 * @return  -1 on failure.
4766 */
4767int mlkem_cmp(const byte* a, const byte* b, int sz)
4768{
4769#if defined(__aarch64__) && defined(WOLFSSL_ARMASM)
4770    return mlkem_cmp_neon(a, b, sz);
4771#else
4772    int fail;
4773
4774#ifdef USE_INTEL_SPEEDUP
4775    if (IS_INTEL_AVX2(cpuid_flags) && (SAVE_VECTOR_REGISTERS2() == 0)) {
4776        fail = mlkem_cmp_avx2(a, b, sz);
4777        RESTORE_VECTOR_REGISTERS();
4778    }
4779    else
4780#endif
4781    {
4782        fail = mlkem_cmp_c(a, b, sz);
4783    }
4784
4785    return fail;
4786#endif
4787}
4788
4789/******************************************************************************/
4790
4791#if !defined(WOLFSSL_ARMASM)
4792
4793/* Conditional subtraction of q to each coefficient of a polynomial.
4794 *
4795 * FIPS 203, Section 4.2.1, Compression and decompression
4796 *
4797 * @param  [in, out]  p  Polynomial.
4798 */
4799static MLKEM_NOINLINE void mlkem_csubq_c(sword16* p)
4800{
4801    unsigned int i;
4802
4803    for (i = 0; i < MLKEM_N; ++i) {
4804        sword16 t = (sword16)(p[i] - MLKEM_Q);
4805        /* When top bit set, -ve number - need to add q back. */
4806        p[i] = (sword16)(((word16)(-((word16)t >> 15)) & MLKEM_Q) +
4807            (word16)t);
4808    }
4809}
4810
4811#elif defined(__aarch64__)
4812
4813/* Conditional subtraction of q to each coefficient of a polynomial.
4814 *
4815 * FIPS 203, Section 4.2.1, Compression and decompression
4816 *
4817 * @param  [in, out]  p  Polynomial.
4818 */
4819#define mlkem_csubq_c   mlkem_csubq_neon
4820
4821#elif defined(WOLFSSL_ARMASM_THUMB2)
4822
4823/* Conditional subtraction of q to each coefficient of a polynomial.
4824 *
4825 * FIPS 203, Section 4.2.1, Compression and decompression
4826 *
4827 * @param  [in, out]  p  Polynomial.
4828 */
4829#define mlkem_csubq_c   mlkem_thumb2_csubq
4830
4831#else
4832
4833/* Conditional subtraction of q to each coefficient of a polynomial.
4834 *
4835 * FIPS 203, Section 4.2.1, Compression and decompression
4836 *
4837 * @param  [in, out]  p  Polynomial.
4838 */
4839#define mlkem_csubq_c   mlkem_arm32_csubq
4840
4841#endif
4842
4843/******************************************************************************/
4844
4845#if defined(CONV_WITH_DIV) || !defined(WORD64_AVAILABLE)
4846
4847/* Compress value.
4848 *
4849 * Uses div operator that may be slow and not constant-time.
4850 *
4851 * FIPS 203, Section 4.2.1, Compression and decompression
4852 *
4853 * @param  [in]  v  Vector of polynomials.
4854 * @param  [in]  i  Index of polynomial in vector.
4855 * @param  [in]  j  Index into polynomial.
4856 * @param  [in]  k  Offset from indices.
4857 * @param  [in]  s  Shift amount to apply to value being compressed.
4858 * @param  [in]  m  Mask to apply get the required number of bits.
4859 * @return  Compressed value.
4860 */
4861#define TO_COMP_WORD_VEC(v, i, j, k, s, m) \
4862    ((((word32)v[i * MLKEM_N + j + k] << s) + MLKEM_Q_HALF) / MLKEM_Q) & m
4863
4864/* Compress value to 10 bits.
4865 *
4866 * Uses div operator that may be slow and not constant-time.
4867 *
4868 * FIPS 203, Section 4.2.1, Compression and decompression
4869 *
4870 * @param  [in]  v  Vector of polynomials.
4871 * @param  [in]  i  Index of polynomial in vector.
4872 * @param  [in]  j  Index into polynomial.
4873 * @param  [in]  k  Offset from indices.
4874 * @return  Compressed value.
4875 */
4876#define TO_COMP_WORD_10(v, i, j, k) \
4877    TO_COMP_WORD_VEC(v, i, j, k, 10, 0x3ff)
4878
4879/* Compress value to 11 bits.
4880 *
4881 * Uses div operator that may be slow and not constant-time.
4882 *
4883 * FIPS 203, Section 4.2.1, Compression and decompression
4884 *
4885 * @param  [in]  v  Vector of polynomials.
4886 * @param  [in]  i  Index of polynomial in vector.
4887 * @param  [in]  j  Index into polynomial.
4888 * @param  [in]  k  Offset from indices.
4889 * @return  Compressed value.
4890 */
4891#define TO_COMP_WORD_11(v, i, j, k) \
4892    TO_COMP_WORD_VEC(v, i, j, k, 11, 0x7ff)
4893
4894#else
4895
4896/* Multiplier that does div q.
4897 * ((1 << 53) + MLKEM_Q_HALF) / MLKEM_Q
4898 */
4899#define MLKEM_V53         0x275f6ed0176UL
4900/* Multiplier times half of q.
4901 * MLKEM_V53 * (MLKEM_Q_HALF + 1)
4902 */
4903#define MLKEM_V53_HALF    0x10013afb768076UL
4904
4905/* Multiplier that does div q.
4906 * ((1 << 54) + MLKEM_Q_HALF) / MLKEM_Q
4907 */
4908#define MLKEM_V54         0x4ebedda02ecUL
4909/* Multiplier times half of q.
4910 * MLKEM_V54 * (MLKEM_Q_HALF + 1)
4911 */
4912#define MLKEM_V54_HALF    0x200275f6ed00ecUL
4913
4914/* Compress value to 10 bits.
4915 *
4916 * Uses mul instead of div.
4917 *
4918 * FIPS 203, Section 4.2.1, Compression and decompression
4919 *
4920 * @param  [in]  v  Vector of polynomials.
4921 * @param  [in]  i  Index of polynomial in vector.
4922 * @param  [in]  j  Index into polynomial.
4923 * @param  [in]  k  Offset from indices.
4924 * @return  Compressed value.
4925 */
4926#define TO_COMP_WORD_10(v, i, j, k) \
4927    (sword16)((((MLKEM_V54 << 10) * (word64)(v)[(i) * MLKEM_N + (j) + (k)]) + \
4928               MLKEM_V54_HALF) >> 54)
4929
4930/* Compress value to 11 bits.
4931 *
4932 * Uses mul instead of div.
4933 * Only works for values in range: 0..3228
4934 *
4935 * FIPS 203, Section 4.2.1, Compression and decompression
4936 *
4937 * @param  [in]  v  Vector of polynomials.
4938 * @param  [in]  i  Index of polynomial in vector.
4939 * @param  [in]  j  Index into polynomial.
4940 * @param  [in]  k  Offset from indices.
4941 * @return  Compressed value.
4942 */
4943#define TO_COMP_WORD_11(v, i, j, k) \
4944    (sword16)((((MLKEM_V53 << 11) * (word64)(v)[(i) * MLKEM_N + (j) + (k)]) + \
4945               MLKEM_V53_HALF) >> 53)
4946
4947#endif /* CONV_WITH_DIV */
4948
4949#if !defined(WOLFSSL_MLKEM_NO_ENCAPSULATE) || \
4950    !defined(WOLFSSL_MLKEM_NO_DECAPSULATE)
4951#if defined(WOLFSSL_KYBER512) || defined(WOLFSSL_WC_ML_KEM_512) || \
4952    defined(WOLFSSL_KYBER768) || defined(WOLFSSL_WC_ML_KEM_768)
4953/* Compress the vector of polynomials into a byte array with 10 bits each.
4954 *
4955 * FIPS 203, Section 4.2.1, Compression and decompression
4956 *
4957 * @param  [out]      r  Array of bytes.
4958 * @param  [in, out]  v  Vector of polynomials.
4959 * @param  [in]       k  Number of polynomials in vector.
4960 */
4961static void mlkem_vec_compress_10_c(byte* r, sword16* v, unsigned int k)
4962{
4963    unsigned int i;
4964    unsigned int j;
4965
4966    for (i = 0; i < k; i++) {
4967        /* Reduce each coefficient to mod q. */
4968        mlkem_csubq_c(v + i * MLKEM_N);
4969        /* All values are now positive. */
4970    }
4971
4972    /* Each polynomial. */
4973    for (i = 0; i < k; i++) {
4974#if defined(WOLFSSL_SMALL_STACK) || defined(WOLFSSL_MLKEM_NO_LARGE_CODE) || \
4975    defined(BIG_ENDIAN_ORDER)
4976        /* Each 4 polynomial coefficients. */
4977        for (j = 0; j < MLKEM_N; j += 4) {
4978        #ifdef WOLFSSL_MLKEM_SMALL
4979            unsigned int l;
4980            sword16 t[4];
4981            /* Compress four polynomial values to 10 bits each. */
4982            for (l = 0; l < 4; l++) {
4983                t[l] = TO_COMP_WORD_10(v, i, j, l);
4984            }
4985
4986            /* Pack four 10-bit values into byte array. */
4987            r[ 0] = (t[0] >> 0);
4988            r[ 1] = (t[0] >> 8) | (t[1] << 2);
4989            r[ 2] = (t[1] >> 6) | (t[2] << 4);
4990            r[ 3] = (t[2] >> 4) | (t[3] << 6);
4991            r[ 4] = (t[3] >> 2);
4992        #else
4993            /* Compress four polynomial values to 10 bits each. */
4994            sword16 t0 = TO_COMP_WORD_10(v, i, j, 0);
4995            sword16 t1 = TO_COMP_WORD_10(v, i, j, 1);
4996            sword16 t2 = TO_COMP_WORD_10(v, i, j, 2);
4997            sword16 t3 = TO_COMP_WORD_10(v, i, j, 3);
4998
4999            /* Pack four 10-bit values into byte array. */
5000            r[ 0] = (byte)( t0 >> 0);
5001            r[ 1] = (byte)((t0 >> 8) | (t1 << 2));
5002            r[ 2] = (byte)((t1 >> 6) | (t2 << 4));
5003            r[ 3] = (byte)((t2 >> 4) | (t3 << 6));
5004            r[ 4] = (byte)( t3 >> 2);
5005        #endif
5006
5007            /* Move over set bytes. */
5008            r += 5;
5009        }
5010#else
5011        /* Each 16 polynomial coefficients. */
5012        for (j = 0; j < MLKEM_N; j += 16) {
5013            /* Compress four polynomial values to 10 bits each. */
5014            sword16 t0  = TO_COMP_WORD_10(v, i, j, 0);
5015            sword16 t1  = TO_COMP_WORD_10(v, i, j, 1);
5016            sword16 t2  = TO_COMP_WORD_10(v, i, j, 2);
5017            sword16 t3  = TO_COMP_WORD_10(v, i, j, 3);
5018            sword16 t4  = TO_COMP_WORD_10(v, i, j, 4);
5019            sword16 t5  = TO_COMP_WORD_10(v, i, j, 5);
5020            sword16 t6  = TO_COMP_WORD_10(v, i, j, 6);
5021            sword16 t7  = TO_COMP_WORD_10(v, i, j, 7);
5022            sword16 t8  = TO_COMP_WORD_10(v, i, j, 8);
5023            sword16 t9  = TO_COMP_WORD_10(v, i, j, 9);
5024            sword16 t10 = TO_COMP_WORD_10(v, i, j, 10);
5025            sword16 t11 = TO_COMP_WORD_10(v, i, j, 11);
5026            sword16 t12 = TO_COMP_WORD_10(v, i, j, 12);
5027            sword16 t13 = TO_COMP_WORD_10(v, i, j, 13);
5028            sword16 t14 = TO_COMP_WORD_10(v, i, j, 14);
5029            sword16 t15 = TO_COMP_WORD_10(v, i, j, 15);
5030
5031            word32* r32 = (word32*)r;
5032            /* Pack sixteen 10-bit values into byte array. */
5033            r32[0] =  (word32)t0         | ((word32)t1  << 10) |
5034                     ((word32)t2  << 20) | ((word32)t3  << 30);
5035            r32[1] = ((word32)t3  >>  2) | ((word32)t4  <<  8) |
5036                     ((word32)t5  << 18) | ((word32)t6  << 28);
5037            r32[2] = ((word32)t6  >>  4) | ((word32)t7  <<  6) |
5038                     ((word32)t8  << 16) | ((word32)t9  << 26);
5039            r32[3] = ((word32)t9  >>  6) | ((word32)t10 <<  4) |
5040                     ((word32)t11 << 14) | ((word32)t12 << 24);
5041            r32[4] = ((word32)t12 >>  8) | ((word32)t13 <<  2) |
5042                     ((word32)t14 << 12) | ((word32)t15 << 22);
5043
5044            /* Move over set bytes. */
5045            r += 20;
5046        }
5047#endif
5048    }
5049}
5050
5051/* Compress the vector of polynomials into a byte array with 10 bits each.
5052 *
5053 * FIPS 203, Section 4.2.1, Compression and decompression
5054 *
5055 * @param  [out]      r  Array of bytes.
5056 * @param  [in, out]  v  Vector of polynomials.
5057 * @param  [in]       k  Number of polynomials in vector.
5058 */
5059void mlkem_vec_compress_10(byte* r, sword16* v, unsigned int k)
5060{
5061#ifdef USE_INTEL_SPEEDUP
5062    if (IS_INTEL_AVX2(cpuid_flags) && (SAVE_VECTOR_REGISTERS2() == 0)) {
5063        mlkem_compress_10_avx2(r, v, (int)k);
5064        RESTORE_VECTOR_REGISTERS();
5065    }
5066    else
5067#endif
5068    {
5069        mlkem_vec_compress_10_c(r, v, k);
5070    }
5071}
5072#endif
5073
5074#if defined(WOLFSSL_KYBER1024) || defined(WOLFSSL_WC_ML_KEM_1024)
5075/* Compress the vector of polynomials into a byte array with 11 bits each.
5076 *
5077 * FIPS 203, Section 4.2.1, Compression and decompression
5078 *
5079 * @param  [out]      r  Array of bytes.
5080 * @param  [in, out]  v  Vector of polynomials.
5081 */
5082static void mlkem_vec_compress_11_c(byte* r, sword16* v)
5083{
5084    unsigned int i;
5085    unsigned int j;
5086#ifdef WOLFSSL_MLKEM_SMALL
5087    unsigned int k;
5088#endif
5089
5090    for (i = 0; i < 4; i++) {
5091        /* Reduce each coefficient to mod q. */
5092        mlkem_csubq_c(v + i * MLKEM_N);
5093        /* All values are now positive. */
5094    }
5095
5096    /* Each polynomial. */
5097    for (i = 0; i < 4; i++) {
5098        /* Each 8 polynomial coefficients. */
5099        for (j = 0; j < MLKEM_N; j += 8) {
5100        #ifdef WOLFSSL_MLKEM_SMALL
5101            sword16 t[8];
5102            /* Compress eight polynomial values to 11 bits each. */
5103            for (k = 0; k < 8; k++) {
5104                t[k] = TO_COMP_WORD_11(v, i, j, k);
5105            }
5106
5107            /* Pack eight 11-bit values into byte array. */
5108            r[ 0] = (byte)( t[0] >>  0);
5109            r[ 1] = (byte)((t[0] >>  8) | (t[1] << 3));
5110            r[ 2] = (byte)((t[1] >>  5) | (t[2] << 6));
5111            r[ 3] = (byte)( t[2] >>  2);
5112            r[ 4] = (byte)((t[2] >> 10) | (t[3] << 1));
5113            r[ 5] = (byte)((t[3] >>  7) | (t[4] << 4));
5114            r[ 6] = (byte)((t[4] >>  4) | (t[5] << 7));
5115            r[ 7] = (byte)( t[5] >>  1);
5116            r[ 8] = (byte)((t[5] >>  9) | (t[6] << 2));
5117            r[ 9] = (byte)((t[6] >>  6) | (t[7] << 5));
5118            r[10] = (byte)( t[7] >>  3);
5119        #else
5120            /* Compress eight polynomial values to 11 bits each. */
5121            sword16 t0 = TO_COMP_WORD_11(v, i, j, 0);
5122            sword16 t1 = TO_COMP_WORD_11(v, i, j, 1);
5123            sword16 t2 = TO_COMP_WORD_11(v, i, j, 2);
5124            sword16 t3 = TO_COMP_WORD_11(v, i, j, 3);
5125            sword16 t4 = TO_COMP_WORD_11(v, i, j, 4);
5126            sword16 t5 = TO_COMP_WORD_11(v, i, j, 5);
5127            sword16 t6 = TO_COMP_WORD_11(v, i, j, 6);
5128            sword16 t7 = TO_COMP_WORD_11(v, i, j, 7);
5129
5130            /* Pack eight 11-bit values into byte array. */
5131            r[ 0] = (byte)( t0 >>  0);
5132            r[ 1] = (byte)((t0 >>  8) | (t1 << 3));
5133            r[ 2] = (byte)((t1 >>  5) | (t2 << 6));
5134            r[ 3] = (byte)( t2 >>  2);
5135            r[ 4] = (byte)((t2 >> 10) | (t3 << 1));
5136            r[ 5] = (byte)((t3 >>  7) | (t4 << 4));
5137            r[ 6] = (byte)((t4 >>  4) | (t5 << 7));
5138            r[ 7] = (byte)( t5 >>  1);
5139            r[ 8] = (byte)((t5 >>  9) | (t6 << 2));
5140            r[ 9] = (byte)((t6 >>  6) | (t7 << 5));
5141            r[10] = (byte)( t7 >>  3);
5142        #endif
5143
5144            /* Move over set bytes. */
5145            r += 11;
5146        }
5147    }
5148}
5149
5150/* Compress the vector of polynomials into a byte array with 11 bits each.
5151 *
5152 * FIPS 203, Section 4.2.1, Compression and decompression
5153 *
5154 * @param  [out]      r  Array of bytes.
5155 * @param  [in, out]  v  Vector of polynomials.
5156 */
5157void mlkem_vec_compress_11(byte* r, sword16* v)
5158{
5159#ifdef USE_INTEL_SPEEDUP
5160    if (IS_INTEL_AVX2(cpuid_flags) && (SAVE_VECTOR_REGISTERS2() == 0)) {
5161        mlkem_compress_11_avx2(r, v, 4);
5162        RESTORE_VECTOR_REGISTERS();
5163    }
5164    else
5165#endif
5166    {
5167        mlkem_vec_compress_11_c(r, v);
5168    }
5169}
5170#endif
5171#endif /* !WOLFSSL_MLKEM_NO_ENCAPSULATE || !WOLFSSL_MLKEM_NO_DECAPSULATE */
5172
5173#ifndef WOLFSSL_MLKEM_NO_DECAPSULATE
5174/* Decompress a 10 bit value.
5175 *
5176 * FIPS 203, Section 4.2.1, Compression and decompression
5177 *
5178 * @param  [out]  v  Vector of polynomials.
5179 * @param  [in]   i  Index of polynomial in vector.
5180 * @param  [in]   j  Index into polynomial.
5181 * @param  [in]   k  Offset from indices.
5182 * @param  [in]   t  Value to decompress.
5183 */
5184#define DECOMP_10(v, i, j, k, t) \
5185    v[(i) * MLKEM_N + 4 * (j) + (k)] = \
5186        (sword16)((((word32)((t) & 0x3ff) * MLKEM_Q) + 512) >> 10)
5187
5188/* Decompress an 11 bit value.
5189 *
5190 * FIPS 203, Section 4.2.1, Compression and decompression
5191 *
5192 * @param  [out]  v  Vector of polynomials.
5193 * @param  [in]   i  Index of polynomial in vector.
5194 * @param  [in]   j  Index into polynomial.
5195 * @param  [in]   k  Offset from indices.
5196 * @param  [in]   t  Value to decompress.
5197 */
5198#define DECOMP_11(v, i, j, k, t) \
5199    v[(i) * MLKEM_N + 8 * (j) + (k)] = \
5200        (sword16)((((word32)((t) & 0x7ff) * MLKEM_Q) + 1024) >> 11)
5201
5202#if defined(WOLFSSL_KYBER512) || defined(WOLFSSL_WC_ML_KEM_512) || \
5203    defined(WOLFSSL_KYBER768) || defined(WOLFSSL_WC_ML_KEM_768)
5204/* Decompress the byte array of packed 10 bits into vector of polynomials.
5205 *
5206 * FIPS 203, Section 4.2.1, Compression and decompression
5207 *
5208 * @param  [out]  v  Vector of polynomials.
5209 * @param  [in]   b  Array of bytes.
5210 * @param  [in]   k  Number of polynomials in vector.
5211 */
5212static void mlkem_vec_decompress_10_c(sword16* v, const byte* b, unsigned int k)
5213{
5214    unsigned int i;
5215    unsigned int j;
5216#ifdef WOLFSSL_MLKEM_SMALL
5217    unsigned int l;
5218#endif
5219
5220    /* Each polynomial. */
5221    for (i = 0; i < k; i++) {
5222        /* Each 4 polynomial coefficients. */
5223        for (j = 0; j < MLKEM_N / 4; j++) {
5224        #ifdef WOLFSSL_MLKEM_SMALL
5225            word16 t[4];
5226            /* Extract out 4 values of 10 bits each. */
5227            t[0] = (word16)((b[0] >> 0) | ((word16)b[ 1] << 8));
5228            t[1] = (word16)((b[1] >> 2) | ((word16)b[ 2] << 6));
5229            t[2] = (word16)((b[2] >> 4) | ((word16)b[ 3] << 4));
5230            t[3] = (word16)((b[3] >> 6) | ((word16)b[ 4] << 2));
5231            b += 5;
5232
5233            /* Decompress 4 values. */
5234            for (l = 0; l < 4; l++) {
5235                DECOMP_10(v, i, j, l, t[l]);
5236            }
5237        #else
5238            /* Extract out 4 values of 10 bits each. */
5239            word16 t0 = (word16)((b[0] >> 0) | ((word16)b[ 1] << 8));
5240            word16 t1 = (word16)((b[1] >> 2) | ((word16)b[ 2] << 6));
5241            word16 t2 = (word16)((b[2] >> 4) | ((word16)b[ 3] << 4));
5242            word16 t3 = (word16)((b[3] >> 6) | ((word16)b[ 4] << 2));
5243            b += 5;
5244
5245            /* Decompress 4 values. */
5246            DECOMP_10(v, i, j, 0, t0);
5247            DECOMP_10(v, i, j, 1, t1);
5248            DECOMP_10(v, i, j, 2, t2);
5249            DECOMP_10(v, i, j, 3, t3);
5250        #endif
5251        }
5252    }
5253}
5254
5255/* Decompress the byte array of packed 10 bits into vector of polynomials.
5256 *
5257 * FIPS 203, Section 4.2.1, Compression and decompression
5258 *
5259 * @param  [out]  v  Vector of polynomials.
5260 * @param  [in]   b  Array of bytes.
5261 * @param  [in]   k  Number of polynomials in vector.
5262 */
5263void mlkem_vec_decompress_10(sword16* v, const byte* b, unsigned int k)
5264{
5265#ifdef USE_INTEL_SPEEDUP
5266    if (IS_INTEL_AVX2(cpuid_flags) && (SAVE_VECTOR_REGISTERS2() == 0)) {
5267        mlkem_decompress_10_avx2(v, b, (int)k);
5268        RESTORE_VECTOR_REGISTERS();
5269    }
5270    else
5271#endif
5272    {
5273        mlkem_vec_decompress_10_c(v, b, k);
5274    }
5275}
5276#endif
5277#if defined(WOLFSSL_KYBER1024) || defined(WOLFSSL_WC_ML_KEM_1024)
5278/* Decompress the byte array of packed 11 bits into vector of polynomials.
5279 *
5280 * FIPS 203, Section 4.2.1, Compression and decompression
5281 *
5282 * @param  [out]  v       Vector of polynomials.
5283 * @param  [in]   b       Array of bytes.
5284 */
5285static void mlkem_vec_decompress_11_c(sword16* v, const byte* b)
5286{
5287    unsigned int i;
5288    unsigned int j;
5289#ifdef WOLFSSL_MLKEM_SMALL
5290    unsigned int l;
5291#endif
5292
5293    /* Each polynomial. */
5294    for (i = 0; i < 4; i++) {
5295        /* Each 8 polynomial coefficients. */
5296        for (j = 0; j < MLKEM_N / 8; j++) {
5297        #ifdef WOLFSSL_MLKEM_SMALL
5298            word16 t[8];
5299            /* Extract out 8 values of 11 bits each. */
5300            t[0] = (word16)((b[0] >> 0) | ((word16)b[ 1] << 8));
5301            t[1] = (word16)((b[1] >> 3) | ((word16)b[ 2] << 5));
5302            t[2] = (word16)((b[2] >> 6) | ((word16)b[ 3] << 2) |
5303                   ((word16)b[4] << 10));
5304            t[3] = (word16)((b[4] >> 1) | ((word16)b[ 5] << 7));
5305            t[4] = (word16)((b[5] >> 4) | ((word16)b[ 6] << 4));
5306            t[5] = (word16)((b[6] >> 7) | ((word16)b[ 7] << 1) |
5307                   ((word16)b[8] <<  9));
5308            t[6] = (word16)((b[8] >> 2) | ((word16)b[ 9] << 6));
5309            t[7] = (word16)((b[9] >> 5) | ((word16)b[10] << 3));
5310            b += 11;
5311
5312            /* Decompress 8 values. */
5313            for (l = 0; l < 8; l++) {
5314                DECOMP_11(v, i, j, l, t[l]);
5315            }
5316        #else
5317            /* Extract out 8 values of 11 bits each. */
5318            word16 t0 = (word16)((b[0] >> 0) | ((word16)b[ 1] << 8));
5319            word16 t1 = (word16)((b[1] >> 3) | ((word16)b[ 2] << 5));
5320            word16 t2 = (word16)((b[2] >> 6) | ((word16)b[ 3] << 2) |
5321                   ((word16)b[4] << 10));
5322            word16 t3 = (word16)((b[4] >> 1) | ((word16)b[ 5] << 7));
5323            word16 t4 = (word16)((b[5] >> 4) | ((word16)b[ 6] << 4));
5324            word16 t5 = (word16)((b[6] >> 7) | ((word16)b[ 7] << 1) |
5325                   ((word16)b[8] <<  9));
5326            word16 t6 = (word16)((b[8] >> 2) | ((word16)b[ 9] << 6));
5327            word16 t7 = (word16)((b[9] >> 5) | ((word16)b[10] << 3));
5328            b += 11;
5329
5330            /* Decompress 8 values. */
5331            DECOMP_11(v, i, j, 0, t0);
5332            DECOMP_11(v, i, j, 1, t1);
5333            DECOMP_11(v, i, j, 2, t2);
5334            DECOMP_11(v, i, j, 3, t3);
5335            DECOMP_11(v, i, j, 4, t4);
5336            DECOMP_11(v, i, j, 5, t5);
5337            DECOMP_11(v, i, j, 6, t6);
5338            DECOMP_11(v, i, j, 7, t7);
5339        #endif
5340        }
5341    }
5342}
5343
5344/* Decompress the byte array of packed 11 bits into vector of polynomials.
5345 *
5346 * FIPS 203, Section 4.2.1, Compression and decompression
5347 *
5348 * @param  [out]  v       Vector of polynomials.
5349 * @param  [in]   b       Array of bytes.
5350 */
5351void mlkem_vec_decompress_11(sword16* v, const byte* b)
5352{
5353#ifdef USE_INTEL_SPEEDUP
5354    if (IS_INTEL_AVX2(cpuid_flags) && (SAVE_VECTOR_REGISTERS2() == 0)) {
5355        mlkem_decompress_11_avx2(v, b, 4);
5356        RESTORE_VECTOR_REGISTERS();
5357    }
5358    else
5359#endif
5360    {
5361        mlkem_vec_decompress_11_c(v, b);
5362    }
5363}
5364#endif
5365#endif /* !WOLFSSL_MLKEM_NO_DECAPSULATE */
5366
5367#ifdef CONV_WITH_DIV
5368
5369/* Compress value.
5370 *
5371 * Uses div operator that may be slow and not constant-time.
5372 *
5373 * FIPS 203, Section 4.2.1, Compression and decompression
5374 *
5375 * @param  [in]  v  Vector of polynomials.
5376 * @param  [in]  i  Index into polynomial.
5377 * @param  [in]  j  Offset from indices.
5378 * @param  [in]  s  Shift amount to apply to value being compressed.
5379 * @param  [in]  m  Mask to apply to get the required number of bits.
5380 * @return  Compressed value.
5381 */
5382#define TO_COMP_WORD(v, i, j, s, m) \
5383    ((((word32)v[i + j] << s) + MLKEM_Q_HALF) / MLKEM_Q) & m
5384
5385/* Compress value to 4 bits.
5386 *
5387 * Uses div operator that may be slow and not constant-time.
5388 *
5389 * FIPS 203, Section 4.2.1, Compression and decompression
5390 *
5391 * @param  [in]  p  Polynomial.
5392 * @param  [in]  i  Index into polynomial.
5393 * @param  [in]  j  Offset from indices.
5394 * @return  Compressed value.
5395 */
5396#define TO_COMP_WORD_4(p, i, j) \
5397    TO_COMP_WORD(p, i, j, 4, 0xf)
5398
5399/* Compress value to 5 bits.
5400 *
5401 * Uses div operator that may be slow and not constant-time.
5402 *
5403 * FIPS 203, Section 4.2.1, Compression and decompression
5404 *
5405 * @param  [in]  p  Polynomial.
5406 * @param  [in]  i  Index into polynomial.
5407 * @param  [in]  j  Offset from indices.
5408 * @return  Compressed value.
5409 */
5410#define TO_COMP_WORD_5(p, i, j) \
5411    TO_COMP_WORD(p, i, j, 5, 0x1f)
5412
5413#else
5414
5415/* Multiplier that does div q. */
5416#define MLKEM_V28         ((word32)(((1U << 28) + MLKEM_Q_HALF)) / MLKEM_Q)
5417/* Multiplier times half of q plus one. */
5418#define MLKEM_V28_HALF    ((word32)(MLKEM_V28 * (MLKEM_Q_HALF + 1)))
5419
5420/* Multiplier that does div q. */
5421#define MLKEM_V27         ((word32)(((1U << 27) + MLKEM_Q_HALF)) / MLKEM_Q)
5422/* Multiplier times half of q. */
5423#define MLKEM_V27_HALF    ((word32)(MLKEM_V27 * MLKEM_Q_HALF))
5424
5425/* Compress value to 4 bits.
5426 *
5427 * Uses mul instead of div.
5428 *
5429 * FIPS 203, Section 4.2.1, Compression and decompression
5430 *
5431 * @param  [in]  p  Polynomial.
5432 * @param  [in]  i  Index into polynomial.
5433 * @param  [in]  j  Offset from indices.
5434 * @return  Compressed value.
5435 */
5436#define TO_COMP_WORD_4(p, i, j) \
5437    (byte)((((MLKEM_V28 << 4) * (word32)(p)[(i) + (j)]) + MLKEM_V28_HALF) >> 28)
5438
5439/* Compress value to 5 bits.
5440 *
5441 * Uses mul instead of div.
5442 *
5443 * FIPS 203, Section 4.2.1, Compression and decompression
5444 *
5445 * @param  [in]  p  Polynomial.
5446 * @param  [in]  i  Index into polynomial.
5447 * @param  [in]  j  Offset from indices.
5448 * @return  Compressed value.
5449 */
5450#define TO_COMP_WORD_5(p, i, j) \
5451    (byte)((((MLKEM_V27 << 5) * (word32)(p)[(i) + (j)]) + MLKEM_V27_HALF) >> 27)
5452
5453#endif /* CONV_WITH_DIV */
5454
5455#if !defined(WOLFSSL_MLKEM_NO_ENCAPSULATE) || \
5456    !defined(WOLFSSL_MLKEM_NO_DECAPSULATE)
5457#if defined(WOLFSSL_KYBER512) || defined(WOLFSSL_WC_ML_KEM_512) || \
5458    defined(WOLFSSL_KYBER768) || defined(WOLFSSL_WC_ML_KEM_768)
5459/* Compress a polynomial into byte array with coefficients of 4 bits.
5460 *
5461 * FIPS 203, Section 4.2.1, Compression and decompression
5462 *
5463 * @param  [out]      b  Array of bytes.
5464 * @param  [in, out]  p  Polynomial.
5465 */
5466static void mlkem_compress_4_c(byte* b, sword16* p)
5467{
5468    unsigned int i;
5469#ifdef WOLFSSL_MLKEM_SMALL
5470    unsigned int j;
5471    byte t[8];
5472#endif
5473
5474    /* Reduce each coefficient to mod q. */
5475    mlkem_csubq_c(p);
5476    /* All values are now positive. */
5477
5478    /* Each 8 polynomial coefficients. */
5479    for (i = 0; i < MLKEM_N; i += 8) {
5480    #ifdef WOLFSSL_MLKEM_SMALL
5481        /* Compress eight polynomial values to 4 bits each. */
5482        for (j = 0; j < 8; j++) {
5483            t[j] = TO_COMP_WORD_4(p, i, j);
5484        }
5485
5486        b[0] = (byte)(t[0] | (t[1] << 4));
5487        b[1] = (byte)(t[2] | (t[3] << 4));
5488        b[2] = (byte)(t[4] | (t[5] << 4));
5489        b[3] = (byte)(t[6] | (t[7] << 4));
5490    #else
5491        /* Compress eight polynomial values to 4 bits each. */
5492        byte t0 = TO_COMP_WORD_4(p, i, 0);
5493        byte t1 = TO_COMP_WORD_4(p, i, 1);
5494        byte t2 = TO_COMP_WORD_4(p, i, 2);
5495        byte t3 = TO_COMP_WORD_4(p, i, 3);
5496        byte t4 = TO_COMP_WORD_4(p, i, 4);
5497        byte t5 = TO_COMP_WORD_4(p, i, 5);
5498        byte t6 = TO_COMP_WORD_4(p, i, 6);
5499        byte t7 = TO_COMP_WORD_4(p, i, 7);
5500
5501        /* Pack eight 4-bit values into byte array. */
5502        b[0] = (byte)(t0 | (t1 << 4));
5503        b[1] = (byte)(t2 | (t3 << 4));
5504        b[2] = (byte)(t4 | (t5 << 4));
5505        b[3] = (byte)(t6 | (t7 << 4));
5506    #endif
5507
5508        /* Move over set bytes. */
5509        b += 4;
5510    }
5511}
5512
5513/* Compress a polynomial into byte array with coefficients of 4 bits.
5514 *
5515 * FIPS 203, Section 4.2.1, Compression and decompression
5516 *
5517 * @param  [out]      b  Array of bytes.
5518 * @param  [in, out]  p  Polynomial.
5519 */
5520void mlkem_compress_4(byte* b, sword16* p)
5521{
5522#ifdef USE_INTEL_SPEEDUP
5523    if (IS_INTEL_AVX2(cpuid_flags) && (SAVE_VECTOR_REGISTERS2() == 0)) {
5524        mlkem_compress_4_avx2(b, p);
5525        RESTORE_VECTOR_REGISTERS();
5526    }
5527    else
5528#endif
5529    {
5530        mlkem_compress_4_c(b, p);
5531    }
5532}
5533#endif
5534#if defined(WOLFSSL_KYBER1024) || defined(WOLFSSL_WC_ML_KEM_1024)
5535/* Compress a polynomial into byte array with coefficients of 5 bits.
5536 *
5537 * FIPS 203, Section 4.2.1, Compression and decompression
5538 *
5539 * @param  [out]      b  Array of bytes.
5540 * @param  [in, out]  p  Polynomial.
5541 */
5542static void mlkem_compress_5_c(byte* b, sword16* p)
5543{
5544    unsigned int i;
5545#ifdef WOLFSSL_MLKEM_SMALL
5546    unsigned int j;
5547    byte t[8];
5548#endif
5549
5550    /* Reduce each coefficient to mod q. */
5551    mlkem_csubq_c(p);
5552    /* All values are now positive. */
5553
5554    for (i = 0; i < MLKEM_N; i += 8) {
5555    #ifdef WOLFSSL_MLKEM_SMALL
5556        /* Compress eight polynomial values to 5 bits each. */
5557        for (j = 0; j < 8; j++) {
5558            t[j] = TO_COMP_WORD_5(p, i, j);
5559        }
5560
5561        /* Pack 5 bits into byte array. */
5562        b[0] = (byte)((t[0] >> 0) | (t[1] << 5));
5563        b[1] = (byte)((t[1] >> 3) | (t[2] << 2) | (t[3] << 7));
5564        b[2] = (byte)((t[3] >> 1) | (t[4] << 4));
5565        b[3] = (byte)((t[4] >> 4) | (t[5] << 1) | (t[6] << 6));
5566        b[4] = (byte)((t[6] >> 2) | (t[7] << 3));
5567    #else
5568        /* Compress eight polynomial values to 5 bits each. */
5569        byte t0 = TO_COMP_WORD_5(p, i, 0);
5570        byte t1 = TO_COMP_WORD_5(p, i, 1);
5571        byte t2 = TO_COMP_WORD_5(p, i, 2);
5572        byte t3 = TO_COMP_WORD_5(p, i, 3);
5573        byte t4 = TO_COMP_WORD_5(p, i, 4);
5574        byte t5 = TO_COMP_WORD_5(p, i, 5);
5575        byte t6 = TO_COMP_WORD_5(p, i, 6);
5576        byte t7 = TO_COMP_WORD_5(p, i, 7);
5577
5578        /* Pack eight 5-bit values into byte array. */
5579        b[0] = (byte)((t0 >> 0) | (t1 << 5));
5580        b[1] = (byte)((t1 >> 3) | (t2 << 2) | (t3 << 7));
5581        b[2] = (byte)((t3 >> 1) | (t4 << 4));
5582        b[3] = (byte)((t4 >> 4) | (t5 << 1) | (t6 << 6));
5583        b[4] = (byte)((t6 >> 2) | (t7 << 3));
5584    #endif
5585
5586        /* Move over set bytes. */
5587        b += 5;
5588    }
5589}
5590
5591/* Compress a polynomial into byte array with coefficients of 5 bits.
5592 *
5593 * FIPS 203, Section 4.2.1, Compression and decompression
5594 *
5595 * @param  [out]      b  Array of bytes.
5596 * @param  [in, out]  p  Polynomial.
5597 */
5598void mlkem_compress_5(byte* b, sword16* p)
5599{
5600#ifdef USE_INTEL_SPEEDUP
5601    if (IS_INTEL_AVX2(cpuid_flags) && (SAVE_VECTOR_REGISTERS2() == 0)) {
5602        mlkem_compress_5_avx2(b, p);
5603        RESTORE_VECTOR_REGISTERS();
5604    }
5605    else
5606#endif
5607    {
5608        mlkem_compress_5_c(b, p);
5609    }
5610}
5611#endif
5612#endif /* !WOLFSSL_MLKEM_NO_ENCAPSULATE || !WOLFSSL_MLKEM_NO_DECAPSULATE */
5613
5614#ifndef WOLFSSL_MLKEM_NO_DECAPSULATE
5615/* Decompress a 4 bit value.
5616 *
5617 * FIPS 203, Section 4.2.1, Compression and decompression
5618 *
5619 * @param  [out]  p  Polynomial.
5620 * @param  [in]   i  Index into polynomial.
5621 * @param  [in]   j  Offset from indices.
5622 * @param  [in]   t  Value to decompress.
5623 */
5624#define DECOMP_4(p, i, j, t) \
5625    p[(i) + (j)] = (sword16)(((word16)((t) * MLKEM_Q) + 8) >> 4)
5626
5627/* Decompress a 5 bit value.
5628 *
5629 * FIPS 203, Section 4.2.1, Compression and decompression
5630 *
5631 * @param  [out]  p  Polynomial.
5632 * @param  [in]   i  Index into polynomial.
5633 * @param  [in]   j  Offset from indices.
5634 * @param  [in]   t  Value to decompress.
5635 */
5636#define DECOMP_5(p, i, j, t) \
5637    p[(i) + (j)] = (sword16)((((word32)((t) & 0x1f) * MLKEM_Q) + 16) >> 5)
5638
5639#if defined(WOLFSSL_KYBER512) || defined(WOLFSSL_WC_ML_KEM_512) || \
5640    defined(WOLFSSL_KYBER768) || defined(WOLFSSL_WC_ML_KEM_768)
5641/* Decompress the byte array of packed 4 bits into polynomial.
5642 *
5643 * FIPS 203, Section 4.2.1, Compression and decompression
5644 *
5645 * @param  [out]  p       Polynomial.
5646 * @param  [in]   b       Array of bytes.
5647 */
5648static void mlkem_decompress_4_c(sword16* p, const byte* b)
5649{
5650    unsigned int i;
5651
5652    /* 2 coefficients at a time. */
5653    for (i = 0; i < MLKEM_N; i += 2) {
5654        /* 2 coefficients decompressed from one byte. */
5655        DECOMP_4(p, i, 0, b[0] & 0xf);
5656        DECOMP_4(p, i, 1, b[0] >>  4);
5657        b += 1;
5658    }
5659}
5660
5661/* Decompress the byte array of packed 4 bits into polynomial.
5662 *
5663 * FIPS 203, Section 4.2.1, Compression and decompression
5664 *
5665 * @param  [out]  p       Polynomial.
5666 * @param  [in]   b       Array of bytes.
5667 */
5668void mlkem_decompress_4(sword16* p, const byte* b)
5669{
5670#ifdef USE_INTEL_SPEEDUP
5671    if (IS_INTEL_AVX2(cpuid_flags) && (SAVE_VECTOR_REGISTERS2() == 0)) {
5672        mlkem_decompress_4_avx2(p, b);
5673        RESTORE_VECTOR_REGISTERS();
5674    }
5675    else
5676#endif
5677    {
5678        mlkem_decompress_4_c(p, b);
5679    }
5680}
5681#endif
5682#if defined(WOLFSSL_KYBER1024) || defined(WOLFSSL_WC_ML_KEM_1024)
5683/* Decompress the byte array of packed 5 bits into polynomial.
5684 *
5685 * FIPS 203, Section 4.2.1, Compression and decompression
5686 *
5687 * @param  [out]  p       Polynomial.
5688 * @param  [in]   b       Array of bytes.
5689 */
5690static void mlkem_decompress_5_c(sword16* p, const byte* b)
5691{
5692    unsigned int i;
5693
5694    /* Each 8 polynomial coefficients. */
5695    for (i = 0; i < MLKEM_N; i += 8) {
5696    #ifdef WOLFSSL_MLKEM_SMALL
5697        unsigned int j;
5698        byte t[8];
5699
5700        /* Extract out 8 values of 5 bits each. */
5701        t[0] = (b[0] >> 0);
5702        t[1] = (byte)((b[0] >> 5) | (b[1] << 3));
5703        t[2] = (b[1] >> 2);
5704        t[3] = (byte)((b[1] >> 7) | (b[2] << 1));
5705        t[4] = (byte)((b[2] >> 4) | (b[3] << 4));
5706        t[5] = (b[3] >> 1);
5707        t[6] = (byte)((b[3] >> 6) | (b[4] << 2));
5708        t[7] = (b[4] >> 3);
5709        b += 5;
5710
5711        /* Decompress 8 values. */
5712        for (j = 0; j < 8; j++) {
5713            DECOMP_5(p, i, j, t[j]);
5714        }
5715    #else
5716        /* Extract out 8 values of 5 bits each. */
5717        byte t0 = (b[0] >> 0);
5718        byte t1 = (byte)((b[0] >> 5) | (b[1] << 3));
5719        byte t2 = (b[1] >> 2);
5720        byte t3 = (byte)((b[1] >> 7) | (b[2] << 1));
5721        byte t4 = (byte)((b[2] >> 4) | (b[3] << 4));
5722        byte t5 = (b[3] >> 1);
5723        byte t6 = (byte)((b[3] >> 6) | (b[4] << 2));
5724        byte t7 = (b[4] >> 3);
5725        b += 5;
5726
5727        /* Decompress 8 values. */
5728        DECOMP_5(p, i, 0, t0);
5729        DECOMP_5(p, i, 1, t1);
5730        DECOMP_5(p, i, 2, t2);
5731        DECOMP_5(p, i, 3, t3);
5732        DECOMP_5(p, i, 4, t4);
5733        DECOMP_5(p, i, 5, t5);
5734        DECOMP_5(p, i, 6, t6);
5735        DECOMP_5(p, i, 7, t7);
5736    #endif
5737    }
5738}
5739
5740/* Decompress the byte array of packed 5 bits into polynomial.
5741 *
5742 * FIPS 203, Section 4.2.1, Compression and decompression
5743 *
5744 * @param  [out]  p       Polynomial.
5745 * @param  [in]   b       Array of bytes.
5746 */
5747void mlkem_decompress_5(sword16* p, const byte* b)
5748{
5749#ifdef USE_INTEL_SPEEDUP
5750    if (IS_INTEL_AVX2(cpuid_flags) && (SAVE_VECTOR_REGISTERS2() == 0)) {
5751        mlkem_decompress_5_avx2(p, b);
5752        RESTORE_VECTOR_REGISTERS();
5753    }
5754    else
5755#endif
5756    {
5757        mlkem_decompress_5_c(p, b);
5758    }
5759}
5760#endif
5761#endif /* !WOLFSSL_MLKEM_NO_DECAPSULATE */
5762
5763/******************************************************************************/
5764
5765#if !(defined(__aarch64__) && defined(WOLFSSL_ARMASM))
5766#if !defined(WOLFSSL_MLKEM_NO_ENCAPSULATE) || \
5767    !defined(WOLFSSL_MLKEM_NO_DECAPSULATE)
5768/* Convert bit from byte to 0 or (MLKEM_Q + 1) / 2.
5769 *
5770 * Constant time implementation.
5771 * XOR in wc_mlkem_opt_blocker() to ensure optimizer doesn't know what will be
5772 * ANDed with MLKEM_Q_1_HALF and can't optimize to non-constant time code.
5773 *
5774 * FIPS 203, Algorithm 6: ByteDecode_d(B)
5775 *
5776 * @param  [out]  p    Polynomial to hold converted value.
5777 * @param  [in]   msg  Message to get bit from byte.
5778 * @param  [in]   i    Index of byte from message.
5779 * @param  [in]   j    Index of bit in byte.
5780 */
5781#define FROM_MSG_BIT(p, msg, i, j) \
5782    ((p)[8 * (i) + (j)] = (((sword16)0 - (sword16)(((msg)[i] >> (j)) & 1)) ^ \
5783                          wc_mlkem_opt_blocker()) & MLKEM_Q_1_HALF)
5784
5785/* Convert message to polynomial.
5786 *
5787 * FIPS 203, Algorithm 6: ByteDecode_d(B)
5788 *
5789 * @param  [out]  p    Polynomial.
5790 * @param  [in]   msg  Message as a byte array.
5791 */
5792static void mlkem_from_msg_c(sword16* p, const byte* msg)
5793{
5794    unsigned int i;
5795
5796    /* For each byte of the message. */
5797    for (i = 0; i < MLKEM_N / 8; i++) {
5798    #ifdef WOLFSSL_MLKEM_SMALL
5799        unsigned int j;
5800        /* For each bit of the message. */
5801        for (j = 0; j < 8; j++) {
5802            FROM_MSG_BIT(p, msg, i, j);
5803        }
5804    #else
5805        FROM_MSG_BIT(p, msg, i, 0);
5806        FROM_MSG_BIT(p, msg, i, 1);
5807        FROM_MSG_BIT(p, msg, i, 2);
5808        FROM_MSG_BIT(p, msg, i, 3);
5809        FROM_MSG_BIT(p, msg, i, 4);
5810        FROM_MSG_BIT(p, msg, i, 5);
5811        FROM_MSG_BIT(p, msg, i, 6);
5812        FROM_MSG_BIT(p, msg, i, 7);
5813    #endif
5814    }
5815}
5816
5817/* Convert message to polynomial.
5818 *
5819 * FIPS 203, Algorithm 6: ByteDecode_d(B)
5820 *
5821 * @param  [out]  p    Polynomial.
5822 * @param  [in]   msg  Message as a byte array.
5823 */
5824void mlkem_from_msg(sword16* p, const byte* msg)
5825{
5826#ifdef USE_INTEL_SPEEDUP
5827    if (IS_INTEL_AVX2(cpuid_flags) && (SAVE_VECTOR_REGISTERS2() == 0)) {
5828        mlkem_from_msg_avx2(p, msg);
5829        RESTORE_VECTOR_REGISTERS();
5830    }
5831    else
5832#endif
5833    {
5834        mlkem_from_msg_c(p, msg);
5835    }
5836}
5837#endif
5838
5839#ifndef WOLFSSL_MLKEM_NO_DECAPSULATE
5840#ifdef CONV_WITH_DIV
5841
5842/* Convert value to bit.
5843 *
5844 * Uses div operator that may be slow.
5845 *
5846 * FIPS 203, Algorithm 5: ByteEncode_d(F)
5847 *
5848 * @param  [in, out]  m   Message.
5849 * @param  [in]       p   Polynomial.
5850 * @param  [in]       i   Index of byte in message.
5851 * @param  [in]       j   Index of bit in byte.
5852 */
5853#define TO_MSG_BIT(m, p, i, j) \
5854    m[i] |= (((((sword16)p[8 * i + j] << 1) + MLKEM_Q_HALF) / MLKEM_Q) & 1) << j
5855
5856#else
5857
5858/* Multiplier that does div q. */
5859#define MLKEM_V31       (((1U << 31) + (MLKEM_Q / 2)) / MLKEM_Q)
5860/* 2 * multiplier that does div q. Only need bit 32 of result. */
5861#define MLKEM_V31_2     ((word32)(MLKEM_V31 * 2))
5862/* Multiplier times half of q. */
5863#define MLKEM_V31_HALF    ((word32)(MLKEM_V31 * MLKEM_Q_HALF))
5864
5865/* Convert value to bit.
5866 *
5867 * Uses mul instead of div.
5868 *
5869 * FIPS 203, Algorithm 5: ByteEncode_d(F)
5870 *
5871 * @param  [in, out]  m   Message.
5872 * @param  [in]       p   Polynomial.
5873 * @param  [in]       i   Index of byte in message.
5874 * @param  [in]       j   Index of bit in byte.
5875 */
5876#define TO_MSG_BIT(m, p, i, j) \
5877    (m)[i] |= (byte)((((MLKEM_V31_2 * (word16)(p)[8 * (i) + (j)]) + \
5878                       MLKEM_V31_HALF) >> 31) << (j))
5879
5880#endif /* CONV_WITH_DIV */
5881
5882/* Convert polynomial to message.
5883 *
5884 * FIPS 203, Algorithm 5: ByteEncode_d(F)
5885 *
5886 * @param  [out]      msg  Message as a byte array.
5887 * @param  [in, out]  p    Polynomial.
5888 */
5889static void mlkem_to_msg_c(byte* msg, sword16* p)
5890{
5891    unsigned int i;
5892
5893    /* Reduce each coefficient to mod q. */
5894    mlkem_csubq_c(p);
5895    /* All values are now in range. */
5896
5897    for (i = 0; i < MLKEM_N / 8; i++) {
5898    #ifdef WOLFSSL_MLKEM_SMALL
5899        unsigned int j;
5900        msg[i] = 0;
5901        for (j = 0; j < 8; j++) {
5902            TO_MSG_BIT(msg, p, i, j);
5903        }
5904    #else
5905        msg[i] = 0;
5906        TO_MSG_BIT(msg, p, i, 0);
5907        TO_MSG_BIT(msg, p, i, 1);
5908        TO_MSG_BIT(msg, p, i, 2);
5909        TO_MSG_BIT(msg, p, i, 3);
5910        TO_MSG_BIT(msg, p, i, 4);
5911        TO_MSG_BIT(msg, p, i, 5);
5912        TO_MSG_BIT(msg, p, i, 6);
5913        TO_MSG_BIT(msg, p, i, 7);
5914    #endif
5915    }
5916}
5917
5918/* Convert polynomial to message.
5919 *
5920 * FIPS 203, Algorithm 5: ByteEncode_d(F)
5921 *
5922 * @param  [out]      msg  Message as a byte array.
5923 * @param  [in, out]  p    Polynomial.
5924 */
5925void mlkem_to_msg(byte* msg, sword16* p)
5926{
5927#ifdef USE_INTEL_SPEEDUP
5928     if (IS_INTEL_AVX2(cpuid_flags) && (SAVE_VECTOR_REGISTERS2() == 0)) {
5929        /* Convert the polynomial into an array of bytes (message). */
5930        mlkem_to_msg_avx2(msg, p);
5931        RESTORE_VECTOR_REGISTERS();
5932    }
5933    else
5934#endif
5935    {
5936        mlkem_to_msg_c(msg, p);
5937    }
5938}
5939#endif /* !WOLFSSL_MLKEM_NO_DECAPSULATE */
5940#else
5941#if !defined(WOLFSSL_MLKEM_NO_ENCAPSULATE) || \
5942    !defined(WOLFSSL_MLKEM_NO_DECAPSULATE)
5943/* Convert message to polynomial.
5944 *
5945 * FIPS 203, Algorithm 6: ByteDecode_d(B)
5946 *
5947 * @param  [out]  p    Polynomial.
5948 * @param  [in]   msg  Message as a byte array.
5949 */
5950void mlkem_from_msg(sword16* p, const byte* msg)
5951{
5952    mlkem_from_msg_neon(p, msg);
5953}
5954#endif /* !WOLFSSL_MLKEM_NO_ENCAPSULATE || !WOLFSSL_MLKEM_NO_DECAPSULATE */
5955
5956#ifndef WOLFSSL_MLKEM_NO_DECAPSULATE
5957/* Convert polynomial to message.
5958 *
5959 * FIPS 203, Algorithm 5: ByteEncode_d(F)
5960 *
5961 * @param  [out]      msg  Message as a byte array.
5962 * @param  [in, out]  p    Polynomial.
5963 */
5964void mlkem_to_msg(byte* msg, sword16* p)
5965{
5966    mlkem_to_msg_neon(msg, p);
5967}
5968#endif /* WOLFSSL_MLKEM_NO_DECAPSULATE */
5969#endif /* !(__aarch64__ && WOLFSSL_ARMASM) */
5970
5971/******************************************************************************/
5972
5973/* Convert bytes to polynomial.
5974 *
5975 * Consecutive 12 bits hold each coefficient of polynomial.
5976 * Used in decoding private and public keys.
5977 *
5978 * FIPS 203, Algorithm 6: ByteDecode_d(B)
5979 *
5980 * @param  [out]  p  Vector of polynomials.
5981 * @param  [in]   b  Array of bytes.
5982 * @param  [in]   k  Number of polynomials in vector.
5983 */
5984static void mlkem_from_bytes_c(sword16* p, const byte* b, int k)
5985{
5986    int i;
5987    int j;
5988
5989    for (j = 0; j < k; j++) {
5990        for (i = 0; i < MLKEM_N / 2; i++) {
5991            p[2 * i + 0] = ((b[3 * i + 0] >> 0) |
5992                            ((word16)b[3 * i + 1] << 8)) & 0xfff;
5993            p[2 * i + 1] = ((b[3 * i + 1] >> 4) |
5994                            ((word16)b[3 * i + 2] << 4)) & 0xfff;
5995        }
5996        p += MLKEM_N;
5997        b += WC_ML_KEM_POLY_SIZE;
5998    }
5999}
6000
6001/* Convert bytes to polynomial.
6002 *
6003 * Consecutive 12 bits hold each coefficient of polynomial.
6004 * Used in decoding private and public keys.
6005 *
6006 * FIPS 203, Algorithm 6: ByteDecode_d(B)
6007 *
6008 * @param  [out]  p  Vector of polynomials.
6009 * @param  [in]   b  Array of bytes.
6010 * @param  [in]   k  Number of polynomials in vector.
6011 */
6012void mlkem_from_bytes(sword16* p, const byte* b, int k)
6013{
6014#ifdef USE_INTEL_SPEEDUP
6015     if (IS_INTEL_AVX2(cpuid_flags) && (SAVE_VECTOR_REGISTERS2() == 0)) {
6016        int i;
6017
6018        for (i = 0; i < k; i++) {
6019            mlkem_from_bytes_avx2(p, b);
6020            p += MLKEM_N;
6021            b += WC_ML_KEM_POLY_SIZE;
6022        }
6023
6024        RESTORE_VECTOR_REGISTERS();
6025    }
6026    else
6027#endif
6028    {
6029        mlkem_from_bytes_c(p, b, k);
6030    }
6031}
6032
6033/* Convert polynomial to bytes.
6034 *
6035 * Consecutive 12 bits hold each coefficient of polynomial.
6036 * Used in encoding private and public keys.
6037 *
6038 * FIPS 203, Algorithm 5: ByteEncode_d(F)
6039 *
6040 * @param  [out]      b  Array of bytes.
6041 * @param  [in, out]  p  Polynomial.
6042 * @param  [in]       k  Number of polynomials in vector.
6043 */
6044static void mlkem_to_bytes_c(byte* b, sword16* p, int k)
6045{
6046    int i;
6047    int j;
6048
6049    for (j = 0; j < k; j++) {
6050        /* Reduce each coefficient to mod q. */
6051        mlkem_csubq_c(p);
6052        /* All values are now positive. */
6053
6054        for (i = 0; i < MLKEM_N / 2; i++) {
6055            word16 t0 = (word16)p[2 * i];
6056            word16 t1 = (word16)p[2 * i + 1];
6057            b[3 * i + 0] = (byte)(t0 >> 0);
6058            b[3 * i + 1] = (byte)((t0 >> 8) | (t1 << 4));
6059            b[3 * i + 2] = (byte)(t1 >> 4);
6060        }
6061        p += MLKEM_N;
6062        b += WC_ML_KEM_POLY_SIZE;
6063    }
6064}
6065
6066/* Convert polynomial to bytes.
6067 *
6068 * Consecutive 12 bits hold each coefficient of polynomial.
6069 * Used in encoding private and public keys.
6070 *
6071 * FIPS 203, Algorithm 5: ByteEncode_d(F)
6072 *
6073 * @param  [out]      b  Array of bytes.
6074 * @param  [in, out]  p  Polynomial.
6075 * @param  [in]       k  Number of polynomials in vector.
6076 */
6077void mlkem_to_bytes(byte* b, sword16* p, int k)
6078{
6079#ifdef USE_INTEL_SPEEDUP
6080     if (IS_INTEL_AVX2(cpuid_flags) && (SAVE_VECTOR_REGISTERS2() == 0)) {
6081        int i;
6082
6083        for (i = 0; i < k; i++) {
6084            mlkem_to_bytes_avx2(b, p);
6085            p += MLKEM_N;
6086            b += WC_ML_KEM_POLY_SIZE;
6087        }
6088
6089        RESTORE_VECTOR_REGISTERS();
6090    }
6091    else
6092#endif
6093    {
6094        mlkem_to_bytes_c(b, p, k);
6095    }
6096}
6097
6098/**
6099 * Check the public key values are smaller than the modulus.
6100 *
6101 * @param [in] p  Public key - vector.
6102 * @param [in] k  Number of polynomials in vector.
6103 * @return  0 when all values are in range.
6104 * @return  PUBLIC_KEY_E when at least one value is out of range.
6105 */
6106int mlkem_check_public(const sword16* p, int k)
6107{
6108    int ret = 0;
6109    int i;
6110
6111    for (i = 0; i < k * MLKEM_N; i++) {
6112        if (p[i] >= MLKEM_Q) {
6113            ret = PUBLIC_KEY_E;
6114            break;
6115        }
6116    }
6117
6118    return ret;
6119}
6120
6121#endif /* WOLFSSL_HAVE_MLKEM */