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
curl/lib/vtls/openssl.c raw
   1/***************************************************************************
   2 *                                  _   _ ____  _
   3 *  Project                     ___| | | |  _ \| |
   4 *                             / __| | | | |_) | |
   5 *                            | (__| |_| |  _ <| |___
   6 *                             \___|\___/|_| \_\_____|
   7 *
   8 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
   9 *
  10 * This software is licensed as described in the file COPYING, which
  11 * you should have received as part of this distribution. The terms
  12 * are also available at https://curl.se/docs/copyright.html.
  13 *
  14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
  15 * copies of the Software, and permit persons to whom the Software is
  16 * furnished to do so, under the terms of the COPYING file.
  17 *
  18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  19 * KIND, either express or implied.
  20 *
  21 * SPDX-License-Identifier: curl
  22 *
  23 ***************************************************************************/
  24/*
  25 * Source file for all OpenSSL-specific code for the TLS/SSL layer. No code
  26 * but vtls.c should ever call or use these functions.
  27 */
  28#include "curl_setup.h"
  29
  30#ifdef USE_OPENSSL
  31
  32#include "urldata.h"
  33#include "curl_trc.h"
  34#include "httpsrr.h"
  35#include "formdata.h" /* for the boundary function */
  36#include "url.h" /* for the ssl config check function */
  37#include "curlx/inet_pton.h"
  38#include "vtls/openssl.h"
  39#include "connect.h"
  40#include "cf-dns.h"
  41#include "progress.h"
  42#include "vtls/vtls.h"
  43#include "vtls/vtls_int.h"
  44#include "vtls/vtls_scache.h"
  45#include "vauth/vauth.h"
  46#include "vtls/keylog.h"
  47#include "vtls/hostcheck.h"
  48#include "transfer.h"
  49#include "multiif.h"
  50#include "curlx/strerr.h"
  51#include "curlx/strparse.h"
  52#include "curlx/strcopy.h"
  53#include "curlx/strdup.h"
  54#include "vtls/apple.h"
  55#ifdef USE_ECH
  56#include "curlx/base64.h"
  57#endif
  58
  59#include <openssl/rand.h>
  60#include <openssl/x509v3.h>
  61#ifndef OPENSSL_NO_DSA
  62#include <openssl/dsa.h>
  63#endif
  64#include <openssl/dh.h>
  65#include <openssl/err.h>
  66#include <openssl/conf.h>
  67#include <openssl/bn.h>
  68#include <openssl/rsa.h>
  69#include <openssl/bio.h>
  70#include <openssl/pkcs12.h>
  71#include <openssl/tls1.h>
  72#include <openssl/evp.h>
  73
  74#if defined(HAVE_SSL_SET1_ECH_CONFIG_LIST) && !defined(HAVE_BORINGSSL_LIKE)
  75#include <openssl/ech.h>
  76#endif
  77
  78#ifndef OPENSSL_NO_OCSP
  79#include <openssl/ocsp.h>
  80#endif
  81
  82#if !defined(OPENSSL_NO_ENGINE) && !defined(OPENSSL_NO_UI_CONSOLE)
  83#define USE_OPENSSL_ENGINE
  84#include <openssl/engine.h>
  85#endif
  86
  87#ifdef LIBRESSL_VERSION_NUMBER
  88/* As of LibreSSL 2.0.0-4.0.0: OPENSSL_VERSION_NUMBER == 0x20000000L */
  89#  if LIBRESSL_VERSION_NUMBER < 0x2090100fL /* 2019-04-13 */
  90#    error "LibreSSL 2.9.1 or later required"
  91#  endif
  92#elif !defined(HAVE_BORINGSSL_LIKE)
  93#  ifndef HAVE_OPENSSL3 /* 2021-09-07 */
  94#    error "OpenSSL 3.0.0 or later required"
  95#  endif
  96#endif
  97
  98#if defined(HAVE_OPENSSL3) && !defined(OPENSSL_NO_UI_CONSOLE)
  99#include <openssl/provider.h>
 100#include <openssl/store.h>
 101/* this is used in the following conditions to make them easier to read */
 102#define OPENSSL_HAS_PROVIDERS
 103#endif
 104
 105/* AWS-LC fixed a bug with large buffers in v1.61.0 which also introduced
 106 * X509_V_ERR_EC_KEY_EXPLICIT_PARAMS. */
 107#if !defined(LIBRESSL_VERSION_NUMBER) && !defined(OPENSSL_IS_BORINGSSL) && \
 108  (!defined(OPENSSL_IS_AWSLC) || defined(X509_V_ERR_EC_KEY_EXPLICIT_PARAMS))
 109#define HAVE_SSL_CTX_SET_DEFAULT_READ_BUFFER_LEN 1
 110#endif
 111
 112#if defined(USE_OPENSSL_ENGINE) || defined(OPENSSL_HAS_PROVIDERS)
 113#include <openssl/ui.h>
 114#endif
 115
 116#ifdef HAVE_OPENSSL3
 117#define HAVE_EVP_PKEY_GET_PARAMS 1
 118#endif
 119
 120#ifdef HAVE_EVP_PKEY_GET_PARAMS
 121#include <openssl/core_names.h>
 122#define DECLARE_PKEY_PARAM_BIGNUM(name) BIGNUM *name = NULL
 123#define FREE_PKEY_PARAM_BIGNUM(name) BN_clear_free(name)
 124#else
 125#define DECLARE_PKEY_PARAM_BIGNUM(name) const BIGNUM *name
 126#define FREE_PKEY_PARAM_BIGNUM(name)
 127#endif
 128
 129/* Whether SSL_CTX_set_ciphersuites is available.
 130 * BoringSSL: no
 131 * LibreSSL: supported since 3.4.1 (released 2021-10-14)
 132 * OpenSSL: supported since 1.1.1 (commit a53b5be6a05)
 133 */
 134#if (!defined(LIBRESSL_VERSION_NUMBER) || \
 135     (defined(LIBRESSL_VERSION_NUMBER) && \
 136      LIBRESSL_VERSION_NUMBER >= 0x3040100fL)) && \
 137    !defined(OPENSSL_IS_BORINGSSL)
 138#  define HAVE_SSL_CTX_SET_CIPHERSUITES
 139#  ifndef OPENSSL_IS_AWSLC
 140#    define HAVE_SSL_CTX_SET_POST_HANDSHAKE_AUTH
 141#  endif
 142#endif
 143
 144/* Whether SSL_CTX_set1_sigalgs_list is available
 145 * BoringSSL: supported since 0.20240913.0 (commit 826ce15)
 146 * LibreSSL: no
 147 * OpenSSL: supported since 1.0.2 (commit 0b362de5f575)
 148 */
 149#ifndef LIBRESSL_VERSION_NUMBER
 150#define HAVE_SSL_CTX_SET1_SIGALGS
 151#endif
 152
 153#ifdef LIBRESSL_VERSION_NUMBER
 154#define OSSL_PACKAGE "LibreSSL"
 155#elif defined(OPENSSL_IS_AWSLC)
 156#define OSSL_PACKAGE "AWS-LC"
 157#elif defined(OPENSSL_IS_BORINGSSL)
 158#define OSSL_PACKAGE "BoringSSL"
 159#elif defined(USE_NGTCP2) && defined(USE_NGHTTP3) && \
 160  !defined(OPENSSL_QUIC_API2)
 161#define OSSL_PACKAGE "quictls"
 162#else
 163#define OSSL_PACKAGE "OpenSSL"
 164#endif
 165
 166#ifdef HAVE_BORINGSSL_LIKE
 167typedef size_t numcert_t;
 168typedef uint32_t sslerr_t;
 169#else
 170typedef int numcert_t;
 171typedef unsigned long sslerr_t;
 172#endif
 173#define ossl_valsize_t numcert_t
 174
 175static CURLcode push_certinfo(struct Curl_easy *data,
 176                              BIO *mem, const char *label, int num)
 177  WARN_UNUSED_RESULT;
 178
 179static CURLcode push_certinfo(struct Curl_easy *data,
 180                              BIO *mem, const char *label, int num)
 181{
 182  char *ptr;
 183  long len = BIO_get_mem_data(mem, &ptr);
 184  CURLcode result = Curl_ssl_push_certinfo_len(data, num, label, ptr, len);
 185  (void)BIO_reset(mem);
 186  return result;
 187}
 188
 189static CURLcode pubkey_show(struct Curl_easy *data,
 190                            BIO *mem,
 191                            int num,
 192                            const char *type,
 193                            const char *name,
 194                            const BIGNUM *bn) WARN_UNUSED_RESULT;
 195
 196static CURLcode pubkey_show(struct Curl_easy *data,
 197                            BIO *mem,
 198                            int num,
 199                            const char *type,
 200                            const char *name,
 201                            const BIGNUM *bn)
 202{
 203  char namebuf[32];
 204
 205  curl_msnprintf(namebuf, sizeof(namebuf), "%s(%s)", type, name);
 206
 207  if(bn)
 208    BN_print(mem, bn);
 209  return push_certinfo(data, mem, namebuf, num);
 210}
 211
 212#define print_pubkey_BN(_type, _name, _num)           \
 213  pubkey_show(data, mem, _num, #_type, #_name, _name)
 214
 215static int asn1_object_dump(const ASN1_OBJECT *a, char *buf, size_t len)
 216{
 217  int i = i2t_ASN1_OBJECT(buf, (int)len, a);
 218  return (i >= (int)len);  /* buffer too small */
 219}
 220
 221static CURLcode X509V3_ext(struct Curl_easy *data,
 222                           int certnum,
 223                           const STACK_OF(X509_EXTENSION) *extsarg)
 224{
 225  int i;
 226  CURLcode result = CURLE_OK;
 227#ifdef LIBRESSL_VERSION_NUMBER
 228  STACK_OF(X509_EXTENSION) *exts = CURL_UNCONST(extsarg);
 229#else
 230  const STACK_OF(X509_EXTENSION) *exts = extsarg;
 231#endif
 232
 233  if((int)sk_X509_EXTENSION_num(exts) <= 0)
 234    /* no extensions, bail out */
 235    return result;
 236
 237  for(i = 0; i < (int)sk_X509_EXTENSION_num(exts); i++) {
 238    const ASN1_OBJECT *obj;
 239    X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, (ossl_valsize_t)i);
 240    BUF_MEM *biomem;
 241    char namebuf[128];
 242    BIO *bio_out = BIO_new(BIO_s_mem());
 243
 244    if(!bio_out)
 245      return result;
 246
 247    obj = X509_EXTENSION_get_object(ext);
 248
 249    if(asn1_object_dump(obj, namebuf, sizeof(namebuf)))
 250      /* make sure the name is null-terminated */
 251      namebuf[sizeof(namebuf) - 1] = 0;
 252
 253    if(!X509V3_EXT_print(bio_out, ext, 0, 0))
 254      ASN1_STRING_print(bio_out,
 255                        (const ASN1_STRING *)X509_EXTENSION_get_data(ext));
 256
 257    BIO_get_mem_ptr(bio_out, &biomem);
 258    result = Curl_ssl_push_certinfo_len(data, certnum, namebuf, biomem->data,
 259                                        biomem->length);
 260    BIO_free(bio_out);
 261    if(result)
 262      break;
 263  }
 264  return result;
 265}
 266
 267static CURLcode get_pkey_rsa(struct Curl_easy *data,
 268                             EVP_PKEY *pubkey, BIO *mem, int i)
 269{
 270  CURLcode result = CURLE_OK;
 271#ifndef HAVE_EVP_PKEY_GET_PARAMS
 272  RSA *rsa = EVP_PKEY_get0_RSA(pubkey);
 273#endif /* !HAVE_EVP_PKEY_GET_PARAMS */
 274  DECLARE_PKEY_PARAM_BIGNUM(n);
 275  DECLARE_PKEY_PARAM_BIGNUM(e);
 276#ifdef HAVE_EVP_PKEY_GET_PARAMS
 277  EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_N, &n);
 278  EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_E, &e);
 279#else
 280  RSA_get0_key(rsa, &n, &e, NULL);
 281#endif /* HAVE_EVP_PKEY_GET_PARAMS */
 282  BIO_printf(mem, "%d", (int)(n ? BN_num_bits(n) : 0));
 283  result = push_certinfo(data, mem, "RSA Public Key", i);
 284  if(!result) {
 285    result = print_pubkey_BN(rsa, n, i);
 286    if(!result)
 287      result = print_pubkey_BN(rsa, e, i);
 288  }
 289  FREE_PKEY_PARAM_BIGNUM(n);
 290  FREE_PKEY_PARAM_BIGNUM(e);
 291  return result;
 292}
 293
 294#ifndef OPENSSL_NO_DSA
 295static CURLcode get_pkey_dsa(struct Curl_easy *data,
 296                             EVP_PKEY *pubkey, BIO *mem, int i)
 297{
 298  CURLcode result = CURLE_OK;
 299#ifndef HAVE_EVP_PKEY_GET_PARAMS
 300  DSA *dsa = EVP_PKEY_get0_DSA(pubkey);
 301#endif /* !HAVE_EVP_PKEY_GET_PARAMS */
 302  DECLARE_PKEY_PARAM_BIGNUM(p);
 303  DECLARE_PKEY_PARAM_BIGNUM(q);
 304  DECLARE_PKEY_PARAM_BIGNUM(g);
 305  DECLARE_PKEY_PARAM_BIGNUM(pub_key);
 306#ifdef HAVE_EVP_PKEY_GET_PARAMS
 307  EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_P, &p);
 308  EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_Q, &q);
 309  EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_G, &g);
 310  EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_PUB_KEY, &pub_key);
 311#else
 312  DSA_get0_pqg(dsa, &p, &q, &g);
 313  DSA_get0_key(dsa, &pub_key, NULL);
 314#endif /* HAVE_EVP_PKEY_GET_PARAMS */
 315  result = print_pubkey_BN(dsa, p, i);
 316  if(!result)
 317    result = print_pubkey_BN(dsa, q, i);
 318  if(!result)
 319    result = print_pubkey_BN(dsa, g, i);
 320  if(!result)
 321    result = print_pubkey_BN(dsa, pub_key, i);
 322  FREE_PKEY_PARAM_BIGNUM(p);
 323  FREE_PKEY_PARAM_BIGNUM(q);
 324  FREE_PKEY_PARAM_BIGNUM(g);
 325  FREE_PKEY_PARAM_BIGNUM(pub_key);
 326  return result;
 327}
 328#endif /* !OPENSSL_NO_DSA */
 329
 330static CURLcode get_pkey_dh(struct Curl_easy *data,
 331                            EVP_PKEY *pubkey, BIO *mem, int i)
 332{
 333  CURLcode result;
 334#ifndef HAVE_EVP_PKEY_GET_PARAMS
 335  DH *dh = EVP_PKEY_get0_DH(pubkey);
 336#endif /* !HAVE_EVP_PKEY_GET_PARAMS */
 337  DECLARE_PKEY_PARAM_BIGNUM(p);
 338  DECLARE_PKEY_PARAM_BIGNUM(q);
 339  DECLARE_PKEY_PARAM_BIGNUM(g);
 340  DECLARE_PKEY_PARAM_BIGNUM(pub_key);
 341#ifdef HAVE_EVP_PKEY_GET_PARAMS
 342  EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_P, &p);
 343  EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_Q, &q);
 344  EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_G, &g);
 345  EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_PUB_KEY, &pub_key);
 346#else
 347  DH_get0_pqg(dh, &p, &q, &g);
 348  DH_get0_key(dh, &pub_key, NULL);
 349#endif /* HAVE_EVP_PKEY_GET_PARAMS */
 350  result = print_pubkey_BN(dh, p, i);
 351  if(!result)
 352    result = print_pubkey_BN(dh, q, i);
 353  if(!result)
 354    result = print_pubkey_BN(dh, g, i);
 355  if(!result)
 356    result = print_pubkey_BN(dh, pub_key, i);
 357  FREE_PKEY_PARAM_BIGNUM(p);
 358  FREE_PKEY_PARAM_BIGNUM(q);
 359  FREE_PKEY_PARAM_BIGNUM(g);
 360  FREE_PKEY_PARAM_BIGNUM(pub_key);
 361  return result;
 362}
 363
 364#ifdef HAVE_OPENSSL3
 365/* from OpenSSL commit fc756e594ed5a27af378 */
 366typedef const X509_PUBKEY pubkeytype_t;
 367#else
 368typedef X509_PUBKEY pubkeytype_t;
 369#endif
 370
 371static CURLcode ossl_certchain(struct Curl_easy *data, SSL *ssl)
 372{
 373  CURLcode result;
 374  STACK_OF(X509) *sk;
 375  int i;
 376  numcert_t numcerts;
 377  BIO *mem;
 378
 379  DEBUGASSERT(ssl);
 380
 381  sk = SSL_get_peer_cert_chain(ssl);
 382  if(!sk)
 383    return CURLE_SSL_CONNECT_ERROR;
 384
 385  numcerts = sk_X509_num(sk);
 386  if(numcerts > MAX_ALLOWED_CERT_AMOUNT) {
 387    failf(data, "%d certificates is more than allowed (%d)", (int)numcerts,
 388          MAX_ALLOWED_CERT_AMOUNT);
 389    return CURLE_SSL_CONNECT_ERROR;
 390  }
 391
 392  result = Curl_ssl_init_certinfo(data, (int)numcerts);
 393  if(result)
 394    return result;
 395
 396  mem = BIO_new(BIO_s_mem());
 397  if(!mem)
 398    result = CURLE_OUT_OF_MEMORY;
 399
 400  for(i = 0; !result && (i < (int)numcerts); i++) {
 401    ASN1_INTEGER *num;
 402    const unsigned char *numdata;
 403    X509 *x = sk_X509_value(sk, (ossl_valsize_t)i);
 404    EVP_PKEY *pubkey = NULL;
 405    int j;
 406    const ASN1_BIT_STRING *psig = NULL;
 407
 408    X509_NAME_print_ex(mem, X509_get_subject_name(x), 0, XN_FLAG_ONELINE);
 409    result = push_certinfo(data, mem, "Subject", i);
 410    if(result)
 411      break;
 412
 413    X509_NAME_print_ex(mem, X509_get_issuer_name(x), 0, XN_FLAG_ONELINE);
 414    result = push_certinfo(data, mem, "Issuer", i);
 415    if(result)
 416      break;
 417
 418    BIO_printf(mem, "%lx", X509_get_version(x));
 419    result = push_certinfo(data, mem, "Version", i);
 420    if(result)
 421      break;
 422
 423    num = X509_get_serialNumber(x);
 424    if(ASN1_STRING_type(num) == V_ASN1_NEG_INTEGER)
 425      BIO_puts(mem, "-");
 426    numdata = ASN1_STRING_get0_data(num);
 427    for(j = 0; j < ASN1_STRING_length(num); j++)
 428      BIO_printf(mem, "%02x", numdata[j]);
 429    result = push_certinfo(data, mem, "Serial Number", i);
 430    if(result)
 431      break;
 432
 433    {
 434      const X509_ALGOR *sigalg = NULL;
 435      pubkeytype_t *xpubkey = NULL;
 436      ASN1_OBJECT *pubkeyoid = NULL;
 437
 438      X509_get0_signature(&psig, &sigalg, x);
 439      if(sigalg) {
 440        const ASN1_OBJECT *sigalgoid = NULL;
 441        X509_ALGOR_get0(&sigalgoid, NULL, NULL, sigalg);
 442        i2a_ASN1_OBJECT(mem, sigalgoid);
 443        result = push_certinfo(data, mem, "Signature Algorithm", i);
 444        if(result)
 445          break;
 446      }
 447
 448      xpubkey = X509_get_X509_PUBKEY(x);
 449      if(xpubkey) {
 450        X509_PUBKEY_get0_param(&pubkeyoid, NULL, NULL, NULL, xpubkey);
 451        if(pubkeyoid) {
 452          i2a_ASN1_OBJECT(mem, pubkeyoid);
 453          result = push_certinfo(data, mem, "Public Key Algorithm", i);
 454          if(result)
 455            break;
 456        }
 457      }
 458
 459      result = X509V3_ext(data, i, X509_get0_extensions(x));
 460      if(result)
 461        break;
 462    }
 463
 464    ASN1_TIME_print(mem, X509_get0_notBefore(x));
 465    result = push_certinfo(data, mem, "Start date", i);
 466    if(result)
 467      break;
 468
 469    ASN1_TIME_print(mem, X509_get0_notAfter(x));
 470    result = push_certinfo(data, mem, "Expire date", i);
 471    if(result)
 472      break;
 473
 474    pubkey = X509_get_pubkey(x);
 475    if(!pubkey)
 476      infof(data, "   Unable to load public key");
 477    else {
 478      switch(EVP_PKEY_id(pubkey)) {
 479      case EVP_PKEY_RSA:
 480        result = get_pkey_rsa(data, pubkey, mem, i);
 481        break;
 482
 483#ifndef OPENSSL_NO_DSA
 484      case EVP_PKEY_DSA:
 485        result = get_pkey_dsa(data, pubkey, mem, i);
 486        break;
 487#endif
 488
 489      case EVP_PKEY_DH:
 490        result = get_pkey_dh(data, pubkey, mem, i);
 491        break;
 492      }
 493      EVP_PKEY_free(pubkey);
 494    }
 495
 496    if(!result && psig) {
 497      const unsigned char *psigdata = ASN1_STRING_get0_data(psig);
 498      for(j = 0; j < ASN1_STRING_length(psig); j++)
 499        BIO_printf(mem, "%02x:", psigdata[j]);
 500      result = push_certinfo(data, mem, "Signature", i);
 501    }
 502
 503    if(!result) {
 504      PEM_write_bio_X509(mem, x);
 505      result = push_certinfo(data, mem, "Cert", i);
 506    }
 507  }
 508
 509  BIO_free(mem);
 510
 511  if(result)
 512    /* cleanup all leftovers */
 513    Curl_ssl_free_certinfo(data);
 514
 515  return result;
 516}
 517
 518static int ossl_bio_cf_create(BIO *bio)
 519{
 520  BIO_set_shutdown(bio, 1);
 521  BIO_set_init(bio, 1);
 522  BIO_set_data(bio, NULL);
 523  return 1;
 524}
 525
 526static int ossl_bio_cf_destroy(BIO *bio)
 527{
 528  if(!bio)
 529    return 0;
 530  return 1;
 531}
 532
 533static long ossl_bio_cf_ctrl(BIO *bio, int cmd, long num, void *ptr)
 534{
 535  struct Curl_cfilter *cf = BIO_get_data(bio);
 536  long ret = 1;
 537
 538  (void)cf;
 539  (void)ptr;
 540  switch(cmd) {
 541  case BIO_CTRL_GET_CLOSE:
 542    ret = (long)BIO_get_shutdown(bio);
 543    break;
 544  case BIO_CTRL_SET_CLOSE:
 545    BIO_set_shutdown(bio, (int)num);
 546    break;
 547  case BIO_CTRL_FLUSH:
 548    /* we do no delayed writes, but if we ever would, this
 549     * needs to trigger it. */
 550    ret = 1;
 551    break;
 552  case BIO_CTRL_DUP:
 553    ret = 1;
 554    break;
 555  case BIO_CTRL_EOF: {
 556    /* EOF has been reached on input? */
 557    struct ssl_connect_data *connssl = cf->ctx;
 558    return connssl->peer_closed;
 559  }
 560  default:
 561    ret = 0;
 562    break;
 563  }
 564  return ret;
 565}
 566
 567static int ossl_bio_cf_out_write(BIO *bio, const char *buf, int blen)
 568{
 569  struct Curl_cfilter *cf = BIO_get_data(bio);
 570  struct ssl_connect_data *connssl = cf->ctx;
 571  struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
 572  struct Curl_easy *data = CF_DATA_CURRENT(cf);
 573  size_t nwritten;
 574  CURLcode result;
 575
 576  DEBUGASSERT(data);
 577  if(blen < 0)
 578    return 0;
 579
 580  result = Curl_conn_cf_send(cf->next, data,
 581                             (const uint8_t *)buf, (size_t)blen, FALSE,
 582                             &nwritten);
 583  CURL_TRC_CF(data, cf, "ossl_bio_cf_out_write(len=%d) -> %d, %zu",
 584              blen, result, nwritten);
 585  BIO_clear_retry_flags(bio);
 586  octx->io_result = result;
 587  if(result) {
 588    if(result == CURLE_AGAIN)
 589      BIO_set_retry_write(bio);
 590    return -1;
 591  }
 592  return (int)nwritten;
 593}
 594
 595static int ossl_bio_cf_in_read(BIO *bio, char *buf, int blen)
 596{
 597  struct Curl_cfilter *cf = BIO_get_data(bio);
 598  struct ssl_connect_data *connssl = cf->ctx;
 599  struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
 600  struct Curl_easy *data = CF_DATA_CURRENT(cf);
 601  size_t nread;
 602  CURLcode result, r2;
 603
 604  DEBUGASSERT(data);
 605  /* OpenSSL catches this case, so should we. */
 606  if(!buf)
 607    return 0;
 608  if(blen < 0)
 609    return 0;
 610
 611  result = Curl_conn_cf_recv(cf->next, data, buf, (size_t)blen, &nread);
 612  CURL_TRC_CF(data, cf, "ossl_bio_cf_in_read(len=%d) -> %d, %zu",
 613              blen, result, nread);
 614  BIO_clear_retry_flags(bio);
 615  octx->io_result = result;
 616  if(result) {
 617    if(result == CURLE_AGAIN)
 618      BIO_set_retry_read(bio);
 619  }
 620  else {
 621    /* feeding data to OpenSSL means SSL_read() might succeed */
 622    connssl->input_pending = TRUE;
 623    if(nread == 0)
 624      connssl->peer_closed = TRUE;
 625  }
 626
 627  /* Before returning server replies to the SSL instance, we need
 628   * to have setup the x509 store or verification fails. */
 629  if(!octx->x509_store_setup) {
 630    r2 = Curl_ssl_setup_x509_store(cf, data, octx);
 631    if(r2) {
 632      BIO_clear_retry_flags(bio);
 633      octx->io_result = r2;
 634      return -1;
 635    }
 636    octx->x509_store_setup = TRUE;
 637  }
 638  return result ? -1 : (int)nread;
 639}
 640
 641static BIO_METHOD *ossl_bio_cf_method_create(void)
 642{
 643  BIO_METHOD *m = BIO_meth_new(BIO_TYPE_MEM, "OpenSSL CF BIO");
 644  if(m) {
 645    BIO_meth_set_write(m, &ossl_bio_cf_out_write);
 646    BIO_meth_set_read(m, &ossl_bio_cf_in_read);
 647    BIO_meth_set_ctrl(m, &ossl_bio_cf_ctrl);
 648    BIO_meth_set_create(m, &ossl_bio_cf_create);
 649    BIO_meth_set_destroy(m, &ossl_bio_cf_destroy);
 650  }
 651  return m;
 652}
 653
 654static void ossl_bio_cf_method_free(BIO_METHOD *m)
 655{
 656  if(m)
 657    BIO_meth_free(m);
 658}
 659
 660#ifndef HAVE_KEYLOG_UPSTREAM
 661#ifdef HAVE_KEYLOG_CALLBACK
 662static void ossl_keylog_callback(const SSL *ssl, const char *line)
 663{
 664  (void)ssl;
 665
 666  Curl_tls_keylog_write_line(line);
 667}
 668#else
 669/*
 670 * ossl_log_tls12_secret is called by libcurl to make the CLIENT_RANDOMs if the
 671 * OpenSSL being used does not have native support for doing that.
 672 */
 673static void ossl_log_tls12_secret(const SSL *ssl, bool *keylog_done)
 674{
 675  const SSL_SESSION *session;
 676  unsigned char client_random[SSL3_RANDOM_SIZE];
 677  unsigned char master_key[SSL_MAX_MASTER_KEY_LENGTH];
 678  int master_key_length = 0;
 679
 680  ERR_set_mark();
 681
 682  session = SSL_get_session(ssl);
 683
 684  if(!session || *keylog_done) {
 685    ERR_pop_to_mark();
 686    return;
 687  }
 688
 689  SSL_get_client_random(ssl, client_random, SSL3_RANDOM_SIZE);
 690  master_key_length = (int)
 691    SSL_SESSION_get_master_key(session, master_key, SSL_MAX_MASTER_KEY_LENGTH);
 692
 693  ERR_pop_to_mark();
 694
 695  /* The handshake has not progressed sufficiently yet, or this is a TLS 1.3
 696   * session (when curl was built with older OpenSSL headers and running with
 697   * newer OpenSSL runtime libraries). */
 698  if(master_key_length <= 0)
 699    return;
 700
 701  *keylog_done = TRUE;
 702  Curl_tls_keylog_write("CLIENT_RANDOM", client_random,
 703                        master_key, master_key_length);
 704}
 705#endif /* !HAVE_KEYLOG_CALLBACK */
 706#endif /* HAVE_KEYLOG_UPSTREAM */
 707
 708static const char *SSL_ERROR_to_str(int err)
 709{
 710  switch(err) {
 711  case SSL_ERROR_NONE:
 712    return "SSL_ERROR_NONE";
 713  case SSL_ERROR_SSL:
 714    return "SSL_ERROR_SSL";
 715  case SSL_ERROR_WANT_READ:
 716    return "SSL_ERROR_WANT_READ";
 717  case SSL_ERROR_WANT_WRITE:
 718    return "SSL_ERROR_WANT_WRITE";
 719  case SSL_ERROR_WANT_X509_LOOKUP:
 720    return "SSL_ERROR_WANT_X509_LOOKUP";
 721  case SSL_ERROR_SYSCALL:
 722    return "SSL_ERROR_SYSCALL";
 723  case SSL_ERROR_ZERO_RETURN:
 724    return "SSL_ERROR_ZERO_RETURN";
 725  case SSL_ERROR_WANT_CONNECT:
 726    return "SSL_ERROR_WANT_CONNECT";
 727  case SSL_ERROR_WANT_ACCEPT:
 728    return "SSL_ERROR_WANT_ACCEPT";
 729#ifdef SSL_ERROR_WANT_ASYNC  /* OpenSSL 1.1.0+, LibreSSL 3.6.0+ */
 730  case SSL_ERROR_WANT_ASYNC:
 731    return "SSL_ERROR_WANT_ASYNC";
 732#endif
 733#ifdef SSL_ERROR_WANT_ASYNC_JOB  /* OpenSSL 1.1.0+, LibreSSL 3.6.0+ */
 734  case SSL_ERROR_WANT_ASYNC_JOB:
 735    return "SSL_ERROR_WANT_ASYNC_JOB";
 736#endif
 737#ifdef SSL_ERROR_WANT_CLIENT_HELLO_CB  /* OpenSSL 1.1.1, LibreSSL 3.6.0+ */
 738  case SSL_ERROR_WANT_CLIENT_HELLO_CB:
 739    return "SSL_ERROR_WANT_CLIENT_HELLO_CB";
 740#endif
 741  default:
 742    return "SSL_ERROR unknown";
 743  }
 744}
 745
 746/* Return error string for last OpenSSL error
 747 */
 748static char *ossl_strerror(unsigned long error, char *buf, size_t size)
 749{
 750  size_t len;
 751  DEBUGASSERT(size);
 752  *buf = '\0';
 753
 754  len = Curl_ossl_version(buf, size);
 755  DEBUGASSERT(len < (size - 2));
 756  if(len < (size - 2)) {
 757    buf += len;
 758    size -= (len + 2);
 759    *buf++ = ':';
 760    *buf++ = ' ';
 761    *buf = '\0';
 762  }
 763
 764#ifdef HAVE_BORINGSSL_LIKE
 765  ERR_error_string_n((uint32_t)error, buf, size);
 766#else
 767  ERR_error_string_n(error, buf, size);
 768#endif
 769
 770  if(!*buf) {
 771    const char *msg = error ? "Unknown error" : "No error";
 772    curlx_strcopy(buf, size, msg, strlen(msg));
 773  }
 774
 775  return buf;
 776}
 777
 778static int passwd_callback(char *buf, int num, int encrypting, void *password)
 779{
 780  DEBUGASSERT(encrypting == 0);
 781
 782  if(!encrypting && num >= 0 && password) {
 783    int klen = curlx_uztosi(strlen((char *)password));
 784    if(num > klen) {
 785      memcpy(buf, password, klen + 1);
 786      return klen;
 787    }
 788  }
 789  return 0;
 790}
 791
 792/*
 793 * rand_enough() returns TRUE if we have seeded the random engine properly.
 794 */
 795static bool rand_enough(void)
 796{
 797  return RAND_status() != 0;
 798}
 799
 800static CURLcode ossl_seed(struct Curl_easy *data)
 801{
 802  /* This might get called before it has been added to a multi handle */
 803  if(data->multi && data->multi->ssl_seeded)
 804    return CURLE_OK;
 805
 806  if(rand_enough()) {
 807    /* OpenSSL 1.1.0+ should return here */
 808    if(data->multi)
 809      data->multi->ssl_seeded = TRUE;
 810    return CURLE_OK;
 811  }
 812  failf(data, "Insufficient randomness");
 813  return CURLE_SSL_CONNECT_ERROR;
 814}
 815
 816#ifndef SSL_FILETYPE_ENGINE
 817#define SSL_FILETYPE_ENGINE 42
 818#endif
 819#ifndef SSL_FILETYPE_PKCS12
 820#define SSL_FILETYPE_PKCS12 43
 821#endif
 822#ifndef SSL_FILETYPE_PROVIDER
 823#define SSL_FILETYPE_PROVIDER 44
 824#endif
 825static int ossl_do_file_type(const char *type)
 826{
 827  if(!type || !type[0])
 828    return SSL_FILETYPE_PEM;
 829  if(curl_strequal(type, "PEM"))
 830    return SSL_FILETYPE_PEM;
 831  if(curl_strequal(type, "DER"))
 832    return SSL_FILETYPE_ASN1;
 833  if(curl_strequal(type, "PROV"))
 834    return SSL_FILETYPE_PROVIDER;
 835  if(curl_strequal(type, "ENG"))
 836    return SSL_FILETYPE_ENGINE;
 837  if(curl_strequal(type, "P12"))
 838    return SSL_FILETYPE_PKCS12;
 839  return -1;
 840}
 841
 842#if defined(USE_OPENSSL_ENGINE) || defined(OPENSSL_HAS_PROVIDERS)
 843/*
 844 * Supply default password to the engine user interface conversation.
 845 * The password is passed by OpenSSL engine from ENGINE_load_private_key()
 846 * last argument to the ui and can be obtained by UI_get0_user_data(ui) here.
 847 */
 848static int ssl_ui_reader(UI *ui, UI_STRING *uis)
 849{
 850  const char *password;
 851  switch(UI_get_string_type(uis)) {
 852  case UIT_PROMPT:
 853  case UIT_VERIFY:
 854    password = (const char *)UI_get0_user_data(ui);
 855    if(password && (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD)) {
 856      UI_set_result(ui, uis, password);
 857      return 1;
 858    }
 859    FALLTHROUGH();
 860  default:
 861    break;
 862  }
 863  return (UI_method_get_reader(UI_OpenSSL()))(ui, uis);
 864}
 865
 866/*
 867 * Suppress interactive request for a default password if available.
 868 */
 869static int ssl_ui_writer(UI *ui, UI_STRING *uis)
 870{
 871  switch(UI_get_string_type(uis)) {
 872  case UIT_PROMPT:
 873  case UIT_VERIFY:
 874    if(UI_get0_user_data(ui) &&
 875       (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD)) {
 876      return 1;
 877    }
 878    FALLTHROUGH();
 879  default:
 880    break;
 881  }
 882  return (UI_method_get_writer(UI_OpenSSL()))(ui, uis);
 883}
 884
 885/*
 886 * Check if a given string is a PKCS#11 URI
 887 */
 888static bool is_pkcs11_uri(const char *string)
 889{
 890  return string && curl_strnequal(string, "pkcs11:", 7);
 891}
 892
 893#endif
 894
 895static CURLcode ossl_set_engine(struct Curl_easy *data, const char *name);
 896#ifdef OPENSSL_HAS_PROVIDERS
 897static CURLcode ossl_set_provider(struct Curl_easy *data, const char *iname);
 898#endif
 899
 900static int use_certificate_blob(SSL_CTX *ctx, const struct curl_blob *blob,
 901                                int type, const char *key_passwd)
 902{
 903  int ret = 0;
 904  X509 *x = NULL;
 905  /* the typecast of blob->len is fine since it is guaranteed to never be
 906     larger than CURL_MAX_INPUT_LENGTH */
 907  BIO *in = BIO_new_mem_buf(blob->data, (int)(blob->len));
 908  if(!in)
 909    return CURLE_OUT_OF_MEMORY;
 910
 911  if(type == SSL_FILETYPE_ASN1) {
 912    /* j = ERR_R_ASN1_LIB; */
 913    x = d2i_X509_bio(in, NULL);
 914  }
 915  else if(type == SSL_FILETYPE_PEM) {
 916    /* ERR_R_PEM_LIB; */
 917    x = PEM_read_bio_X509(in, NULL, passwd_callback, CURL_UNCONST(key_passwd));
 918  }
 919  else {
 920    ret = 0;
 921    goto end;
 922  }
 923
 924  if(!x) {
 925    ret = 0;
 926    goto end;
 927  }
 928
 929  ret = SSL_CTX_use_certificate(ctx, x);
 930end:
 931  X509_free(x);
 932  BIO_free(in);
 933  return ret;
 934}
 935
 936static int use_privatekey_blob(SSL_CTX *ctx, const struct curl_blob *blob,
 937                               int type, const char *key_passwd)
 938{
 939  int ret = 0;
 940  EVP_PKEY *pkey = NULL;
 941  BIO *in = BIO_new_mem_buf(blob->data, (int)(blob->len));
 942  if(!in)
 943    return CURLE_OUT_OF_MEMORY;
 944
 945  if(type == SSL_FILETYPE_PEM)
 946    pkey = PEM_read_bio_PrivateKey(in, NULL, passwd_callback,
 947                                   CURL_UNCONST(key_passwd));
 948  else if(type == SSL_FILETYPE_ASN1)
 949    pkey = d2i_PrivateKey_bio(in, NULL);
 950  else
 951    goto end;
 952
 953  if(!pkey)
 954    goto end;
 955
 956  ret = SSL_CTX_use_PrivateKey(ctx, pkey);
 957  EVP_PKEY_free(pkey);
 958end:
 959  BIO_free(in);
 960  return ret;
 961}
 962
 963static int use_certificate_chain_blob(SSL_CTX *ctx,
 964                                      const struct curl_blob *blob,
 965                                      const char *key_passwd)
 966{
 967  int ret = 0;
 968  X509 *x = NULL;
 969  BIO *in = BIO_new_mem_buf(blob->data, (int)(blob->len));
 970  if(!in)
 971    return CURLE_OUT_OF_MEMORY;
 972
 973  ERR_clear_error();
 974
 975  x = PEM_read_bio_X509_AUX(in, NULL,
 976                            passwd_callback, CURL_UNCONST(key_passwd));
 977  if(!x)
 978    goto end;
 979
 980  ret = SSL_CTX_use_certificate(ctx, x);
 981
 982  if(ERR_peek_error() != 0)
 983    ret = 0;
 984
 985  if(ret) {
 986    X509 *ca;
 987    sslerr_t err;
 988
 989    if(!SSL_CTX_clear_chain_certs(ctx)) {
 990      ret = 0;
 991      goto end;
 992    }
 993
 994    while((ca = PEM_read_bio_X509(in, NULL, passwd_callback,
 995                                  CURL_UNCONST(key_passwd))) != NULL) {
 996
 997      if(!SSL_CTX_add0_chain_cert(ctx, ca)) {
 998        X509_free(ca);
 999        ret = 0;
1000        goto end;
1001      }
1002    }
1003
1004    err = ERR_peek_last_error();
1005    if((ERR_GET_LIB(err) == ERR_LIB_PEM) &&
1006       (ERR_GET_REASON(err) == PEM_R_NO_START_LINE))
1007      ERR_clear_error();
1008    else
1009      ret = 0;
1010  }
1011
1012end:
1013  X509_free(x);
1014  BIO_free(in);
1015  return ret;
1016}
1017
1018static int enginecheck(struct Curl_easy *data,
1019                       SSL_CTX* ctx,
1020                       const char *key_file,
1021                       const char *key_passwd)
1022{
1023#ifdef USE_OPENSSL_ENGINE
1024  EVP_PKEY *priv_key = NULL;
1025
1026  /* Implicitly use pkcs11 engine if none was provided and the
1027   * key_file is a PKCS#11 URI */
1028  if(!data->state.engine) {
1029    if(is_pkcs11_uri(key_file)) {
1030      if(ossl_set_engine(data, "pkcs11") != CURLE_OK) {
1031        return 0;
1032      }
1033    }
1034  }
1035
1036  if(data->state.engine) {
1037    UI_METHOD *ui_method = UI_create_method("curl user interface");
1038    if(!ui_method) {
1039      failf(data, "unable to create " OSSL_PACKAGE " user-interface method");
1040      return 0;
1041    }
1042    UI_method_set_opener(ui_method, UI_method_get_opener(UI_OpenSSL()));
1043    UI_method_set_closer(ui_method, UI_method_get_closer(UI_OpenSSL()));
1044    UI_method_set_reader(ui_method, ssl_ui_reader);
1045    UI_method_set_writer(ui_method, ssl_ui_writer);
1046    priv_key = ENGINE_load_private_key(data->state.engine, key_file,
1047                                       ui_method,
1048                                       CURL_UNCONST(key_passwd));
1049    UI_destroy_method(ui_method);
1050    if(!priv_key) {
1051      failf(data, "failed to load private key from crypto engine");
1052      return 0;
1053    }
1054    if(SSL_CTX_use_PrivateKey(ctx, priv_key) != 1) {
1055      failf(data, "unable to set private key");
1056      EVP_PKEY_free(priv_key);
1057      return 0;
1058    }
1059    EVP_PKEY_free(priv_key);  /* we do not need the handle any more... */
1060  }
1061  else {
1062    failf(data, "crypto engine not set, cannot load private key");
1063    return 0;
1064  }
1065  return 1;
1066#else
1067  (void)ctx;
1068  (void)key_file;
1069  (void)key_passwd;
1070  failf(data, "SSL_FILETYPE_ENGINE not supported for private key");
1071  return 0;
1072#endif
1073}
1074
1075static int providercheck(struct Curl_easy *data,
1076                         SSL_CTX* ctx,
1077                         const char *key_file)
1078{
1079#ifdef OPENSSL_HAS_PROVIDERS
1080  char error_buffer[256];
1081  /* Implicitly use pkcs11 provider if none was provided and the
1082   * key_file is a PKCS#11 URI */
1083  if(!data->state.provider_loaded) {
1084    if(is_pkcs11_uri(key_file)) {
1085      if(ossl_set_provider(data, "pkcs11") != CURLE_OK) {
1086        return 0;
1087      }
1088    }
1089  }
1090
1091  if(data->state.provider_loaded) {
1092    /* Load the private key from the provider */
1093    EVP_PKEY *priv_key = NULL;
1094    OSSL_STORE_CTX *store = NULL;
1095    OSSL_STORE_INFO *info = NULL;
1096    UI_METHOD *ui_method = UI_create_method("curl user interface");
1097    if(!ui_method) {
1098      failf(data, "unable to create " OSSL_PACKAGE " user-interface method");
1099      return 0;
1100    }
1101    UI_method_set_opener(ui_method, UI_method_get_opener(UI_OpenSSL()));
1102    UI_method_set_closer(ui_method, UI_method_get_closer(UI_OpenSSL()));
1103    UI_method_set_reader(ui_method, ssl_ui_reader);
1104    UI_method_set_writer(ui_method, ssl_ui_writer);
1105
1106    store = OSSL_STORE_open_ex(key_file, data->state.libctx,
1107                               data->state.propq, ui_method, NULL, NULL,
1108                               NULL, NULL);
1109    if(!store) {
1110      failf(data, "Failed to open OpenSSL store: %s",
1111            ossl_strerror(ERR_get_error(), error_buffer,
1112                          sizeof(error_buffer)));
1113      UI_destroy_method(ui_method);
1114      return 0;
1115    }
1116    if(OSSL_STORE_expect(store, OSSL_STORE_INFO_PKEY) != 1) {
1117      failf(data, "Failed to set store preference. Ignoring the error: %s",
1118            ossl_strerror(ERR_get_error(), error_buffer,
1119                          sizeof(error_buffer)));
1120    }
1121
1122    info = OSSL_STORE_load(store);
1123    if(info) {
1124      int ossl_type = OSSL_STORE_INFO_get_type(info);
1125
1126      if(ossl_type == OSSL_STORE_INFO_PKEY)
1127        priv_key = OSSL_STORE_INFO_get1_PKEY(info);
1128      OSSL_STORE_INFO_free(info);
1129    }
1130    OSSL_STORE_close(store);
1131    UI_destroy_method(ui_method);
1132    if(!priv_key) {
1133      failf(data, "No private key found in the openssl store: %s",
1134            ossl_strerror(ERR_get_error(), error_buffer,
1135                          sizeof(error_buffer)));
1136      return 0;
1137    }
1138
1139    if(SSL_CTX_use_PrivateKey(ctx, priv_key) != 1) {
1140      failf(data, "unable to set private key [%s]",
1141            ossl_strerror(ERR_get_error(), error_buffer,
1142                          sizeof(error_buffer)));
1143      EVP_PKEY_free(priv_key);
1144      return 0;
1145    }
1146    EVP_PKEY_free(priv_key); /* we do not need the handle any more... */
1147  }
1148  else {
1149    failf(data, "crypto provider not set, cannot load private key");
1150    return 0;
1151  }
1152  return 1;
1153#else
1154  (void)ctx;
1155  (void)key_file;
1156  failf(data, "SSL_FILETYPE_PROVIDER not supported for private key");
1157  return 0;
1158#endif
1159}
1160
1161static int engineload(struct Curl_easy *data,
1162                      SSL_CTX* ctx,
1163                      const char *cert_file)
1164{
1165/* ENGINE_CTRL_GET_CMD_FROM_NAME supported by OpenSSL, LibreSSL <=3.8.3 */
1166#if defined(USE_OPENSSL_ENGINE) && defined(ENGINE_CTRL_GET_CMD_FROM_NAME)
1167  char error_buffer[256];
1168  /* Implicitly use pkcs11 engine if none was provided and the
1169   * cert_file is a PKCS#11 URI */
1170  if(!data->state.engine) {
1171    if(is_pkcs11_uri(cert_file)) {
1172      if(ossl_set_engine(data, "pkcs11") != CURLE_OK) {
1173        return 0;
1174      }
1175    }
1176  }
1177
1178  if(data->state.engine) {
1179    const char *cmd_name = "LOAD_CERT_CTRL";
1180    struct {
1181      const char *cert_id;
1182      X509 *cert;
1183    } params;
1184
1185    params.cert_id = cert_file;
1186    params.cert = NULL;
1187
1188    /* Does the engine supports LOAD_CERT_CTRL ? */
1189    if(!ENGINE_ctrl(data->state.engine, ENGINE_CTRL_GET_CMD_FROM_NAME,
1190                    0, CURL_UNCONST(cmd_name), NULL)) {
1191      failf(data, "ssl engine does not support loading certificates");
1192      return 0;
1193    }
1194
1195    /* Load the certificate from the engine */
1196    if(!ENGINE_ctrl_cmd(data->state.engine, cmd_name, 0, &params, NULL, 1)) {
1197      failf(data, "ssl engine cannot load client cert with id '%s' [%s]",
1198            cert_file,
1199            ossl_strerror(ERR_get_error(), error_buffer,
1200                          sizeof(error_buffer)));
1201      return 0;
1202    }
1203
1204    if(!params.cert) {
1205      failf(data, "ssl engine did not initialized the certificate properly.");
1206      return 0;
1207    }
1208
1209    if(SSL_CTX_use_certificate(ctx, params.cert) != 1) {
1210      failf(data, "unable to set client certificate [%s]",
1211            ossl_strerror(ERR_get_error(), error_buffer,
1212                          sizeof(error_buffer)));
1213      X509_free(params.cert);
1214      return 0;
1215    }
1216    X509_free(params.cert); /* we do not need the handle any more... */
1217  }
1218  else {
1219    failf(data, "crypto engine not set, cannot load certificate");
1220    return 0;
1221  }
1222  return 1;
1223#else
1224  (void)ctx;
1225  (void)cert_file;
1226  failf(data, "SSL_FILETYPE_ENGINE not supported for certificate");
1227  return 0;
1228#endif
1229}
1230
1231static int providerload(struct Curl_easy *data,
1232                        SSL_CTX* ctx,
1233                        const char *cert_file)
1234{
1235#ifdef OPENSSL_HAS_PROVIDERS
1236  char error_buffer[256];
1237  /* Implicitly use pkcs11 provider if none was provided and the
1238   * cert_file is a PKCS#11 URI */
1239  if(!data->state.provider_loaded) {
1240    if(is_pkcs11_uri(cert_file)) {
1241      if(ossl_set_provider(data, "pkcs11") != CURLE_OK) {
1242        return 0;
1243      }
1244    }
1245  }
1246
1247  if(data->state.provider_loaded) {
1248    /* Load the certificate from the provider */
1249    OSSL_STORE_INFO *info = NULL;
1250    X509 *cert = NULL;
1251    OSSL_STORE_CTX *store =
1252      OSSL_STORE_open_ex(cert_file, data->state.libctx,
1253                         NULL, NULL, NULL, NULL, NULL, NULL);
1254    int rc;
1255
1256    if(!store) {
1257      failf(data, "Failed to open OpenSSL store: %s",
1258            ossl_strerror(ERR_get_error(), error_buffer,
1259                          sizeof(error_buffer)));
1260      return 0;
1261    }
1262    if(OSSL_STORE_expect(store, OSSL_STORE_INFO_CERT) != 1) {
1263      failf(data, "Failed to set store preference. Ignoring the error: %s",
1264            ossl_strerror(ERR_get_error(), error_buffer,
1265                          sizeof(error_buffer)));
1266    }
1267
1268    info = OSSL_STORE_load(store);
1269    if(info) {
1270      int ossl_type = OSSL_STORE_INFO_get_type(info);
1271
1272      if(ossl_type == OSSL_STORE_INFO_CERT)
1273        cert = OSSL_STORE_INFO_get1_CERT(info);
1274      OSSL_STORE_INFO_free(info);
1275    }
1276    OSSL_STORE_close(store);
1277    if(!cert) {
1278      failf(data, "No cert found in the openssl store: %s",
1279            ossl_strerror(ERR_get_error(), error_buffer,
1280                          sizeof(error_buffer)));
1281      return 0;
1282    }
1283
1284    rc = SSL_CTX_use_certificate(ctx, cert);
1285    X509_free(cert); /* we do not need the handle any more... */
1286
1287    if(rc != 1) {
1288      failf(data, "unable to set client certificate [%s]",
1289            ossl_strerror(ERR_get_error(), error_buffer,
1290                          sizeof(error_buffer)));
1291      return 0;
1292    }
1293  }
1294  else {
1295    failf(data, "crypto provider not set, cannot load certificate");
1296    return 0;
1297  }
1298  return 1;
1299#else
1300  (void)ctx;
1301  (void)cert_file;
1302  failf(data, "SSL_FILETYPE_PROVIDER not supported for certificate");
1303  return 0;
1304#endif
1305}
1306
1307static int pkcs12load(struct Curl_easy *data,
1308                      SSL_CTX* ctx,
1309                      const struct curl_blob *cert_blob,
1310                      const char *cert_file,
1311                      const char *key_passwd)
1312{
1313  char error_buffer[256];
1314  BIO *cert_bio = NULL;
1315  PKCS12 *p12 = NULL;
1316  EVP_PKEY *pri;
1317  X509 *x509;
1318  int cert_done = 0;
1319  STACK_OF(X509) *ca = NULL;
1320  if(cert_blob) {
1321    cert_bio = BIO_new_mem_buf(cert_blob->data, (int)(cert_blob->len));
1322    if(!cert_bio) {
1323      failf(data, "BIO_new_mem_buf NULL, " OSSL_PACKAGE " error %s",
1324            ossl_strerror(ERR_get_error(), error_buffer,
1325                          sizeof(error_buffer)));
1326      return 0;
1327    }
1328  }
1329  else {
1330    cert_bio = BIO_new(BIO_s_file());
1331    if(!cert_bio) {
1332      failf(data, "BIO_new return NULL, " OSSL_PACKAGE " error %s",
1333            ossl_strerror(ERR_get_error(), error_buffer,
1334                          sizeof(error_buffer)));
1335      return 0;
1336    }
1337
1338    if(BIO_read_filename(cert_bio, CURL_UNCONST(cert_file)) <= 0) {
1339      failf(data, "could not open PKCS12 file '%s'", cert_file);
1340      BIO_free(cert_bio);
1341      return 0;
1342    }
1343  }
1344
1345  p12 = d2i_PKCS12_bio(cert_bio, NULL);
1346  BIO_free(cert_bio);
1347
1348  if(!p12) {
1349    failf(data, "error reading PKCS12 file '%s'",
1350          cert_blob ? "(memory blob)" : cert_file);
1351    return 0;
1352  }
1353
1354  if(!PKCS12_parse(p12, key_passwd, &pri, &x509, &ca)) {
1355    failf(data, "could not parse PKCS12 file, check password, " OSSL_PACKAGE
1356          " error %s",
1357          ossl_strerror(ERR_get_error(), error_buffer, sizeof(error_buffer)));
1358    PKCS12_free(p12);
1359    return 0;
1360  }
1361
1362  PKCS12_free(p12);
1363
1364  if(SSL_CTX_use_certificate(ctx, x509) != 1) {
1365    failf(data, "could not load PKCS12 client certificate, " OSSL_PACKAGE
1366          " error %s",
1367          ossl_strerror(ERR_get_error(), error_buffer, sizeof(error_buffer)));
1368    goto fail;
1369  }
1370
1371  if(SSL_CTX_use_PrivateKey(ctx, pri) != 1) {
1372    failf(data, "unable to use private key from PKCS12 file '%s'", cert_file);
1373    goto fail;
1374  }
1375
1376  if(!SSL_CTX_check_private_key(ctx)) {
1377    failf(data, "private key from PKCS12 file '%s' "
1378          "does not match certificate in same file", cert_file);
1379    goto fail;
1380  }
1381  /* Set Certificate Verification chain */
1382  if(ca) {
1383    while(sk_X509_num(ca)) {
1384      /*
1385       * Note that sk_X509_pop() is used below to make sure the cert is
1386       * removed from the stack properly before getting passed to
1387       * SSL_CTX_add_extra_chain_cert(), which takes ownership. Previously
1388       * we used sk_X509_value() instead, but then we would clean it in the
1389       * subsequent sk_X509_pop_free() call.
1390       */
1391      X509 *x = sk_X509_pop(ca);
1392      if(!SSL_CTX_add_client_CA(ctx, x)) {
1393        X509_free(x);
1394        failf(data, "cannot add certificate to client CA list");
1395        goto fail;
1396      }
1397      if(!SSL_CTX_add_extra_chain_cert(ctx, x)) {
1398        X509_free(x);
1399        failf(data, "cannot add certificate to certificate chain");
1400        goto fail;
1401      }
1402    }
1403  }
1404
1405  cert_done = 1;
1406fail:
1407  EVP_PKEY_free(pri);
1408  X509_free(x509);
1409#if defined(__clang__) && __clang_major__ >= 16
1410#pragma clang diagnostic push
1411#pragma clang diagnostic ignored "-Wcast-function-type-strict"
1412#endif
1413  sk_X509_pop_free(ca, X509_free);
1414#if defined(__clang__) && __clang_major__ >= 16
1415#pragma clang diagnostic pop
1416#endif
1417  if(!cert_done)
1418    return 0; /* failure! */
1419  return 1;
1420}
1421
1422static CURLcode client_cert(struct Curl_easy *data,
1423                            SSL_CTX* ctx,
1424                            char *cert_file,
1425                            const struct curl_blob *cert_blob,
1426                            const char *cert_type,
1427                            char *key_file,
1428                            const struct curl_blob *key_blob,
1429                            const char *key_type,
1430                            char *key_passwd)
1431{
1432  char error_buffer[256];
1433  bool check_privkey = TRUE;
1434  int file_type = ossl_do_file_type(cert_type);
1435
1436  if(cert_file || cert_blob || (file_type == SSL_FILETYPE_ENGINE) ||
1437     (file_type == SSL_FILETYPE_PROVIDER)) {
1438    SSL *ssl;
1439    X509 *x509;
1440    bool pcks12_done = FALSE;
1441    int cert_use_result;
1442
1443    if(key_passwd) {
1444      /* set the password in the callback userdata */
1445      SSL_CTX_set_default_passwd_cb_userdata(ctx, key_passwd);
1446      /* Set passwd callback: */
1447      SSL_CTX_set_default_passwd_cb(ctx, passwd_callback);
1448    }
1449
1450    switch(file_type) {
1451    case SSL_FILETYPE_PEM:
1452      /* SSL_CTX_use_certificate_chain_file() only works on PEM files */
1453      cert_use_result = cert_blob ?
1454        use_certificate_chain_blob(ctx, cert_blob, key_passwd) :
1455        SSL_CTX_use_certificate_chain_file(ctx, cert_file);
1456      if(cert_use_result != 1) {
1457        failf(data,
1458              "could not load PEM client certificate from %s, " OSSL_PACKAGE
1459              " error %s, "
1460              "(no key found, wrong passphrase, or wrong file format?)",
1461              (cert_blob ? "CURLOPT_SSLCERT_BLOB" : cert_file),
1462              ossl_strerror(ERR_get_error(), error_buffer,
1463                            sizeof(error_buffer)));
1464        return CURLE_SSL_CERTPROBLEM;
1465      }
1466      break;
1467
1468    case SSL_FILETYPE_ASN1:
1469      /* SSL_CTX_use_certificate_file() works with either PEM or ASN1, but
1470         we use the case above for PEM so this can only be performed with
1471         ASN1 files. */
1472
1473      cert_use_result = cert_blob ?
1474        use_certificate_blob(ctx, cert_blob, file_type, key_passwd) :
1475      SSL_CTX_use_certificate_file(ctx, cert_file, file_type);
1476      if(cert_use_result != 1) {
1477        failf(data,
1478              "could not load ASN1 client certificate from %s, " OSSL_PACKAGE
1479              " error %s, "
1480              "(no key found, wrong passphrase, or wrong file format?)",
1481              (cert_blob ? "CURLOPT_SSLCERT_BLOB" : cert_file),
1482              ossl_strerror(ERR_get_error(), error_buffer,
1483                            sizeof(error_buffer)));
1484        return CURLE_SSL_CERTPROBLEM;
1485      }
1486      break;
1487
1488    case SSL_FILETYPE_ENGINE:
1489      if(!cert_file || !engineload(data, ctx, cert_file))
1490        return CURLE_SSL_CERTPROBLEM;
1491      break;
1492
1493    case SSL_FILETYPE_PROVIDER:
1494      if(!cert_file || !providerload(data, ctx, cert_file))
1495        return CURLE_SSL_CERTPROBLEM;
1496      break;
1497
1498    case SSL_FILETYPE_PKCS12:
1499      if(!pkcs12load(data, ctx, cert_blob, cert_file, key_passwd))
1500        return CURLE_SSL_CERTPROBLEM;
1501      pcks12_done = TRUE;
1502      break;
1503
1504    default:
1505      failf(data, "not supported file type '%s' for certificate", cert_type);
1506      return CURLE_BAD_FUNCTION_ARGUMENT;
1507    }
1508
1509    if(!key_file && !key_blob) {
1510      key_file = cert_file;
1511      key_blob = cert_blob;
1512    }
1513    else
1514      file_type = ossl_do_file_type(key_type);
1515
1516    switch(file_type) {
1517    case SSL_FILETYPE_PEM:
1518    case SSL_FILETYPE_ASN1:
1519      cert_use_result = key_blob ?
1520        use_privatekey_blob(ctx, key_blob, file_type, key_passwd) :
1521      SSL_CTX_use_PrivateKey_file(ctx, key_file, file_type);
1522      if(cert_use_result != 1) {
1523        failf(data, "unable to set private key file: '%s' type %s",
1524              key_file ? key_file : "(memory blob)",
1525              key_type ? key_type : "PEM");
1526        return CURLE_BAD_FUNCTION_ARGUMENT;
1527      }
1528      break;
1529    case SSL_FILETYPE_ENGINE:
1530      if(!enginecheck(data, ctx, key_file, key_passwd))
1531        return CURLE_SSL_CERTPROBLEM;
1532      break;
1533
1534    case SSL_FILETYPE_PROVIDER:
1535      if(!providercheck(data, ctx, key_file))
1536        return CURLE_SSL_CERTPROBLEM;
1537      break;
1538
1539    case SSL_FILETYPE_PKCS12:
1540      if(!pcks12_done) {
1541        failf(data, "file type P12 for private key not supported");
1542        return CURLE_SSL_CERTPROBLEM;
1543      }
1544      break;
1545    default:
1546      failf(data, "not supported file type for private key");
1547      return CURLE_BAD_FUNCTION_ARGUMENT;
1548    }
1549
1550    ssl = SSL_new(ctx);
1551    if(!ssl) {
1552      failf(data, "unable to create an SSL structure");
1553      return CURLE_OUT_OF_MEMORY;
1554    }
1555
1556    x509 = SSL_get_certificate(ssl);
1557
1558    if(x509) {
1559      EVP_PKEY *pktmp = X509_get_pubkey(x509);
1560      EVP_PKEY_copy_parameters(pktmp, SSL_get_privatekey(ssl));
1561      EVP_PKEY_free(pktmp);
1562    }
1563
1564#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DEPRECATED_3_0)
1565    {
1566      /* If RSA is used, do not check the private key if its flags indicate
1567       * it does not support it. */
1568      EVP_PKEY *priv_key = SSL_get_privatekey(ssl);
1569      if(EVP_PKEY_id(priv_key) == EVP_PKEY_RSA) {
1570        RSA *rsa = EVP_PKEY_get1_RSA(priv_key);
1571        if(RSA_flags(rsa) & RSA_METHOD_FLAG_NO_CHECK)
1572          check_privkey = FALSE;
1573        RSA_free(rsa); /* Decrement reference count */
1574      }
1575    }
1576#endif
1577
1578    SSL_free(ssl);
1579
1580    /* If we are using DSA, we can copy the parameters from
1581     * the private key */
1582
1583    if(check_privkey == TRUE) {
1584      /* Now we know that a key and cert have been set against
1585       * the SSL context */
1586      if(!SSL_CTX_check_private_key(ctx)) {
1587        failf(data, "Private key does not match the certificate public key");
1588        return CURLE_SSL_CERTPROBLEM;
1589      }
1590    }
1591  }
1592  return CURLE_OK;
1593}
1594
1595#ifdef CURLVERBOSE
1596/* returns non-zero on failure */
1597static CURLcode x509_name_oneline(const X509_NAME *a, struct dynbuf *d)
1598{
1599  BIO *bio_out = BIO_new(BIO_s_mem());
1600  BUF_MEM *biomem;
1601  int rc;
1602  CURLcode result = CURLE_OUT_OF_MEMORY;
1603
1604  if(bio_out) {
1605    unsigned long flags = XN_FLAG_SEP_SPLUS_SPC |
1606      (XN_FLAG_ONELINE & ~ASN1_STRFLGS_ESC_MSB & ~XN_FLAG_SPC_EQ);
1607    curlx_dyn_reset(d);
1608    rc = X509_NAME_print_ex(bio_out, a, 0, flags);
1609    if(rc != -1) {
1610      BIO_get_mem_ptr(bio_out, &biomem);
1611      result = curlx_dyn_addn(d, biomem->data, biomem->length);
1612    }
1613    BIO_free(bio_out);
1614  }
1615  return result;
1616}
1617#endif
1618
1619/**
1620 * Global SSL init
1621 *
1622 * @retval 0 error initializing SSL
1623 * @retval 1 SSL initialized successfully
1624 */
1625static int ossl_init(void)
1626{
1627  const uint64_t flags =
1628#ifdef OPENSSL_INIT_ENGINE_ALL_BUILTIN
1629    /* not present in BoringSSL */
1630    OPENSSL_INIT_ENGINE_ALL_BUILTIN |
1631#endif
1632#ifdef CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG
1633    OPENSSL_INIT_NO_LOAD_CONFIG |
1634#else
1635    OPENSSL_INIT_LOAD_CONFIG |
1636#endif
1637    0;
1638  OPENSSL_init_ssl(flags, NULL);
1639
1640#ifndef HAVE_KEYLOG_UPSTREAM
1641  Curl_tls_keylog_open();
1642#endif
1643
1644  return 1;
1645}
1646
1647/* Global cleanup */
1648static void ossl_cleanup(void)
1649{
1650#ifndef HAVE_KEYLOG_UPSTREAM
1651  Curl_tls_keylog_close();
1652#endif
1653}
1654
1655/* Selects an OpenSSL crypto engine or provider.
1656 */
1657static CURLcode ossl_set_engine(struct Curl_easy *data, const char *name)
1658{
1659#ifdef USE_OPENSSL_ENGINE
1660  CURLcode result = CURLE_SSL_ENGINE_NOTFOUND;
1661  ENGINE *e = ENGINE_by_id(name);
1662
1663  if(e) {
1664
1665    if(data->state.engine) {
1666      ENGINE_finish(data->state.engine);
1667      ENGINE_free(data->state.engine);
1668      data->state.engine = NULL;
1669    }
1670    if(!ENGINE_init(e)) {
1671      char buf[256];
1672
1673      ENGINE_free(e);
1674      failf(data, "Failed to initialize SSL Engine '%s': %s",
1675            name, ossl_strerror(ERR_get_error(), buf, sizeof(buf)));
1676      result = CURLE_SSL_ENGINE_INITFAILED;
1677      e = NULL;
1678    }
1679    else {
1680      result = CURLE_OK;
1681    }
1682    data->state.engine = e;
1683    return result;
1684  }
1685#endif
1686#ifdef OPENSSL_HAS_PROVIDERS
1687  return ossl_set_provider(data, name);
1688#else
1689  (void)name;
1690  failf(data, "OpenSSL engine not found");
1691  return CURLE_SSL_ENGINE_NOTFOUND;
1692#endif
1693}
1694
1695/* Sets engine as default for all SSL operations
1696 */
1697static CURLcode ossl_set_engine_default(struct Curl_easy *data)
1698{
1699#ifdef USE_OPENSSL_ENGINE
1700  if(data->state.engine) {
1701    if(ENGINE_set_default(data->state.engine, ENGINE_METHOD_ALL) > 0) {
1702      infof(data, "set default crypto engine '%s'",
1703            ENGINE_get_id(data->state.engine));
1704    }
1705    else {
1706      failf(data, "set default crypto engine '%s' failed",
1707            ENGINE_get_id(data->state.engine));
1708      return CURLE_SSL_ENGINE_SETFAILED;
1709    }
1710  }
1711#else
1712  (void)data;
1713#endif
1714  return CURLE_OK;
1715}
1716
1717/* Return list of OpenSSL crypto engine names.
1718 */
1719static struct curl_slist *ossl_engines_list(struct Curl_easy *data)
1720{
1721  struct curl_slist *list = NULL;
1722#ifdef USE_OPENSSL_ENGINE
1723  struct curl_slist *beg;
1724  ENGINE *e;
1725
1726  for(e = ENGINE_get_first(); e; e = ENGINE_get_next(e)) {
1727    beg = curl_slist_append(list, ENGINE_get_id(e));
1728    if(!beg) {
1729      curl_slist_free_all(list);
1730      return NULL;
1731    }
1732    list = beg;
1733  }
1734#endif
1735  (void)data;
1736  return list;
1737}
1738
1739#ifdef OPENSSL_HAS_PROVIDERS
1740
1741static void ossl_provider_cleanup(struct Curl_easy *data)
1742{
1743  if(data->state.baseprov) {
1744    OSSL_PROVIDER_unload(data->state.baseprov);
1745    data->state.baseprov = NULL;
1746  }
1747  if(data->state.provider) {
1748    OSSL_PROVIDER_unload(data->state.provider);
1749    data->state.provider = NULL;
1750  }
1751  OSSL_LIB_CTX_free(data->state.libctx);
1752  data->state.libctx = NULL;
1753  curlx_safefree(data->state.propq);
1754  data->state.provider_loaded = FALSE;
1755}
1756
1757#define MAX_PROVIDER_LEN 128 /* reasonable */
1758
1759/* Selects an OpenSSL crypto provider.
1760 *
1761 * A provider might need an associated property, a string passed on to
1762 * OpenSSL. Specify this as [PROVIDER][:PROPERTY]: separate the name and the
1763 * property with a colon. No colon means no property is set.
1764 *
1765 * An example provider + property looks like "tpm2:?provider=tpm2".
1766 */
1767static CURLcode ossl_set_provider(struct Curl_easy *data, const char *iname)
1768{
1769  char name[MAX_PROVIDER_LEN + 1];
1770  struct Curl_str prov;
1771  const char *propq = NULL;
1772
1773  if(!iname) {
1774    /* clear and cleanup provider use */
1775    ossl_provider_cleanup(data);
1776    return CURLE_OK;
1777  }
1778  if(curlx_str_until(&iname, &prov, MAX_PROVIDER_LEN, ':'))
1779    return CURLE_BAD_FUNCTION_ARGUMENT;
1780
1781  if(!curlx_str_single(&iname, ':'))
1782    /* there was a colon, get the propq until the end of string */
1783    propq = iname;
1784
1785  /* we need the name in a buffer, null-terminated */
1786  memcpy(name, curlx_str(&prov), curlx_strlen(&prov));
1787  name[curlx_strlen(&prov)] = 0;
1788
1789  if(!data->state.libctx) {
1790    OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new();
1791    if(!libctx)
1792      return CURLE_OUT_OF_MEMORY;
1793    if(propq) {
1794      data->state.propq = curlx_strdup(propq);
1795      if(!data->state.propq) {
1796        OSSL_LIB_CTX_free(libctx);
1797        return CURLE_OUT_OF_MEMORY;
1798      }
1799    }
1800    data->state.libctx = libctx;
1801  }
1802
1803#ifndef CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG
1804  /* load the configuration file into the library context before checking the
1805   * provider availability */
1806  if(!OSSL_LIB_CTX_load_config(data->state.libctx, NULL)) {
1807    infof(data, "Failed to load default openssl config. Proceeding.");
1808  }
1809#endif
1810
1811  if(OSSL_PROVIDER_available(data->state.libctx, name)) {
1812    /* already loaded through the configuration - no action needed */
1813    data->state.provider_loaded = TRUE;
1814    return CURLE_OK;
1815  }
1816
1817  data->state.provider = OSSL_PROVIDER_try_load(data->state.libctx, name, 1);
1818  if(!data->state.provider) {
1819    char error_buffer[256];
1820    failf(data, "Failed to initialize provider: %s",
1821          ossl_strerror(ERR_get_error(), error_buffer, sizeof(error_buffer)));
1822    ossl_provider_cleanup(data);
1823    return CURLE_SSL_ENGINE_NOTFOUND;
1824  }
1825
1826  /* load the base provider as well */
1827  data->state.baseprov = OSSL_PROVIDER_try_load(data->state.libctx, "base", 1);
1828  if(!data->state.baseprov) {
1829    ossl_provider_cleanup(data);
1830    failf(data, "Failed to load base");
1831    return CURLE_SSL_ENGINE_NOTFOUND;
1832  }
1833  else
1834    data->state.provider_loaded = TRUE;
1835  return CURLE_OK;
1836}
1837#endif
1838
1839static CURLcode ossl_shutdown(struct Curl_cfilter *cf,
1840                              struct Curl_easy *data,
1841                              bool send_shutdown, bool *done)
1842{
1843  struct ssl_connect_data *connssl = cf->ctx;
1844  struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
1845  CURLcode result = CURLE_OK;
1846  char buf[1024];
1847  int nread = -1, err;
1848  size_t i;
1849
1850  DEBUGASSERT(octx);
1851  if(!octx->ssl || cf->shutdown) {
1852    *done = TRUE;
1853    goto out;
1854  }
1855
1856  connssl->io_need = CURL_SSL_IO_NEED_NONE;
1857  *done = FALSE;
1858  if(!(SSL_get_shutdown(octx->ssl) & SSL_SENT_SHUTDOWN)) {
1859    /* We have not started the shutdown from our side yet. Check
1860     * if the server already sent us one. */
1861    ERR_clear_error();
1862    for(i = 0; i < 10; ++i) {
1863      nread = SSL_read(octx->ssl, buf, (int)sizeof(buf));
1864      CURL_TRC_CF(data, cf, "SSL shutdown not sent, read -> %d", nread);
1865      if(nread <= 0)
1866        break;
1867    }
1868    err = SSL_get_error(octx->ssl, nread);
1869    if(!nread && err == SSL_ERROR_ZERO_RETURN) {
1870      bool input_pending;
1871      /* Yes, it did. */
1872      if(!send_shutdown) {
1873        CURL_TRC_CF(data, cf, "SSL shutdown received, not sending");
1874        *done = TRUE;
1875        goto out;
1876      }
1877      else if(!cf->next->cft->is_alive(cf->next, data, &input_pending)) {
1878        /* Server closed the connection after its closy notify. It
1879         * seems not interested to see our close notify, so do not
1880         * send it. We are done. */
1881        connssl->peer_closed = TRUE;
1882        CURL_TRC_CF(data, cf, "peer closed connection");
1883        *done = TRUE;
1884        goto out;
1885      }
1886    }
1887  }
1888
1889  /* SSL should now have started the shutdown from our side. Since it
1890   * was not complete, we are lacking the close notify from the server. */
1891  if(send_shutdown && !(SSL_get_shutdown(octx->ssl) & SSL_SENT_SHUTDOWN)) {
1892    int rc;
1893    ERR_clear_error();
1894    CURL_TRC_CF(data, cf, "send SSL close notify");
1895    rc = SSL_shutdown(octx->ssl);
1896    if(rc == 1) {
1897      CURL_TRC_CF(data, cf, "SSL shutdown finished");
1898      *done = TRUE;
1899      goto out;
1900    }
1901    if(SSL_ERROR_WANT_WRITE == SSL_get_error(octx->ssl, rc)) {
1902      CURL_TRC_CF(data, cf, "SSL shutdown still wants to send");
1903      connssl->io_need = CURL_SSL_IO_NEED_SEND;
1904      goto out;
1905    }
1906    /* Having sent the close notify, we use SSL_read() to get the
1907     * missing close notify from the server. */
1908  }
1909
1910  for(i = 0; i < 10; ++i) {
1911    ERR_clear_error();
1912    nread = SSL_read(octx->ssl, buf, (int)sizeof(buf));
1913    CURL_TRC_CF(data, cf, "SSL shutdown read -> %d", nread);
1914    if(nread <= 0)
1915      break;
1916  }
1917  err = SSL_get_error(octx->ssl, nread);
1918  switch(err) {
1919  case SSL_ERROR_ZERO_RETURN: /* no more data */
1920    if(SSL_shutdown(octx->ssl) == 1)
1921      CURL_TRC_CF(data, cf, "SSL shutdown finished");
1922    else
1923      CURL_TRC_CF(data, cf, "SSL shutdown not received, but closed");
1924    *done = TRUE;
1925    break;
1926  case SSL_ERROR_NONE: /* did not get anything */
1927  case SSL_ERROR_WANT_READ:
1928    /* SSL has send its notify and now wants to read the reply
1929     * from the server. We are not really interested in that. */
1930    CURL_TRC_CF(data, cf, "SSL shutdown sent, want receive");
1931    connssl->io_need = CURL_SSL_IO_NEED_RECV;
1932    break;
1933  case SSL_ERROR_WANT_WRITE:
1934    CURL_TRC_CF(data, cf, "SSL shutdown send blocked");
1935    connssl->io_need = CURL_SSL_IO_NEED_SEND;
1936    break;
1937  default:
1938    /* Server seems to have closed the connection without sending us
1939     * a close notify. */
1940    {
1941      VERBOSE(unsigned long sslerr = ERR_get_error());
1942      CURL_TRC_CF(data, cf, "SSL shutdown, ignore recv error: '%s', errno %d",
1943                  (sslerr ?
1944                   ossl_strerror(sslerr, buf, sizeof(buf)) :
1945                   SSL_ERROR_to_str(err)),
1946                  SOCKERRNO);
1947    }
1948    *done = TRUE;
1949    result = CURLE_OK;
1950    break;
1951  }
1952
1953out:
1954  cf->shutdown = (result || *done);
1955  if(cf->shutdown || (connssl->io_need != CURL_SSL_IO_NEED_NONE))
1956    connssl->input_pending = FALSE;
1957  return result;
1958}
1959
1960static void ossl_close(struct Curl_cfilter *cf, struct Curl_easy *data)
1961{
1962  struct ssl_connect_data *connssl = cf->ctx;
1963  struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
1964
1965  (void)data;
1966  DEBUGASSERT(octx);
1967
1968  connssl->input_pending = FALSE;
1969  if(octx->ssl) {
1970    SSL_free(octx->ssl);
1971    octx->ssl = NULL;
1972  }
1973  if(octx->ssl_ctx) {
1974    SSL_CTX_free(octx->ssl_ctx);
1975    octx->ssl_ctx = NULL;
1976    octx->x509_store_setup = FALSE;
1977  }
1978  if(octx->bio_method) {
1979    ossl_bio_cf_method_free(octx->bio_method);
1980    octx->bio_method = NULL;
1981  }
1982}
1983
1984/*
1985 * This function is called when the 'data' struct is going away. Close
1986 * down everything and free all resources!
1987 */
1988static void ossl_close_all(struct Curl_easy *data)
1989{
1990#ifdef USE_OPENSSL_ENGINE
1991  if(data->state.engine) {
1992    ENGINE_finish(data->state.engine);
1993    ENGINE_free(data->state.engine);
1994    data->state.engine = NULL;
1995  }
1996#else
1997  (void)data;
1998#endif
1999#ifdef OPENSSL_HAS_PROVIDERS
2000  ossl_provider_cleanup(data);
2001#endif
2002}
2003
2004/* ====================================================== */
2005
2006/* Quote from RFC2818 section 3.1 "Server Identity"
2007
2008   If a subjectAltName extension of type dNSName is present, that MUST
2009   be used as the identity. Otherwise, the (most specific) Common Name
2010   field in the Subject field of the certificate MUST be used. Although
2011   the use of the Common Name is existing practice, it is deprecated and
2012   Certification Authorities are encouraged to use the dNSName instead.
2013
2014   Matching is performed using the matching rules specified by
2015   [RFC2459]. If more than one identity of a given type is present in
2016   the certificate (e.g., more than one dNSName name, a match in any one
2017   of the set is considered acceptable.) Names may contain the wildcard
2018   character * which is considered to match any single domain name
2019   component or component fragment. E.g., *.a.com matches foo.a.com but
2020   not bar.foo.a.com. f*.com matches foo.com but not bar.com.
2021
2022   In some cases, the URI is specified as an IP address rather than a
2023   hostname. In this case, the iPAddress subjectAltName must be present
2024   in the certificate and must exactly match the IP in the URI.
2025
2026   This function is now used from ngtcp2 (QUIC) as well.
2027*/
2028static CURLcode ossl_verifyhost(struct Curl_easy *data,
2029                                struct connectdata *conn,
2030                                struct ssl_peer *peer,
2031                                X509 *server_cert)
2032{
2033  bool matched = FALSE;
2034  int target; /* target type, GEN_DNS or GEN_IPADD */
2035  size_t addrlen = 0;
2036  STACK_OF(GENERAL_NAME) *altnames;
2037#ifdef USE_IPV6
2038  struct in6_addr addr;
2039#else
2040  struct in_addr addr;
2041#endif
2042  CURLcode result = CURLE_OK;
2043  bool dNSName = FALSE; /* if a dNSName field exists in the cert */
2044  bool iPAddress = FALSE; /* if an iPAddress field exists in the cert */
2045  size_t hostlen = strlen(peer->dest->hostname);
2046
2047  (void)conn;
2048  switch(peer->type) {
2049  case CURL_SSL_PEER_IPV4:
2050    if(!curlx_inet_pton(AF_INET, peer->dest->hostname, &addr))
2051      return CURLE_PEER_FAILED_VERIFICATION;
2052    target = GEN_IPADD;
2053    addrlen = sizeof(struct in_addr);
2054    break;
2055#ifdef USE_IPV6
2056  case CURL_SSL_PEER_IPV6:
2057    if(!curlx_inet_pton(AF_INET6, peer->dest->hostname, &addr))
2058      return CURLE_PEER_FAILED_VERIFICATION;
2059    target = GEN_IPADD;
2060    addrlen = sizeof(struct in6_addr);
2061    break;
2062#endif
2063  case CURL_SSL_PEER_DNS:
2064    target = GEN_DNS;
2065    break;
2066  default:
2067    DEBUGASSERT(0);
2068    failf(data, "unexpected ssl peer type: %d", peer->type);
2069    return CURLE_PEER_FAILED_VERIFICATION;
2070  }
2071
2072  /* get a "list" of alternative names */
2073  altnames = X509_get_ext_d2i(server_cert, NID_subject_alt_name, NULL, NULL);
2074
2075  if(altnames) {
2076#ifdef HAVE_BORINGSSL_LIKE
2077    size_t numalts;
2078    size_t i;
2079#else
2080    int numalts;
2081    int i;
2082#endif
2083
2084    /* get amount of alternatives, RFC2459 claims there MUST be at least
2085       one, but we do not depend on it... */
2086    numalts = sk_GENERAL_NAME_num(altnames);
2087
2088    /* loop through all alternatives - until a dnsmatch */
2089    for(i = 0; (i < numalts) && !matched; i++) {
2090      /* get a handle to alternative name number i */
2091      const GENERAL_NAME *check = sk_GENERAL_NAME_value(altnames, i);
2092
2093      if(check->type == GEN_DNS)
2094        dNSName = TRUE;
2095      else if(check->type == GEN_IPADD)
2096        iPAddress = TRUE;
2097
2098      /* only check alternatives of the same type the target is */
2099      if(check->type == target) {
2100        /* get data and length */
2101        const char *altptr = (const char *)ASN1_STRING_get0_data(check->d.ia5);
2102        size_t altlen = (size_t)ASN1_STRING_length(check->d.ia5);
2103
2104        switch(target) {
2105        case GEN_DNS: /* name/pattern comparison */
2106          /* The OpenSSL man page explicitly says: "In general it cannot be
2107             assumed that the data returned by ASN1_STRING_data() is null
2108             terminated or does not contain embedded nulls.", but also that
2109             "The actual format of the data depends on the actual string
2110             type itself: for example for an IA5String the data is ASCII"
2111
2112             It has been however verified that in 0.9.6 and 0.9.7, IA5String
2113             is always null-terminated.
2114          */
2115          if((altlen == strlen(altptr)) &&
2116             /* if this is not true, there was an embedded zero in the name
2117                string and we cannot match it. */
2118             Curl_cert_hostcheck(altptr, altlen,
2119                                 peer->dest->hostname, hostlen)) {
2120            matched = TRUE;
2121            infof(data, "  subjectAltName: \"%s\" matches cert's \"%.*s\"",
2122                  peer->dest->user_hostname, (int)altlen, altptr);
2123          }
2124          break;
2125
2126        case GEN_IPADD: /* IP address comparison */
2127          /* compare alternative IP address if the data chunk is the same size
2128             our server IP address is */
2129          if((altlen == addrlen) && !memcmp(altptr, &addr, altlen)) {
2130            matched = TRUE;
2131            infof(data, "  subjectAltName: \"%s\" matches cert's IP address!",
2132                  peer->dest->user_hostname);
2133          }
2134          break;
2135        }
2136      }
2137    }
2138    GENERAL_NAMES_free(altnames);
2139  }
2140
2141  if(matched)
2142    /* an alternative name matched */
2143    ;
2144  else if(dNSName || iPAddress) {
2145    const char *tname = (peer->type == CURL_SSL_PEER_DNS) ? "hostname" :
2146                        (peer->type == CURL_SSL_PEER_IPV4) ?
2147                        "ipv4 address" : "ipv6 address";
2148    infof(data, " subjectAltName does not match %s %s", tname,
2149          peer->dest->user_hostname);
2150    failf(data, "SSL: no alternative certificate subject name matches "
2151          "target %s '%s'", tname, peer->dest->user_hostname);
2152    result = CURLE_PEER_FAILED_VERIFICATION;
2153  }
2154  else {
2155    /* we have to look to the last occurrence of a commonName in the
2156       distinguished one to get the most significant one. */
2157    int i = -1;
2158    unsigned char *cn = NULL;
2159    int cnlen = 0;
2160    bool free_cn = FALSE;
2161
2162    /* The following is done because of a bug in 0.9.6b */
2163    const X509_NAME *name = X509_get_subject_name(server_cert);
2164    if(name) {
2165      int j;
2166      while((j = X509_NAME_get_index_by_NID(name, NID_commonName, i)) >= 0)
2167        i = j;
2168    }
2169
2170    /* we have the name entry and we now convert this to a string
2171       that we can use for comparison. Doing this we support BMPstring,
2172       UTF8, etc. */
2173
2174    if(i >= 0) {
2175      const ASN1_STRING *tmp =
2176        X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i));
2177
2178      /* In OpenSSL 0.9.7d and earlier, ASN1_STRING_to_UTF8 fails if the input
2179         is already UTF-8 encoded. We check for this case and copy the raw
2180         string manually to avoid the problem. This code can be made
2181         conditional in the future when OpenSSL has been fixed. */
2182      if(tmp) {
2183        if(ASN1_STRING_type(tmp) == V_ASN1_UTF8STRING) {
2184          cnlen = ASN1_STRING_length(tmp);
2185          cn = (unsigned char *)CURL_UNCONST(ASN1_STRING_get0_data(tmp));
2186        }
2187        else { /* not a UTF8 name */
2188          cnlen = ASN1_STRING_to_UTF8(&cn, tmp);
2189          free_cn = TRUE;
2190        }
2191
2192        if((cnlen <= 0) || !cn)
2193          result = CURLE_OUT_OF_MEMORY;
2194        else if((size_t)cnlen != strlen((char *)cn)) {
2195          /* there was a terminating zero before the end of string, this
2196             cannot match and we return failure! */
2197          failf(data, "SSL: illegal cert name field");
2198          result = CURLE_PEER_FAILED_VERIFICATION;
2199        }
2200      }
2201    }
2202
2203    if(result)
2204      /* error already detected, pass through */
2205      ;
2206    else if(!cn) {
2207      failf(data, "SSL: unable to obtain common name from peer certificate");
2208      result = CURLE_PEER_FAILED_VERIFICATION;
2209    }
2210    else if(!Curl_cert_hostcheck((const char *)cn, cnlen,
2211                                 peer->dest->hostname, hostlen)) {
2212      failf(data, "SSL: certificate subject name '%s' does not match "
2213            "target hostname '%s'", cn, peer->dest->user_hostname);
2214      result = CURLE_PEER_FAILED_VERIFICATION;
2215    }
2216    else {
2217      infof(data, " common name: %s (matched)", cn);
2218    }
2219    if(free_cn)
2220      OPENSSL_free(cn);
2221  }
2222
2223  return result;
2224}
2225
2226#ifndef OPENSSL_NO_OCSP
2227static CURLcode verifystatus(struct Curl_cfilter *cf,
2228                             struct Curl_easy *data,
2229                             struct ossl_ctx *octx)
2230{
2231  int i, ocsp_status;
2232#ifdef HAVE_BORINGSSL_LIKE
2233  const uint8_t *status;
2234#else
2235  unsigned char *status;
2236#endif
2237  const unsigned char *p;
2238  CURLcode result = CURLE_OK;
2239  OCSP_RESPONSE *rsp = NULL;
2240  OCSP_BASICRESP *br = NULL;
2241  X509_STORE     *st = NULL;
2242  STACK_OF(X509) *ch = NULL;
2243  X509 *cert;
2244  OCSP_CERTID *id = NULL;
2245  int cert_status, crl_reason;
2246  ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
2247  int ret;
2248  long len;
2249
2250  (void)cf;
2251  DEBUGASSERT(octx);
2252
2253  len = (long)SSL_get_tlsext_status_ocsp_resp(octx->ssl, &status);
2254
2255  if(!status) {
2256    failf(data, "No OCSP response received");
2257    result = CURLE_SSL_INVALIDCERTSTATUS;
2258    goto end;
2259  }
2260  p = status;
2261  rsp = d2i_OCSP_RESPONSE(NULL, &p, len);
2262  if(!rsp) {
2263    failf(data, "Invalid OCSP response");
2264    result = CURLE_SSL_INVALIDCERTSTATUS;
2265    goto end;
2266  }
2267
2268  ocsp_status = OCSP_response_status(rsp);
2269  if(ocsp_status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
2270    failf(data, "Invalid OCSP response status: %s (%d)",
2271          OCSP_response_status_str(ocsp_status), ocsp_status);
2272    result = CURLE_SSL_INVALIDCERTSTATUS;
2273    goto end;
2274  }
2275
2276  br = OCSP_response_get1_basic(rsp);
2277  if(!br) {
2278    failf(data, "Invalid OCSP response");
2279    result = CURLE_SSL_INVALIDCERTSTATUS;
2280    goto end;
2281  }
2282
2283  ch = SSL_get_peer_cert_chain(octx->ssl);
2284  if(!ch) {
2285    failf(data, "Could not get peer certificate chain");
2286    result = CURLE_SSL_INVALIDCERTSTATUS;
2287    goto end;
2288  }
2289  st = SSL_CTX_get_cert_store(octx->ssl_ctx);
2290
2291  if(OCSP_basic_verify(br, ch, st, 0) <= 0) {
2292    failf(data, "OCSP response verification failed");
2293    result = CURLE_SSL_INVALIDCERTSTATUS;
2294    goto end;
2295  }
2296
2297  /* Compute the certificate's ID */
2298  cert = SSL_get1_peer_certificate(octx->ssl);
2299  if(!cert) {
2300    failf(data, "Error getting peer certificate");
2301    result = CURLE_SSL_INVALIDCERTSTATUS;
2302    goto end;
2303  }
2304
2305  for(i = 0; i < (int)sk_X509_num(ch); i++) {
2306    X509 *issuer = sk_X509_value(ch, (ossl_valsize_t)i);
2307    if(X509_check_issued(issuer, cert) == X509_V_OK) {
2308      /* Note to analysis tools: using SHA1 here is fine. The `id`
2309       * generated is used as a hash lookup key, not as a verifier
2310       * of the OCSP data itself. This all according to RFC 5019. */
2311      id = OCSP_cert_to_id(EVP_sha1(), cert, issuer);
2312      break;
2313    }
2314  }
2315  X509_free(cert);
2316
2317  if(!id) {
2318    failf(data, "Error computing OCSP ID");
2319    result = CURLE_SSL_INVALIDCERTSTATUS;
2320    goto end;
2321  }
2322
2323  /* Find the single OCSP response corresponding to the certificate ID */
2324  ret = OCSP_resp_find_status(br, id, &cert_status, &crl_reason, &rev,
2325                              &thisupd, &nextupd);
2326  OCSP_CERTID_free(id);
2327  if(ret != 1) {
2328    failf(data, "Could not find certificate ID in OCSP response");
2329    result = CURLE_SSL_INVALIDCERTSTATUS;
2330    goto end;
2331  }
2332
2333  /* Validate the OCSP response issuing and update times.
2334   * - `thisupd` is the time the OCSP response was issued
2335   * - `nextupd` is the time the OCSP response should be updated
2336   *    (valid life time assigned by the OCSP responder)
2337   * - 3rd param: how many seconds of clock skew we allow between
2338   *   our clock and the instance that issued the OCSP response
2339   * - 4th param: how many seconds in the past `thisupd` may be, with
2340   *   -1 meaning there is no limit. */
2341  if(!OCSP_check_validity(thisupd, nextupd, 300L, -1L)) {
2342    failf(data, "OCSP response has expired");
2343    result = CURLE_SSL_INVALIDCERTSTATUS;
2344    goto end;
2345  }
2346
2347  infof(data, "SSL certificate status: %s (%d)",
2348        OCSP_cert_status_str(cert_status), cert_status);
2349
2350  switch(cert_status) {
2351  case V_OCSP_CERTSTATUS_GOOD:
2352    break;
2353
2354  case V_OCSP_CERTSTATUS_REVOKED:
2355    result = CURLE_SSL_INVALIDCERTSTATUS;
2356    failf(data, "SSL certificate revocation reason: %s (%d)",
2357          OCSP_crl_reason_str(crl_reason), crl_reason);
2358    goto end;
2359
2360  case V_OCSP_CERTSTATUS_UNKNOWN:
2361  default:
2362    result = CURLE_SSL_INVALIDCERTSTATUS;
2363    goto end;
2364  }
2365
2366end:
2367  if(br)
2368    OCSP_BASICRESP_free(br);
2369  OCSP_RESPONSE_free(rsp);
2370
2371  return result;
2372}
2373#endif
2374
2375static const char *ssl_msg_type(int ssl_ver, int msg)
2376{
2377  if(ssl_ver == SSL3_VERSION_MAJOR) {
2378    switch(msg) {
2379    case SSL3_MT_HELLO_REQUEST:
2380      return "Hello request";
2381    case SSL3_MT_CLIENT_HELLO:
2382      return "Client hello";
2383    case SSL3_MT_SERVER_HELLO:
2384      return "Server hello";
2385#ifdef SSL3_MT_NEWSESSION_TICKET
2386    case SSL3_MT_NEWSESSION_TICKET:
2387      return "Newsession Ticket";
2388#endif
2389    case SSL3_MT_CERTIFICATE:
2390      return "Certificate";
2391    case SSL3_MT_SERVER_KEY_EXCHANGE:
2392      return "Server key exchange";
2393    case SSL3_MT_CLIENT_KEY_EXCHANGE:
2394      return "Client key exchange";
2395    case SSL3_MT_CERTIFICATE_REQUEST:
2396      return "Request CERT";
2397    case SSL3_MT_SERVER_DONE:
2398      return "Server finished";
2399    case SSL3_MT_CERTIFICATE_VERIFY:
2400      return "CERT verify";
2401    case SSL3_MT_FINISHED:
2402      return "Finished";
2403#ifdef SSL3_MT_CERTIFICATE_STATUS
2404    case SSL3_MT_CERTIFICATE_STATUS:
2405      return "Certificate Status";
2406#endif
2407#ifdef SSL3_MT_ENCRYPTED_EXTENSIONS
2408    case SSL3_MT_ENCRYPTED_EXTENSIONS:
2409      return "Encrypted Extensions";
2410#endif
2411#ifdef SSL3_MT_SUPPLEMENTAL_DATA
2412    case SSL3_MT_SUPPLEMENTAL_DATA:
2413      return "Supplemental data";
2414#endif
2415#ifdef SSL3_MT_END_OF_EARLY_DATA
2416    case SSL3_MT_END_OF_EARLY_DATA:
2417      return "End of early data";
2418#endif
2419#ifdef SSL3_MT_KEY_UPDATE
2420    case SSL3_MT_KEY_UPDATE:
2421      return "Key update";
2422#endif
2423#ifdef SSL3_MT_NEXT_PROTO
2424    case SSL3_MT_NEXT_PROTO:
2425      return "Next protocol";
2426#endif
2427#ifdef SSL3_MT_MESSAGE_HASH
2428    case SSL3_MT_MESSAGE_HASH:
2429      return "Message hash";
2430#endif
2431    }
2432  }
2433  return "Unknown";
2434}
2435
2436static const char *tls_rt_type(int type)
2437{
2438  switch(type) {
2439#ifdef SSL3_RT_HEADER
2440  case SSL3_RT_HEADER:
2441    return "TLS header";
2442#endif
2443  case SSL3_RT_CHANGE_CIPHER_SPEC:
2444    return "TLS change cipher";
2445  case SSL3_RT_ALERT:
2446    return "TLS alert";
2447  case SSL3_RT_HANDSHAKE:
2448    return "TLS handshake";
2449  case SSL3_RT_APPLICATION_DATA:
2450    return "TLS app data";
2451  default:
2452    return "TLS Unknown";
2453  }
2454}
2455
2456/*
2457 * Our callback from the SSL/TLS layers.
2458 */
2459static void ossl_trace(int direction, int ssl_ver, int content_type,
2460                       const void *buf, size_t len, SSL *ssl,
2461                       void *userp)
2462{
2463  const char *verstr;
2464  struct Curl_cfilter *cf = userp;
2465  struct Curl_easy *data = NULL;
2466  char unknown[32];
2467
2468  if(!cf)
2469    return;
2470  data = CF_DATA_CURRENT(cf);
2471  if(!data || !data->set.fdebug || (direction && direction != 1))
2472    return;
2473
2474  switch(ssl_ver) {
2475#ifdef SSL3_VERSION
2476  case SSL3_VERSION:
2477    verstr = "SSLv3";
2478    break;
2479#endif
2480  case TLS1_VERSION:
2481    verstr = "TLSv1.0";
2482    break;
2483#ifdef TLS1_1_VERSION
2484  case TLS1_1_VERSION:
2485    verstr = "TLSv1.1";
2486    break;
2487#endif
2488#ifdef TLS1_2_VERSION
2489  case TLS1_2_VERSION:
2490    verstr = "TLSv1.2";
2491    break;
2492#endif
2493  case TLS1_3_VERSION:
2494    verstr = "TLSv1.3";
2495    break;
2496  default:
2497    curl_msnprintf(unknown, sizeof(unknown), "(%x)", ssl_ver);
2498    verstr = unknown;
2499    break;
2500  }
2501
2502  /* Log progress for interesting records only (like Handshake or Alert), skip
2503   * all raw record headers (content_type == SSL3_RT_HEADER or ssl_ver == 0).
2504   * For TLS 1.3, skip notification of the decrypted inner Content-Type.
2505   */
2506  if(ssl_ver
2507#ifdef SSL3_RT_HEADER
2508     && content_type != SSL3_RT_HEADER
2509#endif
2510#ifdef SSL3_RT_INNER_CONTENT_TYPE
2511     && content_type != SSL3_RT_INNER_CONTENT_TYPE
2512#endif
2513    ) {
2514    const char *msg_name = "Truncated message";
2515    const char *tls_rt_name;
2516    char ssl_buf[1024];
2517    int msg_type = 0;
2518    int txt_len;
2519
2520    /* the info given when the version is zero is not that useful for us */
2521
2522    ssl_ver >>= 8; /* check the upper 8 bits only below */
2523
2524    /* SSLv2 does not seem to have TLS record-type headers, so OpenSSL
2525     * always pass-up content-type as 0, but the interesting message-type
2526     * is at 'buf[0]'.
2527     */
2528    if(ssl_ver == SSL3_VERSION_MAJOR && content_type)
2529      tls_rt_name = tls_rt_type(content_type);
2530    else
2531      tls_rt_name = "";
2532
2533    if(content_type == SSL3_RT_CHANGE_CIPHER_SPEC) {
2534      if(len) {
2535        msg_type = *(const unsigned char *)buf;
2536        msg_name = "Change cipher spec";
2537      }
2538    }
2539    else if(content_type == SSL3_RT_ALERT) {
2540      if(len >= 2) {
2541        msg_type =
2542          (((const unsigned char *)buf)[0] << 8) +
2543           ((const unsigned char *)buf)[1];
2544        msg_name = SSL_alert_desc_string_long(msg_type);
2545      }
2546    }
2547    else if(len) {
2548      msg_type = *(const unsigned char *)buf;
2549      msg_name = ssl_msg_type(ssl_ver, msg_type);
2550    }
2551
2552    txt_len = curl_msnprintf(ssl_buf, sizeof(ssl_buf),
2553                             "%s (%s), %s, %s (%d):\n",
2554                             verstr, direction ? "OUT" : "IN",
2555                             tls_rt_name, msg_name, msg_type);
2556    Curl_debug(data, CURLINFO_TEXT, ssl_buf, (size_t)txt_len);
2557  }
2558
2559  Curl_debug(data, (direction == 1) ? CURLINFO_SSL_DATA_OUT :
2560             CURLINFO_SSL_DATA_IN, (const char *)buf, len);
2561  (void)ssl;
2562}
2563
2564static CURLcode ossl_set_ssl_version_min_max(struct Curl_cfilter *cf,
2565                                             SSL_CTX *ctx,
2566                                             unsigned int ssl_version_min)
2567{
2568  struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
2569  /* first, TLS min version... */
2570  long curl_ssl_version_min = (long)ssl_version_min;
2571  long curl_ssl_version_max;
2572
2573  /* convert curl min SSL version option to OpenSSL constant */
2574#if defined(HAVE_BORINGSSL_LIKE) || defined(LIBRESSL_VERSION_NUMBER)
2575  uint16_t ossl_ssl_version_min = 0;
2576  uint16_t ossl_ssl_version_max = 0;
2577#else
2578  long ossl_ssl_version_min = 0;
2579  long ossl_ssl_version_max = 0;
2580#endif
2581  /* it cannot be default here */
2582  DEBUGASSERT(curl_ssl_version_min != CURL_SSLVERSION_DEFAULT);
2583  switch(curl_ssl_version_min) {
2584  case CURL_SSLVERSION_TLSv1: /* TLS 1.x */
2585  case CURL_SSLVERSION_TLSv1_0:
2586    ossl_ssl_version_min = TLS1_VERSION;
2587    break;
2588  case CURL_SSLVERSION_TLSv1_1:
2589    ossl_ssl_version_min = TLS1_1_VERSION;
2590    break;
2591  case CURL_SSLVERSION_TLSv1_2:
2592    ossl_ssl_version_min = TLS1_2_VERSION;
2593    break;
2594  case CURL_SSLVERSION_TLSv1_3:
2595    ossl_ssl_version_min = TLS1_3_VERSION;
2596    break;
2597  }
2598
2599  /* ... then, TLS max version */
2600  curl_ssl_version_max = (long)conn_config->version_max;
2601
2602  /* convert curl max SSL version option to OpenSSL constant */
2603  switch(curl_ssl_version_max) {
2604  case CURL_SSLVERSION_MAX_TLSv1_0:
2605    ossl_ssl_version_max = TLS1_VERSION;
2606    break;
2607  case CURL_SSLVERSION_MAX_TLSv1_1:
2608    ossl_ssl_version_max = TLS1_1_VERSION;
2609    break;
2610  case CURL_SSLVERSION_MAX_TLSv1_2:
2611    ossl_ssl_version_max = TLS1_2_VERSION;
2612    break;
2613  case CURL_SSLVERSION_MAX_TLSv1_3:
2614    ossl_ssl_version_max = TLS1_3_VERSION;
2615    break;
2616  case CURL_SSLVERSION_MAX_NONE:  /* none selected */
2617  case CURL_SSLVERSION_MAX_DEFAULT:  /* max selected */
2618  default:
2619    /* SSL_CTX_set_max_proto_version states that: setting the maximum to 0
2620       enables protocol versions up to the highest version supported by
2621       the library */
2622    ossl_ssl_version_max = 0;
2623    break;
2624  }
2625
2626  if(!SSL_CTX_set_min_proto_version(ctx, ossl_ssl_version_min) ||
2627     !SSL_CTX_set_max_proto_version(ctx, ossl_ssl_version_max))
2628    return CURLE_SSL_CONNECT_ERROR;
2629
2630  return CURLE_OK;
2631}
2632
2633#ifdef HAVE_BORINGSSL_LIKE
2634typedef uint32_t ctx_option_t;
2635#elif defined(HAVE_OPENSSL3)
2636typedef uint64_t ctx_option_t;
2637#elif defined(LIBRESSL_VERSION_NUMBER)
2638typedef long ctx_option_t;
2639#else
2640typedef unsigned long ctx_option_t;
2641#endif
2642
2643CURLcode Curl_ossl_add_session(struct Curl_cfilter *cf,
2644                               struct Curl_easy *data,
2645                               const char *ssl_peer_key,
2646                               SSL_SESSION *session,
2647                               int ietf_tls_id,
2648                               const char *alpn,
2649                               unsigned char *quic_tp,
2650                               size_t quic_tp_len)
2651{
2652  unsigned char *der_session_buf = NULL;
2653  unsigned char *qtp_clone = NULL;
2654  CURLcode result = CURLE_OK;
2655
2656  if(!cf || !data)
2657    goto out;
2658
2659  if(Curl_ssl_scache_use(cf, data)) {
2660    struct Curl_ssl_session *sc_session = NULL;
2661    size_t der_session_size;
2662    unsigned char *der_session_ptr;
2663    size_t earlydata_max = 0;
2664
2665    der_session_size = i2d_SSL_SESSION(session, NULL);
2666    if(der_session_size == 0) {
2667      result = CURLE_OUT_OF_MEMORY;
2668      goto out;
2669    }
2670
2671    der_session_buf = der_session_ptr = curlx_malloc(der_session_size);
2672    if(!der_session_buf) {
2673      result = CURLE_OUT_OF_MEMORY;
2674      goto out;
2675    }
2676
2677    der_session_size = i2d_SSL_SESSION(session, &der_session_ptr);
2678    if(der_session_size == 0) {
2679      result = CURLE_OUT_OF_MEMORY;
2680      goto out;
2681    }
2682
2683#ifdef HAVE_OPENSSL_EARLYDATA
2684    earlydata_max = SSL_SESSION_get_max_early_data(session);
2685#endif
2686    if(quic_tp && quic_tp_len) {
2687      qtp_clone = curlx_memdup0((const char *)quic_tp, quic_tp_len);
2688      if(!qtp_clone) {
2689        result = CURLE_OUT_OF_MEMORY;
2690        goto out;
2691      }
2692    }
2693
2694    result = Curl_ssl_session_create2(der_session_buf, der_session_size,
2695                                      ietf_tls_id, alpn,
2696                                      (curl_off_t)time(NULL) +
2697                                        SSL_SESSION_get_timeout(session),
2698                                      earlydata_max, qtp_clone, quic_tp_len,
2699                                      &sc_session);
2700    der_session_buf = NULL;  /* took ownership of sdata */
2701    if(!result) {
2702      result = Curl_ssl_scache_put(cf, data, ssl_peer_key, sc_session);
2703      /* took ownership of `sc_session` */
2704    }
2705  }
2706
2707out:
2708  curlx_free(der_session_buf);
2709  return result;
2710}
2711
2712/* The "new session" callback must return zero if the session can be removed
2713 * or non-zero if the session has been put into the session cache.
2714 */
2715static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
2716{
2717  struct Curl_cfilter *cf = (struct Curl_cfilter *)SSL_get_app_data(ssl);
2718  if(cf) {
2719    struct Curl_easy *data = CF_DATA_CURRENT(cf);
2720    struct ssl_connect_data *connssl = cf->ctx;
2721    Curl_ossl_add_session(cf, data, connssl->peer.scache_key, ssl_sessionid,
2722                          SSL_version(ssl), connssl->negotiated.alpn, NULL, 0);
2723  }
2724  return 0;
2725}
2726
2727static CURLcode load_cacert_from_memory(X509_STORE *store,
2728                                        const struct curl_blob *ca_info_blob)
2729{
2730  /* these need to be freed at the end */
2731  BIO *cbio = NULL;
2732  STACK_OF(X509_INFO) *inf = NULL;
2733
2734  /* everything else is a reference */
2735  int i, count = 0;
2736  X509_INFO *itmp = NULL;
2737
2738  if(ca_info_blob->len > (size_t)INT_MAX)
2739    return CURLE_SSL_CACERT_BADFILE;
2740
2741  cbio = BIO_new_mem_buf(ca_info_blob->data, (int)ca_info_blob->len);
2742  if(!cbio)
2743    return CURLE_OUT_OF_MEMORY;
2744
2745  inf = PEM_X509_INFO_read_bio(cbio, NULL, NULL, NULL);
2746  if(!inf) {
2747    BIO_free(cbio);
2748    return CURLE_SSL_CACERT_BADFILE;
2749  }
2750
2751  /* add each entry from PEM file to x509_store */
2752  for(i = 0; i < (int)sk_X509_INFO_num(inf); ++i) {
2753    itmp = sk_X509_INFO_value(inf, (ossl_valsize_t)i);
2754    if(itmp->x509) {
2755      if(X509_STORE_add_cert(store, itmp->x509)) {
2756        ++count;
2757      }
2758      else {
2759        /* set count to 0 to return an error */
2760        count = 0;
2761        break;
2762      }
2763    }
2764    if(itmp->crl) {
2765      if(X509_STORE_add_crl(store, itmp->crl)) {
2766        ++count;
2767      }
2768      else {
2769        /* set count to 0 to return an error */
2770        count = 0;
2771        break;
2772      }
2773    }
2774  }
2775
2776#if defined(__clang__) && __clang_major__ >= 16
2777#pragma clang diagnostic push
2778#pragma clang diagnostic ignored "-Wcast-function-type-strict"
2779#endif
2780  sk_X509_INFO_pop_free(inf, X509_INFO_free);
2781#if defined(__clang__) && __clang_major__ >= 16
2782#pragma clang diagnostic pop
2783#endif
2784  BIO_free(cbio);
2785
2786  /* if we did not end up importing anything, treat that as an error */
2787  return (count > 0) ? CURLE_OK : CURLE_SSL_CACERT_BADFILE;
2788}
2789
2790#ifdef USE_WIN32_CRYPTO
2791static CURLcode ossl_win_load_store(struct Curl_easy *data,
2792                                    struct Curl_cfilter *cf,
2793                                    const char *win_store,
2794                                    X509_STORE *store,
2795                                    bool *padded)
2796{
2797  CURLcode result = CURLE_OK;
2798  HCERTSTORE hStore;
2799
2800  *padded = FALSE;
2801
2802  hStore = CertOpenSystemStoreA(0, win_store);
2803  if(hStore) {
2804    PCCERT_CONTEXT pContext = NULL;
2805    /* The array of enhanced key usage OIDs varies per certificate and
2806       is declared outside of the loop so that rather than malloc/free each
2807       iteration we can grow it with realloc, when necessary. */
2808    CERT_ENHKEY_USAGE *enhkey_usage = NULL;
2809    DWORD enhkey_usage_size = 0;
2810    VERBOSE(size_t total = 0);
2811    VERBOSE(size_t imported = 0);
2812
2813    /* This loop makes a best effort to import all valid certificates from
2814       the MS root store. If a certificate cannot be imported it is
2815       skipped. 'result' is used to store only hard-fail conditions (such
2816       as out of memory) that cause an early break. */
2817    result = CURLE_OK;
2818    for(;;) {
2819      X509 *x509;
2820      FILETIME now;
2821      BYTE key_usage[2];
2822      DWORD req_size;
2823      const unsigned char *encoded_cert;
2824      pContext = CertEnumCertificatesInStore(hStore, pContext);
2825      if(!pContext)
2826        break;
2827
2828      VERBOSE(++total);
2829
2830#if defined(DEBUGBUILD) && defined(CURLVERBOSE)
2831      {
2832        char cert_name[256];
2833        if(!CertGetNameStringA(pContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0,
2834                               NULL, cert_name, sizeof(cert_name)))
2835          infof(data, "SSL: unknown cert name");
2836        else
2837          infof(data, "SSL: Checking cert \"%s\"", cert_name);
2838      }
2839#endif
2840      encoded_cert = (const unsigned char *)pContext->pbCertEncoded;
2841      if(!encoded_cert)
2842        continue;
2843
2844      GetSystemTimeAsFileTime(&now);
2845      if(CompareFileTime(&pContext->pCertInfo->NotBefore, &now) > 0 ||
2846         CompareFileTime(&now, &pContext->pCertInfo->NotAfter) > 0)
2847        continue;
2848
2849      /* If key usage exists check for signing attribute */
2850      if(CertGetIntendedKeyUsage(pContext->dwCertEncodingType,
2851                                 pContext->pCertInfo,
2852                                 key_usage, sizeof(key_usage))) {
2853        if(!(key_usage[0] & CERT_KEY_CERT_SIGN_KEY_USAGE))
2854          continue;
2855      }
2856      else if(GetLastError())
2857        continue;
2858
2859      /* If enhanced key usage exists check for server auth attribute.
2860       *
2861       * Note "In a Microsoft environment, a certificate might also have
2862       * EKU extended properties that specify valid uses for the
2863       * certificate."  The call below checks both, and behavior varies
2864       * depending on what is found. For more details see
2865       * CertGetEnhancedKeyUsage doc.
2866       */
2867      if(CertGetEnhancedKeyUsage(pContext, 0, NULL, &req_size) && req_size) {
2868        if(req_size > enhkey_usage_size) {
2869          void *tmp = curlx_realloc(enhkey_usage, req_size);
2870
2871          if(!tmp) {
2872            failf(data, "SSL: Out of memory allocating for OID list");
2873            result = CURLE_OUT_OF_MEMORY;
2874            break;
2875          }
2876
2877          enhkey_usage = (CERT_ENHKEY_USAGE *)tmp;
2878          enhkey_usage_size = req_size;
2879        }
2880
2881        if(CertGetEnhancedKeyUsage(pContext, 0, enhkey_usage, &req_size)) {
2882          if(!enhkey_usage->cUsageIdentifier) {
2883            /* "If GetLastError returns CRYPT_E_NOT_FOUND, the certificate
2884               is good for all uses. If it returns zero, the certificate
2885               has no valid uses." */
2886            if((HRESULT)GetLastError() != CRYPT_E_NOT_FOUND)
2887              continue;
2888          }
2889          else {
2890            DWORD i;
2891            bool found = FALSE;
2892
2893            for(i = 0; i < enhkey_usage->cUsageIdentifier; ++i) {
2894              if(!strcmp("1.3.6.1.5.5.7.3.1" /* OID server auth */,
2895                         enhkey_usage->rgpszUsageIdentifier[i])) {
2896                found = TRUE;
2897                break;
2898              }
2899            }
2900
2901            if(!found)
2902              continue;
2903          }
2904        }
2905        else
2906          continue;
2907      }
2908      else
2909        continue;
2910
2911      x509 = d2i_X509(NULL, &encoded_cert, (long)pContext->cbCertEncoded);
2912      if(!x509)
2913        continue;
2914
2915      /* Try to import the certificate. This may fail for legitimate reasons
2916         such as duplicate certificate, which is allowed by MS but not
2917         OpenSSL. */
2918      if(X509_STORE_add_cert(store, x509) == 1) {
2919        VERBOSE(++imported);
2920#ifdef DEBUGBUILD
2921        infof(data, "SSL: Imported cert");
2922#endif
2923        *padded = TRUE;
2924      }
2925      X509_free(x509);
2926    }
2927
2928    curlx_free(enhkey_usage);
2929    CertFreeCertificateContext(pContext);
2930    CertCloseStore(hStore, 0);
2931
2932    CURL_TRC_CF(data, cf,
2933                "ossl_win_load_store() found: %zu imported: %zu certs in %s.",
2934                total, imported, win_store);
2935
2936    if(result)
2937      return result;
2938  }
2939
2940  return result;
2941}
2942
2943static CURLcode ossl_windows_load_anchors(struct Curl_cfilter *cf,
2944                                          struct Curl_easy *data,
2945                                          X509_STORE *store,
2946                                          bool *padded)
2947{
2948  /* Import certificates from the Windows root certificate store if
2949     requested.
2950     https://stackoverflow.com/questions/9507184/
2951     https://github.com/d3x0r/SACK/blob/ff15424d3c581b86d40f818532e5a400c516d39d/src/netlib/ssl_layer.c#L1410
2952     https://datatracker.ietf.org/doc/html/rfc5280 */
2953  const char *win_stores[] = {
2954    "ROOT",   /* Trusted Root Certification Authorities */
2955    "CA"      /* Intermediate Certification Authorities */
2956  };
2957  size_t i;
2958  CURLcode result = CURLE_OK;
2959
2960  *padded = FALSE;
2961  for(i = 0; i < CURL_ARRAYSIZE(win_stores); ++i) {
2962    bool store_added = FALSE;
2963    result = ossl_win_load_store(data, cf, win_stores[i], store, &store_added);
2964    if(result)
2965      return result;
2966    if(store_added) {
2967      CURL_TRC_CF(data, cf, "added trust anchors from Windows %s store",
2968                  win_stores[i]);
2969      *padded = TRUE;
2970    }
2971    else
2972      infof(data, "error importing Windows %s store, continuing anyway",
2973            win_stores[i]);
2974  }
2975  return result;
2976}
2977
2978#endif /* USE_WIN32_CRYPTO */
2979
2980static CURLcode ossl_load_trust_anchors(struct Curl_cfilter *cf,
2981                                        struct Curl_easy *data,
2982                                        struct ossl_ctx *octx,
2983                                        X509_STORE *store)
2984{
2985  struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
2986  struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
2987  CURLcode result = CURLE_OK;
2988  const char * const ssl_cafile =
2989    /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
2990    (conn_config->ca_info_blob ? NULL : conn_config->CAfile);
2991  const char * const ssl_capath = conn_config->CApath;
2992  bool have_native_check = FALSE;
2993
2994  octx->store_is_empty = TRUE;
2995  if(ssl_config->native_ca_store) {
2996#ifdef USE_WIN32_CRYPTO
2997    bool added = FALSE;
2998    result = ossl_windows_load_anchors(cf, data, store, &added);
2999    if(result)
3000      return result;
3001    if(added) {
3002      infof(data, "  Native: Windows System Stores ROOT+CA");
3003      octx->store_is_empty = FALSE;
3004    }
3005#elif defined(USE_APPLE_SECTRUST)
3006    infof(data, "  Native: Apple SecTrust");
3007    have_native_check = TRUE;
3008#endif
3009  }
3010
3011  if(conn_config->ca_info_blob) {
3012    result = load_cacert_from_memory(store, conn_config->ca_info_blob);
3013    if(result) {
3014      failf(data, "error adding trust anchors from certificate blob: %d",
3015            result);
3016      return result;
3017    }
3018    infof(data, "  CA Blob from configuration");
3019    octx->store_is_empty = FALSE;
3020  }
3021
3022  if(ssl_cafile || ssl_capath) {
3023#ifdef HAVE_OPENSSL3
3024    /* OpenSSL 3.0.0 has deprecated SSL_CTX_load_verify_locations */
3025    if(ssl_cafile) {
3026      if(!X509_STORE_load_file(store, ssl_cafile)) {
3027        if(octx->store_is_empty && !have_native_check) {
3028          /* Fail if we insist on successfully verifying the server. */
3029          failf(data, "error adding trust anchors from file: %s", ssl_cafile);
3030          return CURLE_SSL_CACERT_BADFILE;
3031        }
3032        else
3033          infof(data, "error setting certificate file, continuing anyway");
3034      }
3035      infof(data, "  CAfile: %s", ssl_cafile);
3036      octx->store_is_empty = FALSE;
3037    }
3038    if(ssl_capath) {
3039      if(!X509_STORE_load_path(store, ssl_capath)) {
3040        if(octx->store_is_empty && !have_native_check) {
3041          /* Fail if we insist on successfully verifying the server. */
3042          failf(data, "error adding trust anchors from path: %s", ssl_capath);
3043          return CURLE_SSL_CACERT_BADFILE;
3044        }
3045        else
3046          infof(data, "error setting certificate path, continuing anyway");
3047      }
3048      infof(data, "  CApath: %s", ssl_capath);
3049      octx->store_is_empty = FALSE;
3050    }
3051#else
3052    /* tell OpenSSL where to find CA certificates that are used to verify the
3053       server's certificate. */
3054    if(!X509_STORE_load_locations(store, ssl_cafile, ssl_capath)) {
3055      if(octx->store_is_empty && !have_native_check) {
3056        /* Fail if we insist on successfully verifying the server. */
3057        failf(data, "error adding trust anchors from locations:"
3058              "  CAfile: %s CApath: %s",
3059              ssl_cafile ? ssl_cafile : "none",
3060              ssl_capath ? ssl_capath : "none");
3061        return CURLE_SSL_CACERT_BADFILE;
3062      }
3063      else {
3064        infof(data, "error setting certificate verify locations,"
3065              " continuing anyway");
3066      }
3067    }
3068    if(ssl_cafile)
3069      infof(data, "  CAfile: %s", ssl_cafile);
3070    if(ssl_capath)
3071      infof(data, "  CApath: %s", ssl_capath);
3072    octx->store_is_empty = FALSE;
3073#endif
3074  }
3075
3076#ifdef CURL_CA_FALLBACK
3077  if(octx->store_is_empty) {
3078    /* verifying the peer without any CA certificates does not
3079       work so use OpenSSL's built-in default as fallback */
3080    X509_STORE_set_default_paths(store);
3081    infof(data, "  OpenSSL default paths (fallback)");
3082    octx->store_is_empty = FALSE;
3083  }
3084#endif
3085  if(octx->store_is_empty && !have_native_check)
3086    infof(data, "  no trust anchors configured");
3087
3088  return result;
3089}
3090
3091static CURLcode ossl_populate_x509_store(struct Curl_cfilter *cf,
3092                                         struct Curl_easy *data,
3093                                         struct ossl_ctx *octx,
3094                                         X509_STORE *store)
3095{
3096  struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
3097  struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
3098  CURLcode result = CURLE_OK;
3099  X509_LOOKUP *lookup = NULL;
3100  const char * const ssl_crlfile = ssl_config->primary.CRLfile;
3101  unsigned long x509flags = 0;
3102
3103  CURL_TRC_CF(data, cf, "configuring OpenSSL's x509 trust store");
3104  if(!store)
3105    return CURLE_OUT_OF_MEMORY;
3106
3107  if(!conn_config->verifypeer) {
3108    infof(data, "SSL Trust: peer verification disabled");
3109    return CURLE_OK;
3110  }
3111
3112  infof(data, "SSL Trust Anchors:");
3113  result = ossl_load_trust_anchors(cf, data, octx, store);
3114  if(result)
3115    return result;
3116
3117  /* Does not make sense to load a CRL file without peer verification */
3118  if(ssl_crlfile) {
3119    /* tell OpenSSL where to find CRL file that is used to check certificate
3120     * revocation */
3121    lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
3122    if(!lookup ||
3123       (!X509_load_crl_file(lookup, ssl_crlfile, X509_FILETYPE_PEM))) {
3124      failf(data, "error loading CRL file: %s", ssl_crlfile);
3125      return CURLE_SSL_CRL_BADFILE;
3126    }
3127    x509flags = X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL;
3128    infof(data, " CRLfile: %s", ssl_crlfile);
3129  }
3130
3131  /* Try building a chain using issuers in the trusted store first to avoid
3132     problems with server-sent legacy intermediates. Newer versions of
3133     OpenSSL do alternate chain checking by default but we do not know how to
3134     determine that in a reliable manner.
3135     https://web.archive.org/web/20190422050538/rt.openssl.org/Ticket/Display.html?id=3621
3136  */
3137  x509flags |= X509_V_FLAG_TRUSTED_FIRST;
3138
3139  if(!ssl_config->no_partialchain && !ssl_crlfile) {
3140    /* Have intermediate certificates in the trust store be treated as
3141       trust-anchors, in the same way as self-signed root CA certificates are.
3142       This allows users to verify servers using the intermediate cert only,
3143       instead of needing the whole chain.
3144
3145       Due to OpenSSL bug https://github.com/openssl/openssl/issues/5081 we
3146       cannot do partial chains with a CRL check.
3147    */
3148    x509flags |= X509_V_FLAG_PARTIAL_CHAIN;
3149  }
3150  (void)X509_STORE_set_flags(store, x509flags);
3151
3152  return result;
3153}
3154
3155/* key to use at `multi->proto_hash` */
3156#define MPROTO_OSSL_X509_KEY  "tls:ossl:x509:share"
3157
3158struct ossl_x509_share {
3159  char *CAfile;         /* CAfile path used to generate X509 store */
3160  X509_STORE *store;    /* cached X509 store or NULL if none */
3161  struct curltime time; /* when the cached store was created */
3162  BIT(store_is_empty);  /* no certs/paths/blobs are in the store */
3163  BIT(no_partialchain); /* keep partial chain state */
3164};
3165
3166static void oss_x509_share_free(void *key, size_t key_len, void *p)
3167{
3168  struct ossl_x509_share *share = p;
3169  DEBUGASSERT(key_len == (sizeof(MPROTO_OSSL_X509_KEY) - 1));
3170  DEBUGASSERT(!memcmp(MPROTO_OSSL_X509_KEY, key, key_len));
3171  (void)key;
3172  (void)key_len;
3173  if(share->store) {
3174    X509_STORE_free(share->store);
3175  }
3176  curlx_free(share->CAfile);
3177  curlx_free(share);
3178}
3179
3180static bool ossl_cached_x509_store_expired(struct Curl_easy *data,
3181                                           const struct ossl_x509_share *mb)
3182{
3183  const struct ssl_general_config *cfg = &data->set.general_ssl;
3184  if(cfg->ca_cache_timeout < 0)
3185    return FALSE;
3186  else {
3187    timediff_t elapsed_ms = curlx_ptimediff_ms(Curl_pgrs_now(data), &mb->time);
3188    timediff_t timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000;
3189
3190    return elapsed_ms >= timeout_ms;
3191  }
3192}
3193
3194static bool ossl_cached_x509_store_different(struct Curl_cfilter *cf,
3195                                             const struct Curl_easy *data,
3196                                             const struct ossl_x509_share *mb)
3197{
3198  struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
3199  struct ssl_config_data *ssl_config =
3200    Curl_ssl_cf_get_config(cf, CURL_UNCONST(data));
3201  if(mb->no_partialchain != ssl_config->no_partialchain)
3202    return TRUE;
3203  if(!mb->CAfile || !conn_config->CAfile)
3204    return mb->CAfile != conn_config->CAfile;
3205  return strcmp(mb->CAfile, conn_config->CAfile);
3206}
3207
3208static X509_STORE *ossl_get_cached_x509_store(struct Curl_cfilter *cf,
3209                                              struct Curl_easy *data,
3210                                              bool *pempty)
3211{
3212  struct Curl_multi *multi = data->multi;
3213  struct ossl_x509_share *share;
3214  X509_STORE *store = NULL;
3215
3216  DEBUGASSERT(multi);
3217  *pempty = TRUE;
3218  share = multi ? Curl_hash_pick(&multi->proto_hash,
3219                                 CURL_UNCONST(MPROTO_OSSL_X509_KEY),
3220                                 sizeof(MPROTO_OSSL_X509_KEY) - 1) : NULL;
3221  if(share && share->store &&
3222     !ossl_cached_x509_store_expired(data, share) &&
3223     !ossl_cached_x509_store_different(cf, data, share)) {
3224    store = share->store;
3225    *pempty = (bool)share->store_is_empty;
3226  }
3227
3228  return store;
3229}
3230
3231static void ossl_set_cached_x509_store(struct Curl_cfilter *cf,
3232                                       struct Curl_easy *data,
3233                                       X509_STORE *store,
3234                                       bool is_empty)
3235{
3236  struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
3237  struct Curl_multi *multi = data->multi;
3238  struct ossl_x509_share *share;
3239
3240  DEBUGASSERT(multi);
3241  if(!multi)
3242    return;
3243  share = Curl_hash_pick(&multi->proto_hash,
3244                         CURL_UNCONST(MPROTO_OSSL_X509_KEY),
3245                         sizeof(MPROTO_OSSL_X509_KEY) - 1);
3246
3247  if(!share) {
3248    share = curlx_calloc(1, sizeof(*share));
3249    if(!share)
3250      return;
3251    if(!Curl_hash_add2(&multi->proto_hash,
3252                       CURL_UNCONST(MPROTO_OSSL_X509_KEY),
3253                       sizeof(MPROTO_OSSL_X509_KEY) - 1,
3254                       share, oss_x509_share_free)) {
3255      curlx_free(share);
3256      return;
3257    }
3258  }
3259
3260  if(X509_STORE_up_ref(store)) {
3261    char *CAfile = NULL;
3262    struct ssl_config_data *ssl_config =
3263      Curl_ssl_cf_get_config(cf, CURL_UNCONST(data));
3264
3265    if(conn_config->CAfile) {
3266      CAfile = curlx_strdup(conn_config->CAfile);
3267      if(!CAfile) {
3268        X509_STORE_free(store);
3269        return;
3270      }
3271    }
3272
3273    if(share->store) {
3274      X509_STORE_free(share->store);
3275      curlx_free(share->CAfile);
3276    }
3277
3278    share->time = *Curl_pgrs_now(data);
3279    share->store = store;
3280    share->store_is_empty = is_empty;
3281    share->CAfile = CAfile;
3282    share->no_partialchain = ssl_config->no_partialchain;
3283  }
3284}
3285
3286CURLcode Curl_ssl_setup_x509_store(struct Curl_cfilter *cf,
3287                                   struct Curl_easy *data,
3288                                   struct ossl_ctx *octx)
3289{
3290  struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
3291  struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
3292  CURLcode result = CURLE_OK;
3293  X509_STORE *cached_store;
3294  bool cache_criteria_met, is_empty;
3295
3296  /* Consider the X509 store cacheable if it comes exclusively from a CAfile,
3297     or no source is provided and we are falling back to OpenSSL's built-in
3298     default. */
3299  cache_criteria_met = (data->set.general_ssl.ca_cache_timeout != 0) &&
3300    conn_config->verifypeer &&
3301    !conn_config->CApath &&
3302    !conn_config->ca_info_blob &&
3303    !ssl_config->primary.CRLfile &&
3304    !ssl_config->native_ca_store;
3305
3306  ERR_set_mark();
3307
3308  cached_store = ossl_get_cached_x509_store(cf, data, &is_empty);
3309  if(cached_store && cache_criteria_met && X509_STORE_up_ref(cached_store)) {
3310    SSL_CTX_set_cert_store(octx->ssl_ctx, cached_store);
3311    octx->store_is_empty = is_empty;
3312  }
3313  else {
3314    X509_STORE *store = SSL_CTX_get_cert_store(octx->ssl_ctx);
3315
3316    result = ossl_populate_x509_store(cf, data, octx, store);
3317    if(result == CURLE_OK && cache_criteria_met) {
3318      ossl_set_cached_x509_store(cf, data, store, (bool)octx->store_is_empty);
3319    }
3320  }
3321
3322  ERR_pop_to_mark();
3323
3324  return result;
3325}
3326
3327static CURLcode
3328ossl_init_session_and_alpns(struct ossl_ctx *octx,
3329                            struct Curl_cfilter *cf,
3330                            struct Curl_easy *data,
3331                            struct ssl_peer *peer,
3332                            const struct alpn_spec *alpns_requested,
3333                            Curl_ossl_init_session_reuse_cb *sess_reuse_cb)
3334{
3335  struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
3336  struct ssl_primary_config *conn_cfg = Curl_ssl_cf_get_primary_config(cf);
3337  struct alpn_spec alpns;
3338  CURLcode result;
3339
3340  Curl_alpn_copy(&alpns, alpns_requested);
3341
3342  octx->reused_session = FALSE;
3343  if(Curl_ssl_scache_use(cf, data) && !conn_cfg->verifystatus) {
3344    struct Curl_ssl_session *scs = NULL;
3345
3346    result = Curl_ssl_scache_take(cf, data, peer->scache_key, &scs);
3347    if(!result && scs && scs->sdata && scs->sdata_len) {
3348      const unsigned char *der_sessionid = scs->sdata;
3349      size_t der_sessionid_size = scs->sdata_len;
3350      SSL_SESSION *ssl_session = NULL;
3351
3352      /* If OpenSSL does not accept the session from the cache, this
3353       * is not an error. We continue without it. */
3354      ssl_session = d2i_SSL_SESSION(NULL, &der_sessionid,
3355                                    (long)der_sessionid_size);
3356      if(ssl_session) {
3357        if(!SSL_set_session(octx->ssl, ssl_session)) {
3358          VERBOSE(char error_buffer[256]);
3359          infof(data, "SSL: SSL_set_session not accepted, "
3360                "continuing without: %s",
3361                ossl_strerror(ERR_get_error(), error_buffer,
3362                              sizeof(error_buffer)));
3363        }
3364        else {
3365          if(conn_cfg->verifypeer &&
3366             (SSL_get_verify_result(octx->ssl) != X509_V_OK)) {
3367            /* Session was from unverified connection, cannot reuse here */
3368            SSL_set_session(octx->ssl, NULL);
3369            infof(data, "SSL session not peer verified, not reusing");
3370          }
3371          else {
3372            infof(data, "SSL reusing session with ALPN '%s'",
3373                  scs->alpn ? scs->alpn : "-");
3374            octx->reused_session = TRUE;
3375            infof(data, "SSL verify result: %lx",
3376                  SSL_get_verify_result(octx->ssl));
3377#ifdef HAVE_OPENSSL_EARLYDATA
3378            if(ssl_config->earlydata && scs->alpn &&
3379               SSL_SESSION_get_max_early_data(ssl_session) &&
3380               !cf->conn->bits.connect_only &&
3381               (SSL_version(octx->ssl) == TLS1_3_VERSION)) {
3382              bool do_early_data = FALSE;
3383              if(sess_reuse_cb) {
3384                result = sess_reuse_cb(cf, data, &alpns, scs, &do_early_data);
3385                if(result) {
3386                  SSL_SESSION_free(ssl_session);
3387                  return result;
3388                }
3389              }
3390              if(do_early_data) {
3391                /* We only try the ALPN protocol the session used before,
3392                 * otherwise we might send early data for the wrong protocol */
3393                Curl_alpn_restrict_to(&alpns, scs->alpn);
3394              }
3395            }
3396#else
3397            (void)ssl_config;
3398            (void)sess_reuse_cb;
3399#endif
3400          }
3401        }
3402        SSL_SESSION_free(ssl_session);
3403      }
3404      else {
3405        infof(data, "SSL session not accepted by OpenSSL, continuing without");
3406      }
3407    }
3408    Curl_ssl_scache_return(cf, data, peer->scache_key, scs);
3409  }
3410
3411  if(alpns.count) {
3412    struct alpn_proto_buf proto;
3413    memset(&proto, 0, sizeof(proto));
3414    result = Curl_alpn_to_proto_buf(&proto, &alpns);
3415    if(result) {
3416      failf(data, "Error determining ALPN");
3417      return CURLE_SSL_CONNECT_ERROR;
3418    }
3419    if(SSL_set_alpn_protos(octx->ssl, proto.data, proto.len)) {
3420      failf(data, "Error setting ALPN");
3421      return CURLE_SSL_CONNECT_ERROR;
3422    }
3423  }
3424
3425  return CURLE_OK;
3426}
3427
3428#ifdef HAVE_SSL_SET1_ECH_CONFIG_LIST
3429bool Curl_ossl_need_httpsrr(struct Curl_easy *data)
3430{
3431  if(!CURLECH_ENABLED(data))
3432    return FALSE;
3433  if((data->set.tls_ech == CURLECH_GREASE) ||
3434     data->set.str[STRING_ECH_CONFIG])
3435    return FALSE;
3436  return TRUE;
3437}
3438
3439static CURLcode ossl_init_ech(struct ossl_ctx *octx,
3440                              struct Curl_cfilter *cf,
3441                              struct Curl_easy *data,
3442                              struct ssl_peer *peer)
3443{
3444  unsigned char *ech_config = NULL;
3445  size_t ech_config_len = 0;
3446  char *outername = data->set.str[STRING_ECH_PUBLIC];
3447  int trying_ech_now = 0;
3448  CURLcode result = CURLE_OK;
3449
3450  if(!CURLECH_ENABLED(data))
3451    return CURLE_OK;
3452
3453  if(data->set.tls_ech == CURLECH_GREASE) {
3454    infof(data, "ECH: will GREASE ClientHello");
3455#ifdef HAVE_BORINGSSL_LIKE
3456    SSL_set_enable_ech_grease(octx->ssl, 1);
3457#else
3458    SSL_set_options(octx->ssl, SSL_OP_ECH_GREASE);
3459#endif
3460  }
3461  else if(data->set.tls_ech && data->set.str[STRING_ECH_CONFIG]) {
3462#ifdef HAVE_BORINGSSL_LIKE
3463    /* have to do base64 decode here for BoringSSL */
3464    const char *b64 = data->set.str[STRING_ECH_CONFIG];
3465
3466    if(!b64) {
3467      infof(data, "ECH: ECHConfig from command line empty");
3468      return CURLE_SSL_CONNECT_ERROR;
3469    }
3470    ech_config_len = 2 * strlen(b64);
3471    result = curlx_base64_decode(b64, &ech_config, &ech_config_len);
3472    if(result || !ech_config) {
3473      infof(data, "ECH: cannot base64 decode ECHConfig from command line");
3474      if(data->set.tls_ech == CURLECH_HARD)
3475        return result;
3476    }
3477    if(SSL_set1_ech_config_list(octx->ssl, ech_config, ech_config_len) != 1) {
3478      infof(data, "ECH: SSL_ECH_set1_ech_config_list failed");
3479      if(data->set.tls_ech == CURLECH_HARD) {
3480        curlx_free(ech_config);
3481        return CURLE_SSL_CONNECT_ERROR;
3482      }
3483    }
3484    curlx_free(ech_config);
3485    trying_ech_now = 1;
3486#else
3487    ech_config = (unsigned char *)data->set.str[STRING_ECH_CONFIG];
3488    if(!ech_config) {
3489      infof(data, "ECH: ECHConfig from command line empty");
3490      return CURLE_SSL_CONNECT_ERROR;
3491    }
3492    ech_config_len = strlen(data->set.str[STRING_ECH_CONFIG]);
3493    if(SSL_set1_ech_config_list(octx->ssl, ech_config, ech_config_len) != 1) {
3494      infof(data, "ECH: SSL_ECH_set1_ech_config_list failed");
3495      if(data->set.tls_ech == CURLECH_HARD)
3496        return CURLE_SSL_CONNECT_ERROR;
3497    }
3498    else
3499      trying_ech_now = 1;
3500#endif /* HAVE_BORINGSSL_LIKE */
3501    infof(data, "ECH: ECHConfig from command line");
3502  }
3503  else {
3504    const struct Curl_https_rrinfo *rinfo =
3505      Curl_conn_dns_get_https(data, cf->sockindex);
3506
3507    if(rinfo && rinfo->echconfiglist) {
3508      const unsigned char *ecl = rinfo->echconfiglist;
3509      size_t elen = rinfo->echconfiglist_len;
3510
3511      infof(data, "ECH: ECHConfig from HTTPS RR");
3512      if(SSL_set1_ech_config_list(octx->ssl, ecl, elen) != 1) {
3513        infof(data, "ECH: SSL_set1_ech_config_list failed");
3514        if(data->set.tls_ech == CURLECH_HARD)
3515          return CURLE_SSL_CONNECT_ERROR;
3516      }
3517      else {
3518        trying_ech_now = 1;
3519        infof(data, "ECH: imported ECHConfigList of length %zu", elen);
3520      }
3521    }
3522    else {
3523      infof(data, "ECH: requested but no ECHConfig available");
3524      if(data->set.tls_ech == CURLECH_HARD)
3525        return CURLE_SSL_CONNECT_ERROR;
3526    }
3527  }
3528#ifdef HAVE_BORINGSSL_LIKE
3529  (void)peer;
3530  if(trying_ech_now && outername) {
3531    infof(data, "ECH: setting public_name not supported with BoringSSL");
3532    return CURLE_SSL_CONNECT_ERROR;
3533  }
3534#else
3535  if(trying_ech_now && outername) {
3536    infof(data, "ECH: inner: '%s', outer: '%s'",
3537          peer->dest->hostname ? peer->dest->hostname : "NULL", outername);
3538    result = SSL_ech_set1_server_names(octx->ssl,
3539                                       peer->dest->hostname, outername,
3540                                       0 /* do send outer */);
3541    if(result != 1) {
3542      infof(data, "ECH: rv failed to set server name(s) %d [ERROR]", result);
3543      return CURLE_SSL_CONNECT_ERROR;
3544    }
3545  }
3546#endif /* HAVE_BORINGSSL_LIKE */
3547  if(trying_ech_now &&
3548     SSL_set_min_proto_version(octx->ssl, TLS1_3_VERSION) != 1) {
3549    infof(data, "ECH: cannot force TLSv1.3 [ERROR]");
3550    return CURLE_SSL_CONNECT_ERROR;
3551  }
3552
3553  return CURLE_OK;
3554}
3555#else /* HAVE_SSL_SET1_ECH_CONFIG_LIST */
3556bool Curl_ossl_need_httpsrr(struct Curl_easy *data)
3557{
3558  (void)data;
3559  return FALSE;
3560}
3561#endif /* else HAVE_SSL_SET1_ECH_CONFIG_LIST */
3562
3563static CURLcode ossl_init_ssl(struct ossl_ctx *octx,
3564                              struct Curl_cfilter *cf,
3565                              struct Curl_easy *data,
3566                              struct ssl_peer *peer,
3567                              const struct alpn_spec *alpns_requested,
3568                              void *ssl_user_data,
3569                              Curl_ossl_init_session_reuse_cb *sess_reuse_cb)
3570{
3571  /* Let's make an SSL structure */
3572  if(octx->ssl)
3573    SSL_free(octx->ssl);
3574  octx->ssl = SSL_new(octx->ssl_ctx);
3575  if(!octx->ssl) {
3576    failf(data, "SSL: could not create a context (handle)");
3577    return CURLE_OUT_OF_MEMORY;
3578  }
3579
3580  SSL_set_app_data(octx->ssl, ssl_user_data);
3581
3582#ifndef OPENSSL_NO_OCSP
3583  if(Curl_ssl_cf_get_primary_config(cf)->verifystatus)
3584    SSL_set_tlsext_status_type(octx->ssl, TLSEXT_STATUSTYPE_ocsp);
3585#endif
3586
3587  SSL_set_connect_state(octx->ssl);
3588
3589  if(peer->sni) {
3590    if(!SSL_set_tlsext_host_name(octx->ssl, peer->sni)) {
3591      failf(data, "Failed set SNI");
3592      return CURLE_SSL_CONNECT_ERROR;
3593    }
3594  }
3595
3596#ifdef HAVE_SSL_SET1_ECH_CONFIG_LIST
3597  {
3598    CURLcode result = ossl_init_ech(octx, cf, data, peer);
3599    if(result)
3600      return result;
3601  }
3602#endif /* HAVE_SSL_SET1_ECH_CONFIG_LIST */
3603
3604  return ossl_init_session_and_alpns(octx, cf, data, peer,
3605                                     alpns_requested, sess_reuse_cb);
3606}
3607
3608static CURLcode ossl_init_method(struct Curl_cfilter *cf,
3609                                 struct Curl_easy *data,
3610                                 struct ssl_peer *peer,
3611                                 const SSL_METHOD **pmethod,
3612                                 unsigned int *pssl_version_min)
3613{
3614  struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
3615
3616  *pmethod = NULL;
3617  *pssl_version_min = conn_config->version;
3618  DEBUGASSERT(conn_config->version != CURL_SSLVERSION_DEFAULT);
3619  switch(peer->transport) {
3620  case TRNSPRT_TCP:
3621    /* check to see if we have been told to use an explicit SSL/TLS version */
3622    switch(*pssl_version_min) {
3623    case CURL_SSLVERSION_TLSv1:
3624    case CURL_SSLVERSION_TLSv1_0:
3625    case CURL_SSLVERSION_TLSv1_1:
3626    case CURL_SSLVERSION_TLSv1_2:
3627    case CURL_SSLVERSION_TLSv1_3:
3628      /* it is handled later with the context options */
3629      *pmethod = TLS_client_method();
3630      break;
3631    case CURL_SSLVERSION_SSLv2:
3632      failf(data, "No SSLv2 support");
3633      return CURLE_NOT_BUILT_IN;
3634    case CURL_SSLVERSION_SSLv3:
3635      failf(data, "No SSLv3 support");
3636      return CURLE_NOT_BUILT_IN;
3637    default:
3638      failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
3639      return CURLE_SSL_CONNECT_ERROR;
3640    }
3641    break;
3642  case TRNSPRT_QUIC:
3643    *pssl_version_min = CURL_SSLVERSION_TLSv1_3;
3644    if(conn_config->version_max &&
3645       (conn_config->version_max != CURL_SSLVERSION_MAX_DEFAULT) &&
3646       (conn_config->version_max != CURL_SSLVERSION_MAX_TLSv1_3)) {
3647      failf(data, "QUIC needs at least TLS version 1.3");
3648      return CURLE_SSL_CONNECT_ERROR;
3649    }
3650
3651    *pmethod = TLS_method();
3652    break;
3653  default:
3654    failf(data, "unsupported transport %d in SSL init", peer->transport);
3655    return CURLE_SSL_CONNECT_ERROR;
3656  }
3657
3658  return *pmethod ? CURLE_OK : CURLE_SSL_CONNECT_ERROR;
3659}
3660
3661CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
3662                            struct Curl_cfilter *cf,
3663                            struct Curl_easy *data,
3664                            struct ssl_peer *peer,
3665                            const struct alpn_spec *alpns_requested,
3666                            Curl_ossl_ctx_setup_cb *cb_setup,
3667                            void *cb_user_data,
3668                            Curl_ossl_new_session_cb *cb_new_session,
3669                            void *ssl_user_data,
3670                            Curl_ossl_init_session_reuse_cb *sess_reuse_cb)
3671{
3672  CURLcode result = CURLE_OK;
3673  const char *ciphers;
3674  const SSL_METHOD *req_method = NULL;
3675  ctx_option_t ctx_options = 0;
3676  struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
3677  struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
3678  char * const ssl_cert = ssl_config->primary.clientcert;
3679  const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob;
3680  const char * const ssl_cert_type = ssl_config->cert_type;
3681  unsigned int ssl_version_min;
3682  char error_buffer[256];
3683
3684  /* Make funny stuff to get random input */
3685  result = ossl_seed(data);
3686  if(result)
3687    return result;
3688
3689  ssl_config->certverifyresult = !X509_V_OK;
3690
3691  result = ossl_init_method(cf, data, peer, &req_method, &ssl_version_min);
3692  if(result)
3693    return result;
3694  DEBUGASSERT(req_method);
3695
3696  DEBUGASSERT(!octx->ssl_ctx);
3697  octx->ssl_ctx =
3698#ifdef OPENSSL_HAS_PROVIDERS
3699    data->state.libctx ?
3700    SSL_CTX_new_ex(data->state.libctx, data->state.propq, req_method):
3701#endif
3702    SSL_CTX_new(req_method);
3703
3704  if(!octx->ssl_ctx) {
3705    failf(data, "SSL: could not create a context: %s",
3706          ossl_strerror(ERR_peek_error(), error_buffer, sizeof(error_buffer)));
3707    return CURLE_OUT_OF_MEMORY;
3708  }
3709
3710  if(cb_setup) {
3711    result = cb_setup(cf, data, cb_user_data);
3712    if(result)
3713      return result;
3714  }
3715
3716  if(data->set.fdebug && data->set.verbose) {
3717    /* the SSL trace callback is only used for verbose logging */
3718    SSL_CTX_set_msg_callback(octx->ssl_ctx, ossl_trace);
3719    SSL_CTX_set_msg_callback_arg(octx->ssl_ctx, cf);
3720  }
3721
3722  /* OpenSSL contains code to work around lots of bugs and flaws in various
3723     SSL-implementations. SSL_CTX_set_options() is used to enabled those
3724     work-arounds. The man page for this option states that SSL_OP_ALL enables
3725     all the work-arounds and that "It is usually safe to use SSL_OP_ALL to
3726     enable the bug workaround options if compatibility with somewhat broken
3727     implementations is desired."
3728
3729     The "-no_ticket" option was introduced in OpenSSL 0.9.8j. it is a flag to
3730     disable "rfc4507bis session ticket support". rfc4507bis was later turned
3731     into the proper RFC5077: https://datatracker.ietf.org/doc/html/rfc5077
3732
3733     The enabled extension concerns the session management. I wonder how often
3734     libcurl stops a connection and then resumes a TLS session. Also, sending
3735     the session data is some overhead. I suggest that you use your proposed
3736     patch (which explicitly disables TICKET).
3737
3738     If someone writes an application with libcurl and OpenSSL who wants to
3739     enable the feature, one can do this in the SSL callback.
3740
3741     SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG option enabling allowed proper
3742     interoperability with web server Netscape Enterprise Server 2.0.1 which
3743     was released back in 1996.
3744
3745     Due to CVE-2010-4180, option SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG has
3746     become ineffective as of OpenSSL 0.9.8q and 1.0.0c. In order to mitigate
3747     CVE-2010-4180 when using previous OpenSSL versions we no longer enable
3748     this option regardless of OpenSSL version and SSL_OP_ALL definition.
3749
3750     OpenSSL added a work-around for an SSL 3.0/TLS 1.0 CBC vulnerability:
3751     https://web.archive.org/web/20240114184648/openssl.org/~bodo/tls-cbc.txt.
3752     In 0.9.6e they added a bit to SSL_OP_ALL that _disables_ that work-around
3753     despite the fact that SSL_OP_ALL is documented to do "rather harmless"
3754     workarounds. In order to keep the secure work-around, the
3755     SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS bit must not be set.
3756  */
3757
3758  ctx_options = SSL_OP_ALL | SSL_OP_NO_TICKET | SSL_OP_NO_COMPRESSION;
3759
3760  /* mitigate CVE-2010-4180 */
3761  ctx_options &= ~(ctx_option_t)SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG;
3762
3763  /* unless the user explicitly asks to allow the protocol vulnerability we
3764     use the work-around */
3765  if(!ssl_config->enable_beast)
3766    ctx_options &= ~(ctx_option_t)SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
3767
3768  DEBUGASSERT(ssl_version_min != CURL_SSLVERSION_DEFAULT);
3769  switch(ssl_version_min) {
3770  case CURL_SSLVERSION_SSLv2:
3771  case CURL_SSLVERSION_SSLv3:
3772    return CURLE_NOT_BUILT_IN;
3773
3774    /* "--tlsv<x.y>" options mean TLS >= version <x.y> */
3775  case CURL_SSLVERSION_TLSv1:   /* TLS >= version 1.0 */
3776  case CURL_SSLVERSION_TLSv1_0: /* TLS >= version 1.0 */
3777  case CURL_SSLVERSION_TLSv1_1: /* TLS >= version 1.1 */
3778  case CURL_SSLVERSION_TLSv1_2: /* TLS >= version 1.2 */
3779  case CURL_SSLVERSION_TLSv1_3: /* TLS >= version 1.3 */
3780    /* asking for any TLS version as the minimum, means no SSL versions
3781       allowed */
3782    ctx_options |= SSL_OP_NO_SSLv2;
3783    ctx_options |= SSL_OP_NO_SSLv3;
3784
3785    result = ossl_set_ssl_version_min_max(cf, octx->ssl_ctx, ssl_version_min);
3786    if(result)
3787      return result;
3788    break;
3789
3790  default:
3791    failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
3792    return CURLE_SSL_CONNECT_ERROR;
3793  }
3794
3795  SSL_CTX_set_options(octx->ssl_ctx, ctx_options);
3796  SSL_CTX_set_read_ahead(octx->ssl_ctx, 1);
3797
3798  /* Max TLS1.2 record size 0x4000 + 0x800.
3799     OpenSSL supports processing "jumbo TLS record" (8 TLS records) in one go
3800     for some algorithms, so match that here.
3801     Experimentation shows that a slightly larger buffer is needed
3802     to avoid short reads.
3803
3804     However using a large buffer (8 packets) actually decreases performance.
3805     4 packets is better.
3806   */
3807#ifdef HAVE_SSL_CTX_SET_DEFAULT_READ_BUFFER_LEN
3808  SSL_CTX_set_default_read_buffer_len(octx->ssl_ctx, 0x401e * 4);
3809#endif
3810
3811  /* We do retry writes sometimes from another buffer address */
3812  SSL_CTX_set_mode(octx->ssl_ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
3813
3814  ciphers = conn_config->cipher_list;
3815  if(!ciphers && (peer->transport != TRNSPRT_QUIC))
3816    ciphers = NULL;
3817  if(ciphers && (ssl_version_min < CURL_SSLVERSION_TLSv1_3)) {
3818    if(!SSL_CTX_set_cipher_list(octx->ssl_ctx, ciphers)) {
3819      failf(data, "failed setting cipher list: %s", ciphers);
3820      return CURLE_SSL_CIPHER;
3821    }
3822    infof(data, "Cipher selection: %s", ciphers);
3823  }
3824
3825#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
3826  {
3827    const char *ciphers13 = conn_config->cipher_list13;
3828    if(ciphers13 &&
3829       (!conn_config->version_max ||
3830        (conn_config->version_max == CURL_SSLVERSION_MAX_DEFAULT) ||
3831        (conn_config->version_max >= CURL_SSLVERSION_MAX_TLSv1_3))) {
3832      if(!SSL_CTX_set_ciphersuites(octx->ssl_ctx, ciphers13)) {
3833        failf(data, "failed setting TLS 1.3 cipher suite: %s", ciphers13);
3834        return CURLE_SSL_CIPHER;
3835      }
3836      infof(data, "TLS 1.3 cipher selection: %s", ciphers13);
3837    }
3838  }
3839#endif
3840
3841  if(ssl_cert || ssl_cert_blob || ssl_cert_type) {
3842    result = client_cert(data, octx->ssl_ctx,
3843                         ssl_cert, ssl_cert_blob, ssl_cert_type,
3844                         ssl_config->key, ssl_config->key_blob,
3845                         ssl_config->key_type, ssl_config->key_passwd);
3846    if(result)
3847      /* failf() is already done in client_cert() */
3848      return result;
3849  }
3850
3851#ifdef HAVE_SSL_CTX_SET_POST_HANDSHAKE_AUTH
3852  /* OpenSSL 1.1.1 requires clients to opt-in for PHA */
3853  SSL_CTX_set_post_handshake_auth(octx->ssl_ctx, 1);
3854#endif
3855
3856  {
3857    const char *curves = conn_config->curves;
3858    if(curves) {
3859#ifdef HAVE_BORINGSSL_LIKE
3860#define OSSL_CURVE_CAST(x) (x)
3861#else
3862#define OSSL_CURVE_CAST(x) (char *)CURL_UNCONST(x)
3863#endif
3864      if(!SSL_CTX_set1_curves_list(octx->ssl_ctx, OSSL_CURVE_CAST(curves))) {
3865        failf(data, "failed setting curves list: '%s'", curves);
3866        return CURLE_SSL_CIPHER;
3867      }
3868    }
3869  }
3870
3871#ifdef HAVE_SSL_CTX_SET1_SIGALGS
3872#define OSSL_SIGALG_CAST(x) OSSL_CURVE_CAST(x)
3873  {
3874    const char *signature_algorithms = conn_config->signature_algorithms;
3875    if(signature_algorithms) {
3876      if(!SSL_CTX_set1_sigalgs_list(octx->ssl_ctx,
3877                                    OSSL_SIGALG_CAST(signature_algorithms))) {
3878        failf(data, "failed setting signature algorithms: '%s'",
3879              signature_algorithms);
3880        return CURLE_SSL_CIPHER;
3881      }
3882    }
3883  }
3884#endif
3885
3886#if defined(HAVE_OPENSSL_SRP) && defined(USE_TLS_SRP)
3887  if(ssl_config->primary.username && Curl_auth_allowed_to_host(data)) {
3888    char * const ssl_username = ssl_config->primary.username;
3889    char * const ssl_password = ssl_config->primary.password;
3890    infof(data, "Using TLS-SRP username: %s", ssl_username);
3891
3892    if(!SSL_CTX_set_srp_username(octx->ssl_ctx, ssl_username)) {
3893      failf(data, "Unable to set SRP username");
3894      return CURLE_BAD_FUNCTION_ARGUMENT;
3895    }
3896    if(!SSL_CTX_set_srp_password(octx->ssl_ctx, ssl_password)) {
3897      failf(data, "failed setting SRP password");
3898      return CURLE_BAD_FUNCTION_ARGUMENT;
3899    }
3900    if(!conn_config->cipher_list) {
3901      infof(data, "Setting cipher list SRP");
3902
3903      if(!SSL_CTX_set_cipher_list(octx->ssl_ctx, "SRP")) {
3904        failf(data, "failed setting SRP cipher list");
3905        return CURLE_SSL_CIPHER;
3906      }
3907    }
3908  }
3909#endif /* HAVE_OPENSSL_SRP && USE_TLS_SRP */
3910
3911  /* OpenSSL always tries to verify the peer. By setting the failure mode
3912   * to NONE, we allow the connect to complete, regardless of the outcome.
3913   * We then explicitly check the result and may try alternatives like
3914   * Apple's SecTrust for verification. */
3915  SSL_CTX_set_verify(octx->ssl_ctx, SSL_VERIFY_NONE, NULL);
3916
3917  /* Enable logging of secrets to the file specified in env SSLKEYLOGFILE. */
3918#if !defined(HAVE_KEYLOG_UPSTREAM) && defined(HAVE_KEYLOG_CALLBACK)
3919  if(Curl_tls_keylog_enabled()) {
3920    SSL_CTX_set_keylog_callback(octx->ssl_ctx, ossl_keylog_callback);
3921  }
3922#endif
3923
3924  if(cb_new_session) {
3925    /* Enable the session cache because it is a prerequisite for the
3926     * "new session" callback. Use the "external storage" mode to prevent
3927     * OpenSSL from creating an internal session cache.
3928     */
3929    SSL_CTX_set_session_cache_mode(octx->ssl_ctx,
3930                                   SSL_SESS_CACHE_CLIENT |
3931                                   SSL_SESS_CACHE_NO_INTERNAL);
3932    SSL_CTX_sess_set_new_cb(octx->ssl_ctx, cb_new_session);
3933  }
3934
3935  /* give application a chance to interfere with SSL set up. */
3936  if(data->set.ssl.fsslctx) {
3937    /* When a user callback is installed to modify the SSL_CTX,
3938     * we need to do the full initialization before calling it.
3939     * See: #11800 */
3940    if(!octx->x509_store_setup) {
3941      result = Curl_ssl_setup_x509_store(cf, data, octx);
3942      if(result)
3943        return result;
3944      octx->x509_store_setup = TRUE;
3945    }
3946    Curl_set_in_callback(data, TRUE);
3947    result = (*data->set.ssl.fsslctx)(data, octx->ssl_ctx,
3948                                      data->set.ssl.fsslctxp);
3949    Curl_set_in_callback(data, FALSE);
3950    if(result) {
3951      failf(data, "error signaled by ssl ctx callback");
3952      return result;
3953    }
3954  }
3955
3956  return ossl_init_ssl(octx, cf, data, peer, alpns_requested,
3957                       ssl_user_data, sess_reuse_cb);
3958}
3959
3960static CURLcode ossl_on_session_reuse(struct Curl_cfilter *cf,
3961                                      struct Curl_easy *data,
3962                                      struct alpn_spec *alpns,
3963                                      struct Curl_ssl_session *scs,
3964                                      bool *do_early_data)
3965{
3966  struct ssl_connect_data *connssl = cf->ctx;
3967
3968  connssl->earlydata_max = scs->earlydata_max;
3969
3970  return Curl_on_session_reuse(cf, data, alpns, scs, do_early_data,
3971                               connssl->earlydata_max);
3972}
3973
3974void Curl_ossl_report_handshake(struct Curl_easy *data, struct ossl_ctx *octx)
3975{
3976#ifdef CURLVERBOSE
3977  if(Curl_trc_is_verbose(data)) {
3978    int psigtype_nid = NID_undef;
3979    const char *negotiated_group_name = NULL;
3980
3981#ifdef HAVE_OPENSSL3
3982    SSL_get_peer_signature_type_nid(octx->ssl, &psigtype_nid);
3983#if OPENSSL_VERSION_NUMBER >= 0x30200000L
3984    negotiated_group_name = SSL_get0_group_name(octx->ssl);
3985#else
3986    negotiated_group_name =
3987      OBJ_nid2sn(SSL_get_negotiated_group(octx->ssl) & 0x0000FFFF);
3988#endif
3989#endif
3990
3991    /* Informational message */
3992    infof(data, "SSL connection using %s / %s / %s / %s",
3993          SSL_get_version(octx->ssl),
3994          SSL_get_cipher(octx->ssl),
3995          negotiated_group_name ? negotiated_group_name : "[blank]",
3996          OBJ_nid2sn(psigtype_nid));
3997  }
3998#else
3999  (void)data;
4000  (void)octx;
4001#endif /* CURLVERBOSE */
4002}
4003
4004static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
4005                                   struct Curl_easy *data)
4006{
4007  struct ssl_connect_data *connssl = cf->ctx;
4008  struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
4009  BIO *bio;
4010  CURLcode result;
4011
4012  DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
4013  DEBUGASSERT(octx);
4014
4015  result = Curl_ossl_ctx_init(octx, cf, data, &connssl->peer,
4016                              connssl->alpn, NULL, NULL,
4017                              ossl_new_session_cb, cf,
4018                              ossl_on_session_reuse);
4019  if(result)
4020    return result;
4021
4022  octx->bio_method = ossl_bio_cf_method_create();
4023  if(!octx->bio_method)
4024    return CURLE_OUT_OF_MEMORY;
4025  bio = BIO_new(octx->bio_method);
4026  if(!bio)
4027    return CURLE_OUT_OF_MEMORY;
4028
4029  BIO_set_data(bio, cf);
4030#ifdef HAVE_SSL_SET0_WBIO
4031  /* with OpenSSL v1.1.1 we get an alternative to SSL_set_bio() that works
4032   * without backward compat quirks. Every call takes one reference, so we
4033   * up it and pass. SSL* then owns and frees it.
4034   * We check on the function in configure, since LibreSSL and friends
4035   * each have their own versions to add support for this. */
4036  BIO_up_ref(bio);
4037  SSL_set0_rbio(octx->ssl, bio);
4038  SSL_set0_wbio(octx->ssl, bio);
4039#else
4040  SSL_set_bio(octx->ssl, bio, bio);
4041#endif
4042
4043  if(connssl->alpn && (connssl->state != ssl_connection_deferred)) {
4044    struct alpn_proto_buf proto;
4045    memset(&proto, 0, sizeof(proto));
4046    Curl_alpn_to_proto_str(&proto, connssl->alpn);
4047    infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
4048  }
4049
4050  connssl->connecting_state = ssl_connect_2;
4051  return CURLE_OK;
4052}
4053
4054#ifdef HAVE_SSL_SET1_ECH_CONFIG_LIST
4055/* If we have retry configs, then trace those out */
4056static int ossl_trace_ech_retry_configs(struct Curl_easy *data, SSL *ssl,
4057                                        int reason)
4058{
4059  CURLcode result = CURLE_OK;
4060  size_t rcl = 0;
4061  int rv = 1;
4062#ifndef HAVE_BORINGSSL_LIKE
4063  char *inner = NULL;
4064  uint8_t *rcs = NULL;
4065  char *outer = NULL;
4066#else
4067  const char *inner = NULL;
4068  const uint8_t *rcs = NULL;
4069  const char *outer = NULL;
4070  size_t out_name_len = 0;
4071  int servername_type = 0;
4072#endif
4073  NOVERBOSE((void)reason);
4074
4075  /* nothing to trace if not doing ECH */
4076  if(!CURLECH_ENABLED(data))
4077    return rv;
4078#ifndef HAVE_BORINGSSL_LIKE
4079  rv = SSL_ech_get1_retry_config(ssl, &rcs, &rcl);
4080#else
4081  SSL_get0_ech_retry_configs(ssl, &rcs, &rcl);
4082  rv = (int)rcl;
4083#endif
4084
4085  if(rv && rcs) {
4086    char *b64str = NULL;
4087    size_t blen = 0;
4088
4089    result = curlx_base64_encode(rcs, rcl, &b64str, &blen);
4090    if(!result && b64str) {
4091      infof(data, "ECH: retry_configs %s", b64str);
4092      curlx_free(b64str);
4093#ifndef HAVE_BORINGSSL_LIKE
4094      rv = SSL_ech_get1_status(ssl, &inner, &outer);
4095      infof(data, "ECH: retry_configs for %s from %s, %d %d",
4096            inner ? inner : "NULL", outer ? outer : "NULL", reason, rv);
4097#else
4098      rv = SSL_ech_accepted(ssl);
4099      servername_type = SSL_get_servername_type(ssl);
4100      inner = SSL_get_servername(ssl, servername_type);
4101      SSL_get0_ech_name_override(ssl, &outer, &out_name_len);
4102      infof(data, "ECH: retry_configs for %s from %s, %d %d",
4103            inner ? inner : "NULL", outer ? outer : "NULL", reason, rv);
4104#endif
4105    }
4106  }
4107  else
4108    infof(data, "ECH: no retry_configs (rv = %d)", rv);
4109#ifndef HAVE_BORINGSSL_LIKE
4110  OPENSSL_free(inner);
4111  OPENSSL_free(rcs);
4112  OPENSSL_free(outer);
4113#endif
4114  return rv;
4115}
4116
4117#endif
4118
4119static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
4120                                   struct Curl_easy *data)
4121{
4122  int err;
4123  struct ssl_connect_data *connssl = cf->ctx;
4124  struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
4125  struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
4126  DEBUGASSERT(ssl_connect_2 == connssl->connecting_state);
4127  DEBUGASSERT(octx);
4128
4129  connssl->io_need = CURL_SSL_IO_NEED_NONE;
4130  ERR_clear_error();
4131
4132  err = SSL_connect(octx->ssl);
4133
4134  if(!octx->x509_store_setup) {
4135    /* After having send off the ClientHello, we prepare the x509
4136     * store to verify the coming certificate from the server */
4137    CURLcode result = Curl_ssl_setup_x509_store(cf, data, octx);
4138    if(result)
4139      return result;
4140    octx->x509_store_setup = TRUE;
4141  }
4142
4143#if !defined(HAVE_KEYLOG_UPSTREAM) && !defined(HAVE_KEYLOG_CALLBACK)
4144  /* If key logging is enabled, wait for the handshake to complete and then
4145   * proceed with logging secrets (for TLS 1.2 or older).
4146   */
4147  if(Curl_tls_keylog_enabled() && !octx->keylog_done)
4148    ossl_log_tls12_secret(octx->ssl, &octx->keylog_done);
4149#endif
4150
4151  /* 1  is fine
4152     0  is "not successful but was shut down controlled"
4153     <0 is "handshake was not successful, because a fatal error occurred" */
4154  if(err != 1) {
4155    int detail = SSL_get_error(octx->ssl, err);
4156    CURL_TRC_CF(data, cf, "SSL_connect() -> err=%d, detail=%d", err, detail);
4157
4158    if(SSL_ERROR_WANT_READ == detail) {
4159      CURL_TRC_CF(data, cf, "SSL_connect() -> want recv");
4160      connssl->io_need = CURL_SSL_IO_NEED_RECV;
4161      return CURLE_AGAIN;
4162    }
4163    if(SSL_ERROR_WANT_WRITE == detail) {
4164      CURL_TRC_CF(data, cf, "SSL_connect() -> want send");
4165      connssl->io_need = CURL_SSL_IO_NEED_SEND;
4166      return CURLE_AGAIN;
4167    }
4168#ifdef SSL_ERROR_WANT_ASYNC
4169    if(SSL_ERROR_WANT_ASYNC == detail) {
4170      CURL_TRC_CF(data, cf, "SSL_connect() -> want async");
4171      connssl->io_need = CURL_SSL_IO_NEED_RECV;
4172      return CURLE_AGAIN;
4173    }
4174#endif
4175#ifdef SSL_ERROR_WANT_RETRY_VERIFY
4176    if(SSL_ERROR_WANT_RETRY_VERIFY == detail) {
4177      CURL_TRC_CF(data, cf, "SSL_connect() -> want retry_verify");
4178      Curl_xfer_pause_recv(data, TRUE);
4179      return CURLE_AGAIN;
4180    }
4181#endif
4182    else {
4183      /* untreated error */
4184      sslerr_t errdetail;
4185      char error_buffer[256] = "";
4186      CURLcode result;
4187      long lerr;
4188      int lib;
4189      int reason;
4190
4191      /* the connection failed, we are not waiting for anything else. */
4192      connssl->connecting_state = ssl_connect_2;
4193
4194      /* Get the earliest error code from the thread's error queue and remove
4195         the entry. */
4196      errdetail = ERR_get_error();
4197
4198      /* Extract which lib and reason */
4199      lib = ERR_GET_LIB(errdetail);
4200      reason = ERR_GET_REASON(errdetail);
4201
4202      if((lib == ERR_LIB_SSL) &&
4203         ((reason == SSL_R_CERTIFICATE_VERIFY_FAILED)
4204/* Missing from OpenSSL 4+ OPENSSL_NO_DEPRECATED_3_0 builds */
4205#ifdef SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED
4206          || (reason == SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED)
4207#endif
4208         )) {
4209        result = CURLE_PEER_FAILED_VERIFICATION;
4210
4211        lerr = SSL_get_verify_result(octx->ssl);
4212        if(lerr != X509_V_OK) {
4213          ssl_config->certverifyresult = lerr;
4214          failf(data, "SSL certificate problem: %s",
4215                X509_verify_cert_error_string(lerr));
4216        }
4217        else
4218          failf(data, "%s", "SSL certificate verification failed");
4219      }
4220#ifdef SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED
4221      /* SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED is only available on
4222         OpenSSL version above v1.1.1, not AWS-LC, BoringSSL, or LibreSSL */
4223      else if((lib == ERR_LIB_SSL) &&
4224              (reason == SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED)) {
4225        /* If client certificate is required, communicate the
4226           error to client */
4227        result = CURLE_SSL_CLIENTCERT;
4228        failf(data, "TLS cert problem: %s",
4229              ossl_strerror(errdetail, error_buffer, sizeof(error_buffer)));
4230      }
4231#endif
4232#ifdef HAVE_SSL_SET1_ECH_CONFIG_LIST
4233      else if((lib == ERR_LIB_SSL) &&
4234#ifndef HAVE_BORINGSSL_LIKE
4235              (reason == SSL_R_ECH_REQUIRED)) {
4236#else
4237              (reason == SSL_R_ECH_REJECTED)) {
4238#endif /* HAVE_BORINGSSL_LIKE */
4239
4240        /* trace retry_configs if we got some */
4241        ossl_trace_ech_retry_configs(data, octx->ssl, reason);
4242
4243        result = CURLE_ECH_REQUIRED;
4244        failf(data, "ECH required: %s",
4245              ossl_strerror(errdetail, error_buffer, sizeof(error_buffer)));
4246      }
4247#endif
4248      else {
4249        result = CURLE_SSL_CONNECT_ERROR;
4250        failf(data, "TLS connect error: %s",
4251              ossl_strerror(errdetail, error_buffer, sizeof(error_buffer)));
4252      }
4253
4254      /* detail is already set to the SSL error above */
4255
4256      /* If we e.g. use SSLv2 request-method and the server does not like us
4257       * (RST connection, etc.), OpenSSL gives no explanation whatsoever and
4258       * the SO_ERROR is also lost.
4259       */
4260      if(result == CURLE_SSL_CONNECT_ERROR && errdetail == 0) {
4261        char extramsg[80] = "";
4262        int sockerr = SOCKERRNO;
4263
4264        if(sockerr && detail == SSL_ERROR_SYSCALL)
4265          curlx_strerror(sockerr, extramsg, sizeof(extramsg));
4266        failf(data, OSSL_PACKAGE " SSL_connect: %s in connection to %s:%d ",
4267              extramsg[0] ? extramsg : SSL_ERROR_to_str(detail),
4268              connssl->peer.dest->hostname, connssl->peer.dest->port);
4269      }
4270
4271      return result;
4272    }
4273  }
4274  else {
4275    /* we connected fine, we are not waiting for anything else. */
4276    connssl->connecting_state = ssl_connect_3;
4277    Curl_ossl_report_handshake(data, octx);
4278
4279#if defined(HAVE_SSL_SET1_ECH_CONFIG_LIST) && !defined(HAVE_BORINGSSL_LIKE)
4280    if(CURLECH_ENABLED(data)) {
4281      char *inner = NULL, *outer = NULL;
4282      int rv;
4283      VERBOSE(const char *status);
4284
4285      rv = SSL_ech_get1_status(octx->ssl, &inner, &outer);
4286      switch(rv) {
4287      case SSL_ECH_STATUS_SUCCESS:
4288        VERBOSE(status = "succeeded");
4289        break;
4290      case SSL_ECH_STATUS_GREASE_ECH:
4291        VERBOSE(status = "sent GREASE, got retry-configs");
4292        break;
4293      case SSL_ECH_STATUS_GREASE:
4294        VERBOSE(status = "sent GREASE");
4295        break;
4296      case SSL_ECH_STATUS_NOT_TRIED:
4297        VERBOSE(status = "not attempted");
4298        break;
4299      case SSL_ECH_STATUS_NOT_CONFIGURED:
4300        VERBOSE(status = "not configured");
4301        break;
4302      case SSL_ECH_STATUS_BACKEND:
4303        VERBOSE(status = "backend (unexpected)");
4304        break;
4305      case SSL_ECH_STATUS_FAILED:
4306        VERBOSE(status = "failed");
4307        break;
4308      case SSL_ECH_STATUS_BAD_CALL:
4309        VERBOSE(status = "bad call (unexpected)");
4310        break;
4311      case SSL_ECH_STATUS_BAD_NAME: {
4312        struct ssl_primary_config *conn_config =
4313          Curl_ssl_cf_get_primary_config(cf);
4314        if(!conn_config->verifypeer && !conn_config->verifyhost &&
4315           inner && !strcmp(inner, connssl->peer.dest->hostname)) {
4316          VERBOSE(status = "bad name (tolerated without peer verification)");
4317          rv = SSL_ECH_STATUS_SUCCESS;
4318        }
4319        else {
4320          VERBOSE(status = "bad name (unexpected)");
4321        }
4322        break;
4323      }
4324      default:
4325        VERBOSE(status = "unexpected status");
4326        infof(data, "ECH: unexpected status %d", rv);
4327      }
4328      infof(data, "ECH: result: status is %s, inner is %s, outer is %s",
4329            (status ? status : "NULL"),
4330            (inner ? inner : "NULL"),
4331            (outer ? outer : "NULL"));
4332      OPENSSL_free(inner);
4333      OPENSSL_free(outer);
4334      if(rv == SSL_ECH_STATUS_GREASE_ECH) {
4335        /* trace retry_configs if we got some */
4336        ossl_trace_ech_retry_configs(data, octx->ssl, 0);
4337      }
4338      if(rv != SSL_ECH_STATUS_SUCCESS && (data->set.tls_ech == CURLECH_HARD)) {
4339        infof(data, "ECH: ech-hard failed");
4340        return CURLE_SSL_CONNECT_ERROR;
4341      }
4342    }
4343    else {
4344      infof(data, "ECH: result: status is not attempted");
4345    }
4346#endif /* HAVE_SSL_SET1_ECH_CONFIG_LIST && !HAVE_BORINGSSL_LIKE */
4347
4348    /* Sets data and len to negotiated protocol, len is 0 if no protocol was
4349     * negotiated
4350     */
4351    if(connssl->alpn) {
4352      const unsigned char *neg_protocol;
4353      unsigned int len;
4354      SSL_get0_alpn_selected(octx->ssl, &neg_protocol, &len);
4355
4356      return Curl_alpn_set_negotiated(cf, data, connssl, neg_protocol, len);
4357    }
4358
4359    return CURLE_OK;
4360  }
4361}
4362
4363/*
4364 * Heavily modified from:
4365 * https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning#OpenSSL
4366 */
4367static CURLcode ossl_pkp_pin_peer_pubkey(struct Curl_easy *data, X509 *cert,
4368                                         const char *pinnedpubkey)
4369{
4370  /* Scratch */
4371  int len1 = 0, len2 = 0;
4372  unsigned char *buff1 = NULL, *temp = NULL;
4373
4374  /* Result is returned to caller */
4375  CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
4376
4377  /* if a path was not specified, do not pin */
4378  if(!pinnedpubkey)
4379    return CURLE_OK;
4380
4381  if(!cert)
4382    return result;
4383
4384  do {
4385    /* Get the subjectPublicKeyInfo */
4386    /* https://groups.google.com/group/mailing.openssl.users/browse_thread/thread/d61858dae102c6c7 */
4387    len1 = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(cert), NULL);
4388    if(len1 < 1)
4389      break; /* failed */
4390
4391    buff1 = temp = curlx_malloc(len1);
4392    if(!buff1)
4393      break; /* failed */
4394
4395    /* https://docs.openssl.org/master/man3/d2i_X509/ */
4396    len2 = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(cert), &temp);
4397
4398    /*
4399     * These checks are verifying we got back the same values as when we
4400     * sized the buffer. it is pretty weak since they should always be the
4401     * same, but it gives us something to test.
4402     */
4403    if((len1 != len2) || !temp || ((temp - buff1) != len1))
4404      break; /* failed */
4405
4406    /* End Gyrations */
4407
4408    /* The one good exit point */
4409    result = Curl_pin_peer_pubkey(data, pinnedpubkey, buff1, len1);
4410  } while(0);
4411
4412  if(buff1)
4413    curlx_free(buff1);
4414
4415  return result;
4416}
4417
4418#ifdef CURLVERBOSE
4419#if !defined(HAVE_BORINGSSL_LIKE) && \
4420  !(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x3060000fL)
4421static void infof_certstack(struct Curl_easy *data, const SSL *ssl)
4422{
4423  STACK_OF(X509) *certstack;
4424  long verify_result;
4425  int num_cert_levels;
4426  int cert_level;
4427
4428  if(!Curl_trc_is_verbose(data))
4429    return;
4430
4431  verify_result = SSL_get_verify_result(ssl);
4432  if(verify_result != X509_V_OK)
4433    certstack = SSL_get_peer_cert_chain(ssl);
4434  else
4435    certstack = SSL_get0_verified_chain(ssl);
4436  if(!certstack)
4437    return;
4438  num_cert_levels = sk_X509_num(certstack);
4439
4440  for(cert_level = 0; cert_level < num_cert_levels; cert_level++) {
4441    char cert_algorithm[80] = "";
4442    char group_name_final[80] = "";
4443    const X509_ALGOR *palg_cert = NULL;
4444    const ASN1_OBJECT *paobj_cert = NULL;
4445    X509 *current_cert;
4446    EVP_PKEY *current_pkey;
4447    int key_bits;
4448    int key_sec_bits;
4449    int get_group_name;
4450    const char *type_name;
4451
4452    current_cert = sk_X509_value(certstack, cert_level);
4453    if(!current_cert)
4454      continue;
4455
4456    current_pkey = X509_get0_pubkey(current_cert);
4457    if(!current_pkey)
4458      continue;
4459
4460    X509_get0_signature(NULL, &palg_cert, current_cert);
4461    X509_ALGOR_get0(&paobj_cert, NULL, NULL, palg_cert);
4462    OBJ_obj2txt(cert_algorithm, sizeof(cert_algorithm), paobj_cert, 0);
4463
4464    key_bits = EVP_PKEY_bits(current_pkey);
4465#ifndef HAVE_OPENSSL3
4466#define EVP_PKEY_get_security_bits EVP_PKEY_security_bits
4467#endif
4468    key_sec_bits = EVP_PKEY_get_security_bits(current_pkey);
4469#ifdef HAVE_OPENSSL3
4470    {
4471      char group_name[80] = "";
4472      get_group_name = EVP_PKEY_get_group_name(current_pkey, group_name,
4473                                               sizeof(group_name), NULL);
4474      curl_msnprintf(group_name_final, sizeof(group_name_final), "/%s",
4475                     group_name);
4476    }
4477    type_name = EVP_PKEY_get0_type_name(current_pkey);
4478#else
4479    get_group_name = 0;
4480    type_name = NULL;
4481#endif
4482
4483    infof(data, "  Certificate level %d: "
4484          "Public key type %s%s (%d/%d Bits/secBits), signed using %s",
4485          cert_level, type_name ? type_name : "?",
4486          get_group_name == 0 ? "" : group_name_final,
4487          key_bits, key_sec_bits, cert_algorithm);
4488  }
4489}
4490#else
4491#define infof_certstack(data, ssl)
4492#endif
4493#endif /* CURLVERBOSE */
4494
4495static CURLcode ossl_check_issuer(struct Curl_cfilter *cf,
4496                                  struct Curl_easy *data,
4497                                  X509 *server_cert)
4498{
4499  struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
4500  X509 *issuer = NULL;
4501  BIO *fp = NULL;
4502  char err_buf[256] = "";
4503  bool verify_enabled = (conn_config->verifypeer || conn_config->verifyhost);
4504  CURLcode result = CURLE_OK;
4505
4506  /* e.g. match issuer name with provided issuer certificate */
4507  if(conn_config->issuercert_blob) {
4508    fp = BIO_new_mem_buf(conn_config->issuercert_blob->data,
4509                         (int)conn_config->issuercert_blob->len);
4510    if(!fp) {
4511      failf(data, "BIO_new_mem_buf NULL, " OSSL_PACKAGE " error %s",
4512            ossl_strerror(ERR_get_error(), err_buf, sizeof(err_buf)));
4513      result = CURLE_OUT_OF_MEMORY;
4514      goto out;
4515    }
4516  }
4517  else if(conn_config->issuercert) {
4518    fp = BIO_new(BIO_s_file());
4519    if(!fp) {
4520      failf(data, "BIO_new return NULL, " OSSL_PACKAGE " error %s",
4521            ossl_strerror(ERR_get_error(), err_buf, sizeof(err_buf)));
4522      result = CURLE_OUT_OF_MEMORY;
4523      goto out;
4524    }
4525
4526    if(BIO_read_filename(fp, conn_config->issuercert) <= 0) {
4527      if(verify_enabled)
4528        failf(data, "SSL: Unable to open issuer cert (%s)",
4529              conn_config->issuercert);
4530      result = CURLE_SSL_ISSUER_ERROR;
4531      goto out;
4532    }
4533  }
4534
4535  if(fp) {
4536    issuer = PEM_read_bio_X509(fp, NULL, ZERO_NULL, NULL);
4537    if(!issuer) {
4538      if(verify_enabled)
4539        failf(data, "SSL: Unable to read issuer cert (%s)",
4540              conn_config->issuercert);
4541      result = CURLE_SSL_ISSUER_ERROR;
4542      goto out;
4543    }
4544
4545    if(X509_check_issued(issuer, server_cert) != X509_V_OK) {
4546      if(verify_enabled)
4547        failf(data, "SSL: Certificate issuer check failed (%s)",
4548              conn_config->issuercert);
4549      result = CURLE_SSL_ISSUER_ERROR;
4550      goto out;
4551    }
4552
4553    infof(data, " SSL certificate issuer check ok (%s)",
4554          conn_config->issuercert);
4555  }
4556
4557out:
4558  if(fp)
4559    BIO_free(fp);
4560  if(issuer)
4561    X509_free(issuer);
4562  return result;
4563}
4564
4565static CURLcode ossl_check_pinned_key(struct Curl_cfilter *cf,
4566                                      struct Curl_easy *data,
4567                                      X509 *server_cert)
4568{
4569  const char *ptr;
4570  CURLcode result = CURLE_OK;
4571
4572  (void)cf;
4573#ifndef CURL_DISABLE_PROXY
4574  ptr = Curl_ssl_cf_is_proxy(cf) ?
4575    data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
4576    data->set.str[STRING_SSL_PINNEDPUBLICKEY];
4577#else
4578  ptr = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
4579#endif
4580  if(ptr) {
4581    result = ossl_pkp_pin_peer_pubkey(data, server_cert, ptr);
4582    if(result)
4583      failf(data, "SSL: public key does not match pinned public key");
4584  }
4585  return result;
4586}
4587
4588#ifdef CURLVERBOSE
4589#define MAX_CERT_NAME_LENGTH 2048
4590static CURLcode ossl_infof_cert(struct Curl_cfilter *cf,
4591                                struct Curl_easy *data,
4592                                X509 *server_cert)
4593{
4594  BIO *mem = NULL;
4595  struct dynbuf dname;
4596  char err_buf[256] = "";
4597  char *buf;
4598  long len;
4599  CURLcode result = CURLE_OK;
4600
4601  if(!Curl_trc_is_verbose(data))
4602    return CURLE_OK;
4603
4604  curlx_dyn_init(&dname, MAX_CERT_NAME_LENGTH);
4605  mem = BIO_new(BIO_s_mem());
4606  if(!mem) {
4607    failf(data, "BIO_new return NULL, " OSSL_PACKAGE " error %s",
4608          ossl_strerror(ERR_get_error(), err_buf, sizeof(err_buf)));
4609    result = CURLE_OUT_OF_MEMORY;
4610    goto out;
4611  }
4612
4613  infof(data, "%s certificate:", Curl_ssl_cf_is_proxy(cf) ?
4614        "Proxy" : "Server");
4615
4616  result = x509_name_oneline(X509_get_subject_name(server_cert), &dname);
4617  infof(data, "  subject: %s", result ? "[NONE]" : curlx_dyn_ptr(&dname));
4618
4619  ASN1_TIME_print(mem, X509_get0_notBefore(server_cert));
4620  len = BIO_get_mem_data(mem, (char **)&buf);
4621  infof(data, "  start date: %.*s", (int)len, buf);
4622  (void)BIO_reset(mem);
4623
4624  ASN1_TIME_print(mem, X509_get0_notAfter(server_cert));
4625  len = BIO_get_mem_data(mem, (char **)&buf);
4626  infof(data, "  expire date: %.*s", (int)len, buf);
4627  (void)BIO_reset(mem);
4628
4629  result = x509_name_oneline(X509_get_issuer_name(server_cert), &dname);
4630  if(result) /* should be only fatal stuff like OOM */
4631    goto out;
4632  infof(data, "  issuer: %s", curlx_dyn_ptr(&dname));
4633
4634out:
4635  BIO_free(mem);
4636  curlx_dyn_free(&dname);
4637  return result;
4638}
4639#endif /* CURLVERBOSE */
4640
4641#ifdef USE_APPLE_SECTRUST
4642struct ossl_certs_ctx {
4643  STACK_OF(X509) *sk;
4644  size_t num_certs;
4645};
4646
4647static CURLcode ossl_chain_get_der(struct Curl_cfilter *cf,
4648                                   struct Curl_easy *data,
4649                                   void *user_data,
4650                                   size_t i,
4651                                   unsigned char **pder,
4652                                   size_t *pder_len)
4653{
4654  struct ossl_certs_ctx *chain = user_data;
4655  X509 *cert;
4656  int der_len;
4657
4658  (void)cf;
4659  (void)data;
4660  *pder_len = 0;
4661  *pder = NULL;
4662
4663  if(i >= chain->num_certs)
4664    return CURLE_TOO_LARGE;
4665  cert = sk_X509_value(chain->sk, (int)i);
4666  if(!cert)
4667    return CURLE_FAILED_INIT;
4668  der_len = i2d_X509(cert, pder);
4669  if(der_len < 0)
4670    return CURLE_FAILED_INIT;
4671  *pder_len = (size_t)der_len;
4672  return CURLE_OK;
4673}
4674
4675static CURLcode ossl_apple_verify(struct Curl_cfilter *cf,
4676                                  struct Curl_easy *data,
4677                                  struct ossl_ctx *octx,
4678                                  struct ssl_peer *peer,
4679                                  bool *pverified)
4680{
4681  struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
4682  struct ossl_certs_ctx chain;
4683  CURLcode result;
4684
4685  memset(&chain, 0, sizeof(chain));
4686  chain.sk = SSL_get_peer_cert_chain(octx->ssl);
4687  chain.num_certs = chain.sk ? sk_X509_num(chain.sk) : 0;
4688
4689  if(!chain.num_certs &&
4690     (conn_config->verifypeer || conn_config->verifyhost)) {
4691    if(!octx->reused_session) {
4692      failf(data, "SSL: could not get peer certificate chain");
4693      result = CURLE_PEER_FAILED_VERIFICATION;
4694    }
4695    else {
4696      /* when session was reused, there is no peer cert chain */
4697      *pverified = FALSE;
4698      return CURLE_OK;
4699    }
4700  }
4701  else {
4702#ifdef HAVE_BORINGSSL_LIKE
4703    const uint8_t *ocsp_data = NULL;
4704#else
4705    unsigned char *ocsp_data = NULL;
4706#endif
4707    long ocsp_len = 0;
4708    bool ocsp_missing = FALSE;
4709    if(conn_config->verifystatus && !octx->reused_session)
4710      ocsp_len = (long)SSL_get_tlsext_status_ocsp_resp(octx->ssl, &ocsp_data);
4711
4712    /* SSL_get_tlsext_status_ocsp_resp() returns the length of the OCSP
4713       response data or -1 if there is no OCSP response data. */
4714    if(ocsp_len < 0) {
4715      ocsp_len = 0; /* no data available */
4716      ocsp_missing = TRUE;
4717    }
4718    result = Curl_vtls_apple_verify(cf, data, peer, chain.num_certs,
4719                                    ossl_chain_get_der, &chain,
4720                                    ocsp_data, ocsp_len);
4721    if(!result && ocsp_missing && conn_config->verifystatus &&
4722       !octx->reused_session) {
4723      /* verified, but OCSP stapling is required and server sent none */
4724      *pverified = TRUE;
4725      failf(data, "No OCSP response received");
4726      return CURLE_SSL_INVALIDCERTSTATUS;
4727    }
4728  }
4729  *pverified = !result;
4730  return result;
4731}
4732#endif /* USE_APPLE_SECTRUST */
4733
4734CURLcode Curl_ossl_check_peer_cert(struct Curl_cfilter *cf,
4735                                   struct Curl_easy *data,
4736                                   struct ossl_ctx *octx,
4737                                   struct ssl_peer *peer)
4738{
4739  struct connectdata *conn = cf->conn;
4740  struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
4741  struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
4742  CURLcode result = CURLE_OK;
4743  long ossl_verify;
4744  X509 *server_cert;
4745  bool verified = FALSE;
4746#if !defined(OPENSSL_NO_OCSP) && defined(USE_APPLE_SECTRUST)
4747  bool sectrust_verified = FALSE;
4748#endif
4749
4750  if(data->set.ssl.certinfo && !octx->reused_session) {
4751    /* asked to gather certificate info. Reused sessions do not have cert
4752       chains */
4753    result = ossl_certchain(data, octx->ssl);
4754    if(result)
4755      return result;
4756  }
4757
4758  server_cert = SSL_get1_peer_certificate(octx->ssl);
4759  if(!server_cert) {
4760    /* no verification at all, this maybe acceptable */
4761    if(!(conn_config->verifypeer || conn_config->verifyhost))
4762      goto out;
4763
4764    failf(data, "SSL: could not get peer certificate");
4765    result = CURLE_PEER_FAILED_VERIFICATION;
4766    goto out;
4767  }
4768
4769#ifdef CURLVERBOSE
4770  result = ossl_infof_cert(cf, data, server_cert);
4771  if(result)
4772    goto out;
4773  infof_certstack(data, octx->ssl);
4774#endif
4775
4776  if(conn_config->verifyhost) {
4777    result = ossl_verifyhost(data, conn, peer, server_cert);
4778    if(result)
4779      goto out;
4780  }
4781  /* `verifyhost` is either OK or not requested from here on */
4782
4783  ossl_verify = SSL_get_verify_result(octx->ssl);
4784  ssl_config->certverifyresult = ossl_verify;
4785  infof(data, "OpenSSL verify result: %lx", ossl_verify);
4786
4787  verified = (ossl_verify == X509_V_OK);
4788  if(verified)
4789    infof(data, "SSL certificate verified via OpenSSL.");
4790
4791#ifdef USE_APPLE_SECTRUST
4792  if(!verified && conn_config->verifypeer && ssl_config->native_ca_store) {
4793    /* we verify using Apple SecTrust *unless* OpenSSL already verified.
4794     * This may happen if the application intercepted the OpenSSL callback
4795     * and installed its own. */
4796    result = ossl_apple_verify(cf, data, octx, peer, &verified);
4797    if(result && (result != CURLE_PEER_FAILED_VERIFICATION))
4798      goto out; /* unexpected error */
4799    if(verified) {
4800      infof(data, "SSL certificate verified via Apple SecTrust.");
4801      ssl_config->certverifyresult = X509_V_OK;
4802#ifndef OPENSSL_NO_OCSP
4803      sectrust_verified = TRUE;
4804#endif
4805    }
4806  }
4807#endif
4808
4809  if(!verified) {
4810    /* no trust established, report the OpenSSL status */
4811    if(conn_config->verifypeer) {
4812      failf(data, "SSL certificate OpenSSL verify result: %s (%ld)",
4813            X509_verify_cert_error_string(ossl_verify), ossl_verify);
4814      result = CURLE_PEER_FAILED_VERIFICATION;
4815      goto out;
4816    }
4817    infof(data, " SSL certificate verification failed, continuing anyway!");
4818  }
4819
4820#ifndef OPENSSL_NO_OCSP
4821  if(conn_config->verifystatus &&
4822#ifdef USE_APPLE_SECTRUST
4823     !sectrust_verified && /* already verified via apple sectrust, cannot
4824                            * verifystate via OpenSSL in that case as it
4825                            * does not have the trust anchors */
4826#endif
4827     !octx->reused_session) {
4828    /* do not do this after Session ID reuse */
4829    result = verifystatus(cf, data, octx);
4830    if(result)
4831      goto out;
4832  }
4833#endif
4834
4835  result = ossl_check_issuer(cf, data, server_cert);
4836  if(result)
4837    goto out;
4838
4839  result = ossl_check_pinned_key(cf, data, server_cert);
4840
4841out:
4842  X509_free(server_cert);
4843  return result;
4844}
4845
4846static CURLcode ossl_connect_step3(struct Curl_cfilter *cf,
4847                                   struct Curl_easy *data)
4848{
4849  CURLcode result = CURLE_OK;
4850  struct ssl_connect_data *connssl = cf->ctx;
4851  struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
4852
4853  DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
4854
4855  /*
4856   * We check certificates to authenticate the server; otherwise we risk
4857   * man-in-the-middle attack; NEVERTHELESS, if we are told explicitly not to
4858   * verify the peer, ignore faults and failures from the server cert
4859   * operations.
4860   */
4861
4862  result = Curl_ossl_check_peer_cert(cf, data, octx, &connssl->peer);
4863  if(result)
4864    /* on error, remove sessions we might have in the pool */
4865    Curl_ssl_scache_remove_all(cf, data, connssl->peer.scache_key);
4866
4867  return result;
4868}
4869
4870#ifdef HAVE_OPENSSL_EARLYDATA
4871static CURLcode ossl_send_earlydata(struct Curl_cfilter *cf,
4872                                    struct Curl_easy *data)
4873{
4874  struct ssl_connect_data *connssl = cf->ctx;
4875  struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
4876  CURLcode result = CURLE_OK;
4877  const unsigned char *buf;
4878  size_t blen, nwritten;
4879  int rc;
4880
4881  DEBUGASSERT(connssl->earlydata_state == ssl_earlydata_sending);
4882  octx->io_result = CURLE_OK;
4883  while(Curl_bufq_peek(&connssl->earlydata, &buf, &blen)) {
4884    nwritten = 0;
4885    rc = SSL_write_early_data(octx->ssl, buf, blen, &nwritten);
4886    CURL_TRC_CF(data, cf, "SSL_write_early_data(len=%zu) -> %d, %zu",
4887                blen, rc, nwritten);
4888    if(rc <= 0) {
4889      long sslerror;
4890      char error_buffer[256];
4891      int err = SSL_get_error(octx->ssl, rc);
4892
4893      switch(err) {
4894      case SSL_ERROR_WANT_READ:
4895        connssl->io_need = CURL_SSL_IO_NEED_RECV;
4896        result = CURLE_AGAIN;
4897        goto out;
4898      case SSL_ERROR_WANT_WRITE:
4899        connssl->io_need = CURL_SSL_IO_NEED_SEND;
4900        result = CURLE_AGAIN;
4901        goto out;
4902      case SSL_ERROR_SYSCALL: {
4903        int sockerr = SOCKERRNO;
4904
4905        if(octx->io_result == CURLE_AGAIN) {
4906          result = CURLE_AGAIN;
4907          goto out;
4908        }
4909        sslerror = ERR_get_error();
4910        if(sslerror)
4911          ossl_strerror(sslerror, error_buffer, sizeof(error_buffer));
4912        else if(sockerr)
4913          curlx_strerror(sockerr, error_buffer, sizeof(error_buffer));
4914        else
4915          curl_msnprintf(error_buffer, sizeof(error_buffer), "%s",
4916                         SSL_ERROR_to_str(err));
4917
4918        failf(data, OSSL_PACKAGE " SSL_write:early_data: %s, errno %d",
4919              error_buffer, sockerr);
4920        result = CURLE_SEND_ERROR;
4921        goto out;
4922      }
4923      case SSL_ERROR_SSL: {
4924        /*  A failure in the SSL library occurred, usually a protocol error.
4925            The OpenSSL error queue contains more information on the error. */
4926        sslerror = ERR_get_error();
4927        failf(data, "SSL_write_early_data() error: %s",
4928              ossl_strerror(sslerror, error_buffer, sizeof(error_buffer)));
4929        result = CURLE_SEND_ERROR;
4930        goto out;
4931      }
4932      default:
4933        /* a true error */
4934        failf(data, OSSL_PACKAGE " SSL_write_early_data: %s, errno %d",
4935              SSL_ERROR_to_str(err), SOCKERRNO);
4936        result = CURLE_SEND_ERROR;
4937        goto out;
4938      }
4939    }
4940    Curl_bufq_skip(&connssl->earlydata, nwritten);
4941  }
4942  /* sent everything there was */
4943  infof(data, "SSL sending %zu bytes of early data", connssl->earlydata_skip);
4944out:
4945  return result;
4946}
4947#endif /* HAVE_OPENSSL_EARLYDATA */
4948
4949static CURLcode ossl_connect(struct Curl_cfilter *cf,
4950                             struct Curl_easy *data,
4951                             bool *done)
4952{
4953  CURLcode result = CURLE_OK;
4954  struct ssl_connect_data *connssl = cf->ctx;
4955
4956  /* check if the connection has already been established */
4957  if(ssl_connection_complete == connssl->state) {
4958    *done = TRUE;
4959    return CURLE_OK;
4960  }
4961
4962  *done = FALSE;
4963  connssl->io_need = CURL_SSL_IO_NEED_NONE;
4964
4965  if(ssl_connect_1 == connssl->connecting_state) {
4966    if(Curl_ossl_need_httpsrr(data) &&
4967       !Curl_conn_dns_resolved_https(data, cf->sockindex)) {
4968      CURL_TRC_CF(data, cf, "need HTTPS-RR, delaying connect");
4969      return CURLE_OK;
4970    }
4971    CURL_TRC_CF(data, cf, "ossl_connect, step1");
4972    result = ossl_connect_step1(cf, data);
4973    if(result)
4974      goto out;
4975  }
4976
4977  if(ssl_connect_2 == connssl->connecting_state) {
4978    CURL_TRC_CF(data, cf, "ossl_connect, step2");
4979#ifdef HAVE_OPENSSL_EARLYDATA
4980    if(connssl->earlydata_state == ssl_earlydata_await) {
4981      goto out;
4982    }
4983    else if(connssl->earlydata_state == ssl_earlydata_sending) {
4984      result = ossl_send_earlydata(cf, data);
4985      if(result)
4986        goto out;
4987      connssl->earlydata_state = ssl_earlydata_sent;
4988    }
4989#endif
4990    DEBUGASSERT((connssl->earlydata_state == ssl_earlydata_none) ||
4991                (connssl->earlydata_state == ssl_earlydata_sent));
4992
4993    result = ossl_connect_step2(cf, data);
4994    if(result)
4995      goto out;
4996  }
4997
4998  if(ssl_connect_3 == connssl->connecting_state) {
4999    CURL_TRC_CF(data, cf, "ossl_connect, step3");
5000    result = ossl_connect_step3(cf, data);
5001    if(result)
5002      goto out;
5003    connssl->connecting_state = ssl_connect_done;
5004#ifdef HAVE_OPENSSL_EARLYDATA
5005    if(connssl->earlydata_state > ssl_earlydata_none) {
5006      struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
5007      /* We should be in this state by now */
5008      DEBUGASSERT(connssl->earlydata_state == ssl_earlydata_sent);
5009      connssl->earlydata_state =
5010        (SSL_get_early_data_status(octx->ssl) == SSL_EARLY_DATA_ACCEPTED) ?
5011        ssl_earlydata_accepted : ssl_earlydata_rejected;
5012    }
5013#endif
5014  }
5015
5016  if(ssl_connect_done == connssl->connecting_state) {
5017    CURL_TRC_CF(data, cf, "ossl_connect, done");
5018    connssl->state = ssl_connection_complete;
5019  }
5020
5021out:
5022  if(result == CURLE_AGAIN) {
5023    *done = FALSE;
5024    return CURLE_OK;
5025  }
5026  *done = ((connssl->state == ssl_connection_complete) ||
5027           (connssl->state == ssl_connection_deferred));
5028  return result;
5029}
5030
5031static bool ossl_data_pending(struct Curl_cfilter *cf,
5032                              const struct Curl_easy *data)
5033{
5034  struct ssl_connect_data *connssl = cf->ctx;
5035  (void)data;
5036  return (bool)connssl->input_pending;
5037}
5038
5039static CURLcode ossl_send(struct Curl_cfilter *cf,
5040                          struct Curl_easy *data,
5041                          const void *mem,
5042                          size_t len,
5043                          size_t *pnwritten)
5044{
5045  /* SSL_write() is said to return 'int' while write() and send() returns
5046     'size_t' */
5047  int err;
5048  char error_buffer[256];
5049  sslerr_t sslerror;
5050  int memlen;
5051  struct ssl_connect_data *connssl = cf->ctx;
5052  struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
5053  CURLcode result = CURLE_OK;
5054  int nwritten;
5055
5056  DEBUGASSERT(octx);
5057  *pnwritten = 0;
5058  ERR_clear_error();
5059
5060  connssl->io_need = CURL_SSL_IO_NEED_NONE;
5061  memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
5062  if(octx->blocked_ssl_write_len && (octx->blocked_ssl_write_len != memlen)) {
5063    /* The previous SSL_write() call was blocked, using that length.
5064     * We need to use that again or OpenSSL freaks out. A shorter
5065     * length should not happen and is a bug in libcurl. */
5066    if(octx->blocked_ssl_write_len > memlen) {
5067      DEBUGASSERT(0);
5068      return CURLE_BAD_FUNCTION_ARGUMENT;
5069    }
5070    memlen = octx->blocked_ssl_write_len;
5071  }
5072  octx->blocked_ssl_write_len = 0;
5073  nwritten = SSL_write(octx->ssl, mem, memlen);
5074
5075  if(nwritten > 0)
5076    *pnwritten = (size_t)nwritten;
5077  else {
5078    err = SSL_get_error(octx->ssl, nwritten);
5079
5080    switch(err) {
5081    case SSL_ERROR_WANT_READ:
5082      connssl->io_need = CURL_SSL_IO_NEED_RECV;
5083      octx->blocked_ssl_write_len = memlen;
5084      result = CURLE_AGAIN;
5085      goto out;
5086    case SSL_ERROR_WANT_WRITE:
5087      result = CURLE_AGAIN;
5088      octx->blocked_ssl_write_len = memlen;
5089      goto out;
5090    case SSL_ERROR_SYSCALL: {
5091      int sockerr = SOCKERRNO;
5092
5093      if(octx->io_result == CURLE_AGAIN) {
5094        octx->blocked_ssl_write_len = memlen;
5095        result = CURLE_AGAIN;
5096        goto out;
5097      }
5098      sslerror = ERR_get_error();
5099      if(sslerror)
5100        ossl_strerror(sslerror, error_buffer, sizeof(error_buffer));
5101      else if(sockerr)
5102        curlx_strerror(sockerr, error_buffer, sizeof(error_buffer));
5103      else
5104        curl_msnprintf(error_buffer, sizeof(error_buffer), "%s",
5105                       SSL_ERROR_to_str(err));
5106
5107      failf(data, OSSL_PACKAGE " SSL_write: %s, errno %d",
5108            error_buffer, sockerr);
5109      result = CURLE_SEND_ERROR;
5110      goto out;
5111    }
5112    case SSL_ERROR_SSL: {
5113      /*  A failure in the SSL library occurred, usually a protocol error.
5114          The OpenSSL error queue contains more information on the error. */
5115      sslerror = ERR_get_error();
5116      failf(data, "SSL_write() error: %s",
5117            ossl_strerror(sslerror, error_buffer, sizeof(error_buffer)));
5118      result = CURLE_SEND_ERROR;
5119      goto out;
5120    }
5121    default:
5122      /* a true error */
5123      failf(data, OSSL_PACKAGE " SSL_write: %s, errno %d",
5124            SSL_ERROR_to_str(err), SOCKERRNO);
5125      result = CURLE_SEND_ERROR;
5126      goto out;
5127    }
5128  }
5129
5130out:
5131  return result;
5132}
5133
5134static CURLcode ossl_recv(struct Curl_cfilter *cf,
5135                          struct Curl_easy *data,   /* transfer */
5136                          char *buf,                /* store read data here */
5137                          size_t buffersize,        /* max amount to read */
5138                          size_t *pnread)
5139{
5140  char error_buffer[256];
5141  unsigned long sslerror;
5142  int buffsize;
5143  struct ssl_connect_data *connssl = cf->ctx;
5144  struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
5145  CURLcode result = CURLE_OK;
5146  int nread;
5147
5148  DEBUGASSERT(octx);
5149
5150  *pnread = 0;
5151  ERR_clear_error();
5152
5153  connssl->io_need = CURL_SSL_IO_NEED_NONE;
5154  buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
5155  nread = SSL_read(octx->ssl, buf, buffsize);
5156
5157  if(nread > 0)
5158    *pnread = (size_t)nread;
5159  else {
5160    /* failed SSL_read */
5161    int err = SSL_get_error(octx->ssl, nread);
5162
5163    switch(err) {
5164    case SSL_ERROR_NONE: /* this is not an error */
5165      break;
5166    case SSL_ERROR_ZERO_RETURN: /* no more data */
5167      /* close_notify alert */
5168      if(cf->sockindex == FIRSTSOCKET)
5169        /* mark the connection for close if it is indeed the control
5170           connection */
5171        CURL_TRC_CF(data, cf, "TLS close_notify");
5172      break;
5173    case SSL_ERROR_WANT_READ:
5174      connssl->io_need = CURL_SSL_IO_NEED_RECV;
5175      result = CURLE_AGAIN;
5176      goto out;
5177    case SSL_ERROR_WANT_WRITE:
5178      connssl->io_need = CURL_SSL_IO_NEED_SEND;
5179      result = CURLE_AGAIN;
5180      goto out;
5181    default:
5182      /* openssl/ssl.h for SSL_ERROR_SYSCALL says "look at error stack/return
5183         value/errno" */
5184      /* https://docs.openssl.org/master/man3/ERR_get_error/ */
5185      if(octx->io_result == CURLE_AGAIN) {
5186        result = CURLE_AGAIN;
5187        goto out;
5188      }
5189      sslerror = ERR_get_error();
5190      if((nread < 0) || sslerror) {
5191        /* If the return code was negative or there actually is an error in the
5192           queue */
5193        int sockerr = SOCKERRNO;
5194        if(sslerror)
5195          ossl_strerror(sslerror, error_buffer, sizeof(error_buffer));
5196        else if(sockerr && err == SSL_ERROR_SYSCALL)
5197          curlx_strerror(sockerr, error_buffer, sizeof(error_buffer));
5198        else
5199          curl_msnprintf(error_buffer, sizeof(error_buffer), "%s",
5200                         SSL_ERROR_to_str(err));
5201        failf(data, OSSL_PACKAGE " SSL_read: %s, errno %d",
5202              error_buffer, sockerr);
5203        result = CURLE_RECV_ERROR;
5204        goto out;
5205      }
5206      else if(err == SSL_ERROR_SYSCALL) {
5207        if(octx->io_result) {
5208          /* logging handling in underlying filter already */
5209          result = octx->io_result;
5210        }
5211        else if(connssl->peer_closed) {
5212          failf(data, "Connection closed abruptly");
5213          result = CURLE_RECV_ERROR;
5214        }
5215        else {
5216          /* We should no longer get here nowadays, but handle
5217           * the error in case of some weirdness in the OSSL stack */
5218          int sockerr = SOCKERRNO;
5219          if(sockerr)
5220            curlx_strerror(sockerr, error_buffer, sizeof(error_buffer));
5221          else {
5222            curl_msnprintf(error_buffer, sizeof(error_buffer),
5223                           "Connection closed abruptly");
5224          }
5225          failf(data, OSSL_PACKAGE " SSL_read: %s, errno %d",
5226                error_buffer, sockerr);
5227          result = CURLE_RECV_ERROR;
5228        }
5229        goto out;
5230      }
5231    }
5232  }
5233
5234out:
5235  if((!result && !*pnread) || (result == CURLE_AGAIN)) {
5236    /* This happens when:
5237     * - we read an EOF
5238     * - OpenSSLs buffers are empty, there is no more data
5239     * - OpenSSL read is blocked on writing something first
5240     * - an incomplete TLS packet is buffered that cannot be read
5241     *   until more data arrives */
5242    connssl->input_pending = FALSE;
5243  }
5244  CURL_TRC_CF(data, cf, "ossl_recv(len=%zu) -> %d, %zu (in_pending=%d)",
5245              buffersize, result, *pnread, connssl->input_pending);
5246  return result;
5247}
5248
5249static CURLcode ossl_get_channel_binding(struct Curl_easy *data,
5250                                         int sockindex,
5251                                         struct dynbuf *binding)
5252{
5253  X509 *cert;
5254  int mdnid;
5255  bool no_digest_acceptable = FALSE;
5256  const EVP_MD *algo_type = NULL;
5257  const char *algo_name = NULL;
5258  unsigned int length;
5259  unsigned char buf[EVP_MAX_MD_SIZE];
5260
5261  const char prefix[] = "tls-server-end-point:";
5262  struct connectdata *conn = data->conn;
5263  struct Curl_cfilter *cf = conn->cfilter[sockindex];
5264  struct ossl_ctx *octx = NULL;
5265  CURLcode result = CURLE_OK;
5266
5267  do {
5268    const struct Curl_cftype *cft = cf->cft;
5269    struct ssl_connect_data *connssl = cf->ctx;
5270
5271    if(cft->name && !strcmp(cft->name, "SSL")) {
5272      octx = (struct ossl_ctx *)connssl->backend;
5273      break;
5274    }
5275
5276    cf = cf->next;
5277  } while(cf);
5278
5279  if(!octx) {
5280    failf(data, "Failed to find the SSL filter");
5281    return CURLE_BAD_FUNCTION_ARGUMENT;
5282  }
5283
5284  cert = SSL_get1_peer_certificate(octx->ssl);
5285  if(!cert)
5286    /* No server certificate, do not do channel binding */
5287    return CURLE_OK;
5288
5289#ifdef HAVE_OPENSSL3
5290  {
5291    int pknid, secbits;
5292    uint32_t flags;
5293    EVP_PKEY *pkey = X509_get0_pubkey(cert);
5294
5295    if(!X509_get_signature_info(cert, &mdnid, &pknid, &secbits, &flags)) {
5296      failf(data, "certificate signature algorithm not recognized");
5297      result = CURLE_SSL_INVALIDCERTSTATUS;
5298      goto out;
5299    }
5300
5301    if(mdnid != NID_undef) {
5302      if(mdnid == NID_md5 || mdnid == NID_sha1) {
5303        algo_type = EVP_sha256();
5304      }
5305      else
5306        algo_type = EVP_get_digestbynid(mdnid);
5307    }
5308    else if(pkey && !EVP_PKEY_is_a(pkey, OBJ_nid2sn(pknid))) {
5309      /* The cert's pkey is different from the algorithm used to sign
5310       * the certificate. Since the reported `mdnid` is undefined, there
5311       * is no digest algorithm available here. This happens in PQC
5312       * and is accepted, resulting in no addition to the binding. */
5313      no_digest_acceptable = TRUE;
5314    }
5315    else if(pkey) {
5316      /* cert's pkey type is the same as the cert signer (or same family).
5317       * Ask for the mandatory/advisory digest algorithm for the pkey.
5318       */
5319      char mdname[128] = "";
5320      int rc = EVP_PKEY_get_default_digest_name(pkey, mdname, sizeof(mdname));
5321      bool md_is_undef = !strcmp(mdname, "UNDEF");
5322
5323      if(rc == 2 && md_is_undef) {
5324        /* OpenSSL declares "undef" the *mandatory* digest for this key.
5325         * This is some PQC shit, accept it, no addition to binding. */
5326        no_digest_acceptable = TRUE;
5327      }
5328      else if(rc > 0 && mdname[0] != '\0' && !md_is_undef) {
5329        infof(data, "Digest algorithm : %s%s (derived from public key)"
5330              ", but unavailable",
5331              mdname, rc == 2 ? " [mandatory]" : " [advisory]");
5332      }
5333    }
5334  }
5335#else /* HAVE_OPENSSL3 */
5336
5337  if(!OBJ_find_sigid_algs(X509_get_signature_nid(cert), &mdnid, NULL)) {
5338    failf(data,
5339          "Unable to find digest NID for certificate signature algorithm");
5340    result = CURLE_SSL_INVALIDCERTSTATUS;
5341    goto out;
5342  }
5343
5344  /* https://datatracker.ietf.org/doc/html/rfc5929#section-4.1 */
5345  if(mdnid == NID_md5 || mdnid == NID_sha1) {
5346    algo_type = EVP_sha256();
5347  }
5348  else {
5349    algo_type = EVP_get_digestbynid(mdnid);
5350    if(!algo_type) {
5351      algo_name = OBJ_nid2sn(mdnid);
5352      failf(data, "Could not find digest algorithm %s (NID %d)",
5353            algo_name ? algo_name : "(null)", mdnid);
5354      result = CURLE_SSL_INVALIDCERTSTATUS;
5355      goto out;
5356    }
5357  }
5358
5359#endif /* HAVE_OPENSSL3, else */
5360
5361  if(!algo_type) {
5362    if(no_digest_acceptable) {
5363      infof(data, "certificate exposes no signing digest algorithm, "
5364            "nothing to add to channel binding");
5365      result = CURLE_OK;
5366      goto out;
5367    }
5368    /* unacceptable, something is wrong, fail */
5369    algo_name = OBJ_nid2sn(mdnid);
5370    failf(data, "Unable to find digest algorithm %s (NID %d) "
5371          "for channel binding", algo_name ? algo_name : "(null)", mdnid);
5372    result = CURLE_SSL_INVALIDCERTSTATUS;
5373    goto out;
5374  }
5375
5376  if(!X509_digest(cert, algo_type, buf, &length)) {
5377    failf(data, "X509_digest() failed for channel binding");
5378    result = CURLE_SSL_INVALIDCERTSTATUS;
5379    goto out;
5380  }
5381
5382  /* Append "tls-server-end-point:" */
5383  result = curlx_dyn_addn(binding, prefix, sizeof(prefix) - 1);
5384  if(result)
5385    goto out;
5386
5387  /* Append digest */
5388  result = curlx_dyn_addn(binding, buf, length);
5389
5390out:
5391  X509_free(cert);
5392  return result;
5393}
5394
5395size_t Curl_ossl_version(char *buffer, size_t size)
5396{
5397#ifdef LIBRESSL_VERSION_NUMBER
5398  char *p;
5399  size_t count;
5400  const char *ver = OpenSSL_version(OPENSSL_VERSION);
5401  const char expected[] = OSSL_PACKAGE " "; /* ie "LibreSSL " */
5402  if(curl_strnequal(ver, expected, sizeof(expected) - 1)) {
5403    ver += sizeof(expected) - 1;
5404  }
5405  count = curl_msnprintf(buffer, size, "%s/%s", OSSL_PACKAGE, ver);
5406  for(p = buffer; *p; ++p) {
5407    if(ISBLANK(*p))
5408      *p = '_';
5409  }
5410  return count;
5411#elif defined(OPENSSL_IS_AWSLC)
5412  return curl_msnprintf(buffer, size, "%s/%s",
5413                        OSSL_PACKAGE, AWSLC_VERSION_NUMBER_STRING);
5414#elif defined(OPENSSL_IS_BORINGSSL)
5415#ifdef CURL_BORINGSSL_VERSION
5416  return curl_msnprintf(buffer, size, "%s/%s",
5417                        OSSL_PACKAGE, CURL_BORINGSSL_VERSION);
5418#else
5419  return curl_msnprintf(buffer, size, OSSL_PACKAGE);
5420#endif
5421#else /* OpenSSL 3+ */
5422  return curl_msnprintf(buffer, size, "%s/%s",
5423                        OSSL_PACKAGE, OpenSSL_version(OPENSSL_VERSION_STRING));
5424#endif
5425}
5426
5427/* can be called with data == NULL */
5428static CURLcode ossl_random(struct Curl_easy *data,
5429                            unsigned char *entropy, size_t length)
5430{
5431  int rc;
5432  if(data) {
5433    if(ossl_seed(data)) /* Initiate the seed if not already done */
5434      return CURLE_FAILED_INIT; /* could not seed for some reason */
5435  }
5436  else {
5437    if(!rand_enough())
5438      return CURLE_FAILED_INIT;
5439  }
5440  /* RAND_bytes() returns 1 on success, 0 otherwise. */
5441  rc = RAND_bytes(entropy, (ossl_valsize_t)curlx_uztosi(length));
5442  return rc == 1 ? CURLE_OK : CURLE_FAILED_INIT;
5443}
5444
5445static CURLcode ossl_sha256sum(const unsigned char *tmp, /* input */
5446                               size_t tmplen,
5447                               unsigned char *sha256sum /* output */,
5448                               size_t unused)
5449{
5450  EVP_MD_CTX *mdctx;
5451  unsigned int len = 0;
5452  (void)unused;
5453
5454  mdctx = EVP_MD_CTX_create();
5455  if(!mdctx)
5456    return CURLE_OUT_OF_MEMORY;
5457  if(!EVP_DigestInit(mdctx, EVP_sha256())) {
5458    EVP_MD_CTX_destroy(mdctx);
5459    return CURLE_FAILED_INIT;
5460  }
5461  EVP_DigestUpdate(mdctx, tmp, tmplen);
5462  EVP_DigestFinal_ex(mdctx, sha256sum, &len);
5463  EVP_MD_CTX_destroy(mdctx);
5464  return CURLE_OK;
5465}
5466
5467static bool ossl_cert_status_request(void)
5468{
5469#ifndef OPENSSL_NO_OCSP
5470  return TRUE;
5471#else
5472  return FALSE;
5473#endif
5474}
5475
5476static void *ossl_get_internals(struct ssl_connect_data *connssl,
5477                                CURLINFO info)
5478{
5479  /* Legacy: CURLINFO_TLS_SESSION must return an SSL_CTX pointer. */
5480  struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
5481  DEBUGASSERT(octx);
5482  return info == CURLINFO_TLS_SESSION ?
5483    (void *)octx->ssl_ctx : (void *)octx->ssl;
5484}
5485
5486const struct Curl_ssl Curl_ssl_openssl = {
5487  { CURLSSLBACKEND_OPENSSL, "openssl" }, /* info */
5488
5489  SSLSUPP_CA_PATH |
5490  SSLSUPP_CAINFO_BLOB |
5491  SSLSUPP_CERTINFO |
5492  SSLSUPP_PINNEDPUBKEY |
5493  SSLSUPP_SSL_CTX |
5494#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
5495  SSLSUPP_TLS13_CIPHERSUITES |
5496#endif
5497#ifdef HAVE_SSL_CTX_SET1_SIGALGS
5498  SSLSUPP_SIGNATURE_ALGORITHMS |
5499#endif
5500#ifdef HAVE_SSL_SET1_ECH_CONFIG_LIST
5501  SSLSUPP_ECH |
5502#endif
5503  SSLSUPP_CA_CACHE |
5504  SSLSUPP_HTTPS_PROXY |
5505  SSLSUPP_CIPHER_LIST |
5506  SSLSUPP_ISSUERCERT |
5507  SSLSUPP_ISSUERCERT_BLOB |
5508  SSLSUPP_SSL_EC_CURVES |
5509  SSLSUPP_CRLFILE,
5510
5511  sizeof(struct ossl_ctx),
5512
5513  ossl_init,                /* init */
5514  ossl_cleanup,             /* cleanup */
5515  Curl_ossl_version,        /* version */
5516  ossl_shutdown,            /* shutdown */
5517  ossl_data_pending,        /* data_pending */
5518  ossl_random,              /* random */
5519  ossl_cert_status_request, /* cert_status_request */
5520  ossl_connect,             /* connect */
5521  Curl_ssl_adjust_pollset,  /* adjust_pollset */
5522  ossl_get_internals,       /* get_internals */
5523  ossl_close,               /* close_one */
5524  ossl_close_all,           /* close_all */
5525  ossl_set_engine,          /* set_engine or provider */
5526  ossl_set_engine_default,  /* set_engine_default */
5527  ossl_engines_list,        /* engines_list */
5528  ossl_sha256sum,           /* sha256sum */
5529  ossl_recv,                /* recv decrypted data */
5530  ossl_send,                /* send data to encrypt */
5531  ossl_get_channel_binding  /* get_channel_binding */
5532};
5533
5534#endif /* USE_OPENSSL */