cjson
fuzzing
inputs
test1 test10 test11 test2 test3 test3.bu test3.uf test3.uu test4 test5 test6 test7 test8 test9library_config
cJSONConfig.cmake.in cJSONConfigVersion.cmake.in libcjson.pc.in libcjson_utils.pc.in uninstall.cmaketests
inputs
test1 test1.expected test10 test10.expected test11 test11.expected test2 test2.expected test3 test3.expected test4 test4.expected test5 test5.expected test6 test7 test7.expected test8 test8.expected test9 test9.expectedjson-patch-tests
.editorconfig .gitignore .npmignore README.md cjson-utils-tests.json package.json spec_tests.json tests.jsonunity
auto
colour_prompt.rb colour_reporter.rb generate_config.yml generate_module.rb generate_test_runner.rb parse_output.rb stylize_as_junit.rb test_file_filter.rb type_sanitizer.rb unity_test_summary.py unity_test_summary.rb unity_to_junit.pydocs
ThrowTheSwitchCodingStandard.md UnityAssertionsCheatSheetSuitableforPrintingandPossiblyFraming.pdf UnityAssertionsReference.md UnityConfigurationGuide.md UnityGettingStartedGuide.md UnityHelperScriptsGuide.md license.txtexamples
unity_config.hcurl
.github
scripts
cleancmd.pl cmp-config.pl cmp-pkg-config.sh codespell-ignore.words codespell.sh distfiles.sh pyspelling.words pyspelling.yaml randcurl.pl requirements-docs.txt requirements-proselint.txt requirements.txt shellcheck-ci.sh shellcheck.sh spellcheck.curl trimmarkdownheader.pl typos.sh typos.toml verify-examples.pl verify-synopsis.pl yamlcheck.sh yamlcheck.yamlworkflows
appveyor-status.yml checkdocs.yml checksrc.yml checkurls.yml codeql.yml configure-vs-cmake.yml curl-for-win.yml distcheck.yml fuzz.yml http3-linux.yml label.yml linux-old.yml linux.yml macos.yml non-native.yml windows.ymlCMake
CurlSymbolHiding.cmake CurlTests.c FindBrotli.cmake FindCares.cmake FindGSS.cmake FindGnuTLS.cmake FindLDAP.cmake FindLibbacktrace.cmake FindLibgsasl.cmake FindLibidn2.cmake FindLibpsl.cmake FindLibssh.cmake FindLibssh2.cmake FindLibuv.cmake FindMbedTLS.cmake FindNGHTTP2.cmake FindNGHTTP3.cmake FindNGTCP2.cmake FindNettle.cmake FindQuiche.cmake FindRustls.cmake FindWolfSSL.cmake FindZstd.cmake Macros.cmake OtherTests.cmake PickyWarnings.cmake Utilities.cmake cmake_uninstall.in.cmake curl-config.in.cmake unix-cache.cmake win32-cache.cmakedocs
cmdline-opts
.gitignore CMakeLists.txt MANPAGE.md Makefile.am Makefile.inc _AUTHORS.md _BUGS.md _DESCRIPTION.md _ENVIRONMENT.md _EXITCODES.md _FILES.md _GLOBBING.md _NAME.md _OPTIONS.md _OUTPUT.md _PROGRESS.md _PROTOCOLS.md _PROXYPREFIX.md _SEEALSO.md _SYNOPSIS.md _URL.md _VARIABLES.md _VERSION.md _WWW.md abstract-unix-socket.md alt-svc.md anyauth.md append.md aws-sigv4.md basic.md ca-native.md cacert.md capath.md cert-status.md cert-type.md cert.md ciphers.md compressed-ssh.md compressed.md config.md connect-timeout.md connect-to.md continue-at.md cookie-jar.md cookie.md create-dirs.md create-file-mode.md crlf.md crlfile.md curves.md data-ascii.md data-binary.md data-raw.md data-urlencode.md data.md delegation.md digest.md disable-eprt.md disable-epsv.md disable.md disallow-username-in-url.md dns-interface.md dns-ipv4-addr.md dns-ipv6-addr.md dns-servers.md doh-cert-status.md doh-insecure.md doh-url.md dump-ca-embed.md dump-header.md ech.md egd-file.md engine.md etag-compare.md etag-save.md expect100-timeout.md fail-early.md fail-with-body.md fail.md false-start.md follow.md form-escape.md form-string.md form.md ftp-account.md ftp-alternative-to-user.md ftp-create-dirs.md ftp-method.md ftp-pasv.md ftp-port.md ftp-pret.md ftp-skip-pasv-ip.md ftp-ssl-ccc-mode.md ftp-ssl-ccc.md ftp-ssl-control.md get.md globoff.md happy-eyeballs-timeout-ms.md haproxy-clientip.md haproxy-protocol.md head.md header.md help.md hostpubmd5.md hostpubsha256.md hsts.md http0.9.md http1.0.md http1.1.md http2-prior-knowledge.md http2.md http3-only.md http3.md ignore-content-length.md insecure.md interface.md ip-tos.md ipfs-gateway.md ipv4.md ipv6.md json.md junk-session-cookies.md keepalive-cnt.md keepalive-time.md key-type.md key.md knownhosts.md krb.md libcurl.md limit-rate.md list-only.md local-port.md location-trusted.md location.md login-options.md mail-auth.md mail-from.md mail-rcpt-allowfails.md mail-rcpt.md mainpage.idx manual.md max-filesize.md max-redirs.md max-time.md metalink.md mptcp.md negotiate.md netrc-file.md netrc-optional.md netrc.md next.md no-alpn.md no-buffer.md no-clobber.md no-keepalive.md no-npn.md no-progress-meter.md no-sessionid.md noproxy.md ntlm-wb.md ntlm.md oauth2-bearer.md out-null.md output-dir.md output.md parallel-immediate.md parallel-max-host.md parallel-max.md parallel.md pass.md path-as-is.md pinnedpubkey.md post301.md post302.md post303.md preproxy.md progress-bar.md proto-default.md proto-redir.md proto.md proxy-anyauth.md proxy-basic.md proxy-ca-native.md proxy-cacert.md proxy-capath.md proxy-cert-type.md proxy-cert.md proxy-ciphers.md proxy-crlfile.md proxy-digest.md proxy-header.md proxy-http2.md proxy-insecure.md proxy-key-type.md proxy-key.md proxy-negotiate.md proxy-ntlm.md proxy-pass.md proxy-pinnedpubkey.md proxy-service-name.md proxy-ssl-allow-beast.md proxy-ssl-auto-client-cert.md proxy-tls13-ciphers.md proxy-tlsauthtype.md proxy-tlspassword.md proxy-tlsuser.md proxy-tlsv1.md proxy-user.md proxy.md proxy1.0.md proxytunnel.md pubkey.md quote.md random-file.md range.md rate.md raw.md referer.md remote-header-name.md remote-name-all.md remote-name.md remote-time.md remove-on-error.md request-target.md request.md resolve.md retry-all-errors.md retry-connrefused.md retry-delay.md retry-max-time.md retry.md sasl-authzid.md sasl-ir.md service-name.md show-error.md show-headers.md sigalgs.md silent.md skip-existing.md socks4.md socks4a.md socks5-basic.md socks5-gssapi-nec.md socks5-gssapi-service.md socks5-gssapi.md socks5-hostname.md socks5.md speed-limit.md speed-time.md ssl-allow-beast.md ssl-auto-client-cert.md ssl-no-revoke.md ssl-reqd.md ssl-revoke-best-effort.md ssl-sessions.md ssl.md sslv2.md sslv3.md stderr.md styled-output.md suppress-connect-headers.md tcp-fastopen.md tcp-nodelay.md telnet-option.md tftp-blksize.md tftp-no-options.md time-cond.md tls-earlydata.md tls-max.md tls13-ciphers.md tlsauthtype.md tlspassword.md tlsuser.md tlsv1.0.md tlsv1.1.md tlsv1.2.md tlsv1.3.md tlsv1.md tr-encoding.md trace-ascii.md trace-config.md trace-ids.md trace-time.md trace.md unix-socket.md upload-file.md upload-flags.md url-query.md url.md use-ascii.md user-agent.md user.md variable.md verbose.md version.md vlan-priority.md write-out.md xattr.mdexamples
.checksrc .gitignore 10-at-a-time.c CMakeLists.txt Makefile.am Makefile.example Makefile.inc README.md adddocsref.pl address-scope.c altsvc.c anyauthput.c block_ip.c cacertinmem.c certinfo.c chkspeed.c connect-to.c cookie_interface.c crawler.c debug.c default-scheme.c ephiperfifo.c evhiperfifo.c externalsocket.c fileupload.c ftp-delete.c ftp-wildcard.c ftpget.c ftpgetinfo.c ftpgetresp.c ftpsget.c ftpupload.c ftpuploadfrommem.c ftpuploadresume.c getinfo.c getinmemory.c getredirect.c getreferrer.c ghiper.c headerapi.c hiperfifo.c hsts-preload.c htmltidy.c htmltitle.cpp http-options.c http-post.c http2-download.c http2-pushinmemory.c http2-serverpush.c http2-upload.c http3-present.c http3.c httpcustomheader.c httpput-postfields.c httpput.c https.c imap-append.c imap-authzid.c imap-copy.c imap-create.c imap-delete.c imap-examine.c imap-fetch.c imap-list.c imap-lsub.c imap-multi.c imap-noop.c imap-search.c imap-ssl.c imap-store.c imap-tls.c interface.c ipv6.c keepalive.c localport.c log_failed_transfers.c maxconnects.c multi-app.c multi-debugcallback.c multi-double.c multi-event.c multi-formadd.c multi-legacy.c multi-post.c multi-single.c multi-uv.c netrc.c parseurl.c persistent.c pop3-authzid.c pop3-dele.c pop3-list.c pop3-multi.c pop3-noop.c pop3-retr.c pop3-ssl.c pop3-stat.c pop3-tls.c pop3-top.c pop3-uidl.c post-callback.c postinmemory.c postit2-formadd.c postit2.c progressfunc.c protofeats.c range.c resolve.c rtsp-options.c sendrecv.c sepheaders.c sessioninfo.c sftpget.c sftpuploadresume.c shared-connection-cache.c simple.c simplepost.c simplessl.c smooth-gtk-thread.c smtp-authzid.c smtp-expn.c smtp-mail.c smtp-mime.c smtp-multi.c smtp-ssl.c smtp-tls.c smtp-vrfy.c sslbackend.c synctime.c threaded.c unixsocket.c url2file.c urlapi.c usercertinmem.c version-check.pl websocket-cb.c websocket-updown.c websocket.c xmlstream.cinternals
BUFQ.md BUFREF.md CHECKSRC.md CLIENT-READERS.md CLIENT-WRITERS.md CODE_STYLE.md CONNECTION-FILTERS.md CREDENTIALS.md CURLX.md DYNBUF.md HASH.md LLIST.md MID.md MQTT.md MULTI-EV.md NEW-PROTOCOL.md PEERS.md PORTING.md RATELIMITS.md README.md SCORECARD.md SPLAY.md STRPARSE.md THRDPOOL-AND-QUEUE.md TIME-KEEPING.md TLS-SESSIONS.md UINT_SETS.md WEBSOCKET.mdlibcurl
opts
CMakeLists.txt CURLINFO_ACTIVESOCKET.md CURLINFO_APPCONNECT_TIME.md CURLINFO_APPCONNECT_TIME_T.md CURLINFO_CAINFO.md CURLINFO_CAPATH.md CURLINFO_CERTINFO.md CURLINFO_CONDITION_UNMET.md CURLINFO_CONNECT_TIME.md CURLINFO_CONNECT_TIME_T.md CURLINFO_CONN_ID.md CURLINFO_CONTENT_LENGTH_DOWNLOAD.md CURLINFO_CONTENT_LENGTH_DOWNLOAD_T.md CURLINFO_CONTENT_LENGTH_UPLOAD.md CURLINFO_CONTENT_LENGTH_UPLOAD_T.md CURLINFO_CONTENT_TYPE.md CURLINFO_COOKIELIST.md CURLINFO_EARLYDATA_SENT_T.md CURLINFO_EFFECTIVE_METHOD.md CURLINFO_EFFECTIVE_URL.md CURLINFO_FILETIME.md CURLINFO_FILETIME_T.md CURLINFO_FTP_ENTRY_PATH.md CURLINFO_HEADER_SIZE.md CURLINFO_HTTPAUTH_AVAIL.md CURLINFO_HTTPAUTH_USED.md CURLINFO_HTTP_CONNECTCODE.md CURLINFO_HTTP_VERSION.md CURLINFO_LASTSOCKET.md CURLINFO_LOCAL_IP.md CURLINFO_LOCAL_PORT.md CURLINFO_NAMELOOKUP_TIME.md CURLINFO_NAMELOOKUP_TIME_T.md CURLINFO_NUM_CONNECTS.md CURLINFO_OS_ERRNO.md CURLINFO_POSTTRANSFER_TIME_T.md CURLINFO_PRETRANSFER_TIME.md CURLINFO_PRETRANSFER_TIME_T.md CURLINFO_PRIMARY_IP.md CURLINFO_PRIMARY_PORT.md CURLINFO_PRIVATE.md CURLINFO_PROTOCOL.md CURLINFO_PROXYAUTH_AVAIL.md CURLINFO_PROXYAUTH_USED.md CURLINFO_PROXY_ERROR.md CURLINFO_PROXY_SSL_VERIFYRESULT.md CURLINFO_QUEUE_TIME_T.md CURLINFO_REDIRECT_COUNT.md CURLINFO_REDIRECT_TIME.md CURLINFO_REDIRECT_TIME_T.md CURLINFO_REDIRECT_URL.md CURLINFO_REFERER.md CURLINFO_REQUEST_SIZE.md CURLINFO_RESPONSE_CODE.md CURLINFO_RETRY_AFTER.md CURLINFO_RTSP_CLIENT_CSEQ.md CURLINFO_RTSP_CSEQ_RECV.md CURLINFO_RTSP_SERVER_CSEQ.md CURLINFO_RTSP_SESSION_ID.md CURLINFO_SCHEME.md CURLINFO_SIZE_DELIVERED.md CURLINFO_SIZE_DOWNLOAD.md CURLINFO_SIZE_DOWNLOAD_T.md CURLINFO_SIZE_UPLOAD.md CURLINFO_SIZE_UPLOAD_T.md CURLINFO_SPEED_DOWNLOAD.md CURLINFO_SPEED_DOWNLOAD_T.md CURLINFO_SPEED_UPLOAD.md CURLINFO_SPEED_UPLOAD_T.md CURLINFO_SSL_ENGINES.md CURLINFO_SSL_VERIFYRESULT.md CURLINFO_STARTTRANSFER_TIME.md CURLINFO_STARTTRANSFER_TIME_T.md CURLINFO_TLS_SESSION.md CURLINFO_TLS_SSL_PTR.md CURLINFO_TOTAL_TIME.md CURLINFO_TOTAL_TIME_T.md CURLINFO_USED_PROXY.md CURLINFO_XFER_ID.md CURLMINFO_XFERS_ADDED.md CURLMINFO_XFERS_CURRENT.md CURLMINFO_XFERS_DONE.md CURLMINFO_XFERS_PENDING.md CURLMINFO_XFERS_RUNNING.md CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE.md CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE.md CURLMOPT_MAXCONNECTS.md CURLMOPT_MAX_CONCURRENT_STREAMS.md CURLMOPT_MAX_HOST_CONNECTIONS.md CURLMOPT_MAX_PIPELINE_LENGTH.md CURLMOPT_MAX_TOTAL_CONNECTIONS.md CURLMOPT_NETWORK_CHANGED.md CURLMOPT_NOTIFYDATA.md CURLMOPT_NOTIFYFUNCTION.md CURLMOPT_PIPELINING.md CURLMOPT_PIPELINING_SERVER_BL.md CURLMOPT_PIPELINING_SITE_BL.md CURLMOPT_PUSHDATA.md CURLMOPT_PUSHFUNCTION.md CURLMOPT_QUICK_EXIT.md CURLMOPT_RESOLVE_THREADS_MAX.md CURLMOPT_SOCKETDATA.md CURLMOPT_SOCKETFUNCTION.md CURLMOPT_TIMERDATA.md CURLMOPT_TIMERFUNCTION.md CURLOPT_ABSTRACT_UNIX_SOCKET.md CURLOPT_ACCEPTTIMEOUT_MS.md CURLOPT_ACCEPT_ENCODING.md CURLOPT_ADDRESS_SCOPE.md CURLOPT_ALTSVC.md CURLOPT_ALTSVC_CTRL.md CURLOPT_APPEND.md CURLOPT_AUTOREFERER.md CURLOPT_AWS_SIGV4.md CURLOPT_BUFFERSIZE.md CURLOPT_CAINFO.md CURLOPT_CAINFO_BLOB.md CURLOPT_CAPATH.md CURLOPT_CA_CACHE_TIMEOUT.md CURLOPT_CERTINFO.md CURLOPT_CHUNK_BGN_FUNCTION.md CURLOPT_CHUNK_DATA.md CURLOPT_CHUNK_END_FUNCTION.md CURLOPT_CLOSESOCKETDATA.md CURLOPT_CLOSESOCKETFUNCTION.md CURLOPT_CONNECTTIMEOUT.md CURLOPT_CONNECTTIMEOUT_MS.md CURLOPT_CONNECT_ONLY.md CURLOPT_CONNECT_TO.md CURLOPT_CONV_FROM_NETWORK_FUNCTION.md CURLOPT_CONV_FROM_UTF8_FUNCTION.md CURLOPT_CONV_TO_NETWORK_FUNCTION.md CURLOPT_COOKIE.md CURLOPT_COOKIEFILE.md CURLOPT_COOKIEJAR.md CURLOPT_COOKIELIST.md CURLOPT_COOKIESESSION.md CURLOPT_COPYPOSTFIELDS.md CURLOPT_CRLF.md CURLOPT_CRLFILE.md CURLOPT_CURLU.md CURLOPT_CUSTOMREQUEST.md CURLOPT_DEBUGDATA.md CURLOPT_DEBUGFUNCTION.md CURLOPT_DEFAULT_PROTOCOL.md CURLOPT_DIRLISTONLY.md CURLOPT_DISALLOW_USERNAME_IN_URL.md CURLOPT_DNS_CACHE_TIMEOUT.md CURLOPT_DNS_INTERFACE.md CURLOPT_DNS_LOCAL_IP4.md CURLOPT_DNS_LOCAL_IP6.md CURLOPT_DNS_SERVERS.md CURLOPT_DNS_SHUFFLE_ADDRESSES.md CURLOPT_DNS_USE_GLOBAL_CACHE.md CURLOPT_DOH_SSL_VERIFYHOST.md CURLOPT_DOH_SSL_VERIFYPEER.md CURLOPT_DOH_SSL_VERIFYSTATUS.md CURLOPT_DOH_URL.md CURLOPT_ECH.md CURLOPT_EGDSOCKET.md CURLOPT_ERRORBUFFER.md CURLOPT_EXPECT_100_TIMEOUT_MS.md CURLOPT_FAILONERROR.md CURLOPT_FILETIME.md CURLOPT_FNMATCH_DATA.md CURLOPT_FNMATCH_FUNCTION.md CURLOPT_FOLLOWLOCATION.md CURLOPT_FORBID_REUSE.md CURLOPT_FRESH_CONNECT.md CURLOPT_FTPPORT.md CURLOPT_FTPSSLAUTH.md CURLOPT_FTP_ACCOUNT.md CURLOPT_FTP_ALTERNATIVE_TO_USER.md CURLOPT_FTP_CREATE_MISSING_DIRS.md CURLOPT_FTP_FILEMETHOD.md CURLOPT_FTP_SKIP_PASV_IP.md CURLOPT_FTP_SSL_CCC.md CURLOPT_FTP_USE_EPRT.md CURLOPT_FTP_USE_EPSV.md CURLOPT_FTP_USE_PRET.md CURLOPT_GSSAPI_DELEGATION.md CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.md CURLOPT_HAPROXYPROTOCOL.md CURLOPT_HAPROXY_CLIENT_IP.md CURLOPT_HEADER.md CURLOPT_HEADERDATA.md CURLOPT_HEADERFUNCTION.md CURLOPT_HEADEROPT.md CURLOPT_HSTS.md CURLOPT_HSTSREADDATA.md CURLOPT_HSTSREADFUNCTION.md CURLOPT_HSTSWRITEDATA.md CURLOPT_HSTSWRITEFUNCTION.md CURLOPT_HSTS_CTRL.md CURLOPT_HTTP09_ALLOWED.md CURLOPT_HTTP200ALIASES.md CURLOPT_HTTPAUTH.md CURLOPT_HTTPGET.md CURLOPT_HTTPHEADER.md CURLOPT_HTTPPOST.md CURLOPT_HTTPPROXYTUNNEL.md CURLOPT_HTTP_CONTENT_DECODING.md CURLOPT_HTTP_TRANSFER_DECODING.md CURLOPT_HTTP_VERSION.md CURLOPT_IGNORE_CONTENT_LENGTH.md CURLOPT_INFILESIZE.md CURLOPT_INFILESIZE_LARGE.md CURLOPT_INTERFACE.md CURLOPT_INTERLEAVEDATA.md CURLOPT_INTERLEAVEFUNCTION.md CURLOPT_IOCTLDATA.md CURLOPT_IOCTLFUNCTION.md CURLOPT_IPRESOLVE.md CURLOPT_ISSUERCERT.md CURLOPT_ISSUERCERT_BLOB.md CURLOPT_KEEP_SENDING_ON_ERROR.md CURLOPT_KEYPASSWD.md CURLOPT_KRBLEVEL.md CURLOPT_LOCALPORT.md CURLOPT_LOCALPORTRANGE.md CURLOPT_LOGIN_OPTIONS.md CURLOPT_LOW_SPEED_LIMIT.md CURLOPT_LOW_SPEED_TIME.md CURLOPT_MAIL_AUTH.md CURLOPT_MAIL_FROM.md CURLOPT_MAIL_RCPT.md CURLOPT_MAIL_RCPT_ALLOWFAILS.md CURLOPT_MAXAGE_CONN.md CURLOPT_MAXCONNECTS.md CURLOPT_MAXFILESIZE.md CURLOPT_MAXFILESIZE_LARGE.md CURLOPT_MAXLIFETIME_CONN.md CURLOPT_MAXREDIRS.md CURLOPT_MAX_RECV_SPEED_LARGE.md CURLOPT_MAX_SEND_SPEED_LARGE.md CURLOPT_MIMEPOST.md CURLOPT_MIME_OPTIONS.md CURLOPT_NETRC.md CURLOPT_NETRC_FILE.md CURLOPT_NEW_DIRECTORY_PERMS.md CURLOPT_NEW_FILE_PERMS.md CURLOPT_NOBODY.md CURLOPT_NOPROGRESS.md CURLOPT_NOPROXY.md CURLOPT_NOSIGNAL.md CURLOPT_OPENSOCKETDATA.md CURLOPT_OPENSOCKETFUNCTION.md CURLOPT_PASSWORD.md CURLOPT_PATH_AS_IS.md CURLOPT_PINNEDPUBLICKEY.md CURLOPT_PIPEWAIT.md CURLOPT_PORT.md CURLOPT_POST.md CURLOPT_POSTFIELDS.md CURLOPT_POSTFIELDSIZE.md CURLOPT_POSTFIELDSIZE_LARGE.md CURLOPT_POSTQUOTE.md CURLOPT_POSTREDIR.md CURLOPT_PREQUOTE.md CURLOPT_PREREQDATA.md CURLOPT_PREREQFUNCTION.md CURLOPT_PRE_PROXY.md CURLOPT_PRIVATE.md CURLOPT_PROGRESSDATA.md CURLOPT_PROGRESSFUNCTION.md CURLOPT_PROTOCOLS.md CURLOPT_PROTOCOLS_STR.md CURLOPT_PROXY.md CURLOPT_PROXYAUTH.md CURLOPT_PROXYHEADER.md CURLOPT_PROXYPASSWORD.md CURLOPT_PROXYPORT.md CURLOPT_PROXYTYPE.md CURLOPT_PROXYUSERNAME.md CURLOPT_PROXYUSERPWD.md CURLOPT_PROXY_CAINFO.md CURLOPT_PROXY_CAINFO_BLOB.md CURLOPT_PROXY_CAPATH.md CURLOPT_PROXY_CRLFILE.md CURLOPT_PROXY_ISSUERCERT.md CURLOPT_PROXY_ISSUERCERT_BLOB.md CURLOPT_PROXY_KEYPASSWD.md CURLOPT_PROXY_PINNEDPUBLICKEY.md CURLOPT_PROXY_SERVICE_NAME.md CURLOPT_PROXY_SSLCERT.md CURLOPT_PROXY_SSLCERTTYPE.md CURLOPT_PROXY_SSLCERT_BLOB.md CURLOPT_PROXY_SSLKEY.md CURLOPT_PROXY_SSLKEYTYPE.md CURLOPT_PROXY_SSLKEY_BLOB.md CURLOPT_PROXY_SSLVERSION.md CURLOPT_PROXY_SSL_CIPHER_LIST.md CURLOPT_PROXY_SSL_OPTIONS.md CURLOPT_PROXY_SSL_VERIFYHOST.md CURLOPT_PROXY_SSL_VERIFYPEER.md CURLOPT_PROXY_TLS13_CIPHERS.md CURLOPT_PROXY_TLSAUTH_PASSWORD.md CURLOPT_PROXY_TLSAUTH_TYPE.md CURLOPT_PROXY_TLSAUTH_USERNAME.md CURLOPT_PROXY_TRANSFER_MODE.md CURLOPT_PUT.md CURLOPT_QUICK_EXIT.md CURLOPT_QUOTE.md CURLOPT_RANDOM_FILE.md CURLOPT_RANGE.md CURLOPT_READDATA.md CURLOPT_READFUNCTION.md CURLOPT_REDIR_PROTOCOLS.md CURLOPT_REDIR_PROTOCOLS_STR.md CURLOPT_REFERER.md CURLOPT_REQUEST_TARGET.md CURLOPT_RESOLVE.md CURLOPT_RESOLVER_START_DATA.md CURLOPT_RESOLVER_START_FUNCTION.md CURLOPT_RESUME_FROM.md CURLOPT_RESUME_FROM_LARGE.md CURLOPT_RTSP_CLIENT_CSEQ.md CURLOPT_RTSP_REQUEST.md CURLOPT_RTSP_SERVER_CSEQ.md CURLOPT_RTSP_SESSION_ID.md CURLOPT_RTSP_STREAM_URI.md CURLOPT_RTSP_TRANSPORT.md CURLOPT_SASL_AUTHZID.md CURLOPT_SASL_IR.md CURLOPT_SEEKDATA.md CURLOPT_SEEKFUNCTION.md CURLOPT_SERVER_RESPONSE_TIMEOUT.md CURLOPT_SERVER_RESPONSE_TIMEOUT_MS.md CURLOPT_SERVICE_NAME.md CURLOPT_SHARE.md CURLOPT_SOCKOPTDATA.md CURLOPT_SOCKOPTFUNCTION.md CURLOPT_SOCKS5_AUTH.md CURLOPT_SOCKS5_GSSAPI_NEC.md CURLOPT_SOCKS5_GSSAPI_SERVICE.md CURLOPT_SSH_AUTH_TYPES.md CURLOPT_SSH_COMPRESSION.md CURLOPT_SSH_HOSTKEYDATA.md CURLOPT_SSH_HOSTKEYFUNCTION.md CURLOPT_SSH_HOST_PUBLIC_KEY_MD5.md CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256.md CURLOPT_SSH_KEYDATA.md CURLOPT_SSH_KEYFUNCTION.md CURLOPT_SSH_KNOWNHOSTS.md CURLOPT_SSH_PRIVATE_KEYFILE.md CURLOPT_SSH_PUBLIC_KEYFILE.md CURLOPT_SSLCERT.md CURLOPT_SSLCERTTYPE.md CURLOPT_SSLCERT_BLOB.md CURLOPT_SSLENGINE.md CURLOPT_SSLENGINE_DEFAULT.md CURLOPT_SSLKEY.md CURLOPT_SSLKEYTYPE.md CURLOPT_SSLKEY_BLOB.md CURLOPT_SSLVERSION.md CURLOPT_SSL_CIPHER_LIST.md CURLOPT_SSL_CTX_DATA.md CURLOPT_SSL_CTX_FUNCTION.md CURLOPT_SSL_EC_CURVES.md CURLOPT_SSL_ENABLE_ALPN.md CURLOPT_SSL_ENABLE_NPN.md CURLOPT_SSL_FALSESTART.md CURLOPT_SSL_OPTIONS.md CURLOPT_SSL_SESSIONID_CACHE.md CURLOPT_SSL_SIGNATURE_ALGORITHMS.md CURLOPT_SSL_VERIFYHOST.md CURLOPT_SSL_VERIFYPEER.md CURLOPT_SSL_VERIFYSTATUS.md CURLOPT_STDERR.md CURLOPT_STREAM_DEPENDS.md CURLOPT_STREAM_DEPENDS_E.md CURLOPT_STREAM_WEIGHT.md CURLOPT_SUPPRESS_CONNECT_HEADERS.md CURLOPT_TCP_FASTOPEN.md CURLOPT_TCP_KEEPALIVE.md CURLOPT_TCP_KEEPCNT.md CURLOPT_TCP_KEEPIDLE.md CURLOPT_TCP_KEEPINTVL.md CURLOPT_TCP_NODELAY.md CURLOPT_TELNETOPTIONS.md CURLOPT_TFTP_BLKSIZE.md CURLOPT_TFTP_NO_OPTIONS.md CURLOPT_TIMECONDITION.md CURLOPT_TIMEOUT.md CURLOPT_TIMEOUT_MS.md CURLOPT_TIMEVALUE.md CURLOPT_TIMEVALUE_LARGE.md CURLOPT_TLS13_CIPHERS.md CURLOPT_TLSAUTH_PASSWORD.md CURLOPT_TLSAUTH_TYPE.md CURLOPT_TLSAUTH_USERNAME.md CURLOPT_TRAILERDATA.md CURLOPT_TRAILERFUNCTION.md CURLOPT_TRANSFERTEXT.md CURLOPT_TRANSFER_ENCODING.md CURLOPT_UNIX_SOCKET_PATH.md CURLOPT_UNRESTRICTED_AUTH.md CURLOPT_UPKEEP_INTERVAL_MS.md CURLOPT_UPLOAD.md CURLOPT_UPLOAD_BUFFERSIZE.md CURLOPT_UPLOAD_FLAGS.md CURLOPT_URL.md CURLOPT_USERAGENT.md CURLOPT_USERNAME.md CURLOPT_USERPWD.md CURLOPT_USE_SSL.md CURLOPT_VERBOSE.md CURLOPT_WILDCARDMATCH.md CURLOPT_WRITEDATA.md CURLOPT_WRITEFUNCTION.md CURLOPT_WS_OPTIONS.md CURLOPT_XFERINFODATA.md CURLOPT_XFERINFOFUNCTION.md CURLOPT_XOAUTH2_BEARER.md CURLSHOPT_LOCKFUNC.md CURLSHOPT_SHARE.md CURLSHOPT_UNLOCKFUNC.md CURLSHOPT_UNSHARE.md CURLSHOPT_USERDATA.md Makefile.am Makefile.incinclude
curl
Makefile.am curl.h curlver.h easy.h header.h mprintf.h multi.h options.h stdcheaders.h system.h typecheck-gcc.h urlapi.h websockets.hlib
curlx
base64.c base64.h basename.c basename.h dynbuf.c dynbuf.h fopen.c fopen.h inet_ntop.c inet_ntop.h inet_pton.c inet_pton.h multibyte.c multibyte.h nonblock.c nonblock.h snprintf.c snprintf.h strcopy.c strcopy.h strdup.c strdup.h strerr.c strerr.h strparse.c strparse.h timediff.c timediff.h timeval.c timeval.h version_win32.c version_win32.h wait.c wait.h warnless.c warnless.h winapi.c winapi.hvauth
cleartext.c cram.c digest.c digest.h digest_sspi.c gsasl.c krb5_gssapi.c krb5_sspi.c ntlm.c ntlm_sspi.c oauth2.c spnego_gssapi.c spnego_sspi.c vauth.c vauth.hvquic
curl_ngtcp2.c curl_ngtcp2.h curl_quiche.c curl_quiche.h vquic-tls.c vquic-tls.h vquic.c vquic.h vquic_int.hvtls
apple.c apple.h cipher_suite.c cipher_suite.h gtls.c gtls.h hostcheck.c hostcheck.h keylog.c keylog.h mbedtls.c mbedtls.h openssl.c openssl.h rustls.c rustls.h schannel.c schannel.h schannel_int.h schannel_verify.c vtls.c vtls.h vtls_int.h vtls_scache.c vtls_scache.h vtls_spack.c vtls_spack.h wolfssl.c wolfssl.h x509asn1.c x509asn1.hm4
.gitignore curl-amissl.m4 curl-apple-sectrust.m4 curl-compilers.m4 curl-confopts.m4 curl-functions.m4 curl-gnutls.m4 curl-mbedtls.m4 curl-openssl.m4 curl-override.m4 curl-reentrant.m4 curl-rustls.m4 curl-schannel.m4 curl-sysconfig.m4 curl-wolfssl.m4 xc-am-iface.m4 xc-cc-check.m4 xc-lt-iface.m4 xc-val-flgs.m4 zz40-xc-ovr.m4 zz50-xc-ovr.m4projects
OS400
.checksrc README.OS400 ccsidcurl.c ccsidcurl.h config400.default curl.cmd curl.inc.in curlcl.c curlmain.c initscript.sh make-docs.sh make-include.sh make-lib.sh make-src.sh make-tests.sh makefile.sh os400sys.c os400sys.hWindows
tmpl
.gitattributes README.txt curl-all.sln curl.sln curl.vcxproj curl.vcxproj.filters libcurl.sln libcurl.vcxproj libcurl.vcxproj.filtersvms
Makefile.am backup_gnv_curl_src.com build_curl-config_script.com build_gnv_curl.com build_gnv_curl_pcsi_desc.com build_gnv_curl_pcsi_text.com build_gnv_curl_release_notes.com build_libcurl_pc.com build_vms.com clean_gnv_curl.com compare_curl_source.com config_h.com curl_crtl_init.c curl_gnv_build_steps.txt curl_release_note_start.txt curl_startup.com curlmsg.h curlmsg.msg curlmsg.sdl curlmsg_vms.h generate_config_vms_h_curl.com generate_vax_transfer.com gnv_conftest.c_first gnv_curl_configure.sh gnv_libcurl_symbols.opt gnv_link_curl.com macro32_exactcase.patch make_gnv_curl_install.sh make_pcsi_curl_kit_name.com pcsi_gnv_curl_file_list.txt pcsi_product_gnv_curl.com readme report_openssl_version.c setup_gnv_curl_build.com stage_curl_install.com vms_eco_level.hscripts
.checksrc CMakeLists.txt Makefile.am badwords badwords-all badwords.txt cd2cd cd2nroff cdall checksrc-all.pl checksrc.pl cmakelint.sh completion.pl contributors.sh contrithanks.sh coverage.sh delta dmaketgz extract-unit-protos firefox-db2pem.sh installcheck.sh maketgz managen mdlinkcheck mk-ca-bundle.pl mk-unity.pl nroff2cd perlcheck.sh pythonlint.sh randdisable release-notes.pl release-tools.sh schemetable.c singleuse.pl spacecheck.pl top-complexity top-length verify-release wcurlsrc
.checksrc .gitignore CMakeLists.txt Makefile.am Makefile.inc config2setopts.c config2setopts.h curl.rc curlinfo.c mk-file-embed.pl mkhelp.pl slist_wc.c slist_wc.h terminal.c terminal.h tool_cb_dbg.c tool_cb_dbg.h tool_cb_hdr.c tool_cb_hdr.h tool_cb_prg.c tool_cb_prg.h tool_cb_rea.c tool_cb_rea.h tool_cb_see.c tool_cb_see.h tool_cb_soc.c tool_cb_soc.h tool_cb_wrt.c tool_cb_wrt.h tool_cfgable.c tool_cfgable.h tool_dirhie.c tool_dirhie.h tool_doswin.c tool_doswin.h tool_easysrc.c tool_easysrc.h tool_filetime.c tool_filetime.h tool_findfile.c tool_findfile.h tool_formparse.c tool_formparse.h tool_getparam.c tool_getparam.h tool_getpass.c tool_getpass.h tool_help.c tool_help.h tool_helpers.c tool_helpers.h tool_hugehelp.h tool_ipfs.c tool_ipfs.h tool_libinfo.c tool_libinfo.h tool_listhelp.c tool_main.c tool_main.h tool_msgs.c tool_msgs.h tool_operate.c tool_operate.h tool_operhlp.c tool_operhlp.h tool_paramhlp.c tool_paramhlp.h tool_parsecfg.c tool_parsecfg.h tool_progress.c tool_progress.h tool_sdecls.h tool_setopt.c tool_setopt.h tool_setup.h tool_ssls.c tool_ssls.h tool_stderr.c tool_stderr.h tool_urlglob.c tool_urlglob.h tool_util.c tool_util.h tool_version.h tool_vms.c tool_vms.h tool_writeout.c tool_writeout.h tool_writeout_json.c tool_writeout_json.h tool_xattr.c tool_xattr.h var.c var.htests
certs
.gitignore CMakeLists.txt Makefile.am Makefile.inc genserv.pl srp-verifier-conf srp-verifier-db test-ca.cnf test-ca.prm test-client-cert.prm test-client-eku-only.prm test-localhost-san-first.prm test-localhost-san-last.prm test-localhost.nn.prm test-localhost.prm test-localhost0h.prmdata
.gitignore DISABLED Makefile.am data-xml1 data1400.c data1401.c data1402.c data1403.c data1404.c data1405.c data1406.c data1407.c data1420.c data1461.txt data1463.txt data1465.c data1481.c data1705-1.md data1705-2.md data1705-3.md data1705-4.md data1705-stdout.1 data1706-1.md data1706-2.md data1706-3.md data1706-4.md data1706-stdout.txt data320.html test1 test10 test100 test1000 test1001 test1002 test1003 test1004 test1005 test1006 test1007 test1008 test1009 test101 test1010 test1011 test1012 test1013 test1014 test1015 test1016 test1017 test1018 test1019 test102 test1020 test1021 test1022 test1023 test1024 test1025 test1026 test1027 test1028 test1029 test103 test1030 test1031 test1032 test1033 test1034 test1035 test1036 test1037 test1038 test1039 test104 test1040 test1041 test1042 test1043 test1044 test1045 test1046 test1047 test1048 test1049 test105 test1050 test1051 test1052 test1053 test1054 test1055 test1056 test1057 test1058 test1059 test106 test1060 test1061 test1062 test1063 test1064 test1065 test1066 test1067 test1068 test1069 test107 test1070 test1071 test1072 test1073 test1074 test1075 test1076 test1077 test1078 test1079 test108 test1080 test1081 test1082 test1083 test1084 test1085 test1086 test1087 test1088 test1089 test109 test1090 test1091 test1092 test1093 test1094 test1095 test1096 test1097 test1098 test1099 test11 test110 test1100 test1101 test1102 test1103 test1104 test1105 test1106 test1107 test1108 test1109 test111 test1110 test1111 test1112 test1113 test1114 test1115 test1116 test1117 test1118 test1119 test112 test1120 test1121 test1122 test1123 test1124 test1125 test1126 test1127 test1128 test1129 test113 test1130 test1131 test1132 test1133 test1134 test1135 test1136 test1137 test1138 test1139 test114 test1140 test1141 test1142 test1143 test1144 test1145 test1146 test1147 test1148 test1149 test115 test1150 test1151 test1152 test1153 test1154 test1155 test1156 test1157 test1158 test1159 test116 test1160 test1161 test1162 test1163 test1164 test1165 test1166 test1167 test1168 test1169 test117 test1170 test1171 test1172 test1173 test1174 test1175 test1176 test1177 test1178 test1179 test118 test1180 test1181 test1182 test1183 test1184 test1185 test1186 test1187 test1188 test1189 test119 test1190 test1191 test1192 test1193 test1194 test1195 test1196 test1197 test1198 test1199 test12 test120 test1200 test1201 test1202 test1203 test1204 test1205 test1206 test1207 test1208 test1209 test121 test1210 test1211 test1212 test1213 test1214 test1215 test1216 test1217 test1218 test1219 test122 test1220 test1221 test1222 test1223 test1224 test1225 test1226 test1227 test1228 test1229 test123 test1230 test1231 test1232 test1233 test1234 test1235 test1236 test1237 test1238 test1239 test124 test1240 test1241 test1242 test1243 test1244 test1245 test1246 test1247 test1248 test1249 test125 test1250 test1251 test1252 test1253 test1254 test1255 test1256 test1257 test1258 test1259 test126 test1260 test1261 test1262 test1263 test1264 test1265 test1266 test1267 test1268 test1269 test127 test1270 test1271 test1272 test1273 test1274 test1275 test1276 test1277 test1278 test1279 test128 test1280 test1281 test1282 test1283 test1284 test1285 test1286 test1287 test1288 test1289 test129 test1290 test1291 test1292 test1293 test1294 test1295 test1296 test1297 test1298 test1299 test13 test130 test1300 test1301 test1302 test1303 test1304 test1305 test1306 test1307 test1308 test1309 test131 test1310 test1311 test1312 test1313 test1314 test1315 test1316 test1317 test1318 test1319 test132 test1320 test1321 test1322 test1323 test1324 test1325 test1326 test1327 test1328 test1329 test133 test1330 test1331 test1332 test1333 test1334 test1335 test1336 test1337 test1338 test1339 test134 test1340 test1341 test1342 test1343 test1344 test1345 test1346 test1347 test1348 test1349 test135 test1350 test1351 test1352 test1353 test1354 test1355 test1356 test1357 test1358 test1359 test136 test1360 test1361 test1362 test1363 test1364 test1365 test1366 test1367 test1368 test1369 test137 test1370 test1371 test1372 test1373 test1374 test1375 test1376 test1377 test1378 test1379 test138 test1380 test1381 test1382 test1383 test1384 test1385 test1386 test1387 test1388 test1389 test139 test1390 test1391 test1392 test1393 test1394 test1395 test1396 test1397 test1398 test1399 test14 test140 test1400 test1401 test1402 test1403 test1404 test1405 test1406 test1407 test1408 test1409 test141 test1410 test1411 test1412 test1413 test1414 test1415 test1416 test1417 test1418 test1419 test142 test1420 test1421 test1422 test1423 test1424 test1425 test1426 test1427 test1428 test1429 test143 test1430 test1431 test1432 test1433 test1434 test1435 test1436 test1437 test1438 test1439 test144 test1440 test1441 test1442 test1443 test1444 test1445 test1446 test1447 test1448 test1449 test145 test1450 test1451 test1452 test1453 test1454 test1455 test1456 test1457 test1458 test1459 test146 test1460 test1461 test1462 test1463 test1464 test1465 test1466 test1467 test1468 test1469 test147 test1470 test1471 test1472 test1473 test1474 test1475 test1476 test1477 test1478 test1479 test148 test1480 test1481 test1482 test1483 test1484 test1485 test1486 test1487 test1488 test1489 test149 test1490 test1491 test1492 test1493 test1494 test1495 test1496 test1497 test1498 test1499 test15 test150 test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 test1508 test1509 test151 test1510 test1511 test1512 test1513 test1514 test1515 test1516 test1517 test1518 test1519 test152 test1520 test1521 test1522 test1523 test1524 test1525 test1526 test1527 test1528 test1529 test153 test1530 test1531 test1532 test1533 test1534 test1535 test1536 test1537 test1538 test1539 test154 test1540 test1541 test1542 test1543 test1544 test1545 test1546 test1547 test1548 test1549 test155 test1550 test1551 test1552 test1553 test1554 test1555 test1556 test1557 test1558 test1559 test156 test1560 test1561 test1562 test1563 test1564 test1565 test1566 test1567 test1568 test1569 test157 test1570 test1571 test1572 test1573 test1574 test1575 test1576 test1577 test1578 test1579 test158 test1580 test1581 test1582 test1583 test1584 test1585 test1586 test1587 test1588 test1589 test159 test1590 test1591 test1592 test1593 test1594 test1595 test1596 test1597 test1598 test1599 test16 test160 test1600 test1601 test1602 test1603 test1604 test1605 test1606 test1607 test1608 test1609 test161 test1610 test1611 test1612 test1613 test1614 test1615 test1616 test1617 test1618 test1619 test162 test1620 test1621 test1622 test1623 test1624 test1625 test1626 test1627 test1628 test1629 test163 test1630 test1631 test1632 test1633 test1634 test1635 test1636 test1637 test1638 test1639 test164 test1640 test1641 test1642 test1643 test1644 test1645 test165 test1650 test1651 test1652 test1653 test1654 test1655 test1656 test1657 test1658 test1659 test166 test1660 test1661 test1662 test1663 test1664 test1665 test1666 test1667 test1668 test1669 test167 test1670 test1671 test1672 test1673 test1674 test1675 test1676 test168 test1680 test1681 test1682 test1683 test1684 test1685 test169 test17 test170 test1700 test1701 test1702 test1703 test1704 test1705 test1706 test1707 test1708 test1709 test171 test1710 test1711 test1712 test1713 test1714 test1715 test172 test1720 test1721 test173 test174 test175 test176 test177 test178 test179 test18 test180 test1800 test1801 test1802 test181 test182 test183 test184 test1847 test1848 test1849 test185 test1850 test1851 test186 test187 test188 test189 test19 test190 test1900 test1901 test1902 test1903 test1904 test1905 test1906 test1907 test1908 test1909 test191 test1910 test1911 test1912 test1913 test1914 test1915 test1916 test1917 test1918 test1919 test192 test1920 test1921 test193 test1933 test1934 test1935 test1936 test1937 test1938 test1939 test194 test1940 test1941 test1942 test1943 test1944 test1945 test1946 test1947 test1948 test195 test1955 test1956 test1957 test1958 test1959 test196 test1960 test1964 test1965 test1966 test197 test1970 test1971 test1972 test1973 test1974 test1975 test1976 test1977 test1978 test1979 test198 test1980 test1981 test1982 test1983 test1984 test199 test2 test20 test200 test2000 test2001 test2002 test2003 test2004 test2005 test2006 test2007 test2008 test2009 test201 test2010 test2011 test2012 test2013 test2014 test202 test2023 test2024 test2025 test2026 test2027 test2028 test2029 test203 test2030 test2031 test2032 test2033 test2034 test2035 test2037 test2038 test2039 test204 test2040 test2041 test2042 test2043 test2044 test2045 test2046 test2047 test2048 test2049 test205 test2050 test2051 test2052 test2053 test2054 test2055 test2056 test2057 test2058 test2059 test206 test2060 test2061 test2062 test2063 test2064 test2065 test2066 test2067 test2068 test2069 test207 test2070 test2071 test2072 test2073 test2074 test2075 test2076 test2077 test2078 test2079 test208 test2080 test2081 test2082 test2083 test2084 test2085 test2086 test2087 test2088 test2089 test209 test2090 test2091 test2092 test21 test210 test2100 test2101 test2102 test2103 test2104 test211 test212 test213 test214 test215 test216 test217 test218 test219 test22 test220 test2200 test2201 test2202 test2203 test2204 test2205 test2206 test2207 test221 test222 test223 test224 test225 test226 test227 test228 test229 test23 test230 test2300 test2301 test2302 test2303 test2304 test2306 test2307 test2308 test2309 test231 test232 test233 test234 test235 test236 test237 test238 test239 test24 test240 test2400 test2401 test2402 test2403 test2404 test2405 test2406 test2407 test2408 test2409 test241 test2410 test2411 test242 test243 test244 test245 test246 test247 test248 test249 test25 test250 test2500 test2501 test2502 test2503 test2504 test2505 test2506 test251 test252 test253 test254 test255 test256 test257 test258 test259 test26 test260 test2600 test2601 test2602 test2603 test2604 test2605 test261 test262 test263 test264 test265 test266 test267 test268 test269 test27 test270 test2700 test2701 test2702 test2703 test2704 test2705 test2706 test2707 test2708 test2709 test271 test2710 test2711 test2712 test2713 test2714 test2715 test2716 test2717 test2718 test2719 test272 test2720 test2721 test2722 test2723 test273 test274 test275 test276 test277 test278 test279 test28 test280 test281 test282 test283 test284 test285 test286 test287 test288 test289 test29 test290 test291 test292 test293 test294 test295 test296 test297 test298 test299 test3 test30 test300 test3000 test3001 test3002 test3003 test3004 test3005 test3006 test3007 test3008 test3009 test301 test3010 test3011 test3012 test3013 test3014 test3015 test3016 test3017 test3018 test3019 test302 test3020 test3021 test3022 test3023 test3024 test3025 test3026 test3027 test3028 test3029 test303 test3030 test3031 test3032 test3033 test3034 test3035 test3036 test304 test305 test306 test307 test308 test309 test31 test310 test3100 test3101 test3102 test3103 test3104 test3105 test3106 test311 test312 test313 test314 test315 test316 test317 test318 test319 test32 test320 test3200 test3201 test3202 test3203 test3204 test3205 test3206 test3207 test3208 test3209 test321 test3210 test3211 test3212 test3213 test3214 test3215 test3216 test3217 test3218 test3219 test322 test3220 test323 test324 test325 test326 test327 test328 test329 test33 test330 test3300 test3301 test3302 test331 test332 test333 test334 test335 test336 test337 test338 test339 test34 test340 test341 test342 test343 test344 test345 test346 test347 test348 test349 test35 test350 test351 test352 test353 test354 test355 test356 test357 test358 test359 test36 test360 test361 test362 test363 test364 test365 test366 test367 test368 test369 test37 test370 test371 test372 test373 test374 test375 test376 test378 test379 test38 test380 test381 test383 test384 test385 test386 test387 test388 test389 test39 test390 test391 test392 test393 test394 test395 test396 test397 test398 test399 test4 test40 test400 test4000 test4001 test401 test402 test403 test404 test405 test406 test407 test408 test409 test41 test410 test411 test412 test413 test414 test415 test416 test417 test418 test419 test42 test420 test421 test422 test423 test424 test425 test426 test427 test428 test429 test43 test430 test431 test432 test433 test434 test435 test436 test437 test438 test439 test44 test440 test441 test442 test443 test444 test445 test446 test447 test448 test449 test45 test450 test451 test452 test453 test454 test455 test456 test457 test458 test459 test46 test460 test461 test462 test463 test467 test468 test469 test47 test470 test471 test472 test473 test474 test475 test476 test477 test478 test479 test48 test480 test481 test482 test483 test484 test485 test486 test487 test488 test489 test49 test490 test491 test492 test493 test494 test495 test496 test497 test498 test499 test5 test50 test500 test501 test502 test503 test504 test505 test506 test507 test508 test509 test51 test510 test511 test512 test513 test514 test515 test516 test517 test518 test519 test52 test520 test521 test522 test523 test524 test525 test526 test527 test528 test529 test53 test530 test531 test532 test533 test534 test535 test536 test537 test538 test539 test54 test540 test541 test542 test543 test544 test545 test546 test547 test548 test549 test55 test550 test551 test552 test553 test554 test555 test556 test557 test558 test559 test56 test560 test561 test562 test563 test564 test565 test566 test567 test568 test569 test57 test570 test571 test572 test573 test574 test575 test576 test577 test578 test579 test58 test580 test581 test582 test583 test584 test585 test586 test587 test588 test589 test59 test590 test591 test592 test593 test594 test595 test596 test597 test598 test599 test6 test60 test600 test601 test602 test603 test604 test605 test606 test607 test608 test609 test61 test610 test611 test612 test613 test614 test615 test616 test617 test618 test619 test62 test620 test621 test622 test623 test624 test625 test626 test627 test628 test629 test63 test630 test631 test632 test633 test634 test635 test636 test637 test638 test639 test64 test640 test641 test642 test643 test644 test645 test646 test647 test648 test649 test65 test650 test651 test652 test653 test654 test655 test656 test658 test659 test66 test660 test661 test662 test663 test664 test665 test666 test667 test668 test669 test67 test670 test671 test672 test673 test674 test675 test676 test677 test678 test679 test68 test680 test681 test682 test683 test684 test685 test686 test687 test688 test689 test69 test690 test691 test692 test693 test694 test695 test696 test697 test698 test699 test7 test70 test700 test701 test702 test703 test704 test705 test706 test707 test708 test709 test71 test710 test711 test712 test713 test714 test715 test716 test717 test718 test719 test72 test720 test721 test722 test723 test724 test725 test726 test727 test728 test729 test73 test730 test731 test732 test733 test734 test735 test736 test737 test738 test739 test74 test740 test741 test742 test743 test744 test745 test746 test747 test748 test749 test75 test750 test751 test752 test753 test754 test755 test756 test757 test758 test759 test76 test760 test761 test762 test763 test764 test765 test766 test767 test768 test769 test77 test770 test771 test772 test773 test774 test775 test776 test777 test778 test779 test78 test780 test781 test782 test783 test784 test785 test786 test787 test788 test789 test79 test790 test791 test792 test793 test794 test795 test796 test797 test798 test799 test8 test80 test800 test801 test802 test803 test804 test805 test806 test807 test808 test809 test81 test810 test811 test812 test813 test814 test815 test816 test817 test818 test819 test82 test820 test821 test822 test823 test824 test825 test826 test827 test828 test829 test83 test830 test831 test832 test833 test834 test835 test836 test837 test838 test839 test84 test840 test841 test842 test843 test844 test845 test846 test847 test848 test849 test85 test850 test851 test852 test853 test854 test855 test856 test857 test858 test859 test86 test860 test861 test862 test863 test864 test865 test866 test867 test868 test869 test87 test870 test871 test872 test873 test874 test875 test876 test877 test878 test879 test88 test880 test881 test882 test883 test884 test885 test886 test887 test888 test889 test89 test890 test891 test892 test893 test894 test895 test896 test897 test898 test899 test9 test90 test900 test901 test902 test903 test904 test905 test906 test907 test908 test909 test91 test910 test911 test912 test913 test914 test915 test916 test917 test918 test919 test92 test920 test921 test922 test923 test924 test925 test926 test927 test928 test929 test93 test930 test931 test932 test933 test934 test935 test936 test937 test938 test939 test94 test940 test941 test942 test943 test944 test945 test946 test947 test948 test949 test95 test950 test951 test952 test953 test954 test955 test956 test957 test958 test959 test96 test960 test961 test962 test963 test964 test965 test966 test967 test968 test969 test97 test970 test971 test972 test973 test974 test975 test976 test977 test978 test979 test98 test980 test981 test982 test983 test984 test985 test986 test987 test988 test989 test99 test990 test991 test992 test993 test994 test995 test996 test997 test998 test999http
testenv
__init__.py caddy.py certs.py client.py curl.py dante.py dnsd.py env.py httpd.py nghttpx.py ports.py sshd.py vsftpd.py ws_echo_server.pylibtest
.gitignore CMakeLists.txt Makefile.am Makefile.inc cli_ftp_upload.c cli_h2_pausing.c cli_h2_serverpush.c cli_h2_upgrade_extreme.c cli_hx_download.c cli_hx_upload.c cli_tls_session_reuse.c cli_upload_pausing.c cli_ws_data.c cli_ws_pingpong.c first.c first.h lib1156.c lib1301.c lib1308.c lib1485.c lib1500.c lib1501.c lib1502.c lib1506.c lib1507.c lib1508.c lib1509.c lib1510.c lib1511.c lib1512.c lib1513.c lib1514.c lib1515.c lib1517.c lib1518.c lib1520.c lib1522.c lib1523.c lib1525.c lib1526.c lib1527.c lib1528.c lib1529.c lib1530.c lib1531.c lib1532.c lib1533.c lib1534.c lib1535.c lib1536.c lib1537.c lib1538.c lib1540.c lib1541.c lib1542.c lib1545.c lib1549.c lib1550.c lib1551.c lib1552.c lib1553.c lib1554.c lib1555.c lib1556.c lib1557.c lib1558.c lib1559.c lib1560.c lib1564.c lib1565.c lib1567.c lib1568.c lib1569.c lib1571.c lib1576.c lib1582.c lib1587.c lib1588.c lib1589.c lib1591.c lib1592.c lib1593.c lib1594.c lib1597.c lib1598.c lib1599.c lib1662.c lib1900.c lib1901.c lib1902.c lib1903.c lib1905.c lib1906.c lib1907.c lib1908.c lib1910.c lib1911.c lib1912.c lib1913.c lib1915.c lib1916.c lib1918.c lib1919.c lib1920.c lib1921.c lib1933.c lib1934.c lib1935.c lib1936.c lib1937.c lib1938.c lib1939.c lib1940.c lib1945.c lib1947.c lib1948.c lib1955.c lib1956.c lib1957.c lib1958.c lib1959.c lib1960.c lib1964.c lib1965.c lib1970.c lib1971.c lib1972.c lib1973.c lib1974.c lib1975.c lib1977.c lib1978.c lib2023.c lib2032.c lib2082.c lib2301.c lib2302.c lib2304.c lib2306.c lib2308.c lib2309.c lib2402.c lib2404.c lib2405.c lib2502.c lib2504.c lib2505.c lib2506.c lib2700.c lib3010.c lib3025.c lib3026.c lib3027.c lib3033.c lib3034.c lib3100.c lib3101.c lib3102.c lib3103.c lib3104.c lib3105.c lib3207.c lib3208.c lib500.c lib501.c lib502.c lib503.c lib504.c lib505.c lib506.c lib507.c lib508.c lib509.c lib510.c lib511.c lib512.c lib513.c lib514.c lib515.c lib516.c lib517.c lib518.c lib519.c lib520.c lib521.c lib523.c lib524.c lib525.c lib526.c lib530.c lib533.c lib536.c lib537.c lib539.c lib540.c lib541.c lib542.c lib543.c lib544.c lib547.c lib549.c lib552.c lib553.c lib554.c lib555.c lib556.c lib557.c lib558.c lib559.c lib560.c lib562.c lib564.c lib566.c lib567.c lib568.c lib569.c lib570.c lib571.c lib572.c lib573.c lib574.c lib575.c lib576.c lib578.c lib579.c lib582.c lib583.c lib586.c lib589.c lib590.c lib591.c lib597.c lib598.c lib599.c lib643.c lib650.c lib651.c lib652.c lib653.c lib654.c lib655.c lib658.c lib659.c lib661.c lib666.c lib667.c lib668.c lib670.c lib674.c lib676.c lib677.c lib678.c lib694.c lib695.c lib751.c lib753.c lib757.c lib758.c lib766.c memptr.c mk-lib1521.pl test1013.pl test1022.pl test307.pl test610.pl test613.pl testtrace.c testtrace.h testutil.c testutil.h unitcheck.hserver
.checksrc .gitignore CMakeLists.txt Makefile.am Makefile.inc dnsd.c first.c first.h getpart.c mqttd.c resolve.c rtspd.c sockfilt.c socksd.c sws.c tftpd.c util.ctunit
.gitignore CMakeLists.txt Makefile.am Makefile.inc README.md tool1394.c tool1604.c tool1621.c tool1622.c tool1623.c tool1720.cunit
.gitignore CMakeLists.txt Makefile.am Makefile.inc README.md unit1300.c unit1302.c unit1303.c unit1304.c unit1305.c unit1307.c unit1309.c unit1323.c unit1330.c unit1395.c unit1396.c unit1397.c unit1398.c unit1399.c unit1600.c unit1601.c unit1602.c unit1603.c unit1605.c unit1606.c unit1607.c unit1608.c unit1609.c unit1610.c unit1611.c unit1612.c unit1614.c unit1615.c unit1616.c unit1620.c unit1625.c unit1626.c unit1627.c unit1636.c unit1650.c unit1651.c unit1652.c unit1653.c unit1654.c unit1655.c unit1656.c unit1657.c unit1658.c unit1660.c unit1661.c unit1663.c unit1664.c unit1666.c unit1667.c unit1668.c unit1669.c unit1674.c unit1675.c unit1676.c unit1979.c unit1980.c unit2600.c unit2601.c unit2602.c unit2603.c unit2604.c unit2605.c unit3200.c unit3205.c unit3211.c unit3212.c unit3213.c unit3214.c unit3216.c unit3219.c unit3300.c unit3301.c unit3302.cexamples
.env config.ini crypto_test.lua env_test.lua fs_example.lua http_server.lua https_test.lua ini_example.lua json.lua log.lua path_fs_example.lua process_example.lua request_download.lua request_test.lua run_all.lua sqlite_example.lua sqlite_http_template.lua stash_test.lua template_test.lua timer.lua websocket.luainiparser
example
iniexample.c iniwrite.c parse.c twisted-errors.ini twisted-genhuge.py twisted-ofkey.ini twisted-ofval.ini twisted.initest
CMakeLists.txt test_dictionary.c test_iniparser.c unity-config.yml unity_config.hjinjac
libjinjac
src
CMakeLists.txt ast.c ast.h block_statement.c block_statement.h buffer.c buffer.h buildin.c buildin.h common.h convert.c convert.h flex_decl.h jfunction.c jfunction.h jinja_expression.l jinja_expression.y jinjac_parse.c jinjac_parse.h jinjac_stream.c jinjac_stream.h jlist.c jlist.h jobject.c jobject.h parameter.c parameter.h str_obj.c str_obj.h trace.c trace.htest
.gitignore CMakeLists.txt autotest.rb test_01.expected test_01.jinja test_01b.expected test_01b.jinja test_01c.expected test_01c.jinja test_01d.expected test_01d.jinja test_02.expected test_02.jinja test_03.expected test_03.jinja test_04.expected test_04.jinja test_05.expected test_05.jinja test_06.expected test_06.jinja test_07.expected test_07.jinja test_08.expected test_08.jinja test_08b.expected test_08b.jinja test_09.expected test_09.jinja test_10.expected test_10.jinja test_11.expected test_11.jinja test_12.expected test_12.jinja test_13.expected test_13.jinja test_14.expected test_14.jinja test_15.expected test_15.jinja test_16.expected test_16.jinja test_17.expected test_17.jinja test_18.expected test_18.jinja test_18b.expected test_18b.jinja test_18c.expected test_18c.jinja test_19.expected test_19.jinja test_19b.expected test_19b.jinja test_19c.expected test_19c.jinja test_19d.expected test_19d.jinja test_19e.expected test_19e.jinja test_19f.expected test_19f.jinja test_20.expected test_20.jinja test_21.expected test_21.jinja test_22.expected test_22.jinja test_22a.expected test_22a.jinja test_22b.expected test_22b.jinja test_23.expected test_23.jinja test_24.expected test_24.jinjalibev
Changes LICENSE Makefile Makefile.am Makefile.in README Symbols.ev Symbols.event aclocal.m4 autogen.sh compile config.guess config.h config.h.in config.status config.sub configure configure.ac depcomp ev++.h ev.3 ev.c ev.h ev.pod ev_epoll.c ev_kqueue.c ev_poll.c ev_port.c ev_select.c ev_vars.h ev_win32.c ev_wrap.h event.c event.h install-sh libev.m4 libtool ltmain.sh missing mkinstalldirs stamp-h1luajit
doc
bluequad-print.css bluequad.css contact.html ext_buffer.html ext_c_api.html ext_ffi.html ext_ffi_api.html ext_ffi_semantics.html ext_ffi_tutorial.html ext_jit.html ext_profiler.html extensions.html install.html luajit.html running.htmldynasm
dasm_arm.h dasm_arm.lua dasm_arm64.h dasm_arm64.lua dasm_mips.h dasm_mips.lua dasm_mips64.lua dasm_ppc.h dasm_ppc.lua dasm_proto.h dasm_x64.lua dasm_x86.h dasm_x86.lua dynasm.luasrc
host
.gitignore README buildvm.c buildvm.h buildvm_asm.c buildvm_fold.c buildvm_lib.c buildvm_libbc.h buildvm_peobj.c genlibbc.lua genminilua.lua genversion.lua minilua.cjit
.gitignore bc.lua bcsave.lua dis_arm.lua dis_arm64.lua dis_arm64be.lua dis_mips.lua dis_mips64.lua dis_mips64el.lua dis_mips64r6.lua dis_mips64r6el.lua dis_mipsel.lua dis_ppc.lua dis_x64.lua dis_x86.lua dump.lua p.lua v.lua zone.luawolfssl
.github
workflows
ada.yml arduino.yml async-examples.yml async.yml atecc608-sim.yml bind.yml cmake-autoconf.yml cmake.yml codespell.yml coverity-scan-fixes.yml cryptocb-only.yml curl.yml cyrus-sasl.yml disable-pk-algs.yml docker-Espressif.yml docker-OpenWrt.yml emnet-nonblock.yml fil-c.yml freertos-mem-track.yml gencertbuf.yml grpc.yml haproxy.yml hostap-vm.yml intelasm-c-fallback.yml ipmitool.yml jwt-cpp.yml krb5.yml libspdm.yml libssh2.yml libvncserver.yml linuxkm.yml macos-apple-native-cert-validation.yml mbedtls.sh mbedtls.yml membrowse-comment.yml membrowse-onboard.yml membrowse-report.yml memcached.sh memcached.yml mono.yml mosquitto.yml msmtp.yml msys2.yml multi-arch.yml multi-compiler.yml net-snmp.yml nginx.yml no-malloc.yml no-tls.yml nss.sh nss.yml ntp.yml ocsp.yml openldap.yml openssh.yml openssl-ech.yml opensslcoexist.yml openvpn.yml os-check.yml packaging.yml pam-ipmi.yml pq-all.yml pr-commit-check.yml psk.yml puf.yml python.yml rng-tools.yml rust-wrapper.yml se050-sim.yml smallStackSize.yml socat.yml softhsm.yml sssd.yml stm32-sim.yml stsafe-a120-sim.yml stunnel.yml symbol-prefixes.yml threadx.yml tls-anvil.yml trackmemory.yml watcomc.yml win-csharp-test.yml wolfCrypt-Wconversion.yml wolfboot-integration.yml wolfsm.yml xcode.yml zephyr-4.x.yml zephyr.ymlIDE
ARDUINO
Arduino_README_prepend.md README.md include.am keywords.txt library.properties.template wolfssl-arduino.cpp wolfssl-arduino.sh wolfssl.hECLIPSE
Espressif
ESP-IDF
examples
template
CMakeLists.txt Makefile README.md partitions_singleapp_large.csv sdkconfig.defaults sdkconfig.defaults.esp8266wolfssl_benchmark
VisualGDB
wolfssl_benchmark_IDF_v4.4_ESP32.sln wolfssl_benchmark_IDF_v4.4_ESP32.vgdbproj wolfssl_benchmark_IDF_v5_ESP32.sln wolfssl_benchmark_IDF_v5_ESP32.vgdbproj wolfssl_benchmark_IDF_v5_ESP32C3.sln wolfssl_benchmark_IDF_v5_ESP32C3.vgdbproj wolfssl_benchmark_IDF_v5_ESP32S3.sln wolfssl_benchmark_IDF_v5_ESP32S3.vgdbprojwolfssl_client
CMakeLists.txt Makefile README.md README_server_sm.md partitions_singleapp_large.csv sdkconfig.defaults sdkconfig.defaults.esp32c2 sdkconfig.defaults.esp8266 wolfssl_client_ESP8266.vgdbprojwolfssl_server
CMakeLists.txt Makefile README.md README_server_sm.md partitions_singleapp_large.csv sdkconfig.defaults sdkconfig.defaults.esp32c2 sdkconfig.defaults.esp8266 wolfssl_server_ESP8266.vgdbprojwolfssl_test
VisualGDB
wolfssl_test-IDF_v5_ESP32.sln wolfssl_test-IDF_v5_ESP32.vgdbproj wolfssl_test-IDF_v5_ESP32C3.sln wolfssl_test-IDF_v5_ESP32C3.vgdbproj wolfssl_test-IDF_v5_ESP32C6.sln wolfssl_test-IDF_v5_ESP32C6.vgdbproj wolfssl_test_IDF_v5_ESP32S3.sln wolfssl_test_IDF_v5_ESP32S3.vgdbprojGCC-ARM
Makefile Makefile.bench Makefile.client Makefile.common Makefile.server Makefile.static Makefile.test README.md include.am linker.ld linker_fips.ldIAR-EWARM
embOS
SAMV71_XULT
embOS_SAMV71_XULT_user_settings
user_settings.h user_settings_simple_example.h user_settings_verbose_example.hembOS_wolfcrypt_benchmark_SAMV71_XULT
README_wolfcrypt_benchmark wolfcrypt_benchmark.ewd wolfcrypt_benchmark.ewpINTIME-RTOS
Makefile README.md include.am libwolfssl.c libwolfssl.vcxproj user_settings.h wolfExamples.c wolfExamples.h wolfExamples.sln wolfExamples.vcxproj wolfssl-lib.sln wolfssl-lib.vcxprojMQX
Makefile README-jp.md README.md client-tls.c include.am server-tls.c user_config.h user_settings.hMSVS-2019-AZSPHERE
wolfssl_new_azsphere
.gitignore CMakeLists.txt CMakeSettings.json app_manifest.json applibs_versions.h launch.vs.json main.cNETOS
Makefile.wolfcrypt.inc README.md include.am user_settings.h user_settings.h-cert2425 user_settings.h-cert3389 wolfssl_netos_custom.cPlatformIO
examples
wolfssl_benchmark
CMakeLists.txt README.md platformio.ini sdkconfig.defaults wolfssl_benchmark.code-workspaceROWLEY-CROSSWORKS-ARM
Kinetis_FlashPlacement.xml README.md arm_startup.c benchmark_main.c hw.h include.am kinetis_hw.c retarget.c test_main.c user_settings.h wolfssl.hzp wolfssl_ltc.hzpRenesas
e2studio
RA6M3
README.md README_APRA6M_en.md README_APRA6M_jp.md include.amRX72N
EnvisionKit
Simple
README_EN.md README_JP.mdwolfssl_demo
key_data.c key_data.h user_settings.h wolfssl_demo.c wolfssl_demo.h wolfssl_tsip_unit_test.cSTM32Cube
README.md STM32_Benchmarks.md default_conf.ftl include.am main.c wolfssl_example.c wolfssl_example.hWIN
README.txt include.am test.vcxproj user_settings.h user_settings_dtls.h wolfssl-fips.sln wolfssl-fips.vcxprojWIN-SRTP-KDF-140-3
README.txt include.am resource.h test.vcxproj user_settings.h wolfssl-fips.rc wolfssl-fips.sln wolfssl-fips.vcxprojWIN10
README.txt include.am resource.h test.vcxproj user_settings.h wolfssl-fips.rc wolfssl-fips.sln wolfssl-fips.vcxprojXCODE
Benchmark
include.amXilinxSDK
README.md bench.sh combine.sh eclipse_formatter_profile.xml graph.sh include.am user_settings.h wolfssl_example.capple-universal
wolfssl-multiplatform
iotsafe
Makefile README.md ca-cert.c devices.c devices.h include.am main.c memory-tls.c startup.c target.ld user_settings.hmynewt
README.md apps.wolfcrypttest.pkg.yml crypto.wolfssl.pkg.yml crypto.wolfssl.syscfg.yml include.am setup.shcerts
1024
ca-cert.der ca-cert.pem ca-key.der ca-key.pem client-cert.der client-cert.pem client-key.der client-key.pem client-keyPub.der dh1024.der dh1024.pem dsa-pub-1024.pem dsa1024.der dsa1024.pem include.am rsa1024.der server-cert.der server-cert.pem server-key.der server-key.pemcrl
extra-crls
ca-int-cert-revoked.pem claim-root.pem crl_critical_entry.pem crlnum_57oct.pem crlnum_64oct.pem general-server-crl.pem large_crlnum.pem large_crlnum2.pemdilithium
bench_dilithium_level2_key.der bench_dilithium_level3_key.der bench_dilithium_level5_key.der include.amecc
bp256r1-key.der bp256r1-key.pem ca-secp256k1-cert.pem ca-secp256k1-key.pem client-bp256r1-cert.der client-bp256r1-cert.pem client-secp256k1-cert.der client-secp256k1-cert.pem genecc.sh include.am secp256k1-key.der secp256k1-key.pem secp256k1-param.pem secp256k1-privkey.der secp256k1-privkey.pem server-bp256r1-cert.der server-bp256r1-cert.pem server-secp256k1-cert.der server-secp256k1-cert.pem server2-secp256k1-cert.der server2-secp256k1-cert.pem wolfssl.cnf wolfssl_384.cnfed25519
ca-ed25519-key.der ca-ed25519-key.pem ca-ed25519-priv.der ca-ed25519-priv.pem ca-ed25519.der ca-ed25519.pem client-ed25519-key.der client-ed25519-key.pem client-ed25519-priv.der client-ed25519-priv.pem client-ed25519.der client-ed25519.pem eddsa-ed25519.der eddsa-ed25519.pem gen-ed25519-certs.sh gen-ed25519-keys.sh gen-ed25519.sh include.am root-ed25519-key.der root-ed25519-key.pem root-ed25519-priv.der root-ed25519-priv.pem root-ed25519.der root-ed25519.pem server-ed25519-cert.pem server-ed25519-key.der server-ed25519-key.pem server-ed25519-priv.der server-ed25519-priv.pem server-ed25519.der server-ed25519.pemed448
ca-ed448-key.der ca-ed448-key.pem ca-ed448-priv.der ca-ed448-priv.pem ca-ed448.der ca-ed448.pem client-ed448-key.der client-ed448-key.pem client-ed448-priv.der client-ed448-priv.pem client-ed448.der client-ed448.pem gen-ed448-certs.sh gen-ed448-keys.sh include.am root-ed448-key.der root-ed448-key.pem root-ed448-priv.der root-ed448-priv.pem root-ed448.der root-ed448.pem server-ed448-cert.pem server-ed448-key.der server-ed448-key.pem server-ed448-priv.der server-ed448-priv.pem server-ed448.der server-ed448.pemexternal
DigiCertGlobalRootCA.pem README.txt ca-digicert-ev.pem ca-globalsign-root.pem ca-google-root.pem ca_collection.pem include.amintermediate
ca_false_intermediate
gentestcert.sh int_ca.key server.key test_ca.key test_ca.pem test_int_not_cacert.pem test_sign_bynoca_srv.pem wolfssl_base.conf wolfssl_srv.conflms
bc_hss_L2_H5_W8_root.der bc_hss_L3_H5_W4_root.der bc_lms_chain_ca.der bc_lms_chain_leaf.der bc_lms_native_bc_root.der bc_lms_sha256_h10_w8_root.der bc_lms_sha256_h5_w4_root.der include.ammldsa
README.txt include.am mldsa44-cert.der mldsa44-cert.pem mldsa44-key.pem mldsa44_bare-priv.der mldsa44_bare-seed.der mldsa44_oqskeypair.der mldsa44_priv-only.der mldsa44_pub-spki.der mldsa44_seed-only.der mldsa44_seed-priv.der mldsa65-cert.der mldsa65-cert.pem mldsa65-key.pem mldsa65_bare-priv.der mldsa65_bare-seed.der mldsa65_oqskeypair.der mldsa65_priv-only.der mldsa65_pub-spki.der mldsa65_seed-only.der mldsa65_seed-priv.der mldsa87-cert.der mldsa87-cert.pem mldsa87-key.pem mldsa87_bare-priv.der mldsa87_bare-seed.der mldsa87_oqskeypair.der mldsa87_priv-only.der mldsa87_pub-spki.der mldsa87_seed-only.der mldsa87_seed-priv.derocsp
imposter-root-ca-cert.der imposter-root-ca-cert.pem imposter-root-ca-key.der imposter-root-ca-key.pem include.am index-ca-and-intermediate-cas.txt index-ca-and-intermediate-cas.txt.attr index-intermediate1-ca-issued-certs.txt index-intermediate1-ca-issued-certs.txt.attr index-intermediate2-ca-issued-certs.txt index-intermediate2-ca-issued-certs.txt.attr index-intermediate3-ca-issued-certs.txt index-intermediate3-ca-issued-certs.txt.attr intermediate1-ca-cert.der intermediate1-ca-cert.pem intermediate1-ca-key.der intermediate1-ca-key.pem intermediate2-ca-cert.der intermediate2-ca-cert.pem intermediate2-ca-key.der intermediate2-ca-key.pem intermediate3-ca-cert.der intermediate3-ca-cert.pem intermediate3-ca-key.der intermediate3-ca-key.pem ocsp-responder-cert.der ocsp-responder-cert.pem ocsp-responder-key.der ocsp-responder-key.pem openssl.cnf renewcerts-for-test.sh renewcerts.sh root-ca-cert.der root-ca-cert.pem root-ca-crl.pem root-ca-key.der root-ca-key.pem server1-cert.der server1-cert.pem server1-chain-noroot.pem server1-key.der server1-key.pem server2-cert.der server2-cert.pem server2-key.der server2-key.pem server3-cert.der server3-cert.pem server3-key.der server3-key.pem server4-cert.der server4-cert.pem server4-key.der server4-key.pem server5-cert.der server5-cert.pem server5-key.der server5-key.pem test-leaf-response.der test-multi-response.der test-response-nointern.der test-response-rsapss.der test-response.derp521
ca-p521-key.der ca-p521-key.pem ca-p521-priv.der ca-p521-priv.pem ca-p521.der ca-p521.pem client-p521-key.der client-p521-key.pem client-p521-priv.der client-p521-priv.pem client-p521.der client-p521.pem gen-p521-certs.sh gen-p521-keys.sh include.am root-p521-key.der root-p521-key.pem root-p521-priv.der root-p521-priv.pem root-p521.der root-p521.pem server-p521-cert.pem server-p521-key.der server-p521-key.pem server-p521-priv.der server-p521-priv.pem server-p521.der server-p521.pemrpk
client-cert-rpk.der client-ecc-cert-rpk.der include.am server-cert-rpk.der server-ecc-cert-rpk.derrsapss
ca-3072-rsapss-key.der ca-3072-rsapss-key.pem ca-3072-rsapss-priv.der ca-3072-rsapss-priv.pem ca-3072-rsapss.der ca-3072-rsapss.pem ca-rsapss-key.der ca-rsapss-key.pem ca-rsapss-priv.der ca-rsapss-priv.pem ca-rsapss.der ca-rsapss.pem client-3072-rsapss-key.der client-3072-rsapss-key.pem client-3072-rsapss-priv.der client-3072-rsapss-priv.pem client-3072-rsapss.der client-3072-rsapss.pem client-rsapss-key.der client-rsapss-key.pem client-rsapss-priv.der client-rsapss-priv.pem client-rsapss.der client-rsapss.pem gen-rsapss-keys.sh include.am renew-rsapss-certs.sh root-3072-rsapss-key.der root-3072-rsapss-key.pem root-3072-rsapss-priv.der root-3072-rsapss-priv.pem root-3072-rsapss.der root-3072-rsapss.pem root-rsapss-key.der root-rsapss-key.pem root-rsapss-priv.der root-rsapss-priv.pem root-rsapss.der root-rsapss.pem server-3072-rsapss-cert.pem server-3072-rsapss-key.der server-3072-rsapss-key.pem server-3072-rsapss-priv.der server-3072-rsapss-priv.pem server-3072-rsapss.der server-3072-rsapss.pem server-mix-rsapss-cert.pem server-rsapss-cert.pem server-rsapss-key.der server-rsapss-key.pem server-rsapss-priv.der server-rsapss-priv.pem server-rsapss.der server-rsapss.pemslhdsa
bench_slhdsa_sha2_128f_key.der bench_slhdsa_sha2_128s_key.der bench_slhdsa_sha2_192f_key.der bench_slhdsa_sha2_192s_key.der bench_slhdsa_sha2_256f_key.der bench_slhdsa_sha2_256s_key.der bench_slhdsa_shake128f_key.der bench_slhdsa_shake128s_key.der bench_slhdsa_shake192f_key.der bench_slhdsa_shake192s_key.der bench_slhdsa_shake256f_key.der bench_slhdsa_shake256s_key.der client-mldsa44-priv.pem client-mldsa44-sha2.der client-mldsa44-sha2.pem client-mldsa44-shake.der client-mldsa44-shake.pem gen-slhdsa-mldsa-certs.sh include.am root-slhdsa-sha2-128s-priv.der root-slhdsa-sha2-128s-priv.pem root-slhdsa-sha2-128s.der root-slhdsa-sha2-128s.pem root-slhdsa-shake-128s-priv.der root-slhdsa-shake-128s-priv.pem root-slhdsa-shake-128s.der root-slhdsa-shake-128s.pem server-mldsa44-priv.pem server-mldsa44-sha2.der server-mldsa44-sha2.pem server-mldsa44-shake.der server-mldsa44-shake.pemsm2
ca-sm2-key.der ca-sm2-key.pem ca-sm2-priv.der ca-sm2-priv.pem ca-sm2.der ca-sm2.pem client-sm2-key.der client-sm2-key.pem client-sm2-priv.der client-sm2-priv.pem client-sm2.der client-sm2.pem fix_sm2_spki.py gen-sm2-certs.sh gen-sm2-keys.sh include.am root-sm2-key.der root-sm2-key.pem root-sm2-priv.der root-sm2-priv.pem root-sm2.der root-sm2.pem self-sm2-cert.pem self-sm2-key.pem self-sm2-priv.pem server-sm2-cert.der server-sm2-cert.pem server-sm2-key.der server-sm2-key.pem server-sm2-priv.der server-sm2-priv.pem server-sm2.der server-sm2.pemstatickeys
dh-ffdhe2048-params.pem dh-ffdhe2048-pub.der dh-ffdhe2048-pub.pem dh-ffdhe2048.der dh-ffdhe2048.pem ecc-secp256r1.der ecc-secp256r1.pem gen-static.sh include.am x25519-pub.der x25519-pub.pem x25519.der x25519.pemtest
catalog.txt cert-bad-neg-int.der cert-bad-oid.der cert-bad-utf8.der cert-ext-ia.cfg cert-ext-ia.der cert-ext-ia.pem cert-ext-joi.cfg cert-ext-joi.der cert-ext-joi.pem cert-ext-mnc.der cert-ext-multiple.cfg cert-ext-multiple.der cert-ext-multiple.pem cert-ext-nc-combined.der cert-ext-nc-combined.pem cert-ext-nc.cfg cert-ext-nc.der cert-ext-nc.pem cert-ext-ncdns.der cert-ext-ncdns.pem cert-ext-ncip.der cert-ext-ncip.pem cert-ext-ncmixed.der cert-ext-ncmulti.der cert-ext-ncmulti.pem cert-ext-ncrid.der cert-ext-ncrid.pem cert-ext-nct.cfg cert-ext-nct.der cert-ext-nct.pem cert-ext-ndir-exc.cfg cert-ext-ndir-exc.der cert-ext-ndir-exc.pem cert-ext-ndir.cfg cert-ext-ndir.der cert-ext-ndir.pem cert-ext-ns.der cert-over-max-altnames.cfg cert-over-max-altnames.der cert-over-max-altnames.pem cert-over-max-nc.cfg cert-over-max-nc.der cert-over-max-nc.pem client-ecc-cert-ski.hex cn-ip-literal.der cn-ip-wildcard.der crit-cert.pem crit-key.pem dh1024.der dh1024.pem dh512.der dh512.pem digsigku.pem encrypteddata.msg gen-badsig.sh gen-ext-certs.sh gen-testcerts.sh include.am kari-keyid-cms.msg ktri-keyid-cms.msg ossl-trusted-cert.pem server-badaltname.der server-badaltname.pem server-badaltnull.der server-badaltnull.pem server-badcn.der server-badcn.pem server-badcnnull.der server-badcnnull.pem server-cert-ecc-badsig.der server-cert-ecc-badsig.pem server-cert-rsa-badsig.der server-cert-rsa-badsig.pem server-duplicate-policy.pem server-garbage.der server-garbage.pem server-goodalt.der server-goodalt.pem server-goodaltwild.der server-goodaltwild.pem server-goodcn.der server-goodcn.pem server-goodcnwild.der server-goodcnwild.pem server-localhost.der server-localhost.pem smime-test-canon.p7s smime-test-multipart-badsig.p7s smime-test-multipart.p7s smime-test.p7stest-pathlen
assemble-chains.sh chainA-ICA1-key.pem chainA-ICA1-pathlen0.pem chainA-assembled.pem chainA-entity-key.pem chainA-entity.pem chainB-ICA1-key.pem chainB-ICA1-pathlen0.pem chainB-ICA2-key.pem chainB-ICA2-pathlen1.pem chainB-assembled.pem chainB-entity-key.pem chainB-entity.pem chainC-ICA1-key.pem chainC-ICA1-pathlen1.pem chainC-assembled.pem chainC-entity-key.pem chainC-entity.pem chainD-ICA1-key.pem chainD-ICA1-pathlen127.pem chainD-assembled.pem chainD-entity-key.pem chainD-entity.pem chainE-ICA1-key.pem chainE-ICA1-pathlen128.pem chainE-assembled.pem chainE-entity-key.pem chainE-entity.pem chainF-ICA1-key.pem chainF-ICA1-pathlen1.pem chainF-ICA2-key.pem chainF-ICA2-pathlen0.pem chainF-assembled.pem chainF-entity-key.pem chainF-entity.pem chainG-ICA1-key.pem chainG-ICA1-pathlen0.pem chainG-ICA2-key.pem chainG-ICA2-pathlen1.pem chainG-ICA3-key.pem chainG-ICA3-pathlen99.pem chainG-ICA4-key.pem chainG-ICA4-pathlen5.pem chainG-ICA5-key.pem chainG-ICA5-pathlen20.pem chainG-ICA6-key.pem chainG-ICA6-pathlen10.pem chainG-ICA7-key.pem chainG-ICA7-pathlen100.pem chainG-assembled.pem chainG-entity-key.pem chainG-entity.pem chainH-ICA1-key.pem chainH-ICA1-pathlen0.pem chainH-ICA2-key.pem chainH-ICA2-pathlen2.pem chainH-ICA3-key.pem chainH-ICA3-pathlen2.pem chainH-ICA4-key.pem chainH-ICA4-pathlen2.pem chainH-assembled.pem chainH-entity-key.pem chainH-entity.pem chainI-ICA1-key.pem chainI-ICA1-no_pathlen.pem chainI-ICA2-key.pem chainI-ICA2-no_pathlen.pem chainI-ICA3-key.pem chainI-ICA3-pathlen2.pem chainI-assembled.pem chainI-entity-key.pem chainI-entity.pem chainJ-ICA1-key.pem chainJ-ICA1-no_pathlen.pem chainJ-ICA2-key.pem chainJ-ICA2-no_pathlen.pem chainJ-ICA3-key.pem chainJ-ICA3-no_pathlen.pem chainJ-ICA4-key.pem chainJ-ICA4-pathlen2.pem chainJ-assembled.pem chainJ-entity-key.pem chainJ-entity.pem include.am refreshkeys.shtest-serial0
ee_normal.pem ee_serial0.pem generate_certs.sh include.am intermediate_serial0.pem root_serial0.pem root_serial0_key.pem selfsigned_nonca_serial0.pemxmss
bc_xmss_chain_ca.der bc_xmss_chain_leaf.der bc_xmss_sha2_10_256_root.der bc_xmss_sha2_16_256_root.der bc_xmssmt_sha2_20_2_256_root.der bc_xmssmt_sha2_20_4_256_root.der bc_xmssmt_sha2_40_8_256_root.der include.amcmake
Config.cmake.in README.md config.in functions.cmake include.am options.h.in wolfssl-config-version.cmake.in wolfssl-targets.cmake.indebian
changelog.in control.in copyright include.am libwolfssl-dev.install libwolfssl.install rules.indoc
dox_comments
header_files
aes.h arc4.h ascon.h asn.h asn_public.h blake2.h bn.h camellia.h chacha.h chacha20_poly1305.h cmac.h coding.h compress.h cryptocb.h curve25519.h curve448.h des3.h dh.h doxygen_groups.h doxygen_pages.h dsa.h ecc.h eccsi.h ed25519.h ed448.h error-crypt.h evp.h hash.h hmac.h iotsafe.h kdf.h logging.h md2.h md4.h md5.h memory.h ocsp.h pem.h pkcs11.h pkcs7.h poly1305.h psa.h puf.h pwdbased.h quic.h random.h ripemd.h rsa.h sakke.h sha.h sha256.h sha3.h sha512.h signature.h siphash.h srp.h ssl.h tfm.h types.h wc_encrypt.h wc_port.h wc_she.h wc_slhdsa.h wolfio.hheader_files-ja
aes.h arc4.h ascon.h asn.h asn_public.h blake2.h bn.h camellia.h chacha.h chacha20_poly1305.h cmac.h coding.h compress.h cryptocb.h curve25519.h curve448.h des3.h dh.h doxygen_groups.h doxygen_pages.h dsa.h ecc.h eccsi.h ed25519.h ed448.h error-crypt.h evp.h hash.h hmac.h iotsafe.h kdf.h logging.h md2.h md4.h md5.h memory.h ocsp.h pem.h pkcs11.h pkcs7.h poly1305.h psa.h pwdbased.h quic.h random.h ripemd.h rsa.h sakke.h sha.h sha256.h sha3.h sha512.h signature.h siphash.h srp.h ssl.h tfm.h types.h wc_encrypt.h wc_port.h wolfio.hexamples
async
Makefile README.md async_client.c async_server.c async_tls.c async_tls.h include.am user_settings.hconfigs
README.md include.am user_settings_EBSnet.h user_settings_all.h user_settings_arduino.h user_settings_baremetal.h user_settings_ca.h user_settings_curve25519nonblock.h user_settings_dtls13.h user_settings_eccnonblock.h user_settings_espressif.h user_settings_fipsv2.h user_settings_fipsv5.h user_settings_min_ecc.h user_settings_openssl_compat.h user_settings_pkcs7.h user_settings_platformio.h user_settings_pq.h user_settings_rsa_only.h user_settings_stm32.h user_settings_template.h user_settings_tls12.h user_settings_tls13.h user_settings_wolfboot_keytools.h user_settings_wolfssh.h user_settings_wolftpm.hechoclient
echoclient.c echoclient.h echoclient.sln echoclient.vcproj echoclient.vcxproj include.am quitlinuxkm
Kbuild Makefile README.md get_thread_size.c include.am linuxkm-fips-hash-wrapper.sh linuxkm-fips-hash.c linuxkm_memory.c linuxkm_memory.h linuxkm_wc_port.h lkcapi_aes_glue.c lkcapi_dh_glue.c lkcapi_ecdh_glue.c lkcapi_ecdsa_glue.c lkcapi_glue.c lkcapi_rsa_glue.c lkcapi_sha_glue.c module_exports.c.template module_hooks.c pie_redirect_table.c wolfcrypt.lds x86_vector_register_glue.cm4
ax_add_am_macro.m4 ax_am_jobserver.m4 ax_am_macros.m4 ax_append_compile_flags.m4 ax_append_flag.m4 ax_append_link_flags.m4 ax_append_to_file.m4 ax_atomic.m4 ax_bsdkm.m4 ax_check_compile_flag.m4 ax_check_link_flag.m4 ax_compiler_version.m4 ax_count_cpus.m4 ax_create_generic_config.m4 ax_debug.m4 ax_file_escapes.m4 ax_harden_compiler_flags.m4 ax_linuxkm.m4 ax_print_to_file.m4 ax_pthread.m4 ax_require_defined.m4 ax_tls.m4 ax_vcs_checkout.m4 hexversion.m4 lib_socket_nsl.m4 visibility.m4mqx
wolfcrypt_benchmark
ReferencedRSESystems.xml wolfcrypt_benchmark_twrk70f120m_Int_Flash_DDRData_Debug_PnE_U-MultiLink.launch wolfcrypt_benchmark_twrk70f120m_Int_Flash_DDRData_Release_PnE_U-MultiLink.launch wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Debug_JTrace.jlink wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Debug_JTrace.launch wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Debug_PnE_U-MultiLink.launch wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Release_PnE_U-MultiLink.launchwolfcrypt_test
ReferencedRSESystems.xml wolfcrypt_test_twrk70f120m_Int_Flash_DDRData_Debug_PnE_U-MultiLink.launch wolfcrypt_test_twrk70f120m_Int_Flash_DDRData_Release_PnE_U-MultiLink.launch wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Debug_JTrace.jlink wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Debug_JTrace.launch wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Debug_PnE_U-MultiLink.launch wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Release_PnE_U-MultiLink.launchwolfssl_client
ReferencedRSESystems.xml wolfssl_client_twrk70f120m_Int_Flash_DDRData_Debug_PnE_U-MultiLink.launch wolfssl_client_twrk70f120m_Int_Flash_DDRData_Release_PnE_U-MultiLink.launch wolfssl_client_twrk70f120m_Int_Flash_SramData_Debug_JTrace.jlink wolfssl_client_twrk70f120m_Int_Flash_SramData_Debug_JTrace.launch wolfssl_client_twrk70f120m_Int_Flash_SramData_Debug_PnE_U-MultiLink.launch wolfssl_client_twrk70f120m_Int_Flash_SramData_Release_PnE_U-MultiLink.launchscripts
aria-cmake-build-test.sh asn1_oid_sum.pl benchmark.test benchmark_compare.sh cleanup_testfiles.sh crl-gen-openssl.test crl-revoked.test dertoc.pl dtls.test dtlscid.test external.test google.test include.am makedistsmall.sh memtest.sh ocsp-responder-openssl-interop.test ocsp-stapling-with-ca-as-responder.test ocsp-stapling-with-wolfssl-responder.test ocsp-stapling.test ocsp-stapling2.test ocsp-stapling_tls13multi.test ocsp.test openssl.test openssl_srtp.test pem.test ping.test pkcallbacks.test psk.test resume.test rsapss.test sniffer-gen.sh sniffer-ipv6.pcap sniffer-static-rsa.pcap sniffer-testsuite.test sniffer-tls12-keylog.out sniffer-tls12-keylog.pcap sniffer-tls12-keylog.sslkeylog sniffer-tls13-dh-resume.pcap sniffer-tls13-dh.pcap sniffer-tls13-ecc-resume.pcap sniffer-tls13-ecc.pcap sniffer-tls13-hrr.pcap sniffer-tls13-keylog.out sniffer-tls13-keylog.pcap sniffer-tls13-keylog.sslkeylog sniffer-tls13-x25519-resume.pcap sniffer-tls13-x25519.pcap stm32l4-v4_0_1_build.sh tls13.test trusted_peer.test unit.test.in user_settings_asm.shsrc
bio.c conf.c crl.c dtls.c dtls13.c include.am internal.c keys.c ocsp.c pk.c pk_ec.c pk_rsa.c quic.c sniffer.c ssl.c ssl_api_cert.c ssl_api_crl_ocsp.c ssl_api_pk.c ssl_asn1.c ssl_bn.c ssl_certman.c ssl_crypto.c ssl_ech.c ssl_load.c ssl_misc.c ssl_p7p12.c ssl_sess.c ssl_sk.c tls.c tls13.c wolfio.c x509.c x509_str.ctests
api
api.h api_decl.h create_ocsp_test_blobs.py include.am test_aes.c test_aes.h test_arc4.c test_arc4.h test_ascon.c test_ascon.h test_ascon_kats.h test_asn.c test_asn.h test_blake2.c test_blake2.h test_camellia.c test_camellia.h test_certman.c test_certman.h test_chacha.c test_chacha.h test_chacha20_poly1305.c test_chacha20_poly1305.h test_cmac.c test_cmac.h test_curve25519.c test_curve25519.h test_curve448.c test_curve448.h test_des3.c test_des3.h test_dh.c test_dh.h test_digest.h test_dsa.c test_dsa.h test_dtls.c test_dtls.h test_ecc.c test_ecc.h test_ed25519.c test_ed25519.h test_ed448.c test_ed448.h test_evp.c test_evp.h test_evp_cipher.c test_evp_cipher.h test_evp_digest.c test_evp_digest.h test_evp_pkey.c test_evp_pkey.h test_hash.c test_hash.h test_hmac.c test_hmac.h test_md2.c test_md2.h test_md4.c test_md4.h test_md5.c test_md5.h test_mldsa.c test_mldsa.h test_mlkem.c test_mlkem.h test_ocsp.c test_ocsp.h test_ocsp_test_blobs.h test_ossl_asn1.c test_ossl_asn1.h test_ossl_bio.c test_ossl_bio.h test_ossl_bn.c test_ossl_bn.h test_ossl_cipher.c test_ossl_cipher.h test_ossl_dgst.c test_ossl_dgst.h test_ossl_dh.c test_ossl_dh.h test_ossl_dsa.c test_ossl_dsa.h test_ossl_ec.c test_ossl_ec.h test_ossl_ecx.c test_ossl_ecx.h test_ossl_mac.c test_ossl_mac.h test_ossl_obj.c test_ossl_obj.h test_ossl_p7p12.c test_ossl_p7p12.h test_ossl_pem.c test_ossl_pem.h test_ossl_rand.c test_ossl_rand.h test_ossl_rsa.c test_ossl_rsa.h test_ossl_sk.c test_ossl_sk.h test_ossl_x509.c test_ossl_x509.h test_ossl_x509_acert.c test_ossl_x509_acert.h test_ossl_x509_crypto.c test_ossl_x509_crypto.h test_ossl_x509_ext.c test_ossl_x509_ext.h test_ossl_x509_info.c test_ossl_x509_info.h test_ossl_x509_io.c test_ossl_x509_io.h test_ossl_x509_lu.c test_ossl_x509_lu.h test_ossl_x509_name.c test_ossl_x509_name.h test_ossl_x509_pk.c test_ossl_x509_pk.h test_ossl_x509_str.c test_ossl_x509_str.h test_ossl_x509_vp.c test_ossl_x509_vp.h test_pkcs12.c test_pkcs12.h test_pkcs7.c test_pkcs7.h test_poly1305.c test_poly1305.h test_random.c test_random.h test_rc2.c test_rc2.h test_ripemd.c test_ripemd.h test_rsa.c test_rsa.h test_sha.c test_sha.h test_sha256.c test_sha256.h test_sha3.c test_sha3.h test_sha512.c test_sha512.h test_she.c test_she.h test_signature.c test_signature.h test_slhdsa.c test_slhdsa.h test_sm2.c test_sm2.h test_sm3.c test_sm3.h test_sm4.c test_sm4.h test_tls.c test_tls.h test_tls13.c test_tls13.h test_tls_ext.c test_tls_ext.h test_wc_encrypt.c test_wc_encrypt.h test_wolfmath.c test_wolfmath.h test_x509.c test_x509.hwolfcrypt
benchmark
README.md benchmark-VS2022.sln benchmark-VS2022.vcxproj benchmark-VS2022.vcxproj.user benchmark.c benchmark.h benchmark.sln benchmark.vcproj benchmark.vcxproj include.amsrc
port
Espressif
esp_crt_bundle
README.md cacrt_all.pem cacrt_deprecated.pem cacrt_local.pem esp_crt_bundle.c gen_crt_bundle.py pio_install_cryptography.pyRenesas
README.md renesas_common.c renesas_fspsm_aes.c renesas_fspsm_rsa.c renesas_fspsm_sha.c renesas_fspsm_util.c renesas_rx64_hw_sha.c renesas_rx64_hw_util.c renesas_tsip_aes.c renesas_tsip_rsa.c renesas_tsip_sha.c renesas_tsip_util.carm
armv8-32-aes-asm.S armv8-32-aes-asm_c.c armv8-32-chacha-asm.S armv8-32-chacha-asm_c.c armv8-32-curve25519.S armv8-32-curve25519_c.c armv8-32-mlkem-asm.S armv8-32-mlkem-asm_c.c armv8-32-poly1305-asm.S armv8-32-poly1305-asm_c.c armv8-32-sha256-asm.S armv8-32-sha256-asm_c.c armv8-32-sha3-asm.S armv8-32-sha3-asm_c.c armv8-32-sha512-asm.S armv8-32-sha512-asm_c.c armv8-aes-asm.S armv8-aes-asm_c.c armv8-aes.c armv8-chacha-asm.S armv8-chacha-asm_c.c armv8-curve25519.S armv8-curve25519_c.c armv8-mlkem-asm.S armv8-mlkem-asm_c.c armv8-poly1305-asm.S armv8-poly1305-asm_c.c armv8-sha256-asm.S armv8-sha256-asm_c.c armv8-sha256.c armv8-sha3-asm.S armv8-sha3-asm_c.c armv8-sha512-asm.S armv8-sha512-asm_c.c armv8-sha512.c cryptoCell.c cryptoCellHash.c thumb2-aes-asm.S thumb2-aes-asm_c.c thumb2-chacha-asm.S thumb2-chacha-asm_c.c thumb2-curve25519.S thumb2-curve25519_c.c thumb2-mlkem-asm.S thumb2-mlkem-asm_c.c thumb2-poly1305-asm.S thumb2-poly1305-asm_c.c thumb2-sha256-asm.S thumb2-sha256-asm_c.c thumb2-sha3-asm.S thumb2-sha3-asm_c.c thumb2-sha512-asm.S thumb2-sha512-asm_c.ccaam
README.md caam_aes.c caam_doc.pdf caam_driver.c caam_error.c caam_integrity.c caam_qnx.c caam_sha.c wolfcaam_aes.c wolfcaam_cmac.c wolfcaam_ecdsa.c wolfcaam_fsl_nxp.c wolfcaam_hash.c wolfcaam_hmac.c wolfcaam_init.c wolfcaam_qnx.c wolfcaam_rsa.c wolfcaam_seco.c wolfcaam_x25519.cdevcrypto
README.md devcrypto_aes.c devcrypto_ecdsa.c devcrypto_hash.c devcrypto_hmac.c devcrypto_rsa.c devcrypto_x25519.c wc_devcrypto.criscv
riscv-64-aes.c riscv-64-chacha.c riscv-64-poly1305.c riscv-64-sha256.c riscv-64-sha3.c riscv-64-sha512.cwolfssl
openssl
aes.h asn1.h asn1t.h bio.h bn.h buffer.h camellia.h cmac.h cms.h compat_types.h conf.h crypto.h des.h dh.h dsa.h ec.h ec25519.h ec448.h ecdh.h ecdsa.h ed25519.h ed448.h engine.h err.h evp.h fips_rand.h hmac.h include.am kdf.h lhash.h md4.h md5.h modes.h obj_mac.h objects.h ocsp.h opensslconf.h opensslv.h ossl_typ.h pem.h pkcs12.h pkcs7.h rand.h rc4.h ripemd.h rsa.h safestack.h sha.h sha3.h srp.h ssl.h ssl23.h stack.h tls1.h txt_db.h ui.h x509.h x509_vfy.h x509v3.hwolfcrypt
port
Renesas
renesas-fspsm-crypt.h renesas-fspsm-types.h renesas-rx64-hw-crypt.h renesas-tsip-crypt.h renesas_cmn.h renesas_fspsm_internal.h renesas_sync.h renesas_tsip_internal.h renesas_tsip_types.hcaam
caam_driver.h caam_error.h caam_qnx.h wolfcaam.h wolfcaam_aes.h wolfcaam_cmac.h wolfcaam_ecdsa.h wolfcaam_fsl_nxp.h wolfcaam_hash.h wolfcaam_qnx.h wolfcaam_rsa.h wolfcaam_seco.h wolfcaam_sha.h wolfcaam_x25519.hwrapper
Ada
examples
src
aes_verify_main.adb rsa_verify_main.adb sha256_main.adb spark_sockets.adb spark_sockets.ads spark_terminal.adb spark_terminal.ads tls_client.adb tls_client.ads tls_client_main.adb tls_server.adb tls_server.ads tls_server_main.adbtests
src
aes_bindings_tests.adb aes_bindings_tests.ads rsa_verify_bindings_tests.adb rsa_verify_bindings_tests.ads sha256_bindings_tests.adb sha256_bindings_tests.ads tests.adbCSharp
wolfSSL-Example-IOCallbacks
App.config wolfSSL-Example-IOCallbacks.cs wolfSSL-Example-IOCallbacks.csprojwolfSSL-TLS-ServerThreaded
App.config wolfSSL-TLS-ServerThreaded.cs wolfSSL-TLS-ServerThreaded.csprojrust
wolfssl-wolfcrypt
src
aes.rs blake2.rs chacha20_poly1305.rs cmac.rs cmac_mac.rs curve25519.rs dh.rs dilithium.rs ecc.rs ecdsa.rs ed25519.rs ed448.rs fips.rs hkdf.rs hmac.rs hmac_mac.rs kdf.rs lib.rs lms.rs mlkem.rs mlkem_kem.rs pbkdf2_password_hash.rs prf.rs random.rs rsa.rs rsa_pkcs1v15.rs sha.rs sha_digest.rs sys.rstests
test_aes.rs test_blake2.rs test_chacha20_poly1305.rs test_cmac.rs test_cmac_mac.rs test_curve25519.rs test_dh.rs test_dilithium.rs test_ecc.rs test_ecdsa.rs test_ed25519.rs test_ed448.rs test_hkdf.rs test_hmac.rs test_hmac_mac.rs test_kdf.rs test_lms.rs test_mlkem.rs test_mlkem_kem.rs test_pbkdf2_password_hash.rs test_prf.rs test_random.rs test_rsa.rs test_rsa_pkcs1v15.rs test_sha.rs test_sha_digest.rs test_wolfcrypt.rszephyr
samples
wolfssl_benchmark
CMakeLists.txt README install_test.sh prj.conf sample.yaml zephyr_legacy.conf zephyr_v4.1.confwolfssl_test
CMakeLists.txt README install_test.sh prj-no-malloc.conf prj.conf sample.yaml zephyr_legacy.conf zephyr_v4.1.conf
wolfssl/src/x509.c
raw
1/* x509.c
2 *
3 * Copyright (C) 2006-2026 wolfSSL Inc.
4 *
5 * This file is part of wolfSSL.
6 *
7 * wolfSSL is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * wolfSSL is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20 */
21
22#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
23
24#if !defined(WOLFSSL_X509_INCLUDED)
25 #ifndef WOLFSSL_IGNORE_FILE_WARN
26 #warning x509.c does not need to be compiled separately from ssl.c
27 #endif
28#else
29
30#ifndef WOLFCRYPT_ONLY
31
32#ifndef NO_CERTS
33
34#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
35 #include <wolfssl/openssl/x509v3.h>
36#endif
37#ifdef OPENSSL_EXTRA
38 #include <wolfssl/wolfio.h>
39#endif
40
41/* 16 times MAX_X509_SIZE should be more than enough to read any X509
42 * certificate file */
43#define MAX_BIO_READ_BUFFER (MAX_X509_SIZE * 16)
44
45#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)
46unsigned int wolfSSL_X509_get_extension_flags(WOLFSSL_X509* x509)
47{
48 unsigned int flags = 0;
49
50 WOLFSSL_ENTER("wolfSSL_X509_get_extension_flags");
51
52 if (x509 != NULL) {
53 if (x509->keyUsageSet) {
54 flags |= WOLFSSL_EXFLAG_KUSAGE;
55 }
56 if (x509->extKeyUsageSrc != NULL) {
57 flags |= WOLFSSL_EXFLAG_XKUSAGE;
58 }
59 }
60
61 WOLFSSL_LEAVE("wolfSSL_X509_get_extension_flags", flags);
62
63 return flags;
64}
65
66unsigned int wolfSSL_X509_get_key_usage(WOLFSSL_X509* x509)
67{
68 unsigned int ret = 0;
69
70 WOLFSSL_ENTER("wolfSSL_X509_get_key_usage");
71
72 if (x509 == NULL) {
73 WOLFSSL_MSG("x509 is NULL");
74 }
75 else {
76 if (x509->keyUsageSet) {
77 ret = wolfSSL_X509_get_keyUsage(x509);
78 }
79 else {
80 ret = (unsigned int)-1;
81 }
82 }
83
84 WOLFSSL_LEAVE("wolfSSL_X509_get_key_usage", ret);
85
86 return ret;
87}
88
89unsigned int wolfSSL_X509_get_extended_key_usage(WOLFSSL_X509* x509)
90{
91 int ret = 0;
92
93 WOLFSSL_ENTER("wolfSSL_X509_get_extended_key_usage");
94
95 if (x509 != NULL) {
96 if (x509->extKeyUsage & EXTKEYUSE_OCSP_SIGN)
97 ret |= WOLFSSL_XKU_OCSP_SIGN;
98 if (x509->extKeyUsage & EXTKEYUSE_TIMESTAMP)
99 ret |= WOLFSSL_XKU_TIMESTAMP;
100 if (x509->extKeyUsage & EXTKEYUSE_EMAILPROT)
101 ret |= WOLFSSL_XKU_SMIME;
102 if (x509->extKeyUsage & EXTKEYUSE_CODESIGN)
103 ret |= WOLFSSL_XKU_CODE_SIGN;
104 if (x509->extKeyUsage & EXTKEYUSE_CLIENT_AUTH)
105 ret |= WOLFSSL_XKU_SSL_CLIENT;
106 if (x509->extKeyUsage & EXTKEYUSE_SERVER_AUTH)
107 ret |= WOLFSSL_XKU_SSL_SERVER;
108 if (x509->extKeyUsage & EXTKEYUSE_ANY)
109 ret |= WOLFSSL_XKU_ANYEKU;
110 }
111
112 WOLFSSL_LEAVE("wolfSSL_X509_get_extended_key_usage", ret);
113
114 return (unsigned int)ret;
115}
116
117/* Returns the number of X509V3 extensions in X509 object, or 0 on failure */
118int wolfSSL_X509_get_ext_count(const WOLFSSL_X509* passedCert)
119{
120 int extCount = 0;
121 int length = 0;
122 int outSz = 0;
123 const byte* rawCert;
124 int sz = 0;
125 word32 idx = 0;
126 const byte* input;
127 WC_DECLARE_VAR(cert, DecodedCert, 1, 0);
128
129 WOLFSSL_ENTER("wolfSSL_X509_get_ext_count");
130 if (passedCert == NULL) {
131 WOLFSSL_MSG("\tNot passed a certificate");
132 return WOLFSSL_FAILURE;
133 }
134
135 rawCert = wolfSSL_X509_get_der((WOLFSSL_X509*)passedCert, &outSz);
136 if (rawCert == NULL) {
137 WOLFSSL_MSG("\tpassedCert has no internal DerBuffer set.");
138 return WOLFSSL_FAILURE;
139 }
140
141#ifdef WOLFSSL_SMALL_STACK
142 cert = (DecodedCert *)XMALLOC(sizeof(*cert), NULL, DYNAMIC_TYPE_DCERT);
143 if (cert == NULL) {
144 WOLFSSL_MSG("out of memory");
145 return WOLFSSL_FAILURE;
146 }
147#endif
148
149 InitDecodedCert(cert, rawCert, (word32)outSz, 0);
150
151 if (ParseCert(cert,
152#ifdef WOLFSSL_CERT_REQ
153 passedCert->isCSR ? CERTREQ_TYPE :
154#endif
155 CA_TYPE,
156 NO_VERIFY, NULL) < 0) {
157 WOLFSSL_MSG("\tCertificate parsing failed");
158 goto out;
159 }
160
161 input = cert->extensions;
162 sz = cert->extensionsSz;
163
164 if (input == NULL || sz == 0) {
165 WOLFSSL_MSG("\tsz or input NULL error");
166 goto out;
167 }
168
169#ifdef WOLFSSL_CERT_REQ
170 if (!passedCert->isCSR)
171#endif
172 {
173 if (input[idx++] != ASN_EXTENSIONS) {
174 WOLFSSL_MSG("\tfail: should be an EXTENSIONS");
175 goto out;
176 }
177
178 if (GetLength(input, &idx, &length, (word32)sz) < 0) {
179 WOLFSSL_MSG("\tfail: invalid length");
180 goto out;
181 }
182 }
183
184 if (GetSequence(input, &idx, &length, (word32)sz) < 0) {
185 WOLFSSL_MSG("\tfail: should be a SEQUENCE (1)");
186 goto out;
187 }
188
189 while (idx < (word32)sz) {
190 if (GetSequence(input, &idx, &length, (word32)sz) < 0) {
191 WOLFSSL_MSG("\tfail: should be a SEQUENCE");
192 FreeDecodedCert(cert);
193 return WOLFSSL_FAILURE;
194 }
195 idx += length;
196 extCount++;
197 }
198
199out:
200
201 FreeDecodedCert(cert);
202 WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_DCERT);
203 return extCount;
204}
205
206/* Creates and returns pointer to a new X509_EXTENSION object in memory */
207WOLFSSL_X509_EXTENSION* wolfSSL_X509_EXTENSION_new(void)
208{
209 WOLFSSL_X509_EXTENSION* newExt;
210
211 WOLFSSL_ENTER("wolfSSL_X509_EXTENSION_new");
212
213 newExt = (WOLFSSL_X509_EXTENSION*)XMALLOC(sizeof(WOLFSSL_X509_EXTENSION),
214 NULL, DYNAMIC_TYPE_X509_EXT);
215 if (newExt == NULL)
216 return NULL;
217 XMEMSET(newExt, 0, sizeof(WOLFSSL_X509_EXTENSION));
218
219 return newExt;
220}
221
222
223/* Clear out and free internal pointers of ASN.1 STRING object.
224 *
225 * @param [in] asn1 ASN.1 STRING object.
226 */
227static void wolfSSL_ASN1_STRING_clear(WOLFSSL_ASN1_STRING* asn1)
228{
229 /* Check we have an object to free. */
230 if (asn1 != NULL) {
231 /* Dispose of dynamic data. */
232 if ((asn1->length > 0) && asn1->isDynamic) {
233 XFREE(asn1->data, NULL, DYNAMIC_TYPE_OPENSSL);
234 }
235 XMEMSET(asn1, 0, sizeof(WOLFSSL_ASN1_STRING));
236 }
237}
238
239
240void wolfSSL_X509_EXTENSION_free(WOLFSSL_X509_EXTENSION* x)
241{
242 WOLFSSL_ENTER("wolfSSL_X509_EXTENSION_free");
243 if (x == NULL)
244 return;
245
246 if (x->obj != NULL) {
247 wolfSSL_ASN1_OBJECT_free(x->obj);
248 }
249
250 wolfSSL_ASN1_STRING_clear(&x->value);
251 wolfSSL_sk_pop_free(x->ext_sk, NULL);
252
253 XFREE(x, NULL, DYNAMIC_TYPE_X509_EXT);
254}
255
256WOLFSSL_X509_EXTENSION* wolfSSL_X509_EXTENSION_dup(WOLFSSL_X509_EXTENSION* src)
257{
258 WOLFSSL_X509_EXTENSION* ret = NULL;
259 int err = 0;
260
261 WOLFSSL_ENTER("wolfSSL_X509_EXTENSION_dup");
262
263 if (src == NULL) {
264 err = 1;
265 }
266
267 if (err == 0) {
268 ret = wolfSSL_X509_EXTENSION_new();
269 if (ret == NULL) {
270 err = 1;
271 }
272 }
273 if (err == 0 && src->obj != NULL) {
274 ret->obj = wolfSSL_ASN1_OBJECT_dup(src->obj);
275 if (ret->obj == NULL) {
276 err = 1;
277 }
278 }
279 if (err == 0) {
280 ret->crit = src->crit;
281 if (wolfSSL_ASN1_STRING_copy(&ret->value, &src->value) !=
282 WOLFSSL_SUCCESS) {
283 err = 1;
284 }
285 }
286
287 if (err == 1 && ret != NULL) {
288 wolfSSL_X509_EXTENSION_free(ret);
289 ret = NULL;
290 }
291
292 return ret;
293}
294
295WOLFSSL_X509_EXTENSION* wolfSSL_X509_EXTENSION_create_by_OBJ(
296 WOLFSSL_X509_EXTENSION* ex, WOLFSSL_ASN1_OBJECT *obj, int crit,
297 WOLFSSL_ASN1_STRING *data)
298{
299 int err = 0;
300 WOLFSSL_X509_EXTENSION *ret = ex;
301
302 WOLFSSL_ENTER("wolfSSL_X509_EXTENSION_create_by_OBJ");
303
304 if ((obj == NULL) || (data == NULL)) {
305 return NULL;
306 }
307
308 if (ret == NULL) {
309 ret = wolfSSL_X509_EXTENSION_new();
310 if (ret == NULL) {
311 err = 1;
312 }
313 }
314 else {
315 /* Prevent potential memory leaks and dangling pointers. */
316 wolfSSL_ASN1_OBJECT_free(ret->obj);
317 ret->obj = NULL;
318 wolfSSL_ASN1_STRING_clear(&ret->value);
319 }
320
321 if (err == 0) {
322 ret->crit = crit;
323 ret->obj = wolfSSL_ASN1_OBJECT_dup(obj);
324 if (ret->obj == NULL) {
325 err = 1;
326 }
327 }
328
329 if (err == 0) {
330 if (wolfSSL_ASN1_STRING_copy(&ret->value, data) != WOLFSSL_SUCCESS) {
331 err = 1;
332 }
333 }
334
335 if (err == 1) {
336 if (ret != ex) {
337 wolfSSL_X509_EXTENSION_free(ret);
338 }
339 ret = NULL;
340 }
341 return ret;
342}
343
344/* Creates and returns a new WOLFSSL_X509_EXTENSION stack. */
345WOLFSSL_STACK* wolfSSL_sk_new_x509_ext(void)
346{
347 WOLFSSL_STACK* sk;
348 WOLFSSL_ENTER("wolfSSL_sk_new_x509_ext");
349
350 sk = wolfSSL_sk_new_null();
351 if (sk) {
352 sk->type = STACK_TYPE_X509_EXT;
353 }
354 return sk;
355}
356
357/* This function does NOT return 1 on success. It returns 0 on fail, and the
358 * number of items in the stack upon success. This is for compatibility with
359 * OpenSSL. */
360int wolfSSL_sk_X509_EXTENSION_push(WOLFSSL_STACK* sk,
361 WOLFSSL_X509_EXTENSION* ext)
362{
363 WOLFSSL_ENTER("wolfSSL_sk_X509_EXTENSION_push");
364
365 return wolfSSL_sk_push(sk, ext);
366}
367
368static WOLFSSL_STACK* generateExtStack(const WOLFSSL_X509 *x)
369{
370 int numOfExt, i;
371 WOLFSSL_X509 *x509 = (WOLFSSL_X509*)x;
372 WOLFSSL_STACK* ret;
373 WOLFSSL_STACK* tmp;
374
375 if (!x509) {
376 WOLFSSL_MSG("Bad parameter");
377 return NULL;
378 }
379
380 /* Save x509->ext_sk */
381 tmp = x509->ext_sk;
382 x509->ext_sk = NULL;
383 numOfExt = wolfSSL_X509_get_ext_count(x509);
384
385 for (i = 0; i < numOfExt; i++) {
386 /* Build the extension stack */
387 (void)wolfSSL_X509_set_ext(x509, i);
388 }
389
390 /* Restore */
391 ret = x509->ext_sk;
392 x509->ext_sk = tmp;
393 return ret;
394}
395
396/**
397 * @param x Certificate to extract extensions from
398 * @return STACK_OF(X509_EXTENSION)*
399 */
400const WOLFSSL_STACK *wolfSSL_X509_get0_extensions(const WOLFSSL_X509 *x)
401{
402 int numOfExt;
403 WOLFSSL_X509 *x509 = (WOLFSSL_X509*)x;
404 WOLFSSL_ENTER("wolfSSL_X509_get0_extensions");
405
406 if (!x509) {
407 WOLFSSL_MSG("Bad parameter");
408 return NULL;
409 }
410
411 numOfExt = wolfSSL_X509_get_ext_count(x509);
412
413 if (numOfExt != wolfSSL_sk_num(x509->ext_sk_full)) {
414 wolfSSL_sk_pop_free(x509->ext_sk_full, NULL);
415 x509->ext_sk_full = generateExtStack(x);
416 }
417
418 return x509->ext_sk_full;
419}
420
421/**
422 * Caller is responsible for freeing the returned stack.
423 */
424const WOLFSSL_STACK *wolfSSL_X509_REQ_get_extensions(const WOLFSSL_X509 *x)
425{
426 return generateExtStack(x);
427}
428
429/* Gets the X509_EXTENSION* ext based on it's location in WOLFSSL_X509* x509.
430 *
431 * x509 : The X509 structure to look for the extension.
432 * loc : Location of the extension. If the extension is found at the given
433 * location, a new X509_EXTENSION structure is populated with extension-specific
434 * data based on the extension type.
435
436 * Returns NULL on error or pointer to X509_EXTENSION structure containing the
437 * extension. The returned X509_EXTENSION should not be free'd by caller.
438 * The returned X509_EXTENSION is pushed onto a stack inside the x509 argument.
439 * This is later free'd when x509 is free'd.
440 *
441 * NOTE: for unknown extension NIDs, a X509_EXTENSION is populated with the
442 * extension oid as the ASN1_OBJECT (QT compatibility)
443 */
444WOLFSSL_X509_EXTENSION* wolfSSL_X509_get_ext(const WOLFSSL_X509* x509, int loc)
445{
446 WOLFSSL_X509_EXTENSION* ext = NULL;
447 WOLFSSL_ENTER("wolfSSL_X509_get_ext");
448 if (x509 == NULL)
449 return NULL;
450
451 ext = wolfSSL_X509_set_ext((WOLFSSL_X509*) x509, loc);
452 return ext;
453}
454
455int wolfSSL_X509_get_ext_by_OBJ(const WOLFSSL_X509 *x,
456 const WOLFSSL_ASN1_OBJECT *obj, int lastpos)
457{
458 const WOLF_STACK_OF(WOLFSSL_X509_EXTENSION) *sk;
459
460 if (!x || !obj) {
461 WOLFSSL_MSG("Bad parameter");
462 return WOLFSSL_FATAL_ERROR;
463 }
464
465 sk = wolfSSL_X509_get0_extensions(x);
466 if (!sk) {
467 WOLFSSL_MSG("No extensions");
468 return WOLFSSL_FATAL_ERROR;
469 }
470 lastpos++;
471 if (lastpos < 0)
472 lastpos = 0;
473 for (; lastpos < wolfSSL_sk_num(sk); lastpos++) {
474 const WOLFSSL_X509_EXTENSION *ext =
475 wolfSSL_sk_X509_EXTENSION_value(sk, lastpos);
476 if (ext == NULL)
477 continue;
478 if (wolfSSL_OBJ_cmp(ext->obj, obj) == 0)
479 return lastpos;
480 }
481 return WOLFSSL_FATAL_ERROR;
482}
483
484
485int wolfSSL_X509_OBJECT_set1_X509(WOLFSSL_X509_OBJECT *a, WOLFSSL_X509 *obj)
486{
487 WOLFSSL_STUB("wolfSSL_X509_OBJECT_set1_X509");
488 (void)a;
489 (void)obj;
490 return 0;
491}
492
493int wolfSSL_X509_OBJECT_set1_X509_CRL(WOLFSSL_X509_OBJECT *a,
494 WOLFSSL_X509_CRL *obj)
495{
496 WOLFSSL_STUB("wolfSSL_X509_OBJECT_set1_X509_CRL");
497 (void)a;
498 (void)obj;
499 return 0;
500}
501
502#endif /* OPENSSL_ALL || OPENSSL_EXTRA */
503
504#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || \
505 defined(WOLFSSL_WPAS_SMALL)
506/* Set a general name from the DNS entry data.
507 *
508 * @param [in] dns DNS entry.
509 * @param [in, out] gn General name to place data in.
510 * @return 1 on success.
511 * @return 0 on failure.
512 */
513static int wolfssl_dns_entry_othername_to_gn(DNS_entry* dns,
514 WOLFSSL_GENERAL_NAME* gn)
515{
516 int ret = 0;
517 WOLFSSL_ASN1_OBJECT* obj = NULL;
518 WOLFSSL_ASN1_TYPE* type = NULL;
519 WOLFSSL_ASN1_STRING* str = NULL;
520 byte tag = 0;
521 unsigned char* p = (unsigned char *)dns->name;
522 long len = dns->len;
523
524#ifdef WOLFSSL_FPKI
525 if (dns->oidSum != 0) {
526 /* UPN OID: 1.3.6.1.4.1.311.20.2.3 */
527 static const unsigned char upn_oid[] = {
528 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x14, 0x02, 0x03
529 };
530 /* FASCN OID: 2.16.840.1.101.3.6.6 */
531 static const unsigned char fascn_oid[] = {
532 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x06, 0x06
533 };
534 const unsigned char* oid;
535 word32 oidSz;
536
537 if ((oid = OidFromId(dns->oidSum, oidCertAltNameType, &oidSz)) ==
538 NULL) {
539 if (dns->oidSum == UPN_OID) {
540 oid = upn_oid;
541 oidSz = (word32)sizeof(upn_oid);
542 }
543 else if (dns->oidSum == FASCN_OID) {
544 oid = fascn_oid;
545 oidSz = (word32)sizeof(fascn_oid);
546 }
547 else {
548 goto err;
549 }
550 }
551 if ((obj = wolfSSL_c2i_ASN1_OBJECT(NULL, &oid, oidSz)) == NULL) {
552 goto err;
553 }
554
555 tag = WOLFSSL_V_ASN1_UTF8STRING;
556 }
557 else
558#endif
559 {
560 word32 idx = 0;
561 int nameLen;
562
563 /* Create an object id for general name from DER encoding. */
564 obj = wolfSSL_d2i_ASN1_OBJECT(NULL, (const unsigned char**)&p, len);
565 if (obj == NULL)
566 goto err;
567 /* Pointer moved on and now update length of remaining data. */
568 len -= (long)((size_t)p - (size_t)dns->name);
569
570 /* Next is "value [0] EXPLICIT ANY DEFINED BY type-id" */
571 if (GetASNHeader(p, ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0,
572 &idx, &nameLen, (word32)len) < 0)
573 goto err;
574 p += idx;
575 len -= idx;
576
577 /* Set the tag to object so that it gets output in raw form */
578 tag = WOLFSSL_V_ASN1_SEQUENCE;
579 }
580
581 /* Create a WOLFSSL_ASN1_STRING from the DER. */
582 str = wolfSSL_ASN1_STRING_type_new(tag);
583 if (str == NULL) {
584 goto err;
585 }
586 wolfSSL_ASN1_STRING_set(str, p, (int)len);
587
588 /* Wrap string in a WOLFSSL_ASN1_TYPE. */
589 type = wolfSSL_ASN1_TYPE_new();
590 if (type == NULL)
591 goto err;
592 wolfSSL_ASN1_TYPE_set(type, tag, str);
593 str = NULL; /* type now owns str */
594
595 if (wolfSSL_GENERAL_NAME_set_type(gn, WOLFSSL_GEN_OTHERNAME)
596 != WOLFSSL_SUCCESS) {
597 goto err;
598 }
599
600 /* Store the object and string in general name. */
601 gn->d.otherName->type_id = obj;
602 gn->d.otherName->value = type;
603 type = NULL; /* gn->d.otherName owns type */
604
605 ret = 1;
606err:
607 if (ret != 1) {
608 wolfSSL_ASN1_OBJECT_free(obj);
609 wolfSSL_ASN1_TYPE_free(type);
610 wolfSSL_ASN1_STRING_free(str);
611 }
612 return ret;
613}
614#endif /* OPENSSL_ALL || WOLFSSL_WPAS_SMALL */
615
616#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)
617static int DNS_to_GENERAL_NAME(WOLFSSL_GENERAL_NAME* gn, DNS_entry* dns)
618{
619 switch (dns->type) {
620 case WOLFSSL_GEN_OTHERNAME:
621 /* Sets gn->type internally */
622 if (!wolfssl_dns_entry_othername_to_gn(dns, gn)) {
623 WOLFSSL_MSG("OTHERNAME set failed");
624 return WOLFSSL_FAILURE;
625 }
626 break;
627
628 case WOLFSSL_GEN_EMAIL:
629 case WOLFSSL_GEN_DNS:
630 case WOLFSSL_GEN_URI:
631 case WOLFSSL_GEN_IPADD:
632 case WOLFSSL_GEN_IA5:
633 gn->type = dns->type;
634 gn->d.ia5->length = dns->len;
635 if (wolfSSL_ASN1_STRING_set(gn->d.ia5, dns->name,
636 gn->d.ia5->length) != WOLFSSL_SUCCESS) {
637 WOLFSSL_MSG("ASN1_STRING_set failed");
638 return WOLFSSL_FAILURE;
639 }
640 break;
641
642
643 case WOLFSSL_GEN_DIRNAME:
644 gn->type = dns->type;
645 /* wolfSSL_GENERAL_NAME_new() mallocs this by default */
646 wolfSSL_ASN1_STRING_free(gn->d.ia5);
647 gn->d.ia5 = NULL;
648
649 gn->d.dirn = wolfSSL_X509_NAME_new();;
650 /* @TODO extract dir name info from DNS_entry */
651 break;
652
653 case WOLFSSL_GEN_RID:
654 /* registeredID is parsed into altNames unconditionally so
655 * ConfirmNameConstraints can enforce RID name constraints
656 * (RFC 5280 Sec. 4.2.1.10). The body uses only the raw OID
657 * bytes carried in dns->name/dns->len and constructs a
658 * proper ASN1_OBJECT, so this case is independent of
659 * WOLFSSL_RID_ALT_NAME (which only gates the human-readable
660 * ridString form). */
661 gn->type = dns->type;
662 /* wolfSSL_GENERAL_NAME_new() mallocs this by default */
663 wolfSSL_ASN1_STRING_free(gn->d.ia5);
664 gn->d.ia5 = NULL;
665
666 gn->d.registeredID = wolfSSL_ASN1_OBJECT_new();
667 if (gn->d.registeredID == NULL) {
668 return WOLFSSL_FAILURE;
669 }
670 {
671 /* Store DER-encoded OID (tag + length + content) in obj */
672 word32 derSz = 1 + SetLength(dns->len, NULL) + dns->len;
673 byte* der = (byte*)XMALLOC(derSz,
674 gn->d.registeredID->heap, DYNAMIC_TYPE_ASN1);
675 if (der == NULL) {
676 return WOLFSSL_FAILURE;
677 }
678 {
679 word32 idx = 0;
680 der[idx++] = ASN_OBJECT_ID;
681 idx += SetLength(dns->len, der + idx);
682 XMEMCPY(der + idx, dns->name, dns->len);
683 }
684 gn->d.registeredID->obj = der;
685 gn->d.registeredID->objSz = derSz;
686 }
687 gn->d.registeredID->dynamic |= WOLFSSL_ASN1_DYNAMIC_DATA;
688 gn->d.registeredID->grp = oidCertExtType;
689 break;
690
691 case WOLFSSL_GEN_X400:
692 /* Unsupported: fall through */
693 case WOLFSSL_GEN_EDIPARTY:
694 /* Unsupported: fall through */
695 default:
696 WOLFSSL_MSG("Unsupported type conversion");
697 return WOLFSSL_FAILURE;
698 }
699 return WOLFSSL_SUCCESS;
700}
701
702
703static int wolfssl_x509_alt_names_to_gn(WOLFSSL_X509* x509,
704 WOLFSSL_X509_EXTENSION* ext)
705{
706 int ret = 0;
707 WOLFSSL_GENERAL_NAME* gn = NULL;
708 DNS_entry* dns = NULL;
709 WOLFSSL_STACK* sk;
710
711 sk = (WOLFSSL_GENERAL_NAMES*)XMALLOC(sizeof(WOLFSSL_GENERAL_NAMES), NULL,
712 DYNAMIC_TYPE_ASN1);
713 if (sk == NULL) {
714 goto err;
715 }
716 XMEMSET(sk, 0, sizeof(WOLFSSL_GENERAL_NAMES));
717 sk->type = STACK_TYPE_GEN_NAME;
718
719 if (x509->subjAltNameSet && x509->altNames != NULL) {
720 /* alt names are DNS_entry structs */
721 dns = x509->altNames;
722 /* Currently only support GEN_DNS type */
723 while (dns != NULL) {
724 gn = wolfSSL_GENERAL_NAME_new();
725 if (gn == NULL) {
726 WOLFSSL_MSG("Error creating GENERAL_NAME");
727 wolfSSL_sk_pop_free(sk, NULL);
728 goto err;
729 }
730
731 if (DNS_to_GENERAL_NAME(gn, dns) != WOLFSSL_SUCCESS) {
732 wolfSSL_GENERAL_NAME_free(gn);
733 wolfSSL_sk_pop_free(sk, NULL);
734 goto err;
735 }
736
737 if (wolfSSL_sk_GENERAL_NAME_push(sk, gn) <= 0) {
738 WOLFSSL_MSG("Error pushing onto stack");
739 wolfSSL_GENERAL_NAME_free(gn);
740 wolfSSL_sk_pop_free(sk, NULL);
741 goto err;
742 }
743
744 dns = dns->next;
745 }
746 }
747 ext->ext_sk = sk;
748 ext->crit = x509->subjAltNameCrit;
749
750 ret = 1;
751err:
752 return ret;
753}
754
755/* Pushes a new X509_EXTENSION* ext onto the stack inside WOLFSSL_X509* x509.
756 * This is currently a helper function for wolfSSL_X509_get_ext
757 * Caller does not free the returned WOLFSSL_X509_EXTENSION*
758 */
759WOLFSSL_X509_EXTENSION* wolfSSL_X509_set_ext(WOLFSSL_X509* x509, int loc)
760{
761 int extCount = 0, length = 0, outSz = 0, sz = 0, ret = 0;
762 int objSz = 0, isSet = 0;
763 const byte* rawCert;
764 const byte* input;
765 byte* oidBuf;
766 word32 oid, idx = 0, tmpIdx = 0, nid;
767 WOLFSSL_X509_EXTENSION* ext = NULL;
768 WC_DECLARE_VAR(cert, DecodedCert, 1, 0);
769
770 WOLFSSL_ENTER("wolfSSL_X509_set_ext");
771
772 if (x509 == NULL) {
773 WOLFSSL_MSG("\tNot passed a certificate");
774 return NULL;
775 }
776
777 if (loc < 0 || (loc > wolfSSL_X509_get_ext_count(x509))) {
778 WOLFSSL_MSG("\tBad location argument");
779 return NULL;
780 }
781
782 ext = wolfSSL_X509_EXTENSION_new();
783 if (ext == NULL) {
784 WOLFSSL_MSG("\tX509_EXTENSION_new() failed");
785 return NULL;
786 }
787
788 rawCert = wolfSSL_X509_get_der((WOLFSSL_X509*)x509, &outSz);
789 if (rawCert == NULL) {
790 WOLFSSL_MSG("\tX509_get_der() failed");
791 wolfSSL_X509_EXTENSION_free(ext);
792 return NULL;
793 }
794
795#ifdef WOLFSSL_SMALL_STACK
796 cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT);
797 if (cert == NULL) {
798 WOLFSSL_MSG("Failed to allocate memory for DecodedCert");
799 wolfSSL_X509_EXTENSION_free(ext);
800 return NULL;
801 }
802#endif
803
804 InitDecodedCert(cert, rawCert, (word32)outSz, 0);
805
806 if (ParseCert(cert,
807#ifdef WOLFSSL_CERT_REQ
808 x509->isCSR ? CERTREQ_TYPE :
809#endif
810 CA_TYPE,
811 NO_VERIFY, NULL) < 0) {
812 WOLFSSL_MSG("\tCertificate parsing failed");
813 wolfSSL_X509_EXTENSION_free(ext);
814 FreeDecodedCert(cert);
815 WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_DCERT);
816 return NULL;
817 }
818
819 input = cert->extensions;
820 sz = cert->extensionsSz;
821
822 if (input == NULL || sz == 0) {
823 WOLFSSL_MSG("\tfail: should be an EXTENSIONS");
824 wolfSSL_X509_EXTENSION_free(ext);
825 FreeDecodedCert(cert);
826 WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_DCERT);
827 return NULL;
828 }
829
830#ifdef WOLFSSL_CERT_REQ
831 if (!x509->isCSR)
832#endif
833 {
834 if (input[idx++] != ASN_EXTENSIONS) {
835 WOLFSSL_MSG("\tfail: should be an EXTENSIONS");
836 wolfSSL_X509_EXTENSION_free(ext);
837 FreeDecodedCert(cert);
838 WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_DCERT);
839 return NULL;
840 }
841
842 if (GetLength(input, &idx, &length, (word32)sz) < 0) {
843 WOLFSSL_MSG("\tfail: invalid length");
844 wolfSSL_X509_EXTENSION_free(ext);
845 FreeDecodedCert(cert);
846 WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_DCERT);
847 return NULL;
848 }
849 }
850
851 if (GetSequence(input, &idx, &length, (word32)sz) < 0) {
852 WOLFSSL_MSG("\tfail: should be a SEQUENCE (1)");
853 wolfSSL_X509_EXTENSION_free(ext);
854 FreeDecodedCert(cert);
855 WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_DCERT);
856 return NULL;
857 }
858
859 while (idx < (word32)sz) {
860 oid = 0;
861
862 if (GetSequence(input, &idx, &length, (word32)sz) < 0) {
863 WOLFSSL_MSG("\tfail: should be a SEQUENCE");
864 wolfSSL_X509_EXTENSION_free(ext);
865 FreeDecodedCert(cert);
866 WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_DCERT);
867 return NULL;
868 }
869
870 tmpIdx = idx;
871 ret = GetObjectId(input, &idx, &oid, oidCertExtType, (word32)sz);
872 if (ret < 0) {
873 WOLFSSL_MSG("\tfail: OBJECT ID");
874 wolfSSL_X509_EXTENSION_free(ext);
875 FreeDecodedCert(cert);
876 WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_DCERT);
877 return NULL;
878 }
879 idx = tmpIdx;
880 nid = (word32)oid2nid(oid, oidCertExtType);
881
882 /* Continue while loop until extCount == loc or idx > sz */
883 if (extCount != loc) {
884 idx += length;
885 extCount++;
886 continue;
887 }
888 /* extCount == loc. Now get the extension. */
889 /* Check if extension has been set */
890 isSet = wolfSSL_X509_ext_isSet_by_NID((WOLFSSL_X509*)x509, (int)nid);
891
892 if (wolfSSL_OBJ_nid2ln((int)nid) != NULL) {
893 /* This is NOT an unknown OID. */
894 ext->obj = wolfSSL_OBJ_nid2obj((int)nid);
895 if (ext->obj == NULL) {
896 WOLFSSL_MSG("\tfail: Invalid OBJECT");
897 wolfSSL_X509_EXTENSION_free(ext);
898 FreeDecodedCert(cert);
899 WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_DCERT);
900 return NULL;
901 }
902 }
903
904 if (ext->obj) {
905 ext->obj->nid = (int)nid;
906 }
907
908 switch (oid) {
909 case BASIC_CA_OID:
910 {
911 WOLFSSL_ASN1_INTEGER* a;
912 word32 dataIdx = idx;
913 word32 dummyOid;
914 int dataLen = 0;
915
916 if (!isSet)
917 break;
918
919 /* Set pathlength */
920 a = wolfSSL_ASN1_INTEGER_new();
921
922 /* Set the data */
923 ret = GetObjectId(input, &dataIdx, &dummyOid, oidCertExtType,
924 (word32)sz) == 0;
925 if (ret && dataIdx < (word32)sz) {
926 /* Skip the critical information */
927 if (input[dataIdx] == ASN_BOOLEAN) {
928 dataIdx++;
929 ret = GetLength(input, &dataIdx, &dataLen, sz) >= 0;
930 dataIdx += dataLen;
931 }
932 }
933 if (ret) {
934 ret = GetOctetString(input, &dataIdx, &dataLen,
935 (word32)sz) > 0;
936 }
937 if (ret) {
938 ret = wolfSSL_ASN1_STRING_set(&ext->value, input + dataIdx,
939 dataLen) == 1;
940 }
941
942 if (a == NULL || !ret) {
943 wolfSSL_X509_EXTENSION_free(ext);
944 FreeDecodedCert(cert);
945 WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_DCERT);
946 return NULL;
947 }
948 a->length = (int)x509->pathLength;
949
950 /* Save ASN1_INTEGER in x509 extension */
951 ext->obj->pathlen = a;
952
953 ext->obj->ca = x509->isCa;
954 break;
955 }
956
957 case AUTH_INFO_OID:
958 {
959 WOLFSSL_STACK* sk;
960
961 if (!isSet)
962 break;
963
964 /* Create a stack to hold both the caIssuer and ocsp objects
965 in X509_EXTENSION structure */
966 sk = wolfSSL_sk_new_asn1_obj();
967 if (sk == NULL) {
968 WOLFSSL_MSG("Failed to malloc stack");
969 wolfSSL_X509_EXTENSION_free(ext);
970 FreeDecodedCert(cert);
971 WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_DCERT);
972 return NULL;
973 }
974
975 /* Add CaIssuers object to stack */
976 if (x509->authInfoCaIssuer != NULL &&
977 x509->authInfoCaIssuerSz > 0)
978 {
979 WOLFSSL_ASN1_OBJECT* obj;
980 obj = wolfSSL_ASN1_OBJECT_new();
981 if (obj == NULL) {
982 WOLFSSL_MSG("Error creating ASN1 object");
983 wolfSSL_sk_ASN1_OBJECT_pop_free(sk, NULL);
984 wolfSSL_X509_EXTENSION_free(ext);
985 FreeDecodedCert(cert);
986 WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_DCERT);
987 return NULL;
988 }
989 obj->obj = (byte*)x509->authInfoCaIssuer;
990 obj->objSz = (unsigned int)x509->authInfoCaIssuerSz;
991 obj->grp = oidCertAuthInfoType;
992 obj->nid = WC_NID_ad_ca_issuers;
993
994 ret = wolfSSL_sk_ASN1_OBJECT_push(sk, obj) > 0
995 ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
996 if (ret != WOLFSSL_SUCCESS) {
997 WOLFSSL_MSG("Error pushing ASN1 object onto stack");
998 wolfSSL_ASN1_OBJECT_free(obj);
999 wolfSSL_sk_ASN1_OBJECT_pop_free(sk, NULL);
1000 wolfSSL_X509_EXTENSION_free(ext);
1001 FreeDecodedCert(cert);
1002 WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_DCERT);
1003 return NULL;
1004 }
1005 }
1006
1007 /* Add OCSP object to stack */
1008 if (x509->authInfo != NULL &&
1009 x509->authInfoSz > 0)
1010 {
1011 WOLFSSL_ASN1_OBJECT* obj;
1012 obj = wolfSSL_ASN1_OBJECT_new();
1013 if (obj == NULL) {
1014 WOLFSSL_MSG("Error creating ASN1 object");
1015 wolfSSL_sk_ASN1_OBJECT_pop_free(sk, NULL);
1016 wolfSSL_X509_EXTENSION_free(ext);
1017 FreeDecodedCert(cert);
1018 WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_DCERT);
1019 return NULL;
1020 }
1021 obj->obj = x509->authInfo;
1022 obj->objSz = (unsigned int)x509->authInfoSz;
1023 obj->grp = oidCertAuthInfoType;
1024 obj->nid = WC_NID_ad_OCSP;
1025
1026 ret = wolfSSL_sk_ASN1_OBJECT_push(sk, obj) > 0
1027 ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
1028 if (ret != WOLFSSL_SUCCESS) {
1029 WOLFSSL_MSG("Error pushing ASN1 object onto stack");
1030 wolfSSL_ASN1_OBJECT_free(obj);
1031 wolfSSL_sk_ASN1_OBJECT_pop_free(sk, NULL);
1032 wolfSSL_X509_EXTENSION_free(ext);
1033 FreeDecodedCert(cert);
1034 WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_DCERT);
1035 return NULL;
1036 }
1037 }
1038 ext->ext_sk = sk;
1039 break;
1040 }
1041
1042 case ALT_NAMES_OID:
1043 if (!isSet)
1044 break;
1045 if (!wolfssl_x509_alt_names_to_gn(x509, ext)) {
1046 wolfSSL_X509_EXTENSION_free(ext);
1047 FreeDecodedCert(cert);
1048 WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_DCERT);
1049 return NULL;
1050 }
1051 break;
1052 }
1053
1054 /* The ASN1_OBJECT in the extension is set in the same way
1055 * for recognized and for unrecognized extension types, as
1056 * the full OCTET STRING */
1057
1058 /* Get OID from input */
1059 if (GetASNObjectId(input, &idx, &length, (word32)sz) != 0) {
1060 WOLFSSL_MSG("Failed to Get ASN Object Id");
1061 wolfSSL_X509_EXTENSION_free(ext);
1062 FreeDecodedCert(cert);
1063 WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_DCERT);
1064 return NULL;
1065 }
1066 oidBuf = (byte*)XMALLOC(length+1+MAX_LENGTH_SZ, NULL,
1067 DYNAMIC_TYPE_TMP_BUFFER);
1068 if (oidBuf == NULL) {
1069 WOLFSSL_MSG("Failed to malloc tmp buffer");
1070 wolfSSL_X509_EXTENSION_free(ext);
1071 FreeDecodedCert(cert);
1072 WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_DCERT);
1073 return NULL;
1074 }
1075 oidBuf[0] = ASN_OBJECT_ID;
1076 objSz++;
1077 objSz += SetLength(length, oidBuf + 1);
1078 objSz += length;
1079
1080 /* Set object size and reallocate space in object buffer */
1081 if (ext->obj == NULL) {
1082 ext->obj = wolfSSL_ASN1_OBJECT_new();
1083 if (ext->obj == NULL) {
1084 XFREE(oidBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1085 wolfSSL_X509_EXTENSION_free(ext);
1086 FreeDecodedCert(cert);
1087 WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_DCERT);
1088 return NULL;
1089 }
1090 }
1091
1092 if (((ext->obj->dynamic & WOLFSSL_ASN1_DYNAMIC_DATA) != 0) ||
1093 (ext->obj->obj == NULL)) {
1094 byte* tmp;
1095 #ifdef WOLFSSL_NO_REALLOC
1096 tmp = (byte*)XMALLOC(objSz, NULL, DYNAMIC_TYPE_ASN1);
1097 if (tmp != NULL && ext->obj->obj != NULL) {
1098 XMEMCPY(tmp, ext->obj->obj, ext->obj->objSz);
1099 XFREE((byte*)ext->obj->obj, NULL, DYNAMIC_TYPE_ASN1);
1100 }
1101 else if (tmp == NULL) {
1102 XFREE((byte*)ext->obj->obj, NULL, DYNAMIC_TYPE_ASN1);
1103 }
1104 ext->obj->obj = tmp;
1105 #else
1106 tmp = (byte*)XREALLOC((byte*)ext->obj->obj, objSz, NULL,
1107 DYNAMIC_TYPE_ASN1);
1108 if (tmp == NULL)
1109 XFREE((byte*)ext->obj->obj, NULL, DYNAMIC_TYPE_ASN1);
1110 ext->obj->obj = tmp;
1111 #endif
1112 if (ext->obj->obj == NULL) {
1113 wolfSSL_X509_EXTENSION_free(ext);
1114 FreeDecodedCert(cert);
1115 XFREE(oidBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1116 WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_DCERT);
1117 return NULL;
1118 }
1119 ext->obj->dynamic |= WOLFSSL_ASN1_DYNAMIC_DATA;
1120 }
1121 else {
1122 ext->obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA;
1123 }
1124 ext->obj->objSz = (unsigned int)objSz;
1125
1126 /* Get OID from input and copy to ASN1_OBJECT buffer */
1127 XMEMCPY(oidBuf+2, input+idx, length);
1128 XMEMCPY((byte*)ext->obj->obj, oidBuf, ext->obj->objSz);
1129 XFREE(oidBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1130 oidBuf = NULL;
1131 ext->obj->grp = oidCertExtType;
1132 ext->crit = 0;
1133
1134 tmpIdx = idx + length;
1135
1136 /* Get CRITICAL. If not present, defaults to false.
1137 * It present, must be a valid TRUE */
1138 if ((tmpIdx < (word32)sz) &&
1139 (input[tmpIdx] == ASN_BOOLEAN))
1140 {
1141 if (((tmpIdx + 2) >= (word32)sz) ||
1142 /* Check bool length */
1143 (input[tmpIdx+1] != 1) ||
1144 /* Assert true if CRITICAL present */
1145 (input[tmpIdx+2] != 0xff))
1146 {
1147 WOLFSSL_MSG("Error decoding unknown extension data");
1148 wolfSSL_ASN1_OBJECT_free(ext->obj);
1149 wolfSSL_X509_EXTENSION_free(ext);
1150 FreeDecodedCert(cert);
1151 WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_DCERT);
1152 return NULL;
1153 }
1154
1155 ext->crit = 1;
1156 tmpIdx += 3;
1157 }
1158
1159 /* Get extension data and copy as ASN1_STRING */
1160 if ((tmpIdx >= (word32)sz) ||
1161 (input[tmpIdx] != ASN_OCTET_STRING))
1162 {
1163 WOLFSSL_MSG("Error decoding unknown extension data");
1164 wolfSSL_ASN1_OBJECT_free(ext->obj);
1165 wolfSSL_X509_EXTENSION_free(ext);
1166 FreeDecodedCert(cert);
1167 WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_DCERT);
1168 return NULL;
1169 }
1170
1171 tmpIdx++;
1172
1173 if (GetLength(input, &tmpIdx, &length, (word32)sz) <= 0) {
1174 WOLFSSL_MSG("Error: Invalid Input Length.");
1175 wolfSSL_ASN1_OBJECT_free(ext->obj);
1176 wolfSSL_X509_EXTENSION_free(ext);
1177 FreeDecodedCert(cert);
1178 WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_DCERT);
1179 return NULL;
1180 }
1181 ext->value.data = (char*)XMALLOC(length, NULL,
1182 DYNAMIC_TYPE_ASN1);
1183 ext->value.isDynamic = 1;
1184 if (ext->value.data == NULL) {
1185 WOLFSSL_MSG("Failed to malloc ASN1_STRING data");
1186 wolfSSL_X509_EXTENSION_free(ext);
1187 FreeDecodedCert(cert);
1188 WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_DCERT);
1189 return NULL;
1190 }
1191 XMEMCPY(ext->value.data,input+tmpIdx,length);
1192 ext->value.length = length;
1193
1194 break; /* Got the Extension. Now exit while loop. */
1195
1196 } /* while(idx < sz) */
1197
1198 /* Store the new extension in a stack inside x509
1199 * The extensions on the stack are free'd internally when FreeX509 is called
1200 */
1201 if (x509->ext_sk == NULL)
1202 x509->ext_sk = wolfSSL_sk_new_x509_ext();
1203 if (wolfSSL_sk_insert(x509->ext_sk, ext, -1) <= 0) {
1204 wolfSSL_X509_EXTENSION_free(ext);
1205 ext = NULL;
1206 }
1207
1208 FreeDecodedCert(cert);
1209 WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_DCERT);
1210 return ext;
1211}
1212
1213/**
1214 * @param str String to copy
1215 * @param buf Output buffer. If this contains a pointer then it is free'd
1216 * with the DYNAMIC_TYPE_X509_EXT hint.
1217 * @param len Output length
1218 * @return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on error
1219 */
1220static int asn1_string_copy_to_buffer(WOLFSSL_ASN1_STRING* str, byte** buf,
1221 word32* len, void* heap)
1222{
1223 if (str->data && str->length > 0) {
1224 if (*buf)
1225 XFREE(*buf, heap, DYNAMIC_TYPE_X509_EXT);
1226 *len = 0;
1227 *buf = (byte*)XMALLOC(str->length, heap, DYNAMIC_TYPE_X509_EXT);
1228 if (!*buf) {
1229 WOLFSSL_MSG("malloc error");
1230 return WOLFSSL_FAILURE;
1231 }
1232 *len = (word32)str->length;
1233 XMEMCPY(*buf, str->data, str->length);
1234 }
1235
1236 (void)heap;
1237 return WOLFSSL_SUCCESS;
1238}
1239
1240int wolfSSL_X509_add_ext(WOLFSSL_X509 *x509, WOLFSSL_X509_EXTENSION *ext,
1241 int loc)
1242{
1243 int nid;
1244
1245 WOLFSSL_ENTER("wolfSSL_X509_add_ext");
1246
1247 if (!x509 || !ext || loc >= 0) {
1248 WOLFSSL_MSG("Bad parameter");
1249 return WOLFSSL_FAILURE;
1250 }
1251 nid = (ext->obj != NULL) ? ext->obj->type : ext->value.nid;
1252
1253 switch (nid) {
1254 case WC_NID_authority_key_identifier:
1255 if (x509->authKeyIdSrc != NULL) {
1256 /* If authKeyId points into authKeyIdSrc then free it and
1257 * revert to old functionality */
1258 XFREE(x509->authKeyIdSrc, x509->heap, DYNAMIC_TYPE_X509_EXT);
1259 x509->authKeyIdSrc = NULL;
1260 x509->authKeyId = NULL;
1261 }
1262 if (asn1_string_copy_to_buffer(&ext->value, &x509->authKeyId,
1263 &x509->authKeyIdSz, x509->heap) != WOLFSSL_SUCCESS) {
1264 WOLFSSL_MSG("asn1_string_copy_to_buffer error");
1265 return WOLFSSL_FAILURE;
1266 }
1267 x509->authKeyIdCrit = (byte)ext->crit;
1268 break;
1269 case WC_NID_subject_key_identifier:
1270 if (asn1_string_copy_to_buffer(&ext->value, &x509->subjKeyId,
1271 &x509->subjKeyIdSz, x509->heap) != WOLFSSL_SUCCESS) {
1272 WOLFSSL_MSG("asn1_string_copy_to_buffer error");
1273 return WOLFSSL_FAILURE;
1274 }
1275 x509->subjKeyIdCrit = (byte)ext->crit;
1276 break;
1277 case WC_NID_subject_alt_name:
1278 {
1279 WOLFSSL_GENERAL_NAMES* gns = ext->ext_sk;
1280 while (gns) {
1281 WOLFSSL_GENERAL_NAME* gn = gns->data.gn;
1282 if ((gn != NULL) && (gn->type == ASN_OTHER_TYPE)) {
1283 char *buf = NULL;
1284 int ret = 0;
1285 word32 len = 0;
1286
1287 len = SetOthername(gn->d.otherName, NULL);
1288 if (len == WC_NO_ERR_TRACE(WOLFSSL_FAILURE)) {
1289 return WOLFSSL_FAILURE;
1290 }
1291
1292 buf = (char*)XMALLOC(len, x509->heap, DYNAMIC_TYPE_X509_EXT);
1293 if (buf == NULL) {
1294 WOLFSSL_MSG("Couldn't allocate memory for othername");
1295 return WOLFSSL_FAILURE;
1296 }
1297
1298 /* SetOthername() cannot fail; already passed above. */
1299 SetOthername(gn->d.otherName, (byte*)buf);
1300
1301 ret = wolfSSL_X509_add_altname_ex(x509, buf, len,
1302 ASN_OTHER_TYPE);
1303 XFREE(buf, x509->heap, DYNAMIC_TYPE_X509_EXT);
1304 if (ret == WC_NO_ERR_TRACE(WOLFSSL_FAILURE)) {
1305 WOLFSSL_MSG("wolfSSL_X509_add_altname_ex() failed");
1306 return WOLFSSL_FAILURE;
1307 }
1308 }
1309 else if (!gn || !gn->d.ia5 ||
1310 wolfSSL_X509_add_altname_ex(x509, gn->d.ia5->data,
1311 gn->d.ia5->length, gn->type) != WOLFSSL_SUCCESS) {
1312 WOLFSSL_MSG("Subject alternative name missing extension");
1313 return WOLFSSL_FAILURE;
1314 }
1315 gns = gns->next;
1316 }
1317 x509->subjAltNameSet = 1;
1318 x509->subjAltNameCrit = (byte)ext->crit;
1319 break;
1320 }
1321 case WC_NID_key_usage:
1322 if (ext && ext->value.data) {
1323 if (ext->value.length == sizeof(word16)) {
1324 /* if ext->value is already word16, set directly */
1325 word16 ku;
1326 XMEMCPY(&ku, ext->value.data, sizeof(word16));
1327 x509->keyUsage = ku;
1328#ifdef BIG_ENDIAN_ORDER
1329 x509->keyUsage = rotlFixed16(x509->keyUsage, 8U);
1330#endif
1331 x509->keyUsageCrit = (byte)ext->crit;
1332 x509->keyUsageSet = 1;
1333 }
1334 else if (ext->value.length > 0) {
1335 /* ext->value is comma-delimited string, convert to word16 */
1336 if (ParseKeyUsageStr(ext->value.data, &x509->keyUsage,
1337 x509->heap) != 0) {
1338 return WOLFSSL_FAILURE;
1339 }
1340 x509->keyUsageCrit = (byte)ext->crit;
1341 x509->keyUsageSet = 1;
1342 }
1343 else {
1344 return WOLFSSL_FAILURE;
1345 }
1346 }
1347 break;
1348 case WC_NID_ext_key_usage:
1349 if (ext && ext->value.data) {
1350 if (ext->value.length == sizeof(byte)) {
1351 /* if ext->value is already 1 byte, set directly */
1352 x509->extKeyUsage = *(byte*)ext->value.data;
1353 x509->extKeyUsageCrit = (byte)ext->crit;
1354 }
1355 else if (ext->value.length > 0) {
1356 /* ext->value is comma-delimited string, convert to word16 */
1357 if (ParseExtKeyUsageStr(ext->value.data, &x509->extKeyUsage,
1358 x509->heap) != 0) {
1359 return WOLFSSL_FAILURE;
1360 }
1361 x509->extKeyUsageCrit = (byte)ext->crit;
1362 }
1363 else {
1364 return WOLFSSL_FAILURE;
1365 }
1366 }
1367 break;
1368 case WC_NID_basic_constraints:
1369 if (ext->obj) {
1370 x509->isCa = (byte)ext->obj->ca;
1371 x509->basicConstCrit = (byte)ext->crit;
1372 if (ext->obj->pathlen) {
1373 x509->pathLength = (word32)ext->obj->pathlen->length;
1374 x509->basicConstPlSet = 1;
1375 x509->pathLengthSet = 1;
1376 }
1377 x509->basicConstSet = 1;
1378 }
1379 break;
1380 default:
1381#ifdef WOLFSSL_CUSTOM_OID
1382 {
1383 char *oid = NULL;
1384 byte *val = NULL;
1385 int err = 0;
1386
1387 if ((ext->obj == NULL) || (ext->value.length == 0)) {
1388 WOLFSSL_MSG("Extension has insufficient information.");
1389 return WOLFSSL_FAILURE;
1390 }
1391
1392 if ((x509->customExtCount < 0) ||
1393 (x509->customExtCount >= NUM_CUSTOM_EXT)) {
1394 WOLFSSL_MSG("Bad value for customExtCount.");
1395 return WOLFSSL_FAILURE;
1396 }
1397
1398 /* This is a viable custom extension. */
1399 oid = (char*)XMALLOC(MAX_OID_STRING_SZ, x509->heap,
1400 DYNAMIC_TYPE_X509_EXT);
1401 val = (byte*)XMALLOC(ext->value.length, x509->heap,
1402 DYNAMIC_TYPE_X509_EXT);
1403 if ((oid == NULL) || (val == NULL)) {
1404 WOLFSSL_MSG("Memory allocation failure.\n");
1405 err = 1;
1406 }
1407
1408 if (err == 0) {
1409 XMEMCPY(val, ext->value.data, ext->value.length);
1410 if (wolfSSL_OBJ_obj2txt(oid, MAX_OID_STRING_SZ, ext->obj, 1) < 0) {
1411 err = 1;
1412 }
1413 }
1414
1415 if (err == 1) {
1416 XFREE(val, x509->heap, DYNAMIC_TYPE_X509_EXT);
1417 XFREE(oid, x509->heap, DYNAMIC_TYPE_X509_EXT);
1418 return WOLFSSL_FAILURE;
1419 }
1420
1421 /* ext->crit is WOLFSSL_ASN1_BOOLEAN */
1422 if (ext->crit != 0 && ext->crit != -1) {
1423 XFREE(val, x509->heap, DYNAMIC_TYPE_X509_EXT);
1424 XFREE(oid, x509->heap, DYNAMIC_TYPE_X509_EXT);
1425 return WOLFSSL_FAILURE;
1426 }
1427
1428 /* x509->custom_exts now owns the buffers and they must be managed. */
1429 x509->custom_exts[x509->customExtCount].oid = oid;
1430 x509->custom_exts[x509->customExtCount].crit = (byte)ext->crit;
1431 x509->custom_exts[x509->customExtCount].val = val;
1432 x509->custom_exts[x509->customExtCount].valSz = ext->value.length;
1433 x509->customExtCount++;
1434 break;
1435 }
1436#else
1437 WOLFSSL_MSG("Unsupported extension to add");
1438 return WOLFSSL_FAILURE;
1439#endif /* WOLFSSL_CUSTOM_OID */
1440 } /* switch (nid) */
1441
1442 return WOLFSSL_SUCCESS;
1443}
1444
1445/* Returns pointer to ASN1_STRING in X509_EXTENSION object */
1446static WOLFSSL_ASN1_STRING* wolfSSL_X509_EXTENSION_get_data_internal(
1447 WOLFSSL_X509_EXTENSION* ext)
1448{
1449 WOLFSSL_ENTER("wolfSSL_X509_EXTENSION_get_data_internal");
1450 if (ext == NULL)
1451 return NULL;
1452
1453 return &ext->value;
1454}
1455
1456
1457#ifndef NO_BIO
1458
1459#ifndef MAX_INDENT
1460 #define MAX_INDENT 40
1461#endif
1462
1463
1464/* Return 0 on success and 1 on failure. Copies ext data to bio, using indent
1465 * to pad the output. flag is ignored. */
1466int wolfSSL_X509V3_EXT_print(WOLFSSL_BIO *out, WOLFSSL_X509_EXTENSION *ext,
1467 unsigned long flag, int indent)
1468{
1469 WOLFSSL_ASN1_OBJECT* obj;
1470 WOLFSSL_ASN1_STRING* str;
1471 int nid;
1472 int rc = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
1473 char tmp[CTC_NAME_SIZE*2 + 1];
1474 const int tmpSz = sizeof(tmp);
1475 int tmpLen = 0;
1476 WOLFSSL_ENTER("wolfSSL_X509V3_EXT_print");
1477
1478 if (indent < 0) indent = 0;
1479 if (indent > MAX_INDENT) indent = MAX_INDENT;
1480
1481 if ((out == NULL) || (ext == NULL)) {
1482 WOLFSSL_MSG("NULL parameter error");
1483 return rc;
1484 }
1485
1486 obj = wolfSSL_X509_EXTENSION_get_object(ext);
1487 if (obj == NULL) {
1488 WOLFSSL_MSG("Error getting ASN1_OBJECT from X509_EXTENSION");
1489 return rc;
1490 }
1491
1492 str = wolfSSL_X509_EXTENSION_get_data_internal(ext);
1493 if (str == NULL) {
1494 WOLFSSL_MSG("Error getting ASN1_STRING from X509_EXTENSION");
1495 return rc;
1496 }
1497
1498 /* Print extension based on the type */
1499 nid = wolfSSL_OBJ_obj2nid(obj);
1500 switch (nid) {
1501 case BASIC_CA_OID:
1502 {
1503 char isCa[] = "TRUE";
1504 char notCa[] = "FALSE";
1505 if ((tmpLen = XSNPRINTF(tmp, tmpSz, "%*sCA:%s", indent, "",
1506 obj->ca ? isCa : notCa))
1507 >= tmpSz)
1508 return rc;
1509 break;
1510 }
1511 case ALT_NAMES_OID:
1512 {
1513 WOLFSSL_STACK* sk;
1514 char* val;
1515 int valLen;
1516 int len;
1517
1518 sk = ext->ext_sk;
1519 while (sk != NULL) {
1520 if (sk->type == STACK_TYPE_GEN_NAME && sk->data.gn) {
1521 /* str is GENERAL_NAME for subject alternative name ext */
1522 str = sk->data.gn->d.ia5;
1523 len = str->length + 2; /* + 2 for NULL char and "," */
1524 if (len > tmpSz) {
1525 WOLFSSL_MSG("len greater than buffer size");
1526 return rc;
1527 }
1528
1529 val = (char*)XMALLOC(len + indent, NULL,
1530 DYNAMIC_TYPE_TMP_BUFFER);
1531 if (val == NULL) {
1532 WOLFSSL_MSG("Memory error");
1533 return rc;
1534 }
1535 valLen = XSNPRINTF(val, (size_t)len, "%*s%s", indent, "",
1536 str->strData);
1537 if ((valLen < 0) || (valLen >= len)
1538 || ((tmpLen + valLen) >= tmpSz)) {
1539 XFREE(val, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1540 return rc;
1541 }
1542 XMEMCPY(tmp + tmpLen, val, valLen);
1543 tmpLen += valLen;
1544 XFREE(val, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1545 }
1546 sk = sk->next;
1547 }
1548 break;
1549 }
1550 case AUTH_KEY_OID:
1551 case SUBJ_KEY_OID:
1552 {
1553 char* asn1str;
1554 asn1str = wolfSSL_i2s_ASN1_STRING(NULL, str);
1555 tmpLen = XSNPRINTF(tmp, tmpSz, "%*s%s", indent, "", asn1str);
1556 XFREE(asn1str, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1557 if (tmpLen >= tmpSz)
1558 tmpLen = tmpSz - 1;
1559 break;
1560 }
1561 case AUTH_INFO_OID:
1562 case CERT_POLICY_OID:
1563 case CRL_DIST_OID:
1564 case KEY_USAGE_OID:
1565 WOLFSSL_MSG("X509V3_EXT_print not yet implemented for ext type");
1566 break;
1567
1568 default:
1569 if ((tmpLen = XSNPRINTF(
1570 tmp, tmpSz, "%*s%s", indent, "", str->strData))
1571 >= tmpSz)
1572 return rc;
1573 }
1574
1575 if (wolfSSL_BIO_write(out, tmp, tmpLen) == tmpLen) {
1576 rc = WOLFSSL_SUCCESS;
1577 }
1578 (void) flag;
1579
1580 return rc;
1581}
1582#endif /* !NO_BIO */
1583
1584#ifndef NO_WOLFSSL_STUB
1585int wolfSSL_X509V3_EXT_add_nconf(WOLFSSL_CONF *conf, WOLFSSL_X509V3_CTX *ctx,
1586 const char *section, WOLFSSL_X509 *cert)
1587{
1588 WOLFSSL_ENTER("wolfSSL_X509V3_EXT_add_nconf");
1589 WOLFSSL_STUB("wolfSSL_X509V3_EXT_add_nconf");
1590 (void)conf;
1591 (void)ctx;
1592 (void)section;
1593 (void)cert;
1594 return WOLFSSL_SUCCESS;
1595}
1596#endif
1597
1598/* Find extension by NID in a stack of extensions.
1599 *
1600 * @param sk Stack of extensions
1601 * @param nid ID to search for
1602 * @param lastpos Start search from this position (not inclusive, -1 means start from beginning)
1603 * @return Index of matching extension or -1 on error/not found
1604 */
1605int wolfSSL_X509v3_get_ext_by_NID(const WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* sk,
1606 int nid, int lastpos)
1607{
1608 int i;
1609 WOLFSSL_ENTER("wolfSSL_X509v3_get_ext_by_NID");
1610
1611 if (sk == NULL) {
1612 WOLFSSL_MSG("Stack pointer is NULL");
1613 return WOLFSSL_FATAL_ERROR;
1614 }
1615
1616 if (lastpos < -1 || lastpos >= wolfSSL_sk_num(sk)) {
1617 WOLFSSL_MSG("Invalid position argument");
1618 return WOLFSSL_FATAL_ERROR;
1619 }
1620
1621 for (i = lastpos + 1; i < wolfSSL_sk_num(sk); i++) {
1622 WOLFSSL_X509_EXTENSION* ext = wolfSSL_sk_X509_EXTENSION_value(sk, i);
1623 if (ext && ext->obj) {
1624 if (wolfSSL_OBJ_obj2nid(ext->obj) == nid)
1625 return i;
1626 }
1627 }
1628
1629 /* Not found */
1630 return -1;
1631}
1632
1633/* Get extension from a stack of extensions by location.
1634 *
1635 * @param sk Stack of extensions
1636 * @param loc Index of extension to retrieve
1637 * @return Pointer to extension or NULL on error
1638 */
1639WOLFSSL_X509_EXTENSION* wolfSSL_X509v3_get_ext(
1640 const WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* sk, int loc)
1641{
1642 WOLFSSL_ENTER("wolfSSL_X509v3_get_ext");
1643
1644 if (sk == NULL) {
1645 WOLFSSL_MSG("Stack pointer is NULL");
1646 return NULL;
1647 }
1648
1649 if (loc < 0 || loc >= wolfSSL_sk_num(sk)) {
1650 WOLFSSL_MSG("Invalid location argument");
1651 return NULL;
1652 }
1653
1654 return wolfSSL_sk_X509_EXTENSION_value(sk, loc);
1655}
1656
1657/* Returns crit flag in X509_EXTENSION object */
1658int wolfSSL_X509_EXTENSION_get_critical(const WOLFSSL_X509_EXTENSION* ex)
1659{
1660 WOLFSSL_ENTER("wolfSSL_X509_EXTENSION_get_critical");
1661 if (ex == NULL)
1662 return BAD_FUNC_ARG;
1663 return ex->crit;
1664}
1665
1666/* Sets if the extension is critical
1667 * returns WOLFSSL_SUCCESS on success
1668 */
1669int wolfSSL_X509_EXTENSION_set_critical(WOLFSSL_X509_EXTENSION* ex, int crit)
1670{
1671 WOLFSSL_ENTER("wolfSSL_X509_EXTENSION_set_critical");
1672 if (ex == NULL)
1673 return WOLFSSL_FAILURE;
1674 ex->crit = crit;
1675 return WOLFSSL_SUCCESS;
1676}
1677
1678/* Creates v3_ext_method for a given X509v3 extension
1679 *
1680 * ex : The X509_EXTENSION used to create v3_ext_method. If the extension is
1681 * not NULL, get the NID of the extension object and populate the
1682 * extension type-specific X509V3_EXT_* function(s) in v3_ext_method.
1683 *
1684 * Returns NULL on error or pointer to the v3_ext_method populated with
1685 * extension type-specific X509V3_EXT_* function(s).
1686 *
1687 * NOTE: WC_NID_subject_key_identifier is currently the only extension
1688 * implementing the X509V3_EXT_* functions, as it is the only type called
1689 * directly by QT. The other extension types return a pointer to a
1690 * v3_ext_method struct that contains only the NID.
1691 */
1692#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L
1693const WOLFSSL_v3_ext_method* wolfSSL_X509V3_EXT_get(WOLFSSL_X509_EXTENSION* ex)
1694#else
1695WOLFSSL_v3_ext_method* wolfSSL_X509V3_EXT_get(WOLFSSL_X509_EXTENSION* ex)
1696#endif
1697{
1698 int nid;
1699 WOLFSSL_v3_ext_method method;
1700
1701 WOLFSSL_ENTER("wolfSSL_X509V3_EXT_get");
1702 if ((ex == NULL) || (ex->obj == NULL)) {
1703 WOLFSSL_MSG("Passed an invalid X509_EXTENSION*");
1704 return NULL;
1705 }
1706 /* Initialize method to 0 */
1707 XMEMSET(&method, 0, sizeof(struct WOLFSSL_v3_ext_method));
1708
1709 nid = ex->obj->nid;
1710 if (nid <= 0) {
1711 WOLFSSL_MSG("Failed to get nid from passed extension object");
1712 return NULL;
1713 }
1714 switch (nid) {
1715 case WC_NID_basic_constraints:
1716 break;
1717 case WC_NID_subject_key_identifier:
1718 method.i2s = (WOLFSSL_X509V3_EXT_I2S)wolfSSL_i2s_ASN1_STRING;
1719 break;
1720 case WC_NID_subject_alt_name:
1721 WOLFSSL_MSG("i2v function not yet implemented for Subject "
1722 "Alternative Name");
1723 break;
1724 case WC_NID_key_usage:
1725 WOLFSSL_MSG("i2v function not yet implemented for Key Usage");
1726 break;
1727 case WC_NID_authority_key_identifier:
1728 WOLFSSL_MSG("i2v function not yet implemented for Auth Key Id");
1729 break;
1730 case WC_NID_info_access:
1731 WOLFSSL_MSG("i2v function not yet implemented for Info Access");
1732 break;
1733 case WC_NID_ext_key_usage:
1734 WOLFSSL_MSG("i2v function not yet implemented for Ext Key Usage");
1735 break;
1736 case WC_NID_certificate_policies:
1737 WOLFSSL_MSG("r2i function not yet implemented for Cert Policies");
1738 break;
1739 case WC_NID_crl_distribution_points:
1740 WOLFSSL_MSG("r2i function not yet implemented for CRL Dist Points");
1741 break;
1742 default:
1743 /* If extension type is unknown, return NULL -- QT makes call to
1744 X509_EXTENSION_get_data() if there is no v3_ext_method */
1745 WOLFSSL_MSG("X509V3_EXT_get(): Unknown extension type found");
1746 return NULL;
1747 }
1748
1749 method.ext_nid = nid;
1750 ex->ext_method = method;
1751
1752#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L
1753 return (const WOLFSSL_v3_ext_method*)&ex->ext_method;
1754#else
1755 return (WOLFSSL_v3_ext_method*)&ex->ext_method;
1756#endif
1757}
1758
1759/* Create an Authority Info Access (AIA) from the contents of the extension.
1760 *
1761 * AIA is a stack of Access Descriptions.
1762 *
1763 * RFC 5280: 4.2.2.1
1764 *
1765 * @param [in] ext X509v3 extension.
1766 * @return Stack of Access Descriptions as an AIA on success.
1767 * @return NULL on error.
1768 */
1769static WOLFSSL_AUTHORITY_INFO_ACCESS* wolfssl_x509v3_ext_aia_d2i(
1770 WOLFSSL_X509_EXTENSION* ext)
1771{
1772 int err = 0;
1773 int ret;
1774 WOLFSSL_AUTHORITY_INFO_ACCESS* aia = NULL;
1775 WOLFSSL_STACK* sk;
1776 WOLFSSL_ACCESS_DESCRIPTION* ad = NULL;
1777
1778 /* Get the type specific data of this extension. */
1779 sk = ext->ext_sk;
1780 if (sk == NULL) {
1781 WOLFSSL_MSG("ACCESS_DESCRIPTION stack NULL");
1782 err = 1;
1783 }
1784
1785 if (!err) {
1786 /* AUTHORITY_INFO_ACCESS is a stack of ACCESS_DESCRIPTION entries. */
1787 aia = wolfSSL_sk_new_null();
1788 if (aia == NULL) {
1789 WOLFSSL_MSG("Failed to malloc AUTHORITY_INFO_ACCESS");
1790 err = 1;
1791 }
1792 }
1793 if (!err) {
1794 /* AIA is a stack of Access Descriptions. */
1795 aia->type = STACK_TYPE_ACCESS_DESCRIPTION;
1796 }
1797
1798 while ((!err) && (sk != NULL)) {
1799 WOLFSSL_ASN1_OBJECT* aiaEntry;
1800
1801 /* Looking for objects in extension's data. */
1802 if (sk->type != STACK_TYPE_OBJ) {
1803 sk = sk->next;
1804 continue;
1805 }
1806
1807 /* Get ASN.1 Object from the stack entry's data. */
1808 aiaEntry = sk->data.obj;
1809
1810 /* ACCESS_DESCRIPTION has two members: method and location.
1811 * method: ASN1_OBJECT as either AIA_OCSP_OID or AIA_CA_ISSUER_OID
1812 * location: GENERAL_NAME structure containing the URI.
1813 */
1814
1815 /* Allocate a new Access Description. */
1816 ad = (WOLFSSL_ACCESS_DESCRIPTION*)XMALLOC(
1817 sizeof(WOLFSSL_ACCESS_DESCRIPTION), NULL, DYNAMIC_TYPE_X509_EXT);
1818 if (ad == NULL) {
1819 WOLFSSL_MSG("Failed to malloc ACCESS_DESCRIPTION");
1820 err = 1;
1821 break;
1822 }
1823 XMEMSET(ad, 0, sizeof(WOLFSSL_ACCESS_DESCRIPTION));
1824
1825 /* Create new ASN1_OBJECT from NID. */
1826 ad->method = wolfSSL_OBJ_nid2obj(aiaEntry->nid);
1827 if (ad->method == NULL) {
1828 WOLFSSL_MSG("OBJ_nid2obj() failed");
1829 err = 1;
1830 break;
1831 }
1832
1833 /* Allocate memory for GENERAL NAME. */
1834 ad->location = wolfSSL_GENERAL_NAME_new();
1835 if (ad->location == NULL) {
1836 WOLFSSL_MSG("Failed to malloc GENERAL_NAME");
1837 err = 1;
1838 break;
1839 }
1840
1841 /* Set the type of general name to URI (only type supported). */
1842 ret = wolfSSL_GENERAL_NAME_set_type(ad->location, WOLFSSL_GEN_URI);
1843 if (ret != WOLFSSL_SUCCESS) {
1844 err = 1;
1845 break;
1846 }
1847
1848 /* Set the URI into GENERAL_NAME. */
1849 ret = wolfSSL_ASN1_STRING_set(ad->location->d.uniformResourceIdentifier,
1850 aiaEntry->obj, aiaEntry->objSz);
1851 if (ret != WOLFSSL_SUCCESS) {
1852 WOLFSSL_MSG("ASN1_STRING_set() failed");
1853 err = 1;
1854 break;
1855 }
1856 /* Push onto AUTHORITY_INFO_ACCESS stack. */
1857 ret = wolfSSL_sk_ACCESS_DESCRIPTION_push(aia, ad) > 0
1858 ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
1859 if (ret != WOLFSSL_SUCCESS) {
1860 WOLFSSL_MSG("Error pushing ASN1 AD onto stack");
1861 err = 1;
1862 break;
1863 }
1864 /* Set to NULL so that it doesn't get freed now it is in AIA stack. */
1865 ad = NULL;
1866
1867 sk = sk->next;
1868 }
1869
1870 if (err) {
1871 /* Dispose of Access Description if not put in stack. */
1872 if (ad != NULL) {
1873 wolfSSL_ASN1_OBJECT_free(ad->method);
1874 wolfSSL_GENERAL_NAME_free(ad->location);
1875 XFREE(ad, NULL, DYNAMIC_TYPE_X509_EXT);
1876 }
1877 /* Dispose of incomplete Access Description stack. */
1878 wolfSSL_sk_ACCESS_DESCRIPTION_pop_free(aia, NULL);
1879 aia = NULL;
1880 }
1881 return aia;
1882}
1883
1884/* Parses and returns an x509v3 extension internal structure.
1885 *
1886 * ext : The X509_EXTENSION for parsing internal structure. If extension is
1887 * not NULL, get the NID of the extension object and create a new
1888 * extension-specific internal structure based on the extension type.
1889 *
1890 * Returns NULL on error or if NID is not found, otherwise returns a pointer to
1891 * the extension type-specific X509_EXTENSION internal structure.
1892 * Return is expected to be free'd by caller.
1893 */
1894void* wolfSSL_X509V3_EXT_d2i(WOLFSSL_X509_EXTENSION* ext)
1895{
1896 const WOLFSSL_v3_ext_method* method;
1897 int ret;
1898 WOLFSSL_ASN1_OBJECT* object;
1899 WOLFSSL_BASIC_CONSTRAINTS* bc;
1900 WOLFSSL_AUTHORITY_KEYID* akey;
1901 WOLFSSL_ASN1_STRING* asn1String = NULL, *newString = NULL;
1902 WOLFSSL_STACK* sk;
1903 void *data = NULL;
1904 WC_DECLARE_VAR(cert, DecodedCert, 1, 0);
1905
1906 WOLFSSL_ENTER("wolfSSL_X509V3_EXT_d2i");
1907
1908 if (ext == NULL) {
1909 WOLFSSL_MSG("Bad function Argument");
1910 return NULL;
1911 }
1912
1913 object = wolfSSL_X509_EXTENSION_get_object(ext);
1914 if (object == NULL) {
1915 WOLFSSL_MSG("X509_EXTENSION_get_object failed");
1916 return NULL;
1917 }
1918 /* extract extension info */
1919 method = wolfSSL_X509V3_EXT_get(ext);
1920 if (method == NULL) {
1921 WOLFSSL_MSG("wolfSSL_X509V3_EXT_get error");
1922 return NULL;
1923 }
1924
1925#ifdef WOLFSSL_SMALL_STACK
1926 cert = (DecodedCert *)XMALLOC(sizeof(*cert), NULL,
1927 DYNAMIC_TYPE_X509_EXT);
1928 if (cert == NULL) {
1929 WOLFSSL_MSG("\tout of memory");
1930 return NULL;
1931 }
1932#endif
1933
1934 InitDecodedCert(cert, NULL, 0, NULL);
1935
1936 if ((object->type != WC_NID_basic_constraints) &&
1937 (object->type != WC_NID_subject_alt_name) &&
1938 (object->type != WC_NID_info_access)) {
1939
1940 asn1String = wolfSSL_X509_EXTENSION_get_data_internal(ext);
1941 if (asn1String == NULL) {
1942 WOLFSSL_MSG("X509_EXTENSION_get_data() failed");
1943 goto out;
1944 }
1945
1946 ret = DecodeExtensionType((const byte*)asn1String->data,
1947 asn1String->length, object->type, (byte)ext->crit, cert, NULL);
1948 if (ret != 0) {
1949 WOLFSSL_MSG("DecodeExtensionType() failed");
1950 goto out;
1951 }
1952 }
1953
1954 /* Return pointer to proper internal structure based on NID */
1955 switch (object->type) {
1956 /* basicConstraints */
1957 case WC_NID_basic_constraints:
1958 WOLFSSL_MSG("basicConstraints");
1959 /* Allocate new BASIC_CONSTRAINTS structure */
1960 bc = wolfSSL_BASIC_CONSTRAINTS_new();
1961 if (bc == NULL) {
1962 WOLFSSL_MSG("Failed to malloc basic constraints");
1963 break;
1964 }
1965 /* Copy pathlen and CA into BASIC_CONSTRAINTS from object */
1966 bc->ca = object->ca;
1967 if (object->pathlen != NULL && object->pathlen->length > 0) {
1968 bc->pathlen = wolfSSL_ASN1_INTEGER_dup(object->pathlen);
1969 if (bc->pathlen == NULL) {
1970 WOLFSSL_MSG("Failed to duplicate ASN1_INTEGER");
1971 wolfSSL_BASIC_CONSTRAINTS_free(bc);
1972 break;
1973 }
1974 }
1975 else
1976 bc->pathlen = NULL;
1977
1978 data = bc;
1979 break;
1980
1981 /* subjectKeyIdentifier */
1982 case WC_NID_subject_key_identifier:
1983 {
1984 WOLFSSL_MSG("subjectKeyIdentifier");
1985
1986 newString = wolfSSL_ASN1_STRING_new();
1987 if (newString == NULL) {
1988 WOLFSSL_MSG("Failed to malloc ASN1_STRING");
1989 break;
1990 }
1991 ret = wolfSSL_ASN1_STRING_set(newString, cert->extSubjKeyId,
1992 cert->extSubjKeyIdSz);
1993 if (ret != WOLFSSL_SUCCESS) {
1994 WOLFSSL_MSG("ASN1_STRING_set() failed");
1995 wolfSSL_ASN1_STRING_free(newString);
1996 break;
1997 };
1998
1999 newString->type = asn1String->type;
2000 data = newString;
2001 break;
2002 }
2003
2004 /* authorityKeyIdentifier */
2005 case WC_NID_authority_key_identifier:
2006 {
2007 WOLFSSL_MSG("AuthorityKeyIdentifier");
2008
2009 akey = (WOLFSSL_AUTHORITY_KEYID*)
2010 XMALLOC(sizeof(WOLFSSL_AUTHORITY_KEYID), NULL,
2011 DYNAMIC_TYPE_X509_EXT);
2012 if (akey == NULL) {
2013 WOLFSSL_MSG("Failed to malloc authority key id");
2014 break;
2015 }
2016
2017 XMEMSET(akey, 0, sizeof(WOLFSSL_AUTHORITY_KEYID));
2018
2019 akey->keyid = wolfSSL_ASN1_STRING_new();
2020 if (akey->keyid == NULL) {
2021 WOLFSSL_MSG("ASN1_STRING_new() failed");
2022 wolfSSL_AUTHORITY_KEYID_free(akey);
2023 break;
2024 }
2025
2026 ret = wolfSSL_ASN1_STRING_set(akey->keyid, cert->extAuthKeyId,
2027 cert->extAuthKeyIdSz);
2028 if (ret != WOLFSSL_SUCCESS) {
2029 WOLFSSL_MSG("ASN1_STRING_set() failed");
2030 wolfSSL_AUTHORITY_KEYID_free(akey);
2031 break;
2032 };
2033 akey->keyid->type = asn1String->type;
2034
2035 /* For now, set issuer and serial to NULL. This may need to be
2036 updated for future use */
2037 akey->issuer = NULL;
2038 akey->serial = NULL;
2039
2040 data = akey;
2041 break;
2042 }
2043
2044 /* keyUsage */
2045 case WC_NID_key_usage:
2046 {
2047 WOLFSSL_MSG("keyUsage");
2048
2049 /* This may need to be updated for future use. The i2v method for
2050 keyUsage is not currently set. For now, return the ASN1_STRING
2051 representation of KeyUsage bit string */
2052 newString = wolfSSL_ASN1_STRING_new();
2053 if (newString == NULL) {
2054 WOLFSSL_MSG("Failed to malloc ASN1_STRING");
2055 break;
2056 }
2057 ret = wolfSSL_ASN1_STRING_set(newString, (byte*)&cert->extKeyUsage,
2058 sizeof(word16));
2059 if (ret != WOLFSSL_SUCCESS) {
2060 WOLFSSL_MSG("ASN1_STRING_set() failed");
2061 wolfSSL_ASN1_STRING_free(newString);
2062 break;
2063 };
2064 newString->type = asn1String->type;
2065 data = newString;
2066 break;
2067 }
2068
2069 /* extKeyUsage */
2070 case WC_NID_ext_key_usage:
2071 WOLFSSL_MSG("extKeyUsage not supported yet");
2072 break;
2073
2074 /* certificatePolicies */
2075 case WC_NID_certificate_policies:
2076 WOLFSSL_MSG("certificatePolicies not supported yet");
2077 break;
2078
2079 /* cRLDistributionPoints */
2080 case WC_NID_crl_distribution_points:
2081 WOLFSSL_MSG("cRLDistributionPoints not supported yet");
2082 break;
2083
2084 case WC_NID_subject_alt_name:
2085 if (ext->ext_sk == NULL) {
2086 WOLFSSL_MSG("Subject alt name stack NULL");
2087 break;
2088 }
2089 sk = wolfSSL_sk_dup(ext->ext_sk);
2090 if (sk == NULL) {
2091 WOLFSSL_MSG("Failed to duplicate subject alt names stack.");
2092 break;
2093 }
2094 data = sk;
2095 break;
2096
2097 /* authorityInfoAccess */
2098 case WC_NID_info_access:
2099 WOLFSSL_MSG("AuthorityInfoAccess");
2100 data = wolfssl_x509v3_ext_aia_d2i(ext);
2101 break;
2102
2103 default:
2104 WOLFSSL_MSG("Extension NID not in table, returning NULL");
2105 break;
2106 }
2107
2108out:
2109
2110 FreeDecodedCert(cert);
2111 WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_X509_EXT);
2112
2113 return data;
2114}
2115
2116/* Looks for the extension matching the passed in nid
2117 *
2118 * x509 : certificate to get parse through for extension.
2119 * nid : Extension OID to be found.
2120 * lastPos : Start search from extension after lastPos.
2121 * Set to -1 to search from index 0.
2122 * return >= 0 If successful the extension index is returned.
2123 * return WOLFSSL_FATAL_ERROR If extension is not found or error is encountered.
2124 */
2125int wolfSSL_X509_get_ext_by_NID(const WOLFSSL_X509* x509, int nid, int lastPos)
2126{
2127 int extCount = 0, length = 0, outSz = 0, sz = 0, ret = 0;
2128 int isSet = 0, found = 0, loc;
2129 const byte* rawCert;
2130 const byte* input;
2131 word32 oid, idx = 0, tmpIdx = 0, foundNID;
2132 WC_DECLARE_VAR(cert, DecodedCert, 1, 0);
2133
2134 WOLFSSL_ENTER("wolfSSL_X509_get_ext_by_NID");
2135
2136 if (x509 == NULL) {
2137 WOLFSSL_MSG("\tNot passed a certificate");
2138 return WOLFSSL_FATAL_ERROR;
2139 }
2140
2141 if (lastPos < -1 || (lastPos > (wolfSSL_X509_get_ext_count(x509) - 1))) {
2142 WOLFSSL_MSG("\tBad location argument");
2143 return WOLFSSL_FATAL_ERROR;
2144 }
2145
2146 loc = lastPos + 1;
2147
2148 rawCert = wolfSSL_X509_get_der((WOLFSSL_X509*)x509, &outSz);
2149 if (rawCert == NULL) {
2150 WOLFSSL_MSG("\tX509_get_der() failed");
2151 return WOLFSSL_FATAL_ERROR;
2152 }
2153
2154#ifdef WOLFSSL_SMALL_STACK
2155 cert = (DecodedCert *)XMALLOC(sizeof(*cert), x509->heap,
2156 DYNAMIC_TYPE_DCERT);
2157 if (cert == NULL) {
2158 WOLFSSL_MSG("\tout of memory");
2159 return WOLFSSL_FATAL_ERROR;
2160 }
2161#endif
2162
2163 InitDecodedCert( cert, rawCert, (word32)outSz, 0);
2164
2165 if (ParseCert(cert,
2166#ifdef WOLFSSL_CERT_REQ
2167 x509->isCSR ? CERTREQ_TYPE :
2168#endif
2169 CA_TYPE,
2170 NO_VERIFY, NULL) < 0) {
2171 WOLFSSL_MSG("\tCertificate parsing failed");
2172 goto out;
2173 }
2174
2175 input = cert->extensions;
2176 sz = cert->extensionsSz;
2177
2178 if (input == NULL || sz == 0) {
2179 WOLFSSL_MSG("\tfail: should be an EXTENSIONS");
2180 goto out;
2181 }
2182
2183#ifdef WOLFSSL_CERT_REQ
2184 if (!x509->isCSR)
2185#endif
2186 {
2187 if (input[idx++] != ASN_EXTENSIONS) {
2188 WOLFSSL_MSG("\tfail: should be an EXTENSIONS");
2189 goto out;
2190 }
2191
2192 if (GetLength(input, &idx, &length, (word32)sz) < 0) {
2193 WOLFSSL_MSG("\tfail: invalid length");
2194 goto out;
2195 }
2196 }
2197
2198 if (GetSequence(input, &idx, &length, (word32)sz) < 0) {
2199 WOLFSSL_MSG("\tfail: should be a SEQUENCE (1)");
2200 goto out;
2201 }
2202
2203 while (idx < (word32)sz) {
2204 oid = 0;
2205
2206 if (GetSequence(input, &idx, &length, (word32)sz) < 0) {
2207 WOLFSSL_MSG("\tfail: should be a SEQUENCE");
2208 goto out;
2209 }
2210
2211 tmpIdx = idx;
2212 ret = GetObjectId(input, &idx, &oid, oidCertExtType, (word32)sz);
2213 if (ret < 0) {
2214 WOLFSSL_MSG("\tfail: OBJECT ID");
2215 goto out;
2216 }
2217 idx = tmpIdx;
2218 foundNID = (word32)oid2nid(oid, oidCertExtType);
2219
2220 if (extCount >= loc) {
2221 /* extCount >= loc. Now check if extension has been set */
2222 isSet = wolfSSL_X509_ext_isSet_by_NID((WOLFSSL_X509*)x509,
2223 (int)foundNID);
2224 if (isSet && ((word32)nid == foundNID)) {
2225 found = 1;
2226 break;
2227 }
2228 }
2229
2230 idx += length;
2231 extCount++;
2232 } /* while(idx < sz) */
2233
2234out:
2235
2236 FreeDecodedCert(cert);
2237 WC_FREE_VAR_EX(cert, x509->heap, DYNAMIC_TYPE_DCERT);
2238
2239 return found ? extCount : WOLFSSL_FATAL_ERROR;
2240}
2241
2242#endif /* OPENSSL_ALL || OPENSSL_EXTRA */
2243
2244#if defined(OPENSSL_EXTRA) && !defined(IGNORE_NAME_CONSTRAINTS)
2245/*
2246 * Convert a Base_entry linked list to a STACK of GENERAL_SUBTREE.
2247 *
2248 * Base_entry stores name constraint data from DecodedCert. This function
2249 * converts it to GENERAL_SUBTREE format.
2250 *
2251 * Supported types: ASN_DNS_TYPE, ASN_RFC822_TYPE, ASN_DIR_TYPE, ASN_IP_TYPE,
2252 * ASN_URI_TYPE
2253 *
2254 * Returns 0 on success, negative on error.
2255 */
2256static int ConvertBaseEntryToSubtreeStack(Base_entry* list, WOLFSSL_STACK* sk,
2257 void* heap)
2258{
2259 Base_entry* entry = list;
2260 WOLFSSL_GENERAL_SUBTREE* subtree = NULL;
2261 WOLFSSL_GENERAL_NAME* gn = NULL;
2262 (void)heap;
2263
2264 while (entry != NULL) {
2265
2266 if (entry->type != ASN_DNS_TYPE && entry->type != ASN_RFC822_TYPE &&
2267 entry->type != ASN_DIR_TYPE && entry->type != ASN_IP_TYPE &&
2268 entry->type != ASN_URI_TYPE) {
2269 entry = entry->next;
2270 continue;
2271 }
2272
2273 /* Allocate subtree and general name */
2274 subtree = (WOLFSSL_GENERAL_SUBTREE*)XMALLOC(
2275 sizeof(WOLFSSL_GENERAL_SUBTREE), heap, DYNAMIC_TYPE_OPENSSL);
2276 if (subtree == NULL) {
2277 WOLFSSL_MSG("Failed to allocate GENERAL_SUBTREE");
2278 return MEMORY_E;
2279 }
2280 XMEMSET(subtree, 0, sizeof(WOLFSSL_GENERAL_SUBTREE));
2281
2282 gn = wolfSSL_GENERAL_NAME_new();
2283 if (gn == NULL) {
2284 WOLFSSL_MSG("Failed to allocate GENERAL_NAME");
2285 XFREE(subtree, heap, DYNAMIC_TYPE_OPENSSL);
2286 return MEMORY_E;
2287 }
2288
2289 /* Free default ia5 string allocated by GENERAL_NAME_new */
2290 wolfSSL_ASN1_STRING_free(gn->d.ia5);
2291 gn->d.ia5 = NULL;
2292
2293 switch (entry->type) {
2294 case ASN_DNS_TYPE:
2295 case ASN_RFC822_TYPE:
2296 case ASN_URI_TYPE:
2297 {
2298 if (entry->type == ASN_DNS_TYPE) {
2299 gn->type = WOLFSSL_GEN_DNS;
2300 }
2301 else if (entry->type == ASN_RFC822_TYPE) {
2302 gn->type = WOLFSSL_GEN_EMAIL;
2303 }
2304 else {
2305 gn->type = WOLFSSL_GEN_URI;
2306 }
2307 gn->d.ia5 = wolfSSL_ASN1_STRING_new();
2308 if (gn->d.ia5 == NULL) {
2309 WOLFSSL_MSG("Failed to allocate ASN1_STRING");
2310 wolfSSL_GENERAL_NAME_free(gn);
2311 XFREE(subtree, heap, DYNAMIC_TYPE_OPENSSL);
2312 return MEMORY_E;
2313 }
2314 if (wolfSSL_ASN1_STRING_set(gn->d.ia5, entry->name,
2315 entry->nameSz) != WOLFSSL_SUCCESS) {
2316 WOLFSSL_MSG("Failed to set ASN1_STRING");
2317 wolfSSL_GENERAL_NAME_free(gn);
2318 XFREE(subtree, heap, DYNAMIC_TYPE_OPENSSL);
2319 return MEMORY_E;
2320 }
2321 gn->d.ia5->type = WOLFSSL_V_ASN1_IA5STRING;
2322 break;
2323 }
2324
2325 case ASN_DIR_TYPE:
2326 {
2327 byte* seqBuf = NULL;
2328 unsigned char* p = NULL;
2329 int seqLen = 0;
2330
2331 /* Wrap in SEQUENCE and parse as X509_NAME */
2332 gn->type = WOLFSSL_GEN_DIRNAME;
2333 seqBuf = (byte*)XMALLOC((word32)entry->nameSz + MAX_SEQ_SZ,
2334 heap, DYNAMIC_TYPE_TMP_BUFFER);
2335 if (seqBuf == NULL) {
2336 WOLFSSL_MSG("Failed to allocate sequence buffer");
2337 wolfSSL_GENERAL_NAME_free(gn);
2338 XFREE(subtree, heap, DYNAMIC_TYPE_OPENSSL);
2339 return MEMORY_E;
2340 }
2341
2342 seqLen = SetSequence(entry->nameSz, seqBuf);
2343 XMEMCPY(seqBuf + seqLen, entry->name, entry->nameSz);
2344
2345 p = seqBuf;
2346 gn->d.directoryName = wolfSSL_d2i_X509_NAME(NULL, &p,
2347 (long)entry->nameSz + seqLen);
2348 XFREE(seqBuf, heap, DYNAMIC_TYPE_TMP_BUFFER);
2349
2350 if (gn->d.directoryName == NULL) {
2351 WOLFSSL_MSG("Failed to parse directoryName");
2352 wolfSSL_GENERAL_NAME_free(gn);
2353 XFREE(subtree, heap, DYNAMIC_TYPE_OPENSSL);
2354 return ASN_PARSE_E;
2355 }
2356 break;
2357 }
2358
2359 case ASN_IP_TYPE:
2360 {
2361 /* For IP address, store raw bytes as OCTET_STRING. */
2362 gn->type = WOLFSSL_GEN_IPADD;
2363 gn->d.iPAddress = wolfSSL_ASN1_STRING_new();
2364 if (gn->d.iPAddress == NULL) {
2365 WOLFSSL_MSG("Failed to allocate ASN1_STRING for IP");
2366 wolfSSL_GENERAL_NAME_free(gn);
2367 XFREE(subtree, heap, DYNAMIC_TYPE_OPENSSL);
2368 return MEMORY_E;
2369 }
2370 if (wolfSSL_ASN1_STRING_set(gn->d.iPAddress, entry->name,
2371 entry->nameSz) != WOLFSSL_SUCCESS) {
2372 WOLFSSL_MSG("Failed to set IP ASN1_STRING");
2373 wolfSSL_GENERAL_NAME_free(gn);
2374 XFREE(subtree, heap, DYNAMIC_TYPE_OPENSSL);
2375 return MEMORY_E;
2376 }
2377 gn->d.iPAddress->type = WOLFSSL_V_ASN1_OCTET_STRING;
2378 break;
2379 }
2380 }
2381
2382 subtree->base = gn;
2383
2384 if (wolfSSL_sk_push(sk, subtree) <= 0) {
2385 WOLFSSL_MSG("Failed to push subtree onto stack");
2386 wolfSSL_GENERAL_NAME_free(gn);
2387 XFREE(subtree, heap, DYNAMIC_TYPE_OPENSSL);
2388 return MEMORY_E;
2389 }
2390 entry = entry->next;
2391 }
2392
2393 return 0;
2394}
2395#endif /* OPENSSL_EXTRA && !IGNORE_NAME_CONSTRAINTS */
2396
2397#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
2398/* Looks for the extension matching the passed in nid
2399 *
2400 * c : if not null then is set to status value -2 if multiple occurrences
2401 * of the extension are found, -1 if not found, 0 if found and not
2402 * critical, and 1 if found and critical.
2403 * nid : Extension OID to be found.
2404 * idx : if NULL return first extension found match, otherwise start search at
2405 * idx location and set idx to the location of extension returned.
2406 * returns NULL or a pointer to an WOLFSSL_ASN1_BIT_STRING (for KEY_USAGE_OID)
2407 * or WOLFSSL_STACK (for other)
2408 * holding extension structure
2409 *
2410 * NOTE code for decoding extensions is in asn.c DecodeCertExtensions --
2411 * use already decoded extension in this function to avoid decoding twice.
2412 * Currently we do not make use of idx since getting pre decoded extensions.
2413 */
2414void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509, int nid, int* c,
2415 int* idx)
2416{
2417 void* ret = NULL;
2418 WOLFSSL_STACK* sk = NULL;
2419 WOLFSSL_ASN1_OBJECT* obj = NULL;
2420 WOLFSSL_GENERAL_NAME* gn = NULL;
2421#ifdef OPENSSL_EXTRA
2422 WOLFSSL_DIST_POINT* dp = NULL;
2423#endif
2424 WOLFSSL_BASIC_CONSTRAINTS* bc = NULL;
2425
2426 WOLFSSL_ENTER("wolfSSL_X509_get_ext_d2i");
2427
2428 if (x509 == NULL) {
2429 return NULL;
2430 }
2431
2432 if (c != NULL) {
2433 *c = -1; /* default to not found */
2434 }
2435
2436 switch (nid) {
2437 case BASIC_CA_OID:
2438 if (x509->basicConstSet) {
2439 WOLFSSL_ASN1_INTEGER* a;
2440
2441 bc = wolfSSL_BASIC_CONSTRAINTS_new();
2442 if (!bc) {
2443 WOLFSSL_MSG("wolfSSL_BASIC_CONSTRAINTS_new error");
2444 return NULL;
2445 }
2446
2447 a = wolfSSL_ASN1_INTEGER_new();
2448 if (!a) {
2449 WOLFSSL_MSG("wolfSSL_ASN1_INTEGER_new error");
2450 wolfSSL_BASIC_CONSTRAINTS_free(bc);
2451 return NULL;
2452 }
2453 a->length = (int)x509->pathLength;
2454
2455#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) || \
2456 defined(WOLFSSL_APACHE_HTTPD)
2457 bc->ca = x509->isCa;
2458#endif
2459 bc->pathlen = a;
2460 if (c != NULL) {
2461 *c = x509->basicConstCrit;
2462 }
2463 }
2464 else {
2465 WOLFSSL_MSG("No Basic Constraint set");
2466 }
2467 return bc;
2468
2469 case ALT_NAMES_OID:
2470 {
2471 DNS_entry* dns = NULL;
2472
2473 if (x509->subjAltNameSet && x509->altNames != NULL) {
2474 /* Malloc GENERAL_NAME stack */
2475 sk = wolfSSL_sk_new_null();
2476 if (sk == NULL)
2477 return NULL;
2478 sk->type = STACK_TYPE_GEN_NAME;
2479
2480 /* alt names are DNS_entry structs */
2481 if (c != NULL) {
2482 if (x509->altNames->next != NULL) {
2483 *c = -2; /* more then one found */
2484 }
2485 else {
2486 *c = x509->subjAltNameCrit;
2487 }
2488 }
2489
2490 dns = x509->altNames;
2491 /* Currently only support GEN_DNS type */
2492 while (dns != NULL) {
2493 gn = wolfSSL_GENERAL_NAME_new();
2494 if (gn == NULL) {
2495 WOLFSSL_MSG("Error creating GENERAL_NAME");
2496 goto err;
2497 }
2498
2499 switch (dns->type) {
2500 case ASN_DIR_TYPE:
2501 gn->type = dns->type;
2502 {
2503 int localIdx = 0;
2504 unsigned char* n = (unsigned char*)XMALLOC(
2505 dns->len + MAX_SEQ_SZ, x509->heap,
2506 DYNAMIC_TYPE_TMP_BUFFER);
2507 if (n == NULL) {
2508 goto err;
2509 }
2510
2511 localIdx += SetSequence(dns->len, n);
2512 XMEMCPY(n + localIdx, dns->name, dns->len);
2513 gn->d.dirn = wolfSSL_d2i_X509_NAME(NULL, &n,
2514 dns->len + localIdx);
2515 XFREE(n, x509->heap, DYNAMIC_TYPE_TMP_BUFFER);
2516 if (gn->d.dirn == NULL) {
2517 WOLFSSL_MSG("Convert altDirName to X509 "
2518 "NAME failed");
2519 goto err;
2520 }
2521 }
2522 break;
2523
2524 case ASN_OTHER_TYPE:
2525 /* gn->type set internally */
2526 if (!wolfssl_dns_entry_othername_to_gn(dns, gn)) {
2527 goto err;
2528 }
2529 break;
2530
2531 case ASN_IP_TYPE:
2532 gn->type = dns->type;
2533 if (wolfSSL_ASN1_STRING_set(gn->d.iPAddress,
2534 dns->name, dns->len) != WOLFSSL_SUCCESS) {
2535 WOLFSSL_MSG("ASN1_STRING_set failed");
2536 goto err;
2537 }
2538 gn->d.iPAddress->type = WOLFSSL_V_ASN1_OCTET_STRING;
2539 break;
2540
2541 case ASN_RID_TYPE:
2542 /* Always handle registeredID: the union
2543 * member d.registeredID is populated from
2544 * raw OID body bytes. WOLFSSL_RID_ALT_NAME
2545 * only gates the human-readable ridString,
2546 * which this path does not need. */
2547 gn->type = dns->type;
2548 /* Free ia5 before using union for registeredID */
2549 wolfSSL_ASN1_STRING_free(gn->d.ia5);
2550 gn->d.ia5 = NULL;
2551
2552 gn->d.registeredID = wolfSSL_ASN1_OBJECT_new();
2553 if (gn->d.registeredID == NULL) {
2554 goto err;
2555 }
2556 {
2557 /* Store DER-encoded OID (tag+length+content) */
2558 word32 derSz = 1 + SetLength(dns->len, NULL)
2559 + dns->len;
2560 byte* der = (byte*)XMALLOC(derSz,
2561 gn->d.registeredID->heap,
2562 DYNAMIC_TYPE_ASN1);
2563 if (der == NULL) {
2564 goto err;
2565 }
2566 {
2567 word32 derIdx = 0;
2568 der[derIdx++] = ASN_OBJECT_ID;
2569 derIdx += SetLength(dns->len, der + derIdx);
2570 XMEMCPY(der + derIdx, dns->name, dns->len);
2571 }
2572 gn->d.registeredID->obj = der;
2573 gn->d.registeredID->objSz = derSz;
2574 }
2575 gn->d.registeredID->dynamic |=
2576 WOLFSSL_ASN1_DYNAMIC_DATA;
2577 gn->d.registeredID->grp = oidCertExtType;
2578 break;
2579
2580 default:
2581 gn->type = dns->type;
2582 if (wolfSSL_ASN1_STRING_set(gn->d.dNSName,
2583 dns->name, dns->len) != WOLFSSL_SUCCESS) {
2584 WOLFSSL_MSG("ASN1_STRING_set failed");
2585 goto err;
2586 }
2587 gn->d.dNSName->type = WOLFSSL_V_ASN1_IA5STRING;
2588 }
2589
2590 dns = dns->next;
2591 /* Using wolfSSL_sk_insert to maintain backwards
2592 * compatibility with earlier versions of _push API that
2593 * pushed items to the start of the list instead of the
2594 * end. */
2595 if (wolfSSL_sk_insert(sk, gn, 0) <= 0) {
2596 WOLFSSL_MSG("Error pushing ASN1 object onto stack");
2597 goto err;
2598 }
2599 /* null so that it doesn't get pushed again after switch */
2600 gn = NULL;
2601 }
2602 }
2603 else {
2604 WOLFSSL_MSG("No Alt Names set");
2605 }
2606
2607 break;
2608 }
2609
2610 case CRL_DIST_OID:
2611 #if defined(OPENSSL_EXTRA)
2612 if (x509->CRLdistSet && x509->CRLInfo != NULL) {
2613 if (c != NULL) {
2614 *c = x509->CRLdistCrit;
2615 }
2616
2617 sk = wolfSSL_sk_new_null();
2618 if (sk == NULL) {
2619 return NULL;
2620 }
2621 sk->type = STACK_TYPE_DIST_POINT;
2622
2623 gn = wolfSSL_GENERAL_NAME_new();
2624 if (gn == NULL) {
2625 WOLFSSL_MSG("Error creating GENERAL_NAME");
2626 goto err;
2627 }
2628
2629 if (wolfSSL_GENERAL_NAME_set_type(gn, WOLFSSL_GEN_URI) !=
2630 WOLFSSL_SUCCESS) {
2631 WOLFSSL_MSG("Error setting GENERAL_NAME type");
2632 goto err;
2633 }
2634
2635 if (wolfSSL_ASN1_STRING_set(gn->d.uniformResourceIdentifier,
2636 x509->CRLInfo, x509->CRLInfoSz) != WOLFSSL_SUCCESS) {
2637 WOLFSSL_MSG("ASN1_STRING_set failed");
2638 goto err;
2639 }
2640
2641 /* wolfSSL only decodes one dist point */
2642 dp = wolfSSL_DIST_POINT_new();
2643 if (dp == NULL) {
2644 WOLFSSL_MSG("Error creating DIST_POINT");
2645 goto err;
2646 }
2647
2648 /* push GENERAL_NAME onto fullname stack */
2649 if (wolfSSL_sk_GENERAL_NAME_push(dp->distpoint->name.fullname,
2650 gn) <= 0) {
2651 WOLFSSL_MSG("wolfSSL_sk_GENERAL_NAME_push error");
2652 goto err;
2653 }
2654
2655 /* push DIST_POINT onto stack */
2656 if (wolfSSL_sk_DIST_POINT_push(sk, dp) <= 0) {
2657 WOLFSSL_MSG("Error pushing DIST_POINT onto stack");
2658 goto err;
2659 }
2660
2661 gn = NULL;
2662 dp = NULL;
2663
2664 }
2665 else {
2666 WOLFSSL_MSG("No CRL dist set");
2667 }
2668 #endif /* OPENSSL_EXTRA */
2669 break;
2670
2671 case AUTH_INFO_OID:
2672 if (x509->authInfoSet && x509->authInfo != NULL) {
2673 if (c != NULL) {
2674 *c = x509->authInfoCrit;
2675 }
2676 obj = wolfSSL_ASN1_OBJECT_new();
2677 if (obj == NULL) {
2678 WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
2679 return NULL;
2680 }
2681 obj->type = AUTH_INFO_OID;
2682 obj->grp = oidCertExtType;
2683 obj->obj = x509->authInfo;
2684 obj->objSz = (unsigned int)x509->authInfoSz;
2685 }
2686 else {
2687 WOLFSSL_MSG("No Auth Info set");
2688 }
2689 break;
2690
2691 case AUTH_KEY_OID:
2692 if (x509->authKeyIdSet) {
2693 WOLFSSL_AUTHORITY_KEYID* akey = wolfSSL_AUTHORITY_KEYID_new();
2694 if (!akey) {
2695 WOLFSSL_MSG(
2696 "Issue creating WOLFSSL_AUTHORITY_KEYID struct");
2697 return NULL;
2698 }
2699
2700 if (c != NULL) {
2701 *c = x509->authKeyIdCrit;
2702 }
2703 obj = wolfSSL_ASN1_OBJECT_new();
2704 if (obj == NULL) {
2705 WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
2706 wolfSSL_AUTHORITY_KEYID_free(akey);
2707 return NULL;
2708 }
2709 obj->type = AUTH_KEY_OID;
2710 obj->grp = oidCertExtType;
2711 obj->obj = x509->authKeyId;
2712 obj->objSz = x509->authKeyIdSz;
2713 akey->issuer = obj;
2714 return akey;
2715 }
2716 else {
2717 WOLFSSL_MSG("No Auth Key set");
2718 }
2719 break;
2720
2721 case SUBJ_KEY_OID:
2722 if (x509->subjKeyIdSet) {
2723 if (c != NULL) {
2724 *c = x509->subjKeyIdCrit;
2725 }
2726 obj = wolfSSL_ASN1_OBJECT_new();
2727 if (obj == NULL) {
2728 WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
2729 return NULL;
2730 }
2731 obj->type = SUBJ_KEY_OID;
2732 obj->grp = oidCertExtType;
2733 obj->obj = x509->subjKeyId;
2734 obj->objSz = x509->subjKeyIdSz;
2735 }
2736 else {
2737 WOLFSSL_MSG("No Subject Key set");
2738 }
2739 break;
2740
2741 case CERT_POLICY_OID:
2742 {
2743 #ifdef WOLFSSL_CERT_EXT
2744 int i;
2745
2746 if (x509->certPoliciesNb > 0) {
2747 if (c != NULL) {
2748 if (x509->certPoliciesNb > 1) {
2749 *c = -2;
2750 }
2751 else {
2752 *c = 0;
2753 }
2754 }
2755
2756 sk = wolfSSL_sk_new_asn1_obj();
2757 if (sk == NULL) {
2758 return NULL;
2759 }
2760
2761 for (i = 0; i < x509->certPoliciesNb - 1; i++) {
2762 obj = wolfSSL_ASN1_OBJECT_new();
2763 if (obj == NULL) {
2764 WOLFSSL_MSG(
2765 "Issue creating WOLFSSL_ASN1_OBJECT struct");
2766 wolfSSL_sk_ASN1_OBJECT_pop_free(sk, NULL);
2767 return NULL;
2768 }
2769 obj->type = CERT_POLICY_OID;
2770 obj->grp = oidCertExtType;
2771 obj->obj = (byte*)(x509->certPolicies[i]);
2772 obj->objSz = MAX_CERTPOL_SZ;
2773 if (wolfSSL_sk_ASN1_OBJECT_push(sk, obj) <= 0) {
2774 WOLFSSL_MSG("Error pushing ASN1 object onto stack");
2775 wolfSSL_ASN1_OBJECT_free(obj);
2776 wolfSSL_sk_ASN1_OBJECT_pop_free(sk, NULL);
2777 sk = NULL;
2778 }
2779 }
2780
2781 obj = wolfSSL_ASN1_OBJECT_new();
2782 if (obj == NULL) {
2783 WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
2784 wolfSSL_sk_ASN1_OBJECT_pop_free(sk, NULL);
2785 return NULL;
2786 }
2787 obj->type = CERT_POLICY_OID;
2788 obj->grp = oidCertExtType;
2789 obj->obj = (byte*)(x509->certPolicies[i]);
2790 obj->objSz = MAX_CERTPOL_SZ;
2791
2792 if (wolfSSL_sk_ASN1_OBJECT_push(sk, obj) <= 0) {
2793 WOLFSSL_MSG("Error pushing ASN1 object onto stack");
2794 wolfSSL_ASN1_OBJECT_free(obj);
2795 wolfSSL_sk_ASN1_OBJECT_pop_free(sk, NULL);
2796 sk = NULL;
2797 }
2798
2799 obj = NULL;
2800 }
2801 else {
2802 WOLFSSL_MSG("No Cert Policy set");
2803 }
2804 #endif /* WOLFSSL_CERT_EXT */
2805 #ifdef WOLFSSL_SEP
2806 if (x509->certPolicySet) {
2807 if (c != NULL) {
2808 *c = x509->certPolicyCrit;
2809 }
2810 obj = wolfSSL_ASN1_OBJECT_new();
2811 if (obj == NULL) {
2812 WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct");
2813 return NULL;
2814 }
2815 obj->type = CERT_POLICY_OID;
2816 obj->grp = oidCertExtType;
2817 }
2818 else {
2819 WOLFSSL_MSG("No Cert Policy set");
2820 }
2821 #endif
2822 break;
2823 }
2824 case KEY_USAGE_OID:
2825 {
2826 WOLFSSL_ASN1_STRING* asn1str = NULL;
2827 if (x509->keyUsageSet) {
2828 if (c != NULL) {
2829 *c = x509->keyUsageCrit;
2830 }
2831
2832 asn1str = wolfSSL_ASN1_STRING_new();
2833 if (asn1str == NULL) {
2834 WOLFSSL_MSG("Failed to malloc ASN1_STRING");
2835 return NULL;
2836 }
2837
2838 if (wolfSSL_ASN1_STRING_set(asn1str, &x509->keyUsage,
2839 sizeof(word16)) != WOLFSSL_SUCCESS) {
2840 WOLFSSL_MSG("wolfSSL_ASN1_STRING_set error");
2841 wolfSSL_ASN1_STRING_free(asn1str);
2842 return NULL;
2843 }
2844
2845 asn1str->type = KEY_USAGE_OID;
2846 }
2847 else {
2848 WOLFSSL_MSG("No Key Usage set");
2849 }
2850 /* don't add stack of and return bit string directly */
2851 return asn1str;
2852 }
2853 case INHIBIT_ANY_OID:
2854 WOLFSSL_MSG("INHIBIT ANY extension not supported");
2855 break;
2856
2857 case EXT_KEY_USAGE_OID:
2858 if (x509->extKeyUsageSrc != NULL) {
2859 const byte* ekuSrc = x509->extKeyUsageSrc;
2860 word32 i;
2861
2862 sk = wolfSSL_sk_new_asn1_obj();
2863 if (sk == NULL) {
2864 WOLFSSL_MSG("Issue creating stack");
2865 return NULL;
2866 }
2867
2868 for (i = 0; i < x509->extKeyUsageCount; i++) {
2869 long ekuSrcLen = (long)(x509->extKeyUsageSz -
2870 (word32)(ekuSrc - x509->extKeyUsageSrc));
2871 WOLFSSL_ASN1_OBJECT* ekuObj = wolfSSL_d2i_ASN1_OBJECT(NULL,
2872 &ekuSrc, ekuSrcLen);
2873 if (ekuObj == NULL) {
2874 wolfSSL_sk_ASN1_OBJECT_pop_free(sk, NULL);
2875 WOLFSSL_MSG("d2i obj error");
2876 return NULL;
2877 }
2878 ekuObj->type = EXT_KEY_USAGE_OID;
2879 ekuObj->grp = oidCertExtType;
2880 /* Push to end to maintain order */
2881 if (wolfSSL_sk_insert(sk, ekuObj, -1) <= 0) {
2882 wolfSSL_ASN1_OBJECT_free(ekuObj);
2883 wolfSSL_sk_ASN1_OBJECT_pop_free(sk, NULL);
2884 WOLFSSL_MSG("d2i obj error");
2885 return NULL;
2886 }
2887 }
2888
2889 if ((word32)(ekuSrc - x509->extKeyUsageSrc)
2890 != x509->extKeyUsageSz ||
2891 i != x509->extKeyUsageCount) {
2892 wolfSSL_sk_ASN1_OBJECT_pop_free(sk, NULL);
2893 WOLFSSL_MSG("incorrect eku count or buffer not exhausted");
2894 return NULL;
2895 }
2896
2897 if (c != NULL) {
2898 if (x509->extKeyUsageCount > 1) {
2899 *c = -2;
2900 }
2901 else {
2902 *c = x509->extKeyUsageCrit;
2903 }
2904 }
2905 }
2906 else {
2907 WOLFSSL_MSG("No Extended Key Usage set");
2908 }
2909 break;
2910
2911 #if defined(OPENSSL_EXTRA) && !defined(IGNORE_NAME_CONSTRAINTS)
2912 case NAME_CONS_OID:
2913 {
2914 WOLFSSL_NAME_CONSTRAINTS* nc = NULL;
2915
2916 /* Check if name constraints exist in stored X509 */
2917 if (x509->permittedNames == NULL && x509->excludedNames == NULL) {
2918 WOLFSSL_MSG("No Name Constraints set");
2919 break;
2920 }
2921
2922 if (c != NULL) {
2923 *c = x509->nameConstraintCrit;
2924 }
2925
2926 nc = (WOLFSSL_NAME_CONSTRAINTS*)XMALLOC(
2927 sizeof(WOLFSSL_NAME_CONSTRAINTS), x509->heap,
2928 DYNAMIC_TYPE_OPENSSL);
2929 if (nc == NULL) {
2930 WOLFSSL_MSG("Failed to allocate NAME_CONSTRAINTS");
2931 break;
2932 }
2933 XMEMSET(nc, 0, sizeof(WOLFSSL_NAME_CONSTRAINTS));
2934
2935 /* Convert permitted names */
2936 if (x509->permittedNames != NULL) {
2937 nc->permittedSubtrees = wolfSSL_sk_new_null();
2938 if (nc->permittedSubtrees == NULL) {
2939 WOLFSSL_MSG("Failed to allocate permitted stack");
2940 wolfSSL_NAME_CONSTRAINTS_free(nc);
2941 break;
2942 }
2943 nc->permittedSubtrees->type = STACK_TYPE_GENERAL_SUBTREE;
2944
2945 if (ConvertBaseEntryToSubtreeStack(x509->permittedNames,
2946 nc->permittedSubtrees, x509->heap) != 0) {
2947 WOLFSSL_MSG("Failed to convert permitted names");
2948 wolfSSL_NAME_CONSTRAINTS_free(nc);
2949 break;
2950 }
2951 }
2952
2953 /* Convert excluded names */
2954 if (x509->excludedNames != NULL) {
2955 nc->excludedSubtrees = wolfSSL_sk_new_null();
2956 if (nc->excludedSubtrees == NULL) {
2957 WOLFSSL_MSG("Failed to allocate excluded stack");
2958 wolfSSL_NAME_CONSTRAINTS_free(nc);
2959 break;
2960 }
2961 nc->excludedSubtrees->type = STACK_TYPE_GENERAL_SUBTREE;
2962
2963 if (ConvertBaseEntryToSubtreeStack(x509->excludedNames,
2964 nc->excludedSubtrees, x509->heap) != 0) {
2965 WOLFSSL_MSG("Failed to convert excluded names");
2966 wolfSSL_NAME_CONSTRAINTS_free(nc);
2967 break;
2968 }
2969 }
2970
2971 return nc;
2972 }
2973 #endif /* OPENSSL_EXTRA && !IGNORE_NAME_CONSTRAINTS */
2974
2975 case PRIV_KEY_USAGE_PERIOD_OID:
2976 WOLFSSL_MSG("Private Key Usage Period extension not supported");
2977 break;
2978
2979 case SUBJ_INFO_ACC_OID:
2980 WOLFSSL_MSG("Subject Info Access extension not supported");
2981 break;
2982
2983 case POLICY_MAP_OID:
2984 WOLFSSL_MSG("Policy Map extension not supported");
2985 break;
2986
2987 case POLICY_CONST_OID:
2988 WOLFSSL_MSG("Policy Constraint extension not supported");
2989 break;
2990
2991 case ISSUE_ALT_NAMES_OID:
2992 WOLFSSL_MSG("Issue Alt Names extension not supported");
2993 break;
2994
2995 case TLS_FEATURE_OID:
2996 WOLFSSL_MSG("TLS Feature extension not supported");
2997 break;
2998
2999 default:
3000 WOLFSSL_MSG("Unsupported/Unknown extension OID");
3001 }
3002
3003 /* make sure stack of is allocated */
3004 if ((obj || gn) && sk == NULL) {
3005 sk = wolfSSL_sk_new_asn1_obj();
3006 if (sk == NULL) {
3007 goto err;
3008 }
3009 }
3010 if (obj) {
3011 if (wolfSSL_sk_ASN1_OBJECT_push(sk, obj) <= 0) {
3012 WOLFSSL_MSG("Error pushing ASN1_OBJECT object onto "
3013 "stack.");
3014 goto err;
3015 }
3016 }
3017
3018 ret = sk;
3019
3020 (void)idx;
3021
3022 return ret;
3023
3024err:
3025 if (obj) {
3026 wolfSSL_ASN1_OBJECT_free(obj);
3027 }
3028 if (gn) {
3029 wolfSSL_GENERAL_NAME_free(gn);
3030 }
3031 #ifdef OPENSSL_EXTRA
3032 if (dp) {
3033 wolfSSL_DIST_POINT_free(dp);
3034 }
3035 #endif
3036 if (sk) {
3037 wolfSSL_sk_pop_free(sk, NULL);
3038 }
3039 return NULL;
3040}
3041#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
3042
3043#ifdef OPENSSL_EXTRA
3044int wolfSSL_X509_add_altname_ex(WOLFSSL_X509* x509, const char* name,
3045 word32 nameSz, int type)
3046{
3047 DNS_entry* newAltName = NULL;
3048 char* nameCopy = NULL;
3049
3050 if (x509 == NULL)
3051 return WOLFSSL_FAILURE;
3052
3053 if ((name == NULL) || (nameSz == 0))
3054 return WOLFSSL_SUCCESS;
3055
3056 newAltName = AltNameNew(x509->heap);
3057 if (newAltName == NULL)
3058 return WOLFSSL_FAILURE;
3059
3060 nameCopy = (char*)XMALLOC(nameSz + 1, x509->heap, DYNAMIC_TYPE_ALTNAME);
3061 if (nameCopy == NULL) {
3062 XFREE(newAltName, x509->heap, DYNAMIC_TYPE_ALTNAME);
3063 return WOLFSSL_FAILURE;
3064 }
3065
3066 XMEMCPY(nameCopy, name, nameSz);
3067
3068 nameCopy[nameSz] = '\0';
3069
3070 newAltName->next = x509->altNames;
3071 newAltName->type = type;
3072 newAltName->len = (int)nameSz;
3073 newAltName->name = nameCopy;
3074 newAltName->nameStored = 1;
3075 x509->altNames = newAltName;
3076
3077 return WOLFSSL_SUCCESS;
3078}
3079
3080int wolfSSL_X509_add_altname(WOLFSSL_X509* x509, const char* name, int type)
3081{
3082 word32 nameSz;
3083
3084 if (name == NULL)
3085 return WOLFSSL_SUCCESS;
3086
3087 nameSz = (word32)XSTRLEN(name);
3088 if (nameSz == 0)
3089 return WOLFSSL_SUCCESS;
3090
3091 if (type == ASN_IP_TYPE) {
3092#ifdef WOLFSSL_IP_ALT_NAME
3093 byte ip4[4];
3094 byte ip6[16];
3095 int ptonRet;
3096
3097 /* Check if this is an ip4 address */
3098 #ifdef FREESCALE_MQX
3099 ptonRet = XINET_PTON(WOLFSSL_IP4, name, ip4, sizeof(ip4));
3100 if (ptonRet == RTCS_OK) {
3101 #else
3102 ptonRet = XINET_PTON(WOLFSSL_IP4, name, ip4);
3103 if (ptonRet == 1) {
3104 #endif
3105 return wolfSSL_X509_add_altname_ex(x509, (const char*)ip4, 4,
3106 type);
3107 }
3108
3109 /* Check for ip6 */
3110 #ifdef FREESCALE_MQX
3111 ptonRet = XINET_PTON(WOLFSSL_IP6, name, ip6, sizeof(ip6));
3112 if (ptonRet == RTCS_OK) {
3113 #else
3114 ptonRet = XINET_PTON(WOLFSSL_IP6, name, ip6);
3115 if (ptonRet == 1) {
3116 #endif
3117 return wolfSSL_X509_add_altname_ex(x509, (const char*)ip6, 16,
3118 type);
3119 }
3120
3121 WOLFSSL_MSG("IP address parse failed");
3122 return WOLFSSL_FAILURE;
3123#else
3124 WOLFSSL_MSG("WOLFSSL_IP_ALT_NAME not enabled");
3125 return WOLFSSL_FAILURE;
3126#endif
3127 }
3128
3129 return wolfSSL_X509_add_altname_ex(x509, name, nameSz, type);
3130}
3131
3132#ifndef NO_WOLFSSL_STUB
3133WOLFSSL_X509_EXTENSION *wolfSSL_X509_delete_ext(WOLFSSL_X509 *x509, int loc)
3134{
3135 WOLFSSL_STUB("wolfSSL_X509_delete_ext");
3136 (void)x509;
3137 (void)loc;
3138 return NULL;
3139}
3140
3141/* currently LHASH is not implemented (and not needed for Apache port) */
3142WOLFSSL_X509_EXTENSION* wolfSSL_X509V3_EXT_conf_nid(
3143 WOLF_LHASH_OF(CONF_VALUE)* conf, WOLFSSL_X509V3_CTX* ctx, int nid,
3144 char* value)
3145{
3146 WOLFSSL_STUB("wolfSSL_X509V3_EXT_conf_nid");
3147
3148 if (conf != NULL) {
3149 WOLFSSL_MSG("Handling LHASH not implemented yet");
3150 return NULL;
3151 }
3152
3153 (void)conf;
3154 (void)ctx;
3155 (void)nid;
3156 (void)value;
3157 return NULL;
3158}
3159
3160void wolfSSL_X509V3_set_ctx_nodb(WOLFSSL_X509V3_CTX* ctx)
3161{
3162 WOLFSSL_STUB("wolfSSL_X509V3_set_ctx_nodb");
3163 (void)ctx;
3164}
3165#endif /* !NO_WOLFSSL_STUB */
3166
3167#ifdef OPENSSL_EXTRA
3168static WOLFSSL_X509_EXTENSION* createExtFromStr(int nid, const char *value)
3169{
3170 WOLFSSL_X509_EXTENSION* ext;
3171
3172 ext = wolfSSL_X509_EXTENSION_new();
3173 if (ext == NULL) {
3174 WOLFSSL_MSG("memory error");
3175 return NULL;
3176 }
3177 ext->value.nid = nid;
3178
3179 switch (nid) {
3180 case WC_NID_subject_key_identifier:
3181 case WC_NID_authority_key_identifier:
3182 if (wolfSSL_ASN1_STRING_set(&ext->value, value, -1)
3183 != WOLFSSL_SUCCESS) {
3184 WOLFSSL_MSG("wolfSSL_ASN1_STRING_set error");
3185 goto err_cleanup;
3186 }
3187 ext->value.type = CTC_UTF8;
3188 break;
3189 case WC_NID_subject_alt_name:
3190 {
3191 WOLFSSL_GENERAL_NAMES* gns;
3192 WOLFSSL_GENERAL_NAME* gn;
3193
3194 if (wolfSSL_ASN1_STRING_set(&ext->value, value, -1)
3195 != WOLFSSL_SUCCESS) {
3196 WOLFSSL_MSG("wolfSSL_ASN1_STRING_set error");
3197 goto err_cleanup;
3198 }
3199 ext->value.type = ASN_DNS_TYPE;
3200
3201 /* add stack of general names */
3202 gns = wolfSSL_sk_new_null();
3203 if (gns == NULL) {
3204 WOLFSSL_MSG("wolfSSL_sk_new_null error");
3205 goto err_cleanup;
3206 }
3207 ext->ext_sk = gns; /* wolfSSL_X509_EXTENSION_free will handle
3208 * free'ing gns */
3209 gns->type = STACK_TYPE_GEN_NAME;
3210 gn = wolfSSL_GENERAL_NAME_new();
3211 if (gn == NULL) {
3212 WOLFSSL_MSG("wolfSSL_GENERAL_NAME_new error");
3213 goto err_cleanup;
3214 }
3215 if (wolfSSL_sk_GENERAL_NAME_push(gns, gn) <= 0) {
3216 WOLFSSL_MSG("wolfSSL_sk_GENERAL_NAME_push error");
3217 wolfSSL_GENERAL_NAME_free(gn);
3218 goto err_cleanup;
3219 }
3220 if (wolfSSL_ASN1_STRING_set(gn->d.ia5, value, -1)
3221 != WOLFSSL_SUCCESS) {
3222 WOLFSSL_MSG("wolfSSL_ASN1_STRING_set failed");
3223 goto err_cleanup;
3224 }
3225 gn->type = ASN_DNS_TYPE;
3226 break;
3227 }
3228 case WC_NID_key_usage:
3229 if (wolfSSL_ASN1_STRING_set(&ext->value, value, -1)
3230 != WOLFSSL_SUCCESS) {
3231 WOLFSSL_MSG("wolfSSL_ASN1_STRING_set error");
3232 goto err_cleanup;
3233 }
3234 ext->value.type = KEY_USAGE_OID;
3235 break;
3236 case WC_NID_ext_key_usage:
3237 if (wolfSSL_ASN1_STRING_set(&ext->value, value, -1)
3238 != WOLFSSL_SUCCESS) {
3239 WOLFSSL_MSG("wolfSSL_ASN1_STRING_set error");
3240 goto err_cleanup;
3241 }
3242 ext->value.type = EXT_KEY_USAGE_OID;
3243 break;
3244 default:
3245 WOLFSSL_MSG("invalid or unsupported NID");
3246 goto err_cleanup;
3247 }
3248 return ext;
3249err_cleanup:
3250 wolfSSL_X509_EXTENSION_free(ext);
3251 return NULL;
3252}
3253
3254/**
3255 * Create a WOLFSSL_X509_EXTENSION from the input arguments.
3256 * @param conf Not used
3257 * @param ctx Not used
3258 * @param nid Interprets the value parameter as the x509 extension that
3259 * corresponds to this NID.
3260 * @param value A NULL terminated string that is taken as the value of the
3261 * newly created extension object.
3262 * @return WOLFSSL_X509_EXTENSION* on success or NULL on failure.
3263 */
3264WOLFSSL_X509_EXTENSION* wolfSSL_X509V3_EXT_nconf_nid(WOLFSSL_CONF* conf,
3265 WOLFSSL_X509V3_CTX *ctx, int nid, const char *value)
3266{
3267 WOLFSSL_ENTER("wolfSSL_X509V3_EXT_nconf_nid");
3268
3269 if (value == NULL) {
3270 WOLFSSL_MSG("value NULL parameter");
3271 return NULL;
3272 }
3273
3274 if (conf != NULL || ctx != NULL) {
3275 WOLFSSL_MSG("wolfSSL_X509V3_EXT_nconf_nid does not handle either "
3276 "conf or ctx parameters");
3277 }
3278
3279 return createExtFromStr(nid, value);
3280}
3281
3282/**
3283 * Create a WOLFSSL_X509_EXTENSION from the input arguments.
3284 * @param conf Not used
3285 * @param ctx Not used
3286 * @param sName The textual representation of the NID that the value parameter
3287 * should be interpreted as.
3288 * @param value A NULL terminated string that is taken as the value of the
3289 * newly created extension object.
3290 * @return WOLFSSL_X509_EXTENSION* on success or NULL on failure.
3291 */
3292WOLFSSL_X509_EXTENSION* wolfSSL_X509V3_EXT_nconf(WOLFSSL_CONF *conf,
3293 WOLFSSL_X509V3_CTX *ctx, const char *sName, const char *value)
3294{
3295 const WOLFSSL_ObjectInfo* info = wolfssl_object_info;
3296 size_t i;
3297
3298 WOLFSSL_ENTER("wolfSSL_X509V3_EXT_nconf");
3299
3300 if (value == NULL || sName == NULL) {
3301 WOLFSSL_MSG("NULL parameter");
3302 return NULL;
3303 }
3304
3305 if (conf != NULL || ctx != NULL) {
3306 WOLFSSL_MSG("wolfSSL_X509V3_EXT_nconf does not handle either "
3307 "conf or ctx parameters");
3308 }
3309
3310 for (i = 0; i < wolfssl_object_info_sz; i++, info++) {
3311 if (XSTRCMP(info->sName, sName) == 0)
3312 return createExtFromStr(info->nid, value);
3313 }
3314
3315 WOLFSSL_MSG("value didn't match any known NID");
3316 return NULL;
3317}
3318
3319static void wolfSSL_X509V3_EXT_METHOD_populate(WOLFSSL_v3_ext_method *method,
3320 int nid)
3321{
3322 if (!method)
3323 return;
3324
3325 WOLFSSL_ENTER("wolfSSL_X509V3_EXT_METHOD_populate");
3326 switch (nid) {
3327 case WC_NID_subject_key_identifier:
3328 method->i2s = (WOLFSSL_X509V3_EXT_I2S)wolfSSL_i2s_ASN1_STRING;
3329 FALL_THROUGH;
3330 case WC_NID_authority_key_identifier:
3331 case WC_NID_key_usage:
3332 case WC_NID_certificate_policies:
3333 case WC_NID_policy_mappings:
3334 case WC_NID_subject_alt_name:
3335 case WC_NID_issuer_alt_name:
3336 case WC_NID_basic_constraints:
3337 case WC_NID_name_constraints:
3338 case WC_NID_policy_constraints:
3339 case WC_NID_ext_key_usage:
3340 case WC_NID_crl_distribution_points:
3341 case WC_NID_inhibit_any_policy:
3342 case WC_NID_info_access:
3343 WOLFSSL_MSG("Nothing to populate for current NID");
3344 break;
3345 default:
3346 WOLFSSL_MSG("Unknown or unsupported NID");
3347 break;
3348 }
3349
3350 return;
3351}
3352
3353/**
3354 * @param nid One of the WC_NID_* constants defined in asn.h
3355 * @param crit
3356 * @param data This data is copied to the returned extension.
3357 * @return
3358 */
3359WOLFSSL_X509_EXTENSION *wolfSSL_X509V3_EXT_i2d(int nid, int crit,
3360 void *data)
3361{
3362 WOLFSSL_X509_EXTENSION *ext = NULL;
3363 WOLFSSL_ASN1_STRING* asn1str = NULL;
3364
3365 WOLFSSL_ENTER("wolfSSL_X509V3_EXT_i2d");
3366
3367 if (!data) {
3368 return NULL;
3369 }
3370
3371 if (!(ext = wolfSSL_X509_EXTENSION_new())) {
3372 return NULL;
3373 }
3374
3375 wolfSSL_X509V3_EXT_METHOD_populate(&ext->ext_method, nid);
3376
3377 switch (nid) {
3378 case WC_NID_subject_key_identifier:
3379 /* WOLFSSL_ASN1_STRING */
3380 case WC_NID_key_usage:
3381 /* WOLFSSL_ASN1_STRING */
3382 {
3383 asn1str = (WOLFSSL_ASN1_STRING*)data;
3384 ext->value = *asn1str;
3385 if (asn1str->isDynamic) {
3386 ext->value.data = (char*)XMALLOC(asn1str->length, NULL,
3387 DYNAMIC_TYPE_OPENSSL);
3388 if (!ext->value.data) {
3389 WOLFSSL_MSG("malloc failed");
3390 /* Zero so that no existing memory is freed */
3391 XMEMSET(&ext->value, 0, sizeof(WOLFSSL_ASN1_STRING));
3392 goto err_cleanup;
3393 }
3394 XMEMCPY(ext->value.data, asn1str->data, asn1str->length);
3395 }
3396 else {
3397 ext->value.data = ext->value.strData;
3398 }
3399
3400 if (!(ext->obj = wolfSSL_OBJ_nid2obj(nid))) {
3401 WOLFSSL_MSG("wolfSSL_ASN1_OBJECT_new failed");
3402 goto err_cleanup;
3403 }
3404
3405 break;
3406 }
3407 case WC_NID_subject_alt_name:
3408 /* typedef STACK_OF(GENERAL_NAME) GENERAL_NAMES */
3409 case WC_NID_issuer_alt_name:
3410 /* typedef STACK_OF(GENERAL_NAME) GENERAL_NAMES */
3411 case WC_NID_ext_key_usage:
3412 /* typedef STACK_OF(ASN1_OBJECT) EXTENDED_KEY_USAGE */
3413 case WC_NID_info_access:
3414 /* typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS */
3415 {
3416 WOLFSSL_STACK* sk = (WOLFSSL_STACK*)data;
3417
3418 if (ext->ext_sk) {
3419 wolfSSL_sk_pop_free(ext->ext_sk, NULL);
3420 }
3421
3422 if (!(ext->ext_sk = wolfSSL_sk_dup(sk))) {
3423 WOLFSSL_MSG("wolfSSL_sk_dup failed");
3424 goto err_cleanup;
3425 }
3426
3427 if (!(ext->obj = wolfSSL_OBJ_nid2obj(nid))) {
3428 WOLFSSL_MSG("wolfSSL_ASN1_OBJECT_new failed");
3429 goto err_cleanup;
3430 }
3431
3432 break;
3433 }
3434 case WC_NID_basic_constraints:
3435 {
3436 /* WOLFSSL_BASIC_CONSTRAINTS */
3437 WOLFSSL_BASIC_CONSTRAINTS* bc = (WOLFSSL_BASIC_CONSTRAINTS*)data;
3438
3439 if (!(ext->obj = wolfSSL_ASN1_OBJECT_new())) {
3440 WOLFSSL_MSG("wolfSSL_ASN1_OBJECT_new failed");
3441 goto err_cleanup;
3442 }
3443
3444 ext->obj->ca = bc->ca;
3445 if (bc->pathlen) {
3446 ext->obj->pathlen = wolfSSL_ASN1_INTEGER_dup(bc->pathlen);
3447 if (!ext->obj->pathlen) {
3448 WOLFSSL_MSG("wolfSSL_ASN1_INTEGER_dup failed");
3449 goto err_cleanup;
3450 }
3451 }
3452 break;
3453 }
3454 case WC_NID_authority_key_identifier:
3455 {
3456 /* AUTHORITY_KEYID */
3457 WOLFSSL_AUTHORITY_KEYID* akey = (WOLFSSL_AUTHORITY_KEYID*)data;
3458
3459 if (akey->keyid) {
3460 if (wolfSSL_ASN1_STRING_set(&ext->value, akey->keyid->data,
3461 akey->keyid->length) != WOLFSSL_SUCCESS) {
3462 WOLFSSL_MSG("wolfSSL_ASN1_STRING_set failed");
3463 goto err_cleanup;
3464 }
3465 ext->value.type = akey->keyid->type;
3466
3467 if (!(ext->obj = wolfSSL_OBJ_nid2obj(nid))) {
3468 WOLFSSL_MSG("wolfSSL_ASN1_OBJECT_new failed");
3469 goto err_cleanup;
3470 }
3471
3472 }
3473 else if (akey->issuer) {
3474 ext->obj = wolfSSL_ASN1_OBJECT_dup(akey->issuer);
3475 if (!ext->obj) {
3476 WOLFSSL_MSG("wolfSSL_ASN1_OBJECT_dup failed");
3477 goto err_cleanup;
3478 }
3479 }
3480 else {
3481 WOLFSSL_MSG("WC_NID_authority_key_identifier empty data");
3482 goto err_cleanup;
3483 }
3484 break;
3485 }
3486 case WC_NID_inhibit_any_policy:
3487 /* ASN1_INTEGER */
3488 case WC_NID_certificate_policies:
3489 /* STACK_OF(POLICYINFO) */
3490 case WC_NID_policy_mappings:
3491 /* STACK_OF(POLICY_MAPPING) */
3492 case WC_NID_name_constraints:
3493 /* NAME_CONSTRAINTS */
3494 case WC_NID_policy_constraints:
3495 /* POLICY_CONSTRAINTS */
3496 case WC_NID_crl_distribution_points:
3497 /* typedef STACK_OF(DIST_POINT) CRL_DIST_POINTS */
3498 default:
3499 WOLFSSL_MSG("Unknown or unsupported NID");
3500 break;
3501 }
3502
3503 ext->crit = crit;
3504
3505 return ext;
3506err_cleanup:
3507 if (ext) {
3508 wolfSSL_X509_EXTENSION_free(ext);
3509 }
3510 return NULL;
3511}
3512
3513/* Returns pointer to ASN1_OBJECT from an X509_EXTENSION object */
3514WOLFSSL_ASN1_OBJECT* wolfSSL_X509_EXTENSION_get_object(
3515 WOLFSSL_X509_EXTENSION* ext)
3516{
3517 WOLFSSL_ENTER("wolfSSL_X509_EXTENSION_get_object");
3518 if (ext == NULL)
3519 return NULL;
3520 return ext->obj;
3521}
3522
3523
3524/**
3525 * duplicates the 'obj' input and sets it into the 'ext' structure
3526 * returns WOLFSSL_SUCCESS on success
3527 */
3528int wolfSSL_X509_EXTENSION_set_object(WOLFSSL_X509_EXTENSION* ext,
3529 const WOLFSSL_ASN1_OBJECT* obj)
3530{
3531 WOLFSSL_ASN1_OBJECT *current;
3532
3533 WOLFSSL_ENTER("wolfSSL_X509_EXTENSION_set_object");
3534 if (ext == NULL)
3535 return WOLFSSL_FAILURE;
3536
3537 current = wolfSSL_X509_EXTENSION_get_object(ext);
3538 if (current != NULL) {
3539 wolfSSL_ASN1_OBJECT_free(current);
3540 }
3541 ext->obj = wolfSSL_ASN1_OBJECT_dup((WOLFSSL_ASN1_OBJECT*)obj);
3542 return WOLFSSL_SUCCESS;
3543}
3544#endif /* OPENSSL_ALL */
3545
3546#ifdef WOLFSSL_OLD_EXTDATA_FMT
3547/*
3548 * Replace the current string in 'asn1str', which is the full X.509
3549 * extension octet string with some data specific for the extension
3550 * type. The extension is the one given in 'oid'.
3551 * Return 0 in case of success, or a negative error code.
3552 */
3553static int wolfSSL_ASN1_STRING_into_old_ext_fmt(WOLFSSL_ASN1_STRING *asn1str,
3554 word32 oid)
3555{
3556 switch (oid)
3557 {
3558 case AUTH_INFO_OID:
3559 wolfSSL_ASN1_STRING_clear(asn1str);
3560 asn1str->data = NULL;
3561 asn1str->length = 0;
3562 return 0;
3563
3564 case AUTH_KEY_OID:
3565 {
3566 int ret = 0;
3567 const byte *extAuthKeyId = NULL;
3568 word32 extAuthKeyIdSz = 0;
3569 char *data = NULL;
3570
3571 ret = DecodeAuthKeyId((const byte *)asn1str->data, asn1str->length,
3572 &extAuthKeyId, &extAuthKeyIdSz, NULL, NULL, NULL, NULL);
3573
3574 if (ret != 0)
3575 return ret;
3576
3577 data = (char*)XMALLOC((size_t)(extAuthKeyIdSz), NULL,
3578 DYNAMIC_TYPE_OPENSSL);
3579 if (data == NULL)
3580 return MEMORY_ERROR;
3581
3582 XMEMCPY(data, extAuthKeyId, (size_t)extAuthKeyIdSz);
3583 wolfSSL_ASN1_STRING_set(asn1str, data, extAuthKeyIdSz);
3584 XFREE(data, NULL, DYNAMIC_TYPE_OPENSSL);
3585 return 0;
3586 }
3587
3588 case SUBJ_KEY_OID:
3589 {
3590 int ret = 0;
3591 const byte *extSubjKeyId = NULL;
3592 word32 extSubjKeyIdSz = 0;
3593 char *data = NULL;
3594
3595 ret = DecodeSubjKeyId((const byte *)asn1str->data, asn1str->length,
3596 &extSubjKeyId, &extSubjKeyIdSz);
3597 if (ret != 0)
3598 return ret;
3599
3600 data = (char*)XMALLOC((size_t)(extSubjKeyIdSz), NULL,
3601 DYNAMIC_TYPE_OPENSSL);
3602 if (data == NULL)
3603 return MEMORY_ERROR;
3604
3605 XMEMCPY(data, extSubjKeyId, (size_t)extSubjKeyIdSz);
3606 wolfSSL_ASN1_STRING_set(asn1str, data, extSubjKeyIdSz);
3607 XFREE(data, NULL, DYNAMIC_TYPE_OPENSSL);
3608 return 0;
3609 }
3610
3611 case CERT_POLICY_OID:
3612 wolfSSL_ASN1_STRING_clear(asn1str);
3613 asn1str->data = NULL;
3614 asn1str->length = 0;
3615 return 0;
3616
3617 case KEY_USAGE_OID:
3618 {
3619 int ret = 0;
3620 word16 extKeyUsage = 0;
3621
3622 ret = DecodeKeyUsage((const byte *)asn1str->data, asn1str->length,
3623 &extKeyUsage);
3624 if (ret != 0)
3625 return ret;
3626
3627 wolfSSL_ASN1_STRING_set(asn1str, (byte*)&extKeyUsage,
3628 sizeof(extKeyUsage));
3629 return 0;
3630 }
3631
3632 case EXT_KEY_USAGE_OID:
3633 {
3634 int ret = 0;
3635 const byte *extExtKeyUsageSrc = NULL;
3636 word32 extExtKeyUsageSz = 0;
3637 word32 extExtKeyUsageCount = 0;
3638 byte extExtKeyUsage = 0;
3639 byte extExtKeyUsageSsh = 0;
3640 char *data = NULL;
3641
3642 ret = DecodeExtKeyUsage((const byte*)asn1str->data, asn1str->length,
3643 &extExtKeyUsageSrc, &extExtKeyUsageSz, &extExtKeyUsageCount,
3644 &extExtKeyUsage, &extExtKeyUsageSsh);
3645 if (ret != 0)
3646 return ret;
3647
3648 data = (char*)XMALLOC((size_t)(extExtKeyUsageSz), NULL,
3649 DYNAMIC_TYPE_OPENSSL);
3650 if (data == NULL)
3651 return MEMORY_ERROR;
3652
3653 XMEMCPY(data, extExtKeyUsageSrc, (size_t)extExtKeyUsageSz);
3654 wolfSSL_ASN1_STRING_set(asn1str, data, extExtKeyUsageSz);
3655 XFREE(data, NULL, DYNAMIC_TYPE_OPENSSL);
3656 return 0;
3657 }
3658
3659 case CRL_DIST_OID:
3660 wolfSSL_ASN1_STRING_clear(asn1str);
3661 asn1str->data = NULL;
3662 asn1str->length = 0;
3663 return 0;
3664
3665 default:
3666 /* Do nothing, it is already set */
3667 return 0;
3668 }
3669}
3670#endif /* WOLFSSL_OLD_EXTDATA_FMT */
3671
3672/* Returns pointer to ASN1_STRING in X509_EXTENSION object */
3673WOLFSSL_ASN1_STRING* wolfSSL_X509_EXTENSION_get_data(
3674 WOLFSSL_X509_EXTENSION* ext)
3675{
3676 WOLFSSL_ASN1_STRING *ret;
3677
3678 ret = wolfSSL_X509_EXTENSION_get_data_internal(ext);
3679
3680#ifdef WOLFSSL_OLD_EXTDATA_FMT
3681 if (ret)
3682 {
3683 int error;
3684 error = wolfSSL_ASN1_STRING_into_old_ext_fmt (ret, ext->obj->type);
3685 if (error != 0)
3686 {
3687 WOLFSSL_MSG("Error calling wolfSSL_ASN1_STRING_into_old_ext_fmt");
3688 return NULL;
3689 }
3690 }
3691#endif
3692
3693 return ret;
3694}
3695
3696
3697/**
3698 * Creates a duplicate of input 'data' and sets it into 'ext' structure
3699 * returns WOLFSSL_SUCCESS on success
3700 */
3701int wolfSSL_X509_EXTENSION_set_data(WOLFSSL_X509_EXTENSION* ext,
3702 WOLFSSL_ASN1_STRING* data)
3703{
3704 WOLFSSL_ASN1_STRING* current;
3705
3706 if (ext == NULL || data == NULL)
3707 return WOLFSSL_FAILURE;
3708
3709 current = wolfSSL_X509_EXTENSION_get_data_internal(ext);
3710 if (current->length > 0 && current->data != NULL && current->isDynamic) {
3711 XFREE(current->data, NULL, DYNAMIC_TYPE_OPENSSL);
3712 }
3713
3714 return wolfSSL_ASN1_STRING_copy(&ext->value, data);
3715}
3716
3717#if !defined(NO_PWDBASED)
3718int wolfSSL_X509_digest(const WOLFSSL_X509* x509, const WOLFSSL_EVP_MD* digest,
3719 unsigned char* buf, unsigned int* len)
3720{
3721 int ret;
3722
3723 WOLFSSL_ENTER("wolfSSL_X509_digest");
3724
3725 if (x509 == NULL || digest == NULL) {
3726 WOLFSSL_MSG("Null argument found");
3727 return WOLFSSL_FAILURE;
3728 }
3729
3730 if (x509->derCert == NULL) {
3731 WOLFSSL_MSG("No DER certificate stored in X509");
3732 return WOLFSSL_FAILURE;
3733 }
3734
3735 ret = wolfSSL_EVP_Digest(x509->derCert->buffer, x509->derCert->length, buf,
3736 len, digest, NULL);
3737 WOLFSSL_LEAVE("wolfSSL_X509_digest", ret);
3738 return ret;
3739}
3740
3741int wolfSSL_X509_pubkey_digest(const WOLFSSL_X509 *x509,
3742 const WOLFSSL_EVP_MD *digest, unsigned char* buf, unsigned int* len)
3743{
3744 int ret;
3745
3746 WOLFSSL_ENTER("wolfSSL_X509_pubkey_digest");
3747
3748 if (x509 == NULL || digest == NULL) {
3749 WOLFSSL_MSG("Null argument found");
3750 return WOLFSSL_FAILURE;
3751 }
3752
3753 if (x509->pubKey.buffer == NULL || x509->pubKey.length == 0) {
3754 WOLFSSL_MSG("No DER public key stored in X509");
3755 return WOLFSSL_FAILURE;
3756 }
3757
3758 ret = wolfSSL_EVP_Digest(x509->pubKey.buffer, x509->pubKey.length, buf,
3759 len, digest, NULL);
3760 WOLFSSL_LEAVE("wolfSSL_X509_pubkey_digest", ret);
3761 return ret;
3762}
3763#endif
3764
3765#endif /* OPENSSL_EXTRA */
3766
3767#ifdef OPENSSL_EXTRA
3768
3769 #ifndef NO_WOLFSSL_STUB
3770 const char* wolfSSL_X509_get_default_cert_file_env(void)
3771 {
3772 WOLFSSL_STUB("X509_get_default_cert_file_env");
3773 return "";
3774 }
3775
3776 const char* wolfSSL_X509_get_default_cert_file(void)
3777 {
3778 WOLFSSL_STUB("X509_get_default_cert_file");
3779 return "";
3780 }
3781
3782 const char* wolfSSL_X509_get_default_cert_dir_env(void)
3783 {
3784 WOLFSSL_STUB("X509_get_default_cert_dir_env");
3785 return "";
3786 }
3787
3788 const char* wolfSSL_X509_get_default_cert_dir(void)
3789 {
3790 WOLFSSL_STUB("X509_get_default_cert_dir");
3791 return "";
3792 }
3793 #endif
3794
3795#endif /* OPENSSL_EXTRA */
3796
3797#if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS) || \
3798 defined(KEEP_OUR_CERT) || \
3799 defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
3800
3801/* user externally called free X509, if dynamic go ahead with free, otherwise
3802 * don't */
3803static void ExternalFreeX509(WOLFSSL_X509* x509)
3804{
3805#if defined(OPENSSL_EXTRA_X509_SMALL) || defined(OPENSSL_EXTRA)
3806 int doFree = 0;
3807#endif
3808
3809 WOLFSSL_ENTER("ExternalFreeX509");
3810 if (x509) {
3811#ifdef HAVE_EX_DATA_CLEANUP_HOOKS
3812 wolfSSL_CRYPTO_cleanup_ex_data(&x509->ex_data);
3813#endif
3814 if (x509->dynamicMemory) {
3815 #if defined(OPENSSL_EXTRA_X509_SMALL) || defined(OPENSSL_EXTRA)
3816 int ret;
3817 wolfSSL_RefDec(&x509->ref, &doFree, &ret);
3818 if (ret != 0) {
3819 WOLFSSL_MSG("Couldn't lock x509 mutex");
3820 }
3821 if (doFree)
3822 #endif /* OPENSSL_EXTRA_X509_SMALL || OPENSSL_EXTRA */
3823 {
3824 FreeX509(x509);
3825 XFREE(x509, x509->heap, DYNAMIC_TYPE_X509);
3826 }
3827 }
3828 else {
3829 WOLFSSL_MSG("free called on non dynamic object, not freeing");
3830 }
3831 }
3832}
3833
3834/* Frees an external WOLFSSL_X509 structure */
3835WOLFSSL_ABI
3836void wolfSSL_X509_free(WOLFSSL_X509* x509)
3837{
3838 WOLFSSL_ENTER("wolfSSL_X509_free");
3839 ExternalFreeX509(x509);
3840}
3841#endif
3842
3843#if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS) || \
3844 defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
3845
3846/* copy name into in buffer, at most sz bytes, if buffer is null will
3847 malloc buffer, call responsible for freeing */
3848WOLFSSL_ABI
3849char* wolfSSL_X509_NAME_oneline(WOLFSSL_X509_NAME* name, char* in, int sz)
3850{
3851 int copySz;
3852
3853 WOLFSSL_ENTER("wolfSSL_X509_NAME_oneline");
3854
3855 if (name == NULL) {
3856 WOLFSSL_MSG("WOLFSSL_X509_NAME pointer was NULL");
3857 return NULL;
3858 }
3859
3860 if (name->sz == 0)
3861 return in;
3862
3863 if (!in) {
3864 #ifdef WOLFSSL_STATIC_MEMORY
3865 WOLFSSL_MSG("Using static memory -- please pass in a buffer");
3866 return NULL;
3867 #else
3868 in = (char*)XMALLOC(name->sz, NULL, DYNAMIC_TYPE_OPENSSL);
3869 if (!in)
3870 return in;
3871 copySz = name->sz;
3872 #endif
3873 }
3874 else {
3875 copySz = (int)min((word32)sz, (word32)name->sz);
3876 if (copySz <= 0)
3877 return in;
3878 }
3879
3880 XMEMCPY(in, name->name, copySz - 1);
3881 in[copySz - 1] = 0;
3882
3883 return in;
3884}
3885
3886#ifdef OPENSSL_EXTRA
3887/* Given an X509_NAME, convert it to canonical form and then hash
3888 * with the provided hash type. Returns the first 4 bytes of the hash
3889 * as unsigned long on success, and 0 otherwise. */
3890static unsigned long X509NameHash(WOLFSSL_X509_NAME* name,
3891 enum wc_HashType hashType)
3892{
3893 unsigned long hash = 0;
3894 unsigned char* canonName = NULL;
3895 byte digest[WC_MAX_DIGEST_SIZE];
3896 int size = 0;
3897 int rc;
3898
3899 WOLFSSL_ENTER("X509NameHash");
3900
3901 if (name == NULL) {
3902 WOLFSSL_ERROR_MSG("WOLFSSL_X509_NAME pointer was NULL");
3903 return 0;
3904 }
3905
3906 if (name->sz == 0) {
3907 WOLFSSL_ERROR_MSG("Nothing to hash in WOLFSSL_X509_NAME");
3908 return 0;
3909 }
3910
3911 size = wolfSSL_i2d_X509_NAME_canon(name, &canonName);
3912
3913 if (size <= 0 || canonName == NULL) {
3914 WOLFSSL_ERROR_MSG("wolfSSL_i2d_X509_NAME_canon error");
3915 return 0;
3916 }
3917
3918 rc = wc_Hash(hashType, (const byte*)canonName, (word32)size, digest,
3919 sizeof(digest));
3920
3921 if (rc == 0) {
3922 hash = (((unsigned long)digest[3] << 24) |
3923 ((unsigned long)digest[2] << 16) |
3924 ((unsigned long)digest[1] << 8) |
3925 ((unsigned long)digest[0]));
3926 }
3927 else if (rc == WC_NO_ERR_TRACE(HASH_TYPE_E)) {
3928 WOLFSSL_ERROR_MSG("Hash function not compiled in");
3929 }
3930 else {
3931 WOLFSSL_ERROR_MSG("Error hashing name");
3932 }
3933
3934 XFREE(canonName, NULL, DYNAMIC_TYPE_OPENSSL);
3935 return hash;
3936}
3937
3938unsigned long wolfSSL_X509_NAME_hash(WOLFSSL_X509_NAME* name)
3939{
3940 return X509NameHash(name, WC_HASH_TYPE_SHA);
3941}
3942
3943/******************************************************************************
3944* wolfSSL_X509_subject_name_hash
3945* wolfSSL_X509_issuer_name_hash
3946* Compute the hash digest of the subject / issuer name.
3947* These functions prefer SHA-1 (if available) for compatibility. Otherwise
3948* they use SHA-256.
3949*
3950* RETURNS:
3951* The first 4 bytes of SHA-1 (or SHA-256) hash in little endian order as
3952* unsigned long.
3953* Otherwise, returns zero.
3954*
3955* Note:
3956* Returns the same hash value as OpenSSL's X509_X_name_hash() API
3957* if SHA-1 support is compiled in. SHA-256 will be used if SHA-1 is
3958* not available.
3959*/
3960unsigned long wolfSSL_X509_subject_name_hash(const WOLFSSL_X509* x509)
3961{
3962 if (x509 == NULL) {
3963 WOLFSSL_ERROR_MSG("WOLFSSL_X509 pointer was NULL");
3964 return 0;
3965 }
3966
3967 #ifndef NO_SHA
3968 return X509NameHash((WOLFSSL_X509_NAME*) &x509->subject, WC_HASH_TYPE_SHA);
3969 #elif !defined(NO_SHA256)
3970 return X509NameHash((WOLFSSL_X509_NAME*) &x509->subject,
3971 WC_HASH_TYPE_SHA256);
3972 #else
3973 WOLFSSL_ERROR_MSG("Hash function not compiled in");
3974 return 0;
3975 #endif
3976}
3977
3978unsigned long wolfSSL_X509_issuer_name_hash(const WOLFSSL_X509* x509)
3979{
3980 if (x509 == NULL) {
3981 WOLFSSL_ERROR_MSG("WOLFSSL_X509 pointer was NULL");
3982 return 0;
3983 }
3984
3985 #ifndef NO_SHA
3986 return X509NameHash((WOLFSSL_X509_NAME*) &x509->issuer, WC_HASH_TYPE_SHA);
3987 #elif !defined(NO_SHA256)
3988 return X509NameHash((WOLFSSL_X509_NAME*) &x509->issuer,
3989 WC_HASH_TYPE_SHA256);
3990 #else
3991 WOLFSSL_ERROR_MSG("Hash function not compiled in");
3992 return 0;
3993 #endif
3994}
3995#endif /* OPENSSL_EXTRA */
3996
3997#if defined(OPENSSL_EXTRA) && defined(XSNPRINTF)
3998/* Copies X509 subject name into a buffer, with comma-separated name entries
3999 * (matching OpenSSL v1.0.0 format)
4000 * Example Output for Issuer:
4001 *
4002 * C=US, ST=Montana, L=Bozeman, O=Sawtooth, OU=Consulting,
4003 * CN=www.wolfssl.com, emailAddress=info@wolfssl.com
4004 */
4005char* wolfSSL_X509_get_name_oneline(WOLFSSL_X509_NAME* name, char* in, int sz)
4006{
4007 int count, i;
4008 int totalLen = 0;
4009 char tmpBuf[256];
4010 WOLFSSL_ENTER("wolfSSL_X509_get_name_oneline");
4011
4012 if (name == NULL) {
4013 WOLFSSL_MSG("wolfSSL_X509_get_name_oneline failed");
4014 return NULL;
4015 }
4016 #ifdef WOLFSSL_STATIC_MEMORY
4017 if (!in) {
4018 WOLFSSL_MSG("Using static memory -- please pass in a buffer");
4019 return NULL;
4020 }
4021 #endif
4022
4023 /* Loop through X509 name entries and copy new format to buffer */
4024 count = wolfSSL_X509_NAME_entry_count(name);
4025 for (i = 0; i < count; i++) {
4026 WOLFSSL_X509_NAME_ENTRY* entry;
4027 int nameSz;
4028 int strSz;
4029 int strLen;
4030 char *str;
4031 const int tmpBufSz = sizeof(tmpBuf);
4032 char buf[80];
4033 const char* sn;
4034
4035 /* Get name entry and size */
4036 entry = wolfSSL_X509_NAME_get_entry(name, i);
4037 if (entry == NULL) {
4038 WOLFSSL_MSG("wolfSSL_X509_NAME_get_entry failed");
4039 return NULL;
4040 }
4041 nameSz = wolfSSL_X509_NAME_get_text_by_NID(name, entry->nid, buf,
4042 sizeof(buf));
4043 if (nameSz < 0) {
4044 WOLFSSL_MSG("wolfSSL_X509_NAME_get_text_by_NID failed");
4045 return NULL;
4046 }
4047
4048 /* Get short name */
4049 sn = wolfSSL_OBJ_nid2sn(entry->nid);
4050 if (sn == NULL) {
4051 WOLFSSL_MSG("OBJ_nid2sn failed");
4052 return NULL;
4053 }
4054
4055 /* Copy sn and name text to buffer
4056 * Add extra strSz for '=', ',', ' ' and '\0' characters in XSNPRINTF.
4057 */
4058 if (i != count - 1) {
4059 strSz = (int)XSTRLEN(sn) + nameSz + 4;
4060 str = (char*)XMALLOC(strSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
4061 if (str == NULL) {
4062 WOLFSSL_MSG("Memory error");
4063 return NULL;
4064 }
4065 strLen = XSNPRINTF(str, (size_t)strSz, "%s=%s, ", sn, buf);
4066 if ((strLen < 0) || (strLen >= strSz)) {
4067 WOLFSSL_MSG("buffer overrun");
4068 XFREE(str, NULL, DYNAMIC_TYPE_TMP_BUFFER);
4069 return NULL;
4070 }
4071 }
4072 else {
4073 /* Copy last name entry
4074 * Add extra strSz for '=' and '\0' characters in XSNPRINTF.
4075 */
4076 strSz = (int)XSTRLEN(sn) + nameSz + 2;
4077 str = (char*)XMALLOC(strSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
4078 if (str == NULL) {
4079 WOLFSSL_MSG("Memory error");
4080 return NULL;
4081 }
4082 strLen = XSNPRINTF(str, (size_t)strSz, "%s=%s", sn, buf);
4083 if ((strLen < 0) || (strLen >= strSz)) {
4084 WOLFSSL_MSG("buffer overrun");
4085 XFREE(str, NULL, DYNAMIC_TYPE_TMP_BUFFER);
4086 return NULL;
4087 }
4088 }
4089 /* Copy string to tmpBuf */
4090 if (totalLen + strLen > tmpBufSz) {
4091 WOLFSSL_MSG("buffer overrun");
4092 XFREE(str, NULL, DYNAMIC_TYPE_TMP_BUFFER);
4093 return NULL;
4094 }
4095 XMEMCPY(tmpBuf + totalLen, str, strLen);
4096 totalLen += strLen;
4097 XFREE(str, NULL, DYNAMIC_TYPE_TMP_BUFFER);
4098 }
4099
4100 /* Allocate space based on total string size if no buffer was provided */
4101 if (!in) {
4102 in = (char*)XMALLOC(totalLen+1, NULL, DYNAMIC_TYPE_OPENSSL);
4103 if (in == NULL) {
4104 WOLFSSL_MSG("Memory error");
4105 return in;
4106 }
4107 }
4108 else {
4109 if (totalLen + 1 > sz) {
4110 WOLFSSL_MSG("buffer overrun");
4111 return NULL;
4112 }
4113 }
4114
4115 XMEMCPY(in, tmpBuf, totalLen); /* cppcheck-suppress uninitvar */
4116 in[totalLen] = '\0';
4117
4118 return in;
4119}
4120#endif
4121
4122
4123/* Wraps wolfSSL_X509_d2i
4124 *
4125 * returns a WOLFSSL_X509 structure pointer on success and NULL on fail
4126 */
4127WOLFSSL_X509* wolfSSL_d2i_X509(WOLFSSL_X509** x509, const unsigned char** in,
4128 int len)
4129{
4130 WOLFSSL_X509* newX509 = NULL;
4131 WOLFSSL_ENTER("wolfSSL_d2i_X509");
4132
4133 if (in == NULL) {
4134 WOLFSSL_MSG("NULL input for wolfSSL_d2i_X509");
4135 return NULL;
4136 }
4137
4138 newX509 = wolfSSL_X509_d2i(x509, *in, len);
4139 if (newX509 != NULL) {
4140 *in += newX509->derCert->length;
4141 }
4142 return newX509;
4143}
4144
4145static WOLFSSL_X509* d2i_X509orX509REQ(WOLFSSL_X509** x509,
4146 const byte* in, int len, int req, void* heap)
4147{
4148 WOLFSSL_X509 *newX509 = NULL;
4149 int type = req ? CERTREQ_TYPE : CERT_TYPE;
4150
4151 WOLFSSL_ENTER("wolfSSL_X509_d2i");
4152
4153 if (in != NULL && len != 0
4154 #ifndef WOLFSSL_CERT_REQ
4155 && req == 0
4156 #else
4157 && (req == 0 || req == 1)
4158 #endif
4159 ) {
4160 WC_DECLARE_VAR(cert, DecodedCert, 1, 0);
4161
4162 WC_ALLOC_VAR_EX(cert, DecodedCert, 1, NULL, DYNAMIC_TYPE_DCERT,
4163 return NULL);
4164
4165 InitDecodedCert(cert, (byte*)in, (word32)len, heap);
4166 #ifdef WOLFSSL_CERT_REQ
4167 cert->isCSR = (byte)req;
4168 #endif
4169 if (ParseCertRelative(cert, type, 0, NULL, NULL) == 0) {
4170 newX509 = wolfSSL_X509_new_ex(heap);
4171 if (newX509 != NULL) {
4172 if (CopyDecodedToX509(newX509, cert) != 0) {
4173 wolfSSL_X509_free(newX509);
4174 newX509 = NULL;
4175 }
4176 }
4177 }
4178 FreeDecodedCert(cert);
4179 WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_DCERT);
4180 }
4181
4182 if (x509 != NULL)
4183 *x509 = newX509;
4184
4185 return newX509;
4186}
4187
4188int wolfSSL_X509_get_isCA(WOLFSSL_X509* x509)
4189{
4190 int isCA = 0;
4191
4192 WOLFSSL_ENTER("wolfSSL_X509_get_isCA");
4193
4194 if (x509 != NULL)
4195 isCA = x509->isCa;
4196
4197 WOLFSSL_LEAVE("wolfSSL_X509_get_isCA", isCA);
4198
4199 return isCA;
4200}
4201
4202WOLFSSL_X509* wolfSSL_X509_d2i_ex(WOLFSSL_X509** x509, const byte* in, int len,
4203 void* heap)
4204{
4205 return d2i_X509orX509REQ(x509, in, len, 0, heap);
4206}
4207
4208WOLFSSL_X509* wolfSSL_X509_d2i(WOLFSSL_X509** x509, const byte* in, int len)
4209{
4210 return wolfSSL_X509_d2i_ex(x509, in, len, NULL);
4211}
4212
4213#ifdef WOLFSSL_CERT_REQ
4214WOLFSSL_X509* wolfSSL_X509_REQ_d2i(WOLFSSL_X509** x509,
4215 const unsigned char* in, int len)
4216{
4217 return d2i_X509orX509REQ(x509, in, len, 1, NULL);
4218}
4219
4220WOLFSSL_X509* wolfSSL_d2i_X509_REQ_INFO(WOLFSSL_X509** req,
4221 const unsigned char** in, int len)
4222{
4223 WOLFSSL_X509* ret = NULL;
4224 WOLFSSL_ENTER("wolfSSL_d2i_X509_REQ_INFO");
4225
4226 if (in == NULL) {
4227 WOLFSSL_MSG("NULL input for wolfSSL_d2i_X509");
4228 return NULL;
4229 }
4230
4231 ret = wolfSSL_X509_REQ_d2i(req, *in, len);
4232 if (ret != NULL) {
4233 *in += ret->derCert->length;
4234 }
4235 return ret;
4236}
4237#endif
4238
4239#endif /* KEEP_PEER_CERT || SESSION_CERTS || OPENSSL_EXTRA ||
4240 OPENSSL_EXTRA_X509_SMALL */
4241
4242#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
4243/* returns the number of entries in the WOLFSSL_X509_NAME */
4244int wolfSSL_X509_NAME_entry_count(WOLFSSL_X509_NAME* name)
4245{
4246 int count = 0;
4247
4248 WOLFSSL_ENTER("wolfSSL_X509_NAME_entry_count");
4249
4250 if (name != NULL)
4251 count = name->entrySz;
4252
4253 WOLFSSL_LEAVE("wolfSSL_X509_NAME_entry_count", count);
4254 return count;
4255}
4256#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
4257
4258#if defined(OPENSSL_EXTRA) || \
4259 defined(KEEP_OUR_CERT) || defined(KEEP_PEER_CERT)
4260
4261/* return the next, if any, altname from the peer cert */
4262WOLFSSL_ABI
4263char* wolfSSL_X509_get_next_altname(WOLFSSL_X509* cert)
4264{
4265 char* ret = NULL;
4266 WOLFSSL_ENTER("wolfSSL_X509_get_next_altname");
4267
4268 /* don't have any to work with */
4269 if (cert == NULL || cert->altNames == NULL)
4270 return NULL;
4271
4272 /* already went through them */
4273 if (cert->altNamesNext == NULL) {
4274#ifdef WOLFSSL_MULTICIRCULATE_ALTNAMELIST
4275 /* Reset altNames List to head
4276 * so that caller can circulate the list again
4277 */
4278 cert->altNamesNext = cert->altNames;
4279#endif
4280 return NULL;
4281 }
4282
4283 /* In default builds iPAddress entries hold raw 4/16 octet payloads
4284 * and registeredID entries hold raw OID body bytes (no human-readable
4285 * ipString/ridString), so returning them as a C string would truncate
4286 * at any embedded NUL byte. Such entries are still parsed into
4287 * altNames for name-constraint enforcement; skip them here so
4288 * string-iteration callers see the same set of entries as before.
4289 *
4290 * With WOLFSSL_MULTICIRCULATE_ALTNAMELIST, a list consisting only of
4291 * skipped entries collapses to "no entries" on the first pass and
4292 * resets to head on the next call; the cycle shape matches the
4293 * pre-fix behavior where such entries were never parsed. */
4294#if !defined(WOLFSSL_IP_ALT_NAME) || !defined(WOLFSSL_RID_ALT_NAME)
4295 while (cert->altNamesNext != NULL) {
4296 int skip = 0;
4297#ifndef WOLFSSL_IP_ALT_NAME
4298 if (cert->altNamesNext->type == ASN_IP_TYPE)
4299 skip = 1;
4300#endif
4301#ifndef WOLFSSL_RID_ALT_NAME
4302 if (cert->altNamesNext->type == ASN_RID_TYPE)
4303 skip = 1;
4304#endif
4305 if (!skip)
4306 break;
4307 cert->altNamesNext = cert->altNamesNext->next;
4308 }
4309 if (cert->altNamesNext == NULL)
4310 return NULL;
4311#endif /* !WOLFSSL_IP_ALT_NAME || !WOLFSSL_RID_ALT_NAME */
4312
4313 /* unsafe cast required for ABI compatibility. */
4314 ret = (char *)(wc_ptr_t)cert->altNamesNext->name;
4315#ifdef WOLFSSL_IP_ALT_NAME
4316 /* return the IP address as a string */
4317 if (cert->altNamesNext->type == ASN_IP_TYPE) {
4318 ret = cert->altNamesNext->ipString;
4319 }
4320#endif
4321#ifdef WOLFSSL_RID_ALT_NAME
4322 /* return the registeredID as a string */
4323 if (cert->altNamesNext->type == ASN_RID_TYPE) {
4324 ret = cert->altNamesNext->ridString;
4325 }
4326#endif
4327 cert->altNamesNext = cert->altNamesNext->next;
4328
4329 return ret;
4330}
4331
4332int wolfSSL_X509_get_signature(WOLFSSL_X509* x509,
4333 unsigned char* buf, int* bufSz)
4334{
4335 WOLFSSL_ENTER("wolfSSL_X509_get_signature");
4336 if (x509 == NULL || bufSz == NULL || (*bufSz < (int)x509->sig.length &&
4337 buf != NULL))
4338 return WOLFSSL_FATAL_ERROR;
4339
4340 if (buf != NULL)
4341 XMEMCPY(buf, x509->sig.buffer, x509->sig.length);
4342 *bufSz = (int)x509->sig.length;
4343
4344 return WOLFSSL_SUCCESS;
4345}
4346
4347
4348/* Getter function that copies over the DER public key buffer to "buf" and
4349 * sets the size in bufSz. If "buf" is NULL then just bufSz is set to needed
4350 * buffer size. "bufSz" passed in should initially be set by the user to be
4351 * the size of "buf". This gets checked to make sure the buffer is large
4352 * enough to hold the public key.
4353 *
4354 * Note: this is the X.509 form of key with "header" info.
4355 * return WOLFSSL_SUCCESS on success
4356 */
4357int wolfSSL_X509_get_pubkey_buffer(WOLFSSL_X509* x509,
4358 unsigned char* buf, int* bufSz)
4359{
4360 WC_DECLARE_VAR(cert, DecodedCert, 1, 0);
4361 const byte* der;
4362 int length = 0;
4363 int ret = 0, derSz = 0;
4364 int badDate = 0;
4365 const byte* pubKeyX509 = NULL;
4366 int pubKeyX509Sz = 0;
4367
4368 WOLFSSL_ENTER("wolfSSL_X509_get_pubkey_buffer");
4369 if (x509 == NULL || bufSz == NULL) {
4370 WOLFSSL_LEAVE("wolfSSL_X509_get_pubkey_buffer", BAD_FUNC_ARG);
4371 return WOLFSSL_FATAL_ERROR;
4372 }
4373
4374
4375#ifdef WOLFSSL_SMALL_STACK
4376 cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert),
4377 x509->heap, DYNAMIC_TYPE_TMP_BUFFER);
4378 if (cert == NULL) {
4379 WOLFSSL_LEAVE("wolfSSL_X509_get_pubkey_buffer", MEMORY_E);
4380 return WOLFSSL_FATAL_ERROR;
4381 }
4382#endif
4383
4384 der = wolfSSL_X509_get_der(x509, &derSz);
4385 if (der != NULL) {
4386 InitDecodedCert(cert, der, (word32)derSz, NULL);
4387 ret = wc_GetPubX509(cert, 0, &badDate);
4388 if (ret >= 0) {
4389 word32 idx = cert->srcIdx;
4390 pubKeyX509 = cert->source + cert->srcIdx;
4391 ret = GetSequence(cert->source, &cert->srcIdx, &length,
4392 cert->maxIdx);
4393 pubKeyX509Sz = length + (cert->srcIdx - idx);
4394 }
4395 FreeDecodedCert(cert);
4396 }
4397 WC_FREE_VAR_EX(cert, x509->heap, DYNAMIC_TYPE_TMP_BUFFER);
4398
4399 if (ret < 0) {
4400 WOLFSSL_LEAVE("wolfSSL_X509_get_pubkey_buffer", ret);
4401 return WOLFSSL_FATAL_ERROR;
4402 }
4403
4404 if (buf != NULL && pubKeyX509 != NULL) {
4405 if (pubKeyX509Sz > *bufSz) {
4406 WOLFSSL_LEAVE("wolfSSL_X509_get_pubkey_buffer", BUFFER_E);
4407 return WOLFSSL_FATAL_ERROR;
4408 }
4409 XMEMCPY(buf, pubKeyX509, pubKeyX509Sz);
4410 }
4411 *bufSz = pubKeyX509Sz;
4412
4413 return WOLFSSL_SUCCESS;
4414}
4415
4416
4417/* Getter function for the public key OID value
4418 * return public key OID stored in WOLFSSL_X509 structure */
4419int wolfSSL_X509_get_pubkey_type(WOLFSSL_X509* x509)
4420{
4421 if (x509 == NULL)
4422 return WOLFSSL_FAILURE;
4423 return x509->pubKeyOID;
4424}
4425
4426#endif /* OPENSSL_EXTRA || KEEP_OUR_CERT || KEEP_PEER_CERT || SESSION_CERTS */
4427
4428#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \
4429 defined(KEEP_OUR_CERT) || defined(KEEP_PEER_CERT) || defined(SESSION_CERTS)
4430
4431/* write X509 serial number in unsigned binary to buffer
4432 buffer needs to be at least EXTERNAL_SERIAL_SIZE (32) for all cases
4433 return WOLFSSL_SUCCESS on success */
4434int wolfSSL_X509_get_serial_number(WOLFSSL_X509* x509,
4435 byte* in, int* inOutSz)
4436{
4437 WOLFSSL_ENTER("wolfSSL_X509_get_serial_number");
4438 if (x509 == NULL || inOutSz == NULL) {
4439 WOLFSSL_MSG("Null argument passed in");
4440 return BAD_FUNC_ARG;
4441 }
4442
4443 if (in != NULL) {
4444 if (*inOutSz < x509->serialSz) {
4445 WOLFSSL_MSG("Serial buffer too small");
4446 return BUFFER_E;
4447 }
4448 XMEMCPY(in, x509->serial, x509->serialSz);
4449 }
4450 *inOutSz = x509->serialSz;
4451
4452 return WOLFSSL_SUCCESS;
4453}
4454
4455/* not an openssl compatibility function - getting for derCert */
4456const byte* wolfSSL_X509_get_der(WOLFSSL_X509* x509, int* outSz)
4457{
4458 WOLFSSL_ENTER("wolfSSL_X509_get_der");
4459
4460 if (x509 == NULL || x509->derCert == NULL || outSz == NULL)
4461 return NULL;
4462
4463 *outSz = (int)x509->derCert->length;
4464 return x509->derCert->buffer;
4465}
4466
4467#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL || KEEP_OUR_CERT ||
4468 * KEEP_PEER_CERT || SESSION_CERTS */
4469
4470#if defined(OPENSSL_EXTRA_X509_SMALL) || defined(OPENSSL_EXTRA) || \
4471 defined(OPENSSL_ALL) || defined(KEEP_OUR_CERT) || \
4472 defined(KEEP_PEER_CERT) || defined(SESSION_CERTS)
4473
4474/* used by JSSE (not a standard compatibility function) */
4475WOLFSSL_ABI
4476const byte* wolfSSL_X509_notBefore(WOLFSSL_X509* x509)
4477{
4478 WOLFSSL_ENTER("wolfSSL_X509_notBefore");
4479
4480 if (x509 == NULL) {
4481 return NULL;
4482 }
4483
4484 if (x509->notBefore.length < 0 ||
4485 x509->notBefore.length > (int)sizeof(x509->notBeforeData) - 2) {
4486 return NULL;
4487 }
4488
4489 XMEMSET(x509->notBeforeData, 0, sizeof(x509->notBeforeData));
4490 x509->notBeforeData[0] = (byte)x509->notBefore.type;
4491 x509->notBeforeData[1] = (byte)x509->notBefore.length;
4492 XMEMCPY(&x509->notBeforeData[2], x509->notBefore.data,
4493 x509->notBefore.length);
4494
4495 return x509->notBeforeData;
4496}
4497
4498/* used by JSSE (not a standard compatibility function) */
4499WOLFSSL_ABI
4500const byte* wolfSSL_X509_notAfter(WOLFSSL_X509* x509)
4501{
4502 WOLFSSL_ENTER("wolfSSL_X509_notAfter");
4503
4504 if (x509 == NULL) {
4505 return NULL;
4506 }
4507
4508 if (x509->notAfter.length < 0 ||
4509 x509->notAfter.length > (int)sizeof(x509->notAfterData) - 2) {
4510 return NULL;
4511 }
4512
4513 XMEMSET(x509->notAfterData, 0, sizeof(x509->notAfterData));
4514 x509->notAfterData[0] = (byte)x509->notAfter.type;
4515 x509->notAfterData[1] = (byte)x509->notAfter.length;
4516 XMEMCPY(&x509->notAfterData[2], x509->notAfter.data, x509->notAfter.length);
4517
4518 return x509->notAfterData;
4519}
4520
4521int wolfSSL_X509_version(WOLFSSL_X509* x509)
4522{
4523 WOLFSSL_ENTER("wolfSSL_X509_version");
4524
4525 if (x509 == NULL)
4526 return 0;
4527
4528 return x509->version;
4529}
4530#endif
4531
4532#ifdef OPENSSL_EXTRA
4533
4534/* get the buffer to be signed (tbs) from the WOLFSSL_X509 certificate
4535 *
4536 * outSz : gets set to the size of the buffer
4537 * returns a pointer to the internal buffer at the location of TBS on
4538 * on success and NULL on failure.
4539 */
4540const unsigned char* wolfSSL_X509_get_tbs(WOLFSSL_X509* x509, int* outSz)
4541{
4542 int sz = 0, len;
4543 unsigned int idx = 0, tmpIdx;
4544 const unsigned char* der = NULL;
4545 const unsigned char* tbs = NULL;
4546
4547 if (x509 == NULL || outSz == NULL) {
4548 return NULL;
4549 }
4550
4551 der = wolfSSL_X509_get_der(x509, &sz);
4552 if (der == NULL) {
4553 return NULL;
4554 }
4555
4556 if (GetSequence(der, &idx, &len, (word32)sz) < 0) {
4557 return NULL;
4558 }
4559 tbs = der + idx;
4560 tmpIdx = idx;
4561 if (GetSequence(der, &idx, &len, (word32)sz) < 0) {
4562 return NULL;
4563 }
4564 *outSz = len + (idx - tmpIdx);
4565 return tbs;
4566}
4567
4568#ifdef WOLFSSL_SEP
4569
4570/* copy oid into in buffer, at most *inOutSz bytes, if buffer is null will
4571 malloc buffer, call responsible for freeing. Actual size returned in
4572 *inOutSz. Requires inOutSz be non-null */
4573byte* wolfSSL_X509_get_device_type(WOLFSSL_X509* x509, byte* in, int *inOutSz)
4574{
4575 int copySz;
4576
4577 WOLFSSL_ENTER("wolfSSL_X509_get_dev_type");
4578 if (x509 == NULL) return NULL;
4579 if (inOutSz == NULL) return NULL;
4580 if (!x509->deviceTypeSz) return in;
4581
4582 copySz = min(*inOutSz, x509->deviceTypeSz);
4583
4584 if (!in) {
4585 #ifdef WOLFSSL_STATIC_MEMORY
4586 WOLFSSL_MSG("Using static memory -- please pass in a buffer");
4587 return NULL;
4588 #else
4589 in = (byte*)XMALLOC(x509->deviceTypeSz, 0, DYNAMIC_TYPE_OPENSSL);
4590 if (!in) return in;
4591 copySz = x509->deviceTypeSz;
4592 #endif
4593 }
4594
4595 XMEMCPY(in, x509->deviceType, copySz);
4596 *inOutSz = copySz;
4597
4598 return in;
4599}
4600
4601
4602byte* wolfSSL_X509_get_hw_type(WOLFSSL_X509* x509, byte* in, int* inOutSz)
4603{
4604 int copySz;
4605
4606 WOLFSSL_ENTER("wolfSSL_X509_get_hw_type");
4607 if (x509 == NULL) return NULL;
4608 if (inOutSz == NULL) return NULL;
4609 if (!x509->hwTypeSz) return in;
4610
4611 copySz = min(*inOutSz, x509->hwTypeSz);
4612
4613 if (!in) {
4614 #ifdef WOLFSSL_STATIC_MEMORY
4615 WOLFSSL_MSG("Using static memory -- please pass in a buffer");
4616 return NULL;
4617 #else
4618 in = (byte*)XMALLOC(x509->hwTypeSz, 0, DYNAMIC_TYPE_OPENSSL);
4619 if (!in) return in;
4620 copySz = x509->hwTypeSz;
4621 #endif
4622 }
4623
4624 XMEMCPY(in, x509->hwType, copySz);
4625 *inOutSz = copySz;
4626
4627 return in;
4628}
4629
4630
4631byte* wolfSSL_X509_get_hw_serial_number(WOLFSSL_X509* x509,byte* in,
4632 int* inOutSz)
4633{
4634 int copySz;
4635
4636 WOLFSSL_ENTER("wolfSSL_X509_get_hw_serial_number");
4637 if (x509 == NULL) return NULL;
4638 if (inOutSz == NULL) return NULL;
4639 if (!x509->hwTypeSz) return in;
4640
4641 copySz = min(*inOutSz, x509->hwSerialNumSz);
4642
4643 if (!in) {
4644 #ifdef WOLFSSL_STATIC_MEMORY
4645 WOLFSSL_MSG("Using static memory -- please pass in a buffer");
4646 return NULL;
4647 #else
4648 in = (byte*)XMALLOC(x509->hwSerialNumSz, 0, DYNAMIC_TYPE_OPENSSL);
4649 if (!in) return in;
4650 copySz = x509->hwSerialNumSz;
4651 #endif
4652 }
4653
4654 XMEMCPY(in, x509->hwSerialNum, copySz);
4655 *inOutSz = copySz;
4656
4657 return in;
4658}
4659
4660#endif /* WOLFSSL_SEP */
4661#endif /* OPENSSL_EXTRA */
4662
4663/* require OPENSSL_EXTRA since wolfSSL_X509_free is wrapped by OPENSSL_EXTRA */
4664#if defined(OPENSSL_EXTRA)
4665
4666WOLFSSL_ASN1_TIME* wolfSSL_X509_get_notBefore(const WOLFSSL_X509* x509)
4667{
4668 WOLFSSL_ENTER("wolfSSL_X509_get_notBefore");
4669
4670 if (x509 == NULL)
4671 return NULL;
4672
4673 return (WOLFSSL_ASN1_TIME*)&x509->notBefore;
4674}
4675
4676
4677WOLFSSL_ASN1_TIME* wolfSSL_X509_get_notAfter(const WOLFSSL_X509* x509)
4678{
4679 WOLFSSL_ENTER("wolfSSL_X509_get_notAfter");
4680
4681 if (x509 == NULL)
4682 return NULL;
4683
4684 return (WOLFSSL_ASN1_TIME*)&x509->notAfter;
4685}
4686
4687
4688/* return number of elements on success 0 on fail */
4689int wolfSSL_sk_X509_push(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk,
4690 WOLFSSL_X509* x509)
4691{
4692 WOLFSSL_ENTER("wolfSSL_sk_X509_push");
4693
4694 if (sk == NULL || x509 == NULL) {
4695 return WOLFSSL_FAILURE;
4696 }
4697
4698 return wolfSSL_sk_push(sk, x509);
4699}
4700
4701
4702/* Return and remove the last x509 pushed on stack */
4703WOLFSSL_X509* wolfSSL_sk_X509_pop(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk)
4704{
4705 return (WOLFSSL_X509*)wolfSSL_sk_pop(sk);
4706}
4707
4708/* Getter function for WOLFSSL_X509 pointer
4709 *
4710 * sk is the stack to retrieve pointer from
4711 * i is the index value in stack
4712 *
4713 * returns a pointer to a WOLFSSL_X509 structure on success and NULL on
4714 * fail
4715 */
4716WOLFSSL_X509* wolfSSL_sk_X509_value(WOLF_STACK_OF(WOLFSSL_X509)* sk, int i)
4717{
4718 WOLFSSL_ENTER("wolfSSL_sk_X509_value");
4719
4720 for (; sk != NULL && i > 0; i--)
4721 sk = sk->next;
4722
4723 if (i != 0 || sk == NULL)
4724 return NULL;
4725 return sk->data.x509;
4726}
4727
4728
4729/* Return and remove the first x509 pushed on stack */
4730WOLFSSL_X509* wolfSSL_sk_X509_shift(WOLF_STACK_OF(WOLFSSL_X509)* sk)
4731{
4732 return (WOLFSSL_X509*)wolfSSL_sk_pop_node(sk, 0);
4733}
4734
4735#endif /* OPENSSL_EXTRA */
4736
4737#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
4738/* Free's all nodes in X509 stack. This is different then wolfSSL_sk_X509_free
4739 * in that it free's the underlying objects pushed to the stack.
4740 *
4741 * sk stack to free nodes in
4742 * f X509 free function
4743 */
4744void wolfSSL_sk_X509_pop_free(WOLF_STACK_OF(WOLFSSL_X509)* sk,
4745 void (*f) (WOLFSSL_X509*))
4746{
4747 WOLFSSL_ENTER("wolfSSL_sk_X509_pop_free");
4748 wolfSSL_sk_pop_free(sk, (wolfSSL_sk_freefunc)f);
4749}
4750
4751
4752/* free just the stack structure */
4753void wolfSSL_sk_X509_free(WOLF_STACK_OF(WOLFSSL_X509)* sk)
4754{
4755 wolfSSL_sk_free(sk);
4756}
4757
4758#ifdef HAVE_CRL
4759WOLFSSL_STACK* wolfSSL_sk_X509_CRL_new(void)
4760{
4761 WOLFSSL_STACK* s = wolfSSL_sk_new_node(NULL);
4762 if (s != NULL)
4763 s->type = STACK_TYPE_X509_CRL;
4764 return s;
4765}
4766
4767WOLFSSL_STACK* wolfSSL_sk_X509_CRL_new_null(void)
4768{
4769 WOLFSSL_STACK* s = wolfSSL_sk_new_null();
4770 if (s != NULL)
4771 s->type = STACK_TYPE_X509_CRL;
4772 return s;
4773}
4774
4775void wolfSSL_sk_X509_CRL_pop_free(WOLF_STACK_OF(WOLFSSL_X509_CRL)* sk,
4776 void (*f) (WOLFSSL_X509_CRL*))
4777{
4778 WOLFSSL_ENTER("wolfSSL_sk_X509_CRL_pop_free");
4779 wolfSSL_sk_pop_free(sk, (wolfSSL_sk_freefunc)f);
4780}
4781
4782void wolfSSL_sk_X509_CRL_free(WOLF_STACK_OF(WOLFSSL_X509_CRL)* sk)
4783{
4784 wolfSSL_sk_X509_CRL_pop_free(sk, NULL);
4785}
4786
4787/* return number of elements on success 0 on fail */
4788int wolfSSL_sk_X509_CRL_push(WOLF_STACK_OF(WOLFSSL_X509_CRL)* sk,
4789 WOLFSSL_X509_CRL* crl)
4790{
4791 WOLFSSL_ENTER("wolfSSL_sk_X509_CRL_push");
4792
4793 if (sk == NULL || crl == NULL) {
4794 return WOLFSSL_FAILURE;
4795 }
4796
4797 return wolfSSL_sk_push(sk, crl);
4798}
4799
4800WOLFSSL_X509_CRL* wolfSSL_sk_X509_CRL_value(WOLF_STACK_OF(WOLFSSL_X509)* sk,
4801 int i)
4802{
4803 WOLFSSL_ENTER("wolfSSL_sk_X509_CRL_value");
4804 if (sk)
4805 return (WOLFSSL_X509_CRL*)wolfSSL_sk_value(sk, i);
4806 return NULL;
4807}
4808
4809int wolfSSL_sk_X509_CRL_num(WOLF_STACK_OF(WOLFSSL_X509)* sk)
4810{
4811 WOLFSSL_ENTER("wolfSSL_sk_X509_CRL_num");
4812 if (sk)
4813 return wolfSSL_sk_num(sk);
4814 return 0;
4815}
4816#endif /* HAVE_CRL */
4817
4818#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
4819
4820#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_QT)
4821/* return number of elements on success 0 on fail */
4822int wolfSSL_sk_ACCESS_DESCRIPTION_push(WOLF_STACK_OF(ACCESS_DESCRIPTION)* sk,
4823 WOLFSSL_ACCESS_DESCRIPTION* a)
4824{
4825 WOLFSSL_ENTER("wolfSSL_sk_ACCESS_DESCRIPTION_push");
4826
4827 return wolfSSL_sk_push(sk, a);
4828}
4829
4830/* Frees all nodes in ACCESS_DESCRIPTION stack
4831*
4832* sk stack of nodes to free
4833* f free function to use
4834*/
4835void wolfSSL_sk_ACCESS_DESCRIPTION_pop_free(WOLFSSL_STACK* sk,
4836 void (*f) (WOLFSSL_ACCESS_DESCRIPTION*))
4837{
4838 WOLFSSL_ENTER("wolfSSL_sk_ACCESS_DESCRIPTION_pop_free");
4839 wolfSSL_sk_pop_free(sk, (wolfSSL_sk_freefunc)f);
4840}
4841
4842void wolfSSL_sk_ACCESS_DESCRIPTION_free(WOLFSSL_STACK* sk)
4843{
4844 wolfSSL_sk_free(sk);
4845}
4846
4847
4848/* AUTHORITY_INFO_ACCESS object is a stack of ACCESS_DESCRIPTION objects,
4849 * to free the stack the WOLFSSL_ACCESS_DESCRIPTION stack free function is
4850 * used */
4851void wolfSSL_AUTHORITY_INFO_ACCESS_free(
4852 WOLF_STACK_OF(WOLFSSL_ACCESS_DESCRIPTION)* sk)
4853{
4854 WOLFSSL_ENTER("wolfSSL_AUTHORITY_INFO_ACCESS_free");
4855 wolfSSL_sk_ACCESS_DESCRIPTION_free(sk);
4856}
4857
4858void wolfSSL_AUTHORITY_INFO_ACCESS_pop_free(
4859 WOLF_STACK_OF(WOLFSSL_ACCESS_DESCRIPTION)* sk,
4860 void (*f) (WOLFSSL_ACCESS_DESCRIPTION*))
4861{
4862 WOLFSSL_ENTER("wolfSSL_AUTHORITY_INFO_ACCESS_free");
4863 wolfSSL_sk_ACCESS_DESCRIPTION_pop_free(sk, f);
4864}
4865
4866
4867void wolfSSL_ACCESS_DESCRIPTION_free(WOLFSSL_ACCESS_DESCRIPTION* a)
4868{
4869 WOLFSSL_ENTER("wolfSSL_ACCESS_DESCRIPTION_free");
4870 if (a == NULL)
4871 return;
4872
4873 if (a->method)
4874 wolfSSL_ASN1_OBJECT_free(a->method);
4875 if (a->location)
4876 wolfSSL_GENERAL_NAME_free(a->location);
4877 XFREE(a, NULL, DYNAMIC_TYPE_X509_EXT);
4878
4879 /* a = NULL, don't try to a or double free it */
4880}
4881#endif /* OPENSSL_EXTRA || WOLFSSL_QT */
4882
4883#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
4884
4885/* Creates and returns new GENERAL_NAME structure */
4886WOLFSSL_GENERAL_NAME* wolfSSL_GENERAL_NAME_new(void)
4887{
4888 WOLFSSL_GENERAL_NAME* gn;
4889 WOLFSSL_ENTER("GENERAL_NAME_new");
4890
4891 gn = (WOLFSSL_GENERAL_NAME*)XMALLOC(sizeof(WOLFSSL_GENERAL_NAME), NULL,
4892 DYNAMIC_TYPE_ASN1);
4893 if (gn == NULL) {
4894 return NULL;
4895 }
4896 XMEMSET(gn, 0, sizeof(WOLFSSL_GENERAL_NAME));
4897
4898 gn->d.ia5 = wolfSSL_ASN1_STRING_new();
4899 if (gn->d.ia5 == NULL) {
4900 WOLFSSL_MSG("Issue creating ASN1_STRING struct");
4901 wolfSSL_GENERAL_NAME_free(gn);
4902 return NULL;
4903 }
4904 gn->type = WOLFSSL_GEN_IA5;
4905 return gn;
4906}
4907
4908WOLFSSL_GENERAL_NAME* wolfSSL_GENERAL_NAME_dup(WOLFSSL_GENERAL_NAME* gn)
4909{
4910 WOLFSSL_GENERAL_NAME* dupl = NULL;
4911
4912 WOLFSSL_ENTER("wolfSSL_GENERAL_NAME_dup");
4913
4914 if (!gn) {
4915 WOLFSSL_MSG("Bad parameter");
4916 return NULL;
4917 }
4918
4919 if (!(dupl = wolfSSL_GENERAL_NAME_new())) {
4920 WOLFSSL_MSG("wolfSSL_GENERAL_NAME_new error");
4921 return NULL;
4922 }
4923
4924 wolfSSL_ASN1_STRING_free(dupl->d.ia5);
4925 dupl->d.ia5 = NULL;
4926 switch (gn->type) {
4927 /* WOLFSSL_ASN1_STRING types */
4928 case WOLFSSL_GEN_DNS:
4929 if (!(dupl->d.dNSName = wolfSSL_ASN1_STRING_dup(gn->d.dNSName))) {
4930 WOLFSSL_MSG("wolfSSL_ASN1_STRING_dup error");
4931 goto error;
4932 }
4933 break;
4934 case WOLFSSL_GEN_IPADD:
4935 if (!(dupl->d.iPAddress = wolfSSL_ASN1_STRING_dup(gn->d.iPAddress))) {
4936 WOLFSSL_MSG("wolfSSL_ASN1_STRING_dup error");
4937 goto error;
4938 }
4939 break;
4940 case WOLFSSL_GEN_EMAIL:
4941 if (!(dupl->d.rfc822Name = wolfSSL_ASN1_STRING_dup(gn->d.rfc822Name))) {
4942 WOLFSSL_MSG("wolfSSL_ASN1_STRING_dup error");
4943 goto error;
4944 }
4945 break;
4946 case WOLFSSL_GEN_URI:
4947 if (!(dupl->d.uniformResourceIdentifier =
4948 wolfSSL_ASN1_STRING_dup(gn->d.uniformResourceIdentifier))) {
4949 WOLFSSL_MSG("wolfSSL_ASN1_STRING_dup error");
4950 goto error;
4951 }
4952 break;
4953 case WOLFSSL_GEN_OTHERNAME:
4954 if (gn->d.otherName->value->type != WOLFSSL_V_ASN1_UTF8STRING) {
4955 WOLFSSL_MSG("Unsupported othername value type");
4956 goto error;
4957 }
4958 dupl->d.otherName = (WOLFSSL_ASN1_OTHERNAME*)XMALLOC(
4959 sizeof(WOLFSSL_ASN1_OTHERNAME), NULL, DYNAMIC_TYPE_ASN1);
4960 if (dupl->d.otherName == NULL) {
4961 WOLFSSL_MSG("XMALLOC error");
4962 goto error;
4963 }
4964 dupl->d.otherName->type_id = wolfSSL_ASN1_OBJECT_dup(
4965 gn->d.otherName->type_id);
4966 dupl->d.otherName->value = (WOLFSSL_ASN1_TYPE*)XMALLOC(
4967 sizeof(WOLFSSL_ASN1_TYPE), NULL, DYNAMIC_TYPE_ASN1);
4968 if (dupl->d.otherName->value != NULL) {
4969 dupl->d.otherName->value->type = gn->d.otherName->value->type;
4970 dupl->d.otherName->value->value.utf8string =
4971 wolfSSL_ASN1_STRING_dup(
4972 gn->d.otherName->value->value.utf8string);
4973 }
4974 if ((dupl->d.otherName->type_id == NULL) ||
4975 (dupl->d.otherName->value == NULL) ||
4976 (dupl->d.otherName->value->value.utf8string == NULL)) {
4977 wolfSSL_ASN1_OBJECT_free(dupl->d.otherName->type_id);
4978 wolfSSL_ASN1_TYPE_free(dupl->d.otherName->value);
4979 XFREE(dupl->d.otherName, NULL, DYNAMIC_TYPE_ASN1);
4980 dupl->d.otherName = NULL;
4981 WOLFSSL_MSG("error duping othername");
4982 goto error;
4983 }
4984 break;
4985 case WOLFSSL_GEN_X400:
4986 case WOLFSSL_GEN_DIRNAME:
4987 case WOLFSSL_GEN_EDIPARTY:
4988 case WOLFSSL_GEN_RID:
4989 default:
4990 WOLFSSL_MSG("Unrecognized or unsupported GENERAL_NAME type");
4991 goto error;
4992 }
4993 dupl->type = gn->type;
4994
4995 return dupl;
4996error:
4997 wolfSSL_GENERAL_NAME_free(dupl);
4998 return NULL;
4999}
5000
5001/* Set an Othername in a general name.
5002 *
5003 * @param [out] gen Pointer to the GENERAL_NAME where the othername is set.
5004 * @param [in] oid Object ID (ie UPN).
5005 * @param [in] name The actual name.
5006 * @return WOLFSSL_FAILURE on invalid parameter or memory error,
5007 * WOLFSSL_SUCCESS otherwise.
5008 */
5009int wolfSSL_GENERAL_NAME_set0_othername(WOLFSSL_GENERAL_NAME* gen,
5010 WOLFSSL_ASN1_OBJECT* oid,
5011 WOLFSSL_ASN1_TYPE* value)
5012{
5013 WOLFSSL_ASN1_OBJECT *x = NULL;
5014
5015 if ((gen == NULL) || (oid == NULL) || (value == NULL)) {
5016 return WOLFSSL_FAILURE;
5017 }
5018
5019 x = wolfSSL_ASN1_OBJECT_dup(oid);
5020 if (x == NULL) {
5021 WOLFSSL_MSG("wolfSSL_ASN1_OBJECT_dup() failed");
5022 return WOLFSSL_FAILURE;
5023 }
5024
5025 if (wolfSSL_GENERAL_NAME_set_type(gen, WOLFSSL_GEN_OTHERNAME)
5026 != WOLFSSL_SUCCESS) {
5027 wolfSSL_ASN1_OBJECT_free(x);
5028 return WOLFSSL_FAILURE;
5029 }
5030
5031 gen->d.otherName->type_id = x;
5032 gen->d.otherName->value = value;
5033 return WOLFSSL_SUCCESS;
5034}
5035
5036/* return number of elements on success 0 on fail */
5037int wolfSSL_sk_GENERAL_NAME_push(WOLFSSL_GENERAL_NAMES* sk,
5038 WOLFSSL_GENERAL_NAME* gn)
5039{
5040 WOLFSSL_ENTER("wolfSSL_sk_GENERAL_NAME_push");
5041
5042 return wolfSSL_sk_push(sk, gn);
5043}
5044
5045#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
5046
5047#ifdef OPENSSL_EXTRA
5048
5049/* Returns the general name at index i from the stack
5050 *
5051 * sk stack to get general name from
5052 * idx index to get
5053 *
5054 * return a pointer to the internal node of the stack
5055 */
5056WOLFSSL_GENERAL_NAME* wolfSSL_sk_GENERAL_NAME_value(WOLFSSL_STACK* sk, int idx)
5057{
5058 return (WOLFSSL_GENERAL_NAME*)wolfSSL_sk_value(sk, idx);
5059}
5060
5061/* Gets the number of nodes in the stack
5062 *
5063 * sk stack to get the number of nodes from
5064 *
5065 * returns the number of nodes, -1 if no nodes
5066 */
5067int wolfSSL_sk_GENERAL_NAME_num(WOLFSSL_STACK* sk)
5068{
5069 WOLFSSL_ENTER("wolfSSL_sk_GENERAL_NAME_num");
5070
5071 return wolfSSL_sk_num(sk);
5072}
5073
5074/* Allocates an empty GENERAL NAME stack */
5075WOLFSSL_STACK* wolfSSL_sk_GENERAL_NAME_new(void *cmpFunc) {
5076 WOLFSSL_STACK* sk = NULL;
5077 (void)cmpFunc;
5078 WOLFSSL_ENTER("wolfSSL_sk_GENERAL_NAME_new");
5079
5080 sk = wolfSSL_sk_new_null();
5081 if (sk != NULL) {
5082 sk->type = STACK_TYPE_GEN_NAME;
5083 }
5084
5085 return sk;
5086}
5087#endif /* OPENSSL_EXTRA */
5088
5089#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
5090
5091/* Frees all nodes in a GENERAL NAME stack
5092 *
5093 * sk stack of nodes to free
5094 * f free function to use, not called with wolfSSL
5095 */
5096void wolfSSL_sk_GENERAL_NAME_pop_free(WOLFSSL_STACK* sk,
5097 void (*f) (WOLFSSL_GENERAL_NAME*))
5098{
5099 WOLFSSL_ENTER("wolfSSL_sk_GENERAL_NAME_pop_free");
5100 wolfSSL_sk_pop_free(sk, (wolfSSL_sk_freefunc)f);
5101}
5102
5103void wolfSSL_sk_GENERAL_NAME_free(WOLFSSL_STACK* sk)
5104{
5105 WOLFSSL_ENTER("wolfSSL_sk_GENERAL_NAME_free");
5106 wolfSSL_sk_X509_pop_free(sk, NULL);
5107}
5108#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
5109
5110#ifdef OPENSSL_EXTRA
5111static void wolfSSL_DIST_POINT_NAME_free(WOLFSSL_DIST_POINT_NAME* dpn)
5112{
5113 if (dpn != NULL) {
5114 if (dpn->name.fullname != NULL) {
5115 wolfSSL_sk_X509_pop_free(dpn->name.fullname, NULL);
5116 }
5117 XFREE(dpn, NULL, DYNAMIC_TYPE_OPENSSL);
5118 }
5119}
5120
5121
5122/* returns new pointer on success and NULL on fail */
5123static WOLFSSL_DIST_POINT_NAME* wolfSSL_DIST_POINT_NAME_new(void)
5124{
5125 WOLFSSL_DIST_POINT_NAME* dpn = NULL;
5126 WOLFSSL_GENERAL_NAMES* gns = NULL;
5127
5128 dpn = (WOLFSSL_DIST_POINT_NAME*)XMALLOC(sizeof(WOLFSSL_DIST_POINT_NAME),
5129 NULL, DYNAMIC_TYPE_OPENSSL);
5130 if (dpn == NULL) {
5131 return NULL;
5132 }
5133 XMEMSET(dpn, 0, sizeof(WOLFSSL_DIST_POINT_NAME));
5134
5135 gns = wolfSSL_sk_new_null();
5136 if (gns == NULL) {
5137 WOLFSSL_MSG("wolfSSL_sk_new_null error");
5138 XFREE(dpn, NULL, DYNAMIC_TYPE_OPENSSL);
5139 return NULL;
5140 }
5141 gns->type = STACK_TYPE_GEN_NAME;
5142
5143 /* DIST_POINT_NAME type may be 0 or 1, indicating whether fullname or
5144 * relativename is used. See: RFC 5280 section 4.2.1.13 */
5145 dpn->name.fullname = gns;
5146 dpn->type = 0;
5147
5148 return dpn;
5149}
5150
5151
5152/* Creates and returns new DIST_POINT structure */
5153WOLFSSL_DIST_POINT* wolfSSL_DIST_POINT_new(void)
5154{
5155 WOLFSSL_DIST_POINT* dp = NULL;
5156 WOLFSSL_DIST_POINT_NAME* dpn = NULL;
5157
5158 WOLFSSL_ENTER("wolfSSL_DIST_POINT_new");
5159
5160 dp = (WOLFSSL_DIST_POINT*)XMALLOC(sizeof(WOLFSSL_DIST_POINT), NULL,
5161 DYNAMIC_TYPE_OPENSSL);
5162 if (dp == NULL) {
5163 return NULL;
5164 }
5165 XMEMSET(dp, 0, sizeof(WOLFSSL_DIST_POINT));
5166
5167 dpn = wolfSSL_DIST_POINT_NAME_new();
5168 if (dpn == NULL) {
5169 XFREE(dp, NULL, DYNAMIC_TYPE_OPENSSL);
5170 return NULL;
5171 }
5172 dp->distpoint = dpn;
5173
5174 return dp;
5175}
5176
5177
5178/* Frees DIST_POINT objects.
5179*/
5180void wolfSSL_DIST_POINT_free(WOLFSSL_DIST_POINT* dp)
5181{
5182 WOLFSSL_ENTER("wolfSSL_DIST_POINT_free");
5183 if (dp != NULL) {
5184 wolfSSL_DIST_POINT_NAME_free(dp->distpoint);
5185 XFREE(dp, NULL, DYNAMIC_TYPE_OPENSSL);
5186 }
5187}
5188
5189void wolfSSL_DIST_POINTS_free(WOLFSSL_DIST_POINTS *dps)
5190{
5191 WOLFSSL_ENTER("wolfSSL_DIST_POINTS_free");
5192
5193 if (dps == NULL) {
5194 return;
5195 }
5196
5197 wolfSSL_sk_free(dps);
5198}
5199
5200/* return number of elements on success 0 on fail */
5201int wolfSSL_sk_DIST_POINT_push(WOLFSSL_DIST_POINTS* sk, WOLFSSL_DIST_POINT* dp)
5202{
5203 WOLFSSL_ENTER("wolfSSL_sk_DIST_POINT_push");
5204
5205 if (sk == NULL || dp == NULL) {
5206 return WOLFSSL_FAILURE;
5207 }
5208
5209 return wolfSSL_sk_push(sk, dp);
5210}
5211
5212/* Returns the CRL dist point at index i from the stack
5213 *
5214 * sk stack to get general name from
5215 * idx index to get
5216 *
5217 * return a pointer to the internal node of the stack
5218 */
5219WOLFSSL_DIST_POINT* wolfSSL_sk_DIST_POINT_value(WOLFSSL_STACK* sk, int idx)
5220{
5221 if (sk == NULL) {
5222 return NULL;
5223 }
5224
5225 return (WOLFSSL_DIST_POINT*)wolfSSL_sk_value(sk, idx);
5226}
5227
5228/* Gets the number of nodes in the stack
5229 *
5230 * sk stack to get the number of nodes from
5231 *
5232 * returns the number of nodes, -1 if no nodes
5233 */
5234int wolfSSL_sk_DIST_POINT_num(WOLFSSL_STACK* sk)
5235{
5236 WOLFSSL_ENTER("wolfSSL_sk_DIST_POINT_num");
5237
5238 if (sk == NULL) {
5239 return WOLFSSL_FATAL_ERROR;
5240 }
5241
5242 return wolfSSL_sk_num(sk);
5243}
5244
5245/* Frees all nodes in a DIST_POINT stack
5246 *
5247 * sk stack of nodes to free
5248 * f free function to use
5249 */
5250void wolfSSL_sk_DIST_POINT_pop_free(WOLFSSL_STACK* sk,
5251 void (*f) (WOLFSSL_DIST_POINT*))
5252{
5253 WOLFSSL_ENTER("wolfSSL_sk_DIST_POINT_pop_free");
5254 wolfSSL_sk_pop_free(sk, (wolfSSL_sk_freefunc)f);
5255}
5256
5257void wolfSSL_sk_DIST_POINT_free(WOLFSSL_STACK* sk)
5258{
5259 WOLFSSL_ENTER("wolfSSL_sk_DIST_POINT_free");
5260 wolfSSL_sk_free(sk);
5261}
5262
5263/* returns the number of nodes in stack on success and WOLFSSL_FATAL_ERROR
5264 * on fail */
5265int wolfSSL_sk_ACCESS_DESCRIPTION_num(WOLFSSL_STACK* sk)
5266{
5267 if (sk == NULL) {
5268 return WOLFSSL_FATAL_ERROR;
5269 }
5270
5271 return (int)sk->num;
5272}
5273
5274/* returns NULL on fail and pointer to internal data on success */
5275WOLFSSL_ACCESS_DESCRIPTION* wolfSSL_sk_ACCESS_DESCRIPTION_value(
5276 WOLFSSL_STACK* sk, int idx)
5277{
5278 WOLFSSL_STACK* ret;
5279
5280 if (sk == NULL) {
5281 return NULL;
5282 }
5283
5284 ret = wolfSSL_sk_get_node(sk, idx);
5285 if (ret != NULL) {
5286 return ret->data.access;
5287 }
5288 return NULL;
5289}
5290#endif /* OPENSSL_EXTRA */
5291
5292#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
5293/* free's the internal type for the general name */
5294static void wolfSSL_GENERAL_NAME_type_free(WOLFSSL_GENERAL_NAME* name)
5295{
5296 if (name != NULL) {
5297 switch (name->type) {
5298 case WOLFSSL_GEN_IA5:
5299 wolfSSL_ASN1_STRING_free(name->d.ia5);
5300 name->d.ia5 = NULL;
5301 break;
5302 case WOLFSSL_GEN_EMAIL:
5303 wolfSSL_ASN1_STRING_free(name->d.rfc822Name);
5304 name->d.rfc822Name = NULL;
5305 break;
5306 case WOLFSSL_GEN_DNS:
5307 wolfSSL_ASN1_STRING_free(name->d.dNSName);
5308 name->d.dNSName = NULL;
5309 break;
5310 case WOLFSSL_GEN_DIRNAME:
5311 wolfSSL_X509_NAME_free(name->d.dirn);
5312 name->d.dirn = NULL;
5313 break;
5314 case WOLFSSL_GEN_URI:
5315 wolfSSL_ASN1_STRING_free(name->d.uniformResourceIdentifier);
5316 name->d.uniformResourceIdentifier = NULL;
5317 break;
5318 case WOLFSSL_GEN_IPADD:
5319 wolfSSL_ASN1_STRING_free(name->d.iPAddress);
5320 name->d.iPAddress = NULL;
5321 break;
5322 case WOLFSSL_GEN_RID:
5323 wolfSSL_ASN1_OBJECT_free(name->d.registeredID);
5324 name->d.registeredID = NULL;
5325 break;
5326 case WOLFSSL_GEN_OTHERNAME:
5327 if (name->d.otherName != NULL) {
5328 wolfSSL_ASN1_OBJECT_free(name->d.otherName->type_id);
5329 wolfSSL_ASN1_TYPE_free(name->d.otherName->value);
5330 XFREE(name->d.otherName, NULL, DYNAMIC_TYPE_ASN1);
5331 name->d.otherName = NULL;
5332 }
5333 break;
5334 case WOLFSSL_GEN_X400:
5335 /* Unsupported: fall through */
5336 case WOLFSSL_GEN_EDIPARTY:
5337 /* Unsupported: fall through */
5338 default:
5339 WOLFSSL_MSG("wolfSSL_GENERAL_NAME_type_free: possible leak");
5340 break;
5341 }
5342 }
5343}
5344
5345/* sets the general name type and free's the existing one
5346 * can fail with a memory error if malloc fails or bad arg error
5347 * otherwise return WOLFSSL_SUCCESS */
5348int wolfSSL_GENERAL_NAME_set_type(WOLFSSL_GENERAL_NAME* name, int typ)
5349{
5350 int ret = WOLFSSL_SUCCESS;
5351
5352 if (name != NULL) {
5353 wolfSSL_GENERAL_NAME_type_free(name);
5354 name->type = typ;
5355
5356 switch (typ) {
5357 case WOLFSSL_GEN_URI:
5358 name->d.uniformResourceIdentifier = wolfSSL_ASN1_STRING_new();
5359 if (name->d.uniformResourceIdentifier == NULL)
5360 ret = MEMORY_E;
5361 break;
5362 case WOLFSSL_GEN_OTHERNAME:
5363 name->d.otherName = (WOLFSSL_ASN1_OTHERNAME*)XMALLOC(
5364 sizeof(WOLFSSL_ASN1_OTHERNAME), NULL, DYNAMIC_TYPE_ASN1);
5365 if (name->d.otherName == NULL) {
5366 ret = MEMORY_E;
5367 }
5368 else {
5369 XMEMSET(name->d.otherName, 0, sizeof(WOLFSSL_ASN1_OTHERNAME));
5370 }
5371 break;
5372 default:
5373 name->type = WOLFSSL_GEN_IA5;
5374 name->d.ia5 = wolfSSL_ASN1_STRING_new();
5375 if (name->d.ia5 == NULL)
5376 ret = MEMORY_E;
5377 }
5378 }
5379 else {
5380 ret = BAD_FUNC_ARG;
5381 }
5382
5383 return ret;
5384}
5385
5386/* Set the value in a general name. This is a compat layer API.
5387 *
5388 * @param [out] a Pointer to the GENERAL_NAME where the othername is set.
5389 * @param [in] type The type of this general name.
5390 * @param [in] value The ASN.1 string that is the value.
5391 * @return none
5392 * @note the set0 indicates we take ownership so the user does NOT free value.
5393 */
5394void wolfSSL_GENERAL_NAME_set0_value(WOLFSSL_GENERAL_NAME *a, int type,
5395 void *value)
5396{
5397 WOLFSSL_ASN1_STRING *val = (WOLFSSL_ASN1_STRING *)value;
5398 if (a == NULL) {
5399 WOLFSSL_MSG("a is NULL");
5400 return;
5401 }
5402
5403 if (val == NULL) {
5404 WOLFSSL_MSG("value is NULL");
5405 return;
5406 }
5407
5408 if (type != WOLFSSL_GEN_DNS) {
5409 WOLFSSL_MSG("Only WOLFSSL_GEN_DNS is supported");
5410 return;
5411 }
5412
5413 wolfSSL_GENERAL_NAME_type_free(a);
5414 a->type = type;
5415 /* Only when WOLFSSL_GEN_DNS. */
5416 a->d.dNSName = val;
5417}
5418
5419/* Frees GENERAL_NAME objects.
5420*/
5421void wolfSSL_GENERAL_NAME_free(WOLFSSL_GENERAL_NAME* name)
5422{
5423 WOLFSSL_ENTER("wolfSSL_GENERAL_NAME_Free");
5424 if (name != NULL) {
5425 wolfSSL_GENERAL_NAME_type_free(name);
5426 XFREE(name, NULL, DYNAMIC_TYPE_OPENSSL);
5427 }
5428}
5429#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL*/
5430
5431#ifdef OPENSSL_EXTRA
5432void wolfSSL_GENERAL_NAMES_free(WOLFSSL_GENERAL_NAMES *gens)
5433{
5434 WOLFSSL_ENTER("wolfSSL_GENERAL_NAMES_free");
5435
5436 if (gens == NULL) {
5437 return;
5438 }
5439
5440 wolfSSL_sk_GENERAL_NAME_free(gens);
5441}
5442
5443void wolfSSL_EXTENDED_KEY_USAGE_free(WOLFSSL_STACK * sk)
5444{
5445 WOLFSSL_ENTER("wolfSSL_EXTENDED_KEY_USAGE_free");
5446
5447 if (sk == NULL) {
5448 return;
5449 }
5450
5451 wolfSSL_sk_X509_pop_free(sk, NULL);
5452}
5453
5454#if !defined(IGNORE_NAME_CONSTRAINTS)
5455/*
5456 * Allocate and initialize an empty GENERAL_SUBTREE structure.
5457 * Returns NULL on allocation failure.
5458 */
5459WOLFSSL_GENERAL_SUBTREE* wolfSSL_GENERAL_SUBTREE_new(void)
5460{
5461 WOLFSSL_GENERAL_SUBTREE* subtree;
5462
5463 WOLFSSL_ENTER("wolfSSL_GENERAL_SUBTREE_new");
5464
5465 subtree = (WOLFSSL_GENERAL_SUBTREE*)XMALLOC(sizeof(WOLFSSL_GENERAL_SUBTREE),
5466 NULL, DYNAMIC_TYPE_OPENSSL);
5467 if (subtree == NULL) {
5468 WOLFSSL_MSG("Failed to allocate GENERAL_SUBTREE");
5469 return NULL;
5470 }
5471 XMEMSET(subtree, 0, sizeof(WOLFSSL_GENERAL_SUBTREE));
5472 return subtree;
5473}
5474
5475/*
5476 * Create an empty NAME_CONSTRAINTS structure.
5477 * Returns NULL on allocation failure.
5478 */
5479WOLFSSL_NAME_CONSTRAINTS* wolfSSL_NAME_CONSTRAINTS_new(void)
5480{
5481 WOLFSSL_NAME_CONSTRAINTS* nc;
5482
5483 WOLFSSL_ENTER("wolfSSL_NAME_CONSTRAINTS_new");
5484
5485 nc = (WOLFSSL_NAME_CONSTRAINTS*)XMALLOC(sizeof(WOLFSSL_NAME_CONSTRAINTS),
5486 NULL, DYNAMIC_TYPE_OPENSSL);
5487 if (nc == NULL) {
5488 WOLFSSL_MSG("Failed to allocate NAME_CONSTRAINTS");
5489 return NULL;
5490 }
5491 XMEMSET(nc, 0, sizeof(WOLFSSL_NAME_CONSTRAINTS));
5492 return nc;
5493}
5494
5495/* Free a GENERAL_SUBTREE and its contents. */
5496void wolfSSL_GENERAL_SUBTREE_free(WOLFSSL_GENERAL_SUBTREE* subtree)
5497{
5498 if (subtree == NULL) {
5499 return;
5500 }
5501 wolfSSL_GENERAL_NAME_free(subtree->base);
5502 XFREE(subtree, NULL, DYNAMIC_TYPE_OPENSSL);
5503}
5504
5505/* Free a NAME_CONSTRAINTS structure and all its contents. */
5506void wolfSSL_NAME_CONSTRAINTS_free(WOLFSSL_NAME_CONSTRAINTS* nc)
5507{
5508 WOLFSSL_ENTER("wolfSSL_NAME_CONSTRAINTS_free");
5509
5510 if (nc == NULL) {
5511 return;
5512 }
5513
5514 if (nc->permittedSubtrees != NULL) {
5515 wolfSSL_sk_pop_free(nc->permittedSubtrees,
5516 (wolfSSL_sk_freefunc)wolfSSL_GENERAL_SUBTREE_free);
5517 }
5518
5519 if (nc->excludedSubtrees != NULL) {
5520 wolfSSL_sk_pop_free(nc->excludedSubtrees,
5521 (wolfSSL_sk_freefunc)wolfSSL_GENERAL_SUBTREE_free);
5522 }
5523
5524 XFREE(nc, NULL, DYNAMIC_TYPE_OPENSSL);
5525}
5526
5527/* Get number of items in GENERAL_SUBTREE stack. */
5528int wolfSSL_sk_GENERAL_SUBTREE_num(const WOLFSSL_STACK* sk)
5529{
5530 WOLFSSL_ENTER("wolfSSL_sk_GENERAL_SUBTREE_num");
5531
5532 return wolfSSL_sk_num(sk);
5533}
5534
5535/* Get GENERAL_SUBTREE at index from stack. */
5536WOLFSSL_GENERAL_SUBTREE* wolfSSL_sk_GENERAL_SUBTREE_value(
5537 const WOLFSSL_STACK* sk, int idx)
5538{
5539 WOLFSSL_ENTER("wolfSSL_sk_GENERAL_SUBTREE_value");
5540
5541 return (WOLFSSL_GENERAL_SUBTREE*)wolfSSL_sk_value(sk, idx);
5542}
5543
5544/* Check IP address string matches constraint.
5545 *
5546 * name: IP address string (ex "192.168.1.50")
5547 * nameSz: length of name string
5548 * gn: GENERAL_NAME containing IP constraint (IP + mask bytes)
5549 *
5550 * Return 1 on match, otherwise 0
5551 */
5552static int MatchIpName(const char* name, int nameSz, WOLFSSL_GENERAL_NAME* gn)
5553{
5554 int ipLen = 0;
5555 int constraintLen;
5556 char ipStr[WOLFSSL_MAX_IPSTR];
5557 unsigned char ipBytes[16]; /* Max 16 bytes for IPv6 */
5558 const unsigned char* constraintData;
5559
5560 if (name == NULL || nameSz <= 0 || gn == NULL || gn->d.iPAddress == NULL) {
5561 return 0;
5562 }
5563
5564 constraintData = wolfSSL_ASN1_STRING_get0_data(gn->d.iPAddress);
5565 constraintLen = wolfSSL_ASN1_STRING_length(gn->d.iPAddress);
5566 if (constraintData == NULL || constraintLen <= 0) {
5567 return 0;
5568 }
5569
5570 /* Null-terminate IP string */
5571 if (nameSz >= (int)sizeof(ipStr)) {
5572 return 0;
5573 }
5574 XMEMCPY(ipStr, name, nameSz);
5575 ipStr[nameSz] = '\0';
5576
5577 /* IPv4 constraint 8 bytes (IP + mask),
5578 * IPv6 constraint 32 bytes (IP + mask) */
5579 if (constraintLen == 8) {
5580 #ifdef FREESCALE_MQX
5581 if (XINET_PTON(WOLFSSL_IP4, ipStr, ipBytes, sizeof(ipBytes)) == RTCS_OK) {
5582 #else
5583 if (XINET_PTON(WOLFSSL_IP4, ipStr, ipBytes) == 1) {
5584 #endif
5585 ipLen = 4;
5586 }
5587 }
5588 else if (constraintLen == 32) {
5589 #ifdef FREESCALE_MQX
5590 if (XINET_PTON(WOLFSSL_IP6, ipStr, ipBytes, sizeof(ipBytes)) == RTCS_OK) {
5591 #else
5592 if (XINET_PTON(WOLFSSL_IP6, ipStr, ipBytes) == 1) {
5593 #endif
5594 ipLen = 16;
5595 }
5596 }
5597
5598 if (ipLen == 0) {
5599 return 0;
5600 }
5601
5602 return wolfssl_local_MatchIpSubnet(ipBytes, ipLen,
5603 constraintData, constraintLen);
5604}
5605
5606/* Extract host from URI for name constraint matching.
5607 * URI format: scheme://[userinfo@]host[:port][/path][?query][#fragment]
5608 * IPv6 literals are enclosed in brackets: scheme://[ipv6addr]:port/path
5609 * Returns pointer to host start and sets hostLen, or NULL on failure. */
5610static const char* ExtractHostFromUri(const char* uri, int uriLen, int* hostLen)
5611{
5612 const char* hostStart;
5613 const char* hostEnd;
5614 const char* p;
5615 const char* uriEnd;
5616
5617 if (uri == NULL || uriLen <= 0 || hostLen == NULL) {
5618 return NULL;
5619 }
5620
5621 uriEnd = uri + uriLen;
5622
5623 /* Find "://" to skip scheme */
5624 hostStart = NULL;
5625 for (p = uri; p < uriEnd - 2; p++) {
5626 if (p[0] == ':' && p[1] == '/' && p[2] == '/') {
5627 hostStart = p + 3;
5628 break;
5629 }
5630 }
5631 if (hostStart == NULL || hostStart >= uriEnd) {
5632 return NULL;
5633 }
5634
5635 /* Skip userinfo if present (look for @ before any /, ?, #)
5636 * userinfo can contain ':' (ex: user:pass@host), don't stop at ':'
5637 * For IPv6, also don't stop at '[' in userinfo */
5638 for (p = hostStart; p < uriEnd; p++) {
5639 if (*p == '@') {
5640 hostStart = p + 1;
5641 break;
5642 }
5643 if (*p == '/' || *p == '?' || *p == '#') {
5644 /* No userinfo found */
5645 break;
5646 }
5647 /* If '[' before '@', found IPv6 literal, not userinfo */
5648 if (*p == '[') {
5649 break;
5650 }
5651 }
5652 if (hostStart >= uriEnd) {
5653 return NULL;
5654 }
5655
5656 /* Check for IPv6 literal */
5657 if (*hostStart == '[') {
5658 /* Find closing bracket, skip opening one */
5659 hostStart++;
5660 hostEnd = hostStart;
5661 while (hostEnd < uriEnd && *hostEnd != ']') {
5662 hostEnd++;
5663 }
5664 if (hostEnd >= uriEnd) {
5665 /* No closing bracket found, malformed */
5666 return NULL;
5667 }
5668 /* hostEnd points to closing bracket, extract content between */
5669 *hostLen = (int)(hostEnd - hostStart);
5670 if (*hostLen <= 0) {
5671 return NULL;
5672 }
5673 return hostStart;
5674 }
5675
5676 /* Regular hostname, find end */
5677 hostEnd = hostStart;
5678 while (hostEnd < uriEnd && *hostEnd != ':' && *hostEnd != '/' &&
5679 *hostEnd != '?' && *hostEnd != '#') {
5680 hostEnd++;
5681 }
5682
5683 *hostLen = (int)(hostEnd - hostStart);
5684 if (*hostLen <= 0) {
5685 return NULL;
5686 }
5687
5688 return hostStart;
5689}
5690
5691/* Helper to check if name string matches a single GENERAL_NAME constraint.
5692 * Returns 1 if matches, 0 if not. */
5693static int MatchNameConstraint(int type, const char* name, int nameSz,
5694 WOLFSSL_GENERAL_NAME* gn)
5695{
5696 const char* baseStr;
5697 int baseLen;
5698
5699 if (gn == NULL || gn->type != type) {
5700 return 0;
5701 }
5702
5703 switch (type) {
5704 case WOLFSSL_GEN_IPADD:
5705 return MatchIpName(name, nameSz, gn);
5706
5707 case WOLFSSL_GEN_DNS:
5708 case WOLFSSL_GEN_EMAIL:
5709 case WOLFSSL_GEN_URI:
5710 if (gn->d.ia5 == NULL) {
5711 return 0;
5712 }
5713 baseStr = (const char*)wolfSSL_ASN1_STRING_get0_data(gn->d.ia5);
5714 baseLen = wolfSSL_ASN1_STRING_length(gn->d.ia5);
5715 if (baseStr == NULL || baseLen <= 0) {
5716 return 0;
5717 }
5718
5719 if (type == WOLFSSL_GEN_EMAIL) {
5720 return wolfssl_local_MatchBaseName(ASN_RFC822_TYPE, name,
5721 nameSz, baseStr, baseLen);
5722 }
5723 else if (type == WOLFSSL_GEN_URI) {
5724 const char* host;
5725 int hostLen;
5726
5727 /* For URI, extract host and match against DNS-style */
5728 host = ExtractHostFromUri(name, nameSz, &hostLen);
5729 if (host == NULL) {
5730 return 0;
5731 }
5732 return wolfssl_local_MatchBaseName(ASN_DNS_TYPE, host, hostLen,
5733 baseStr, baseLen);
5734 }
5735 else {
5736 /* WOLFSSL_GEN_DNS uses DNS-style matching */
5737 return wolfssl_local_MatchBaseName(ASN_DNS_TYPE, name, nameSz,
5738 baseStr, baseLen);
5739 }
5740
5741 default:
5742 /* Unsupported type */
5743 return 0;
5744 }
5745}
5746
5747/*
5748 * Check if a name string satisfies given name constraints.
5749 *
5750 * nc: NAME_CONSTRAINTS struct containing permitted/excluded subtrees
5751 * type: GeneralName type (WOLFSSL_GEN_DNS, WOLFSSL_GEN_EMAIL, etc.)
5752 * name: The name string to check
5753 * nameSz: Length of name string
5754 *
5755 * Returns 1 if name satisfies constraints (permitted and not excluded),
5756 * otherwise 0 if name does not satisfy constraints or on error
5757 *
5758 * A name satisfies constraints if permitted subtrees exist for the type,
5759 * name matches at least one, and name does not match any excluded subtree.
5760 */
5761int wolfSSL_NAME_CONSTRAINTS_check_name(WOLFSSL_NAME_CONSTRAINTS* nc,
5762 int type, const char* name, int nameSz)
5763{
5764 int i, num;
5765 int hasPermittedType = 0;
5766 int matchedPermitted = 0;
5767 WOLFSSL_GENERAL_SUBTREE* subtree;
5768 WOLFSSL_GENERAL_NAME* gn;
5769
5770 WOLFSSL_ENTER("wolfSSL_NAME_CONSTRAINTS_check_name");
5771
5772 if (nc == NULL || name == NULL || nameSz <= 0) {
5773 WOLFSSL_MSG("Bad argument to NAME_CONSTRAINTS_check_name");
5774 return 0;
5775 }
5776
5777 /* Check permitted subtrees */
5778 if (nc->permittedSubtrees != NULL) {
5779 num = wolfSSL_sk_GENERAL_SUBTREE_num(nc->permittedSubtrees);
5780 for (i = 0; i < num; i++) {
5781 subtree = wolfSSL_sk_GENERAL_SUBTREE_value(
5782 nc->permittedSubtrees, i);
5783 if (subtree == NULL || subtree->base == NULL) {
5784 continue;
5785 }
5786
5787 gn = subtree->base;
5788 if (gn->type != type) {
5789 continue;
5790 }
5791 hasPermittedType = 1;
5792
5793 if (MatchNameConstraint(type, name, nameSz, gn)) {
5794 matchedPermitted = 1;
5795 break;
5796 }
5797 }
5798 }
5799
5800 /* If permitted constraints exist for this type but none matched, fail */
5801 if (hasPermittedType && !matchedPermitted) {
5802 WOLFSSL_MSG("Name not in permitted subtrees");
5803 return 0;
5804 }
5805
5806 /* Check excluded subtrees */
5807 if (nc->excludedSubtrees != NULL) {
5808 num = wolfSSL_sk_GENERAL_SUBTREE_num(nc->excludedSubtrees);
5809 for (i = 0; i < num; i++) {
5810 subtree = wolfSSL_sk_GENERAL_SUBTREE_value(nc->excludedSubtrees, i);
5811 if (subtree == NULL || subtree->base == NULL) {
5812 continue;
5813 }
5814
5815 gn = subtree->base;
5816 if (gn->type != type) {
5817 continue;
5818 }
5819
5820 if (MatchNameConstraint(type, name, nameSz, gn)) {
5821 WOLFSSL_MSG("Name in excluded subtrees");
5822 return 0;
5823 }
5824 }
5825 }
5826
5827 return 1;
5828}
5829#endif /* !IGNORE_NAME_CONSTRAINTS */
5830
5831#if defined(OPENSSL_ALL) && !defined(NO_BIO)
5832/* Outputs name string of the given WOLFSSL_GENERAL_NAME_OBJECT to WOLFSSL_BIO.
5833 * Can handle following GENERAL_NAME_OBJECT types:
5834 * - GEN_OTHERNAME #
5835 * - GEN_EMAIL
5836 * - GEN_DNS
5837 * - GEN_X400 #
5838 * - GEN_DIRNAME
5839 * - GEN_EDIPARTY #
5840 * - GEN_URI
5841 * - GEN_RID
5842 * The each name string to be output has "typename:namestring" format.
5843 * For instance, email name string will be output as "email:info@wolfssl.com".
5844 * However,some types above marked with "#" will be output with
5845 * "typename:<unsupported>".
5846 *
5847 * Parameters:
5848 * - out: WOLFSSL_BIO object which is the output destination
5849 * - gen: WOLFSSL_GENERAL_NAME object to be output its name
5850 *
5851 * Returns WOLFSSL_SUCCESS on success, WOLFSSL_FAILURE on failure.
5852 */
5853int wolfSSL_GENERAL_NAME_print(WOLFSSL_BIO* out, WOLFSSL_GENERAL_NAME* gen)
5854{
5855 int ret, i;
5856 unsigned int wd;
5857 unsigned char* p;
5858 (void)wd;
5859 (void)p;
5860 (void)i;
5861 WOLFSSL_ENTER("wolfSSL_GENERAL_NAME_print");
5862
5863 if (out == NULL || gen == NULL)
5864 return WOLFSSL_FAILURE;
5865
5866 ret = WOLFSSL_FAILURE;
5867 switch (gen->type)
5868 {
5869 case GEN_OTHERNAME:
5870 ret = wolfSSL_BIO_printf(out, "othername:<unsupported>");
5871 ret = (ret > 0) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
5872 break;
5873
5874 case GEN_EMAIL:
5875 ret = wolfSSL_BIO_printf(out, "email:");
5876 ret = (ret > 0) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
5877 if (ret == WOLFSSL_SUCCESS)
5878 {
5879 ret = wolfSSL_ASN1_STRING_print(out, gen->d.rfc822Name);
5880 }
5881 break;
5882
5883 case GEN_DNS:
5884 ret = wolfSSL_BIO_printf(out, "DNS:");
5885 ret = (ret > 0) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
5886 if (ret == WOLFSSL_SUCCESS) {
5887 ret = wolfSSL_BIO_printf(out, "%s", gen->d.dNSName->strData);
5888 ret = (ret > 0) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
5889 }
5890 break;
5891
5892 case GEN_X400:
5893 ret = wolfSSL_BIO_printf(out, "X400Name:<unsupported>");
5894 ret = (ret > 0) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
5895 break;
5896
5897 case GEN_DIRNAME:
5898 ret = wolfSSL_BIO_printf(out, "DirName:");
5899 if (ret == WOLFSSL_SUCCESS) {
5900 ret = wolfSSL_X509_NAME_print_ex(out, gen->d.directoryName, 0,
5901 XN_FLAG_ONELINE);
5902 }
5903 break;
5904
5905 case GEN_EDIPARTY:
5906 ret = wolfSSL_BIO_printf(out, "EdiPartyName:<unsupported>");
5907 ret = (ret > 0) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
5908 break;
5909
5910 case GEN_URI:
5911 ret = wolfSSL_BIO_printf(out, "URI:");
5912 ret = (ret > 0) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
5913 if (ret == WOLFSSL_SUCCESS) {
5914 ret = wolfSSL_ASN1_STRING_print(out,
5915 gen->d.uniformResourceIdentifier);
5916 }
5917 break;
5918
5919 case GEN_IPADD:
5920 ret = wolfSSL_BIO_printf(out, "IP Address");
5921 ret = (ret > 0) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
5922 if (ret == WOLFSSL_SUCCESS) {
5923
5924 if (!gen->d.iPAddress->length) {
5925 ret = WOLFSSL_FAILURE;
5926 break;
5927 }
5928 p = (unsigned char*)gen->d.iPAddress->strData;
5929
5930 if (gen->d.iPAddress->length == 4) {
5931 ret = wolfSSL_BIO_printf(out, ":%d.%d.%d.%d",
5932 p[0],p[1],p[2],p[3]);
5933 }
5934 else if (gen->d.iPAddress->length == 16) {
5935
5936 for (i = 0; i < 16 && ret == WOLFSSL_SUCCESS;) {
5937 wd = p[i] << 8 | p[i+1];
5938
5939 i += 2;
5940 ret = wolfSSL_BIO_printf(out, ":%X", wd);
5941 ret = (ret > 0) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
5942 }
5943 }
5944 else {
5945 ret = wolfSSL_BIO_printf(out, "<unsupported>");
5946 }
5947 ret = (ret > 0) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
5948 }
5949 break;
5950
5951 case GEN_RID:
5952 ret = wolfSSL_BIO_printf(out, "Registered ID:");
5953 ret = (ret > 0) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
5954 if (ret == WOLFSSL_SUCCESS) {
5955 ret = wolfSSL_i2a_ASN1_OBJECT(out, gen->d.registeredID);
5956 }
5957 break;
5958
5959 default:
5960 /* unsupported type */
5961 break;
5962 }
5963
5964 if (ret == WC_NO_ERR_TRACE(WOLFSSL_FAILURE))
5965 return WOLFSSL_FAILURE;
5966 else
5967 return WOLFSSL_SUCCESS;
5968}
5969#endif /* OPENSSL_ALL */
5970
5971WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* wolfSSL_sk_X509_EXTENSION_new_null(void)
5972{
5973 WOLFSSL_STACK* sk = wolfSSL_sk_new_node(NULL);
5974 if (sk) {
5975 sk->type = STACK_TYPE_X509_EXT;
5976 }
5977
5978 return (WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)*)sk;;
5979}
5980
5981/* returns the number of nodes on the stack */
5982int wolfSSL_sk_X509_EXTENSION_num(WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* sk)
5983{
5984 if (sk != NULL) {
5985 return (int)sk->num;
5986 }
5987 return WOLFSSL_FATAL_ERROR;
5988}
5989
5990
5991/* returns null on failure and pointer to internal value on success */
5992WOLFSSL_X509_EXTENSION* wolfSSL_sk_X509_EXTENSION_value(
5993 const WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* sk, int idx)
5994{
5995 return (WOLFSSL_X509_EXTENSION*)wolfSSL_sk_value(sk, idx);
5996}
5997
5998/* frees all of the nodes and the values in stack */
5999void wolfSSL_sk_X509_EXTENSION_pop_free(
6000 WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* sk,
6001 void (*f) (WOLFSSL_X509_EXTENSION*))
6002{
6003 wolfSSL_sk_pop_free(sk, (wolfSSL_sk_freefunc)f);
6004}
6005
6006void wolfSSL_sk_X509_EXTENSION_free(WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* sk)
6007{
6008 wolfSSL_sk_pop_free(sk, NULL);
6009}
6010
6011#endif /* OPENSSL_EXTRA */
6012
6013#if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM) && \
6014 !defined(NO_STDIO_FILESYSTEM)
6015
6016WOLFSSL_X509* wolfSSL_X509_d2i_fp(WOLFSSL_X509** x509, XFILE file)
6017{
6018 WOLFSSL_X509* newX509 = NULL;
6019
6020 WOLFSSL_ENTER("wolfSSL_X509_d2i_fp");
6021
6022 if (file != XBADFILE) {
6023 byte* fileBuffer = NULL;
6024 long sz = 0;
6025
6026 if (XFSEEK(file, 0, XSEEK_END) != 0)
6027 return NULL;
6028 sz = XFTELL(file);
6029 if (XFSEEK(file, 0, XSEEK_SET) != 0)
6030 return NULL;
6031
6032 if (sz > MAX_WOLFSSL_FILE_SIZE || sz < 0) {
6033 WOLFSSL_MSG("X509_d2i file size error");
6034 return NULL;
6035 }
6036
6037 fileBuffer = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE);
6038 if (fileBuffer != NULL) {
6039 int ret = (int)XFREAD(fileBuffer, 1, (size_t)sz, file);
6040 if (ret == sz) {
6041 newX509 = wolfSSL_X509_d2i(NULL, fileBuffer, (int)sz);
6042 }
6043 XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE);
6044 }
6045 }
6046
6047 if (x509 != NULL)
6048 *x509 = newX509;
6049
6050 return newX509;
6051}
6052
6053#endif /* OPENSSL_EXTRA && !NO_FILESYSTEM && !NO_STDIO_FILESYSTEM */
6054
6055#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \
6056 defined(KEEP_PEER_CERT) || defined(SESSION_CERTS)
6057
6058#ifndef NO_FILESYSTEM
6059WOLFSSL_ABI
6060WOLFSSL_X509* wolfSSL_X509_load_certificate_file(const char* fname, int format)
6061{
6062#ifdef WOLFSSL_SMALL_STACK
6063 byte staticBuffer[1]; /* force heap usage */
6064#else
6065 byte staticBuffer[FILE_BUFFER_SIZE];
6066#endif
6067 byte* fileBuffer = staticBuffer;
6068 int dynamic = 0;
6069 int ret;
6070 long sz = 0;
6071 XFILE file;
6072
6073 WOLFSSL_X509* x509 = NULL;
6074
6075 /* Check the inputs */
6076 if ((fname == NULL) ||
6077 (format != WOLFSSL_FILETYPE_ASN1 && format != WOLFSSL_FILETYPE_PEM))
6078 return NULL;
6079
6080 file = XFOPEN(fname, "rb");
6081 if (file == XBADFILE)
6082 return NULL;
6083
6084 if (XFSEEK(file, 0, XSEEK_END) != 0) {
6085 XFCLOSE(file);
6086 return NULL;
6087 }
6088 sz = XFTELL(file);
6089 if (XFSEEK(file, 0, XSEEK_SET) != 0) {
6090 XFCLOSE(file);
6091 return NULL;
6092 }
6093
6094 if (sz > MAX_WOLFSSL_FILE_SIZE || sz < 0) {
6095 WOLFSSL_MSG("X509_load_certificate_file size error");
6096 XFCLOSE(file);
6097 return NULL;
6098 }
6099
6100 if (sz > (long)sizeof(staticBuffer)) {
6101 fileBuffer = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE);
6102 if (fileBuffer == NULL) {
6103 XFCLOSE(file);
6104 return NULL;
6105 }
6106 dynamic = 1;
6107 }
6108
6109 ret = (int)XFREAD(fileBuffer, 1, (size_t)sz, file);
6110 if (ret != sz) {
6111 XFCLOSE(file);
6112 if (dynamic)
6113 XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE);
6114 return NULL;
6115 }
6116
6117 XFCLOSE(file);
6118
6119 x509 = wolfSSL_X509_load_certificate_buffer(fileBuffer, (int)sz, format);
6120
6121 if (dynamic)
6122 XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE);
6123
6124 return x509;
6125}
6126#endif /* !NO_FILESYSTEM */
6127
6128static WOLFSSL_X509* loadX509orX509REQFromBuffer(
6129 const unsigned char* buf, int sz, int format, int type,
6130 wc_pem_password_cb *cb, void *u)
6131{
6132
6133 int ret = 0;
6134 WOLFSSL_X509* x509 = NULL;
6135 DerBuffer* der = NULL;
6136
6137 WOLFSSL_ENTER("wolfSSL_X509_load_certificate_ex");
6138
6139 if (format == WOLFSSL_FILETYPE_PEM) {
6140 EncryptedInfo info;
6141 XMEMSET(&info, 0, sizeof(EncryptedInfo));
6142 #ifdef WOLFSSL_ENCRYPTED_KEYS
6143 info.passwd_cb = cb;
6144 info.passwd_userdata = u;
6145 #endif
6146
6147 #ifdef WOLFSSL_PEM_TO_DER
6148 ret = PemToDer(buf, sz, type, &der, NULL, &info, NULL);
6149 if (ret != 0) {
6150 FreeDer(&der);
6151 }
6152 #else
6153 ret = NOT_COMPILED_IN;
6154 #endif
6155 }
6156 else {
6157 ret = AllocDer(&der, (word32)sz, type, NULL);
6158 if (ret == 0) {
6159 XMEMCPY(der->buffer, buf, sz);
6160 }
6161 }
6162
6163 /* At this point we want `der` to have the certificate in DER format */
6164 /* ready to be decoded. */
6165 if (der != NULL && der->buffer != NULL) {
6166 WC_DECLARE_VAR(cert, DecodedCert, 1, 0);
6167 /* For TRUSTED_CERT_TYPE, the DER buffer contains the certificate
6168 * followed by auxiliary trust info. ParseCertRelative expects CERT_TYPE
6169 * and will parse only the certificate portion, ignoring the rest. */
6170 int parseType = (type == TRUSTED_CERT_TYPE) ? CERT_TYPE : type;
6171
6172 WC_ALLOC_VAR_EX(cert, DecodedCert, 1, NULL, DYNAMIC_TYPE_DCERT,
6173 ret=MEMORY_ERROR);
6174 if (WC_VAR_OK(cert))
6175 {
6176 InitDecodedCert(cert, der->buffer, der->length, NULL);
6177 ret = ParseCertRelative(cert, parseType, 0, NULL, NULL);
6178 if (ret == 0) {
6179 /* For TRUSTED_CERT_TYPE, truncate the DER buffer to exclude
6180 * auxiliary trust data. ParseCertRelative sets srcIdx to the
6181 * end of the certificate, so we adjust cert->maxIdx accordingly. */
6182 if (type == TRUSTED_CERT_TYPE && cert->srcIdx < cert->maxIdx) {
6183 cert->maxIdx = cert->srcIdx;
6184 }
6185
6186 x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), NULL,
6187 DYNAMIC_TYPE_X509);
6188 if (x509 != NULL) {
6189 InitX509(x509, 1, NULL);
6190 ret = CopyDecodedToX509(x509, cert);
6191 if (ret != 0) {
6192 wolfSSL_X509_free(x509);
6193 x509 = NULL;
6194 }
6195 }
6196 else {
6197 ret = MEMORY_ERROR;
6198 }
6199 }
6200
6201 FreeDecodedCert(cert);
6202 WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_DCERT);
6203 }
6204
6205 FreeDer(&der);
6206 }
6207
6208 if (ret != 0) {
6209 WOLFSSL_ERROR(ret);
6210 }
6211
6212 /* unused parameter when built without WOLFSSL_ENCRYPTED_KEYS */
6213 (void)cb;
6214 (void)u;
6215 return x509;
6216}
6217
6218WOLFSSL_X509* wolfSSL_X509_load_certificate_buffer(
6219 const unsigned char* buf, int sz, int format)
6220{
6221 return loadX509orX509REQFromBuffer(buf, sz,
6222 format, CERT_TYPE, NULL, NULL);
6223}
6224
6225#ifdef WOLFSSL_CERT_REQ
6226WOLFSSL_X509* wolfSSL_X509_REQ_load_certificate_buffer(
6227 const unsigned char* buf, int sz, int format)
6228{
6229 return loadX509orX509REQFromBuffer(buf, sz,
6230 format, CERTREQ_TYPE, NULL, NULL);
6231}
6232#endif
6233
6234#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL || KEEP_PEER_CERT || \
6235 SESSION_CERTS */
6236
6237#if defined(OPENSSL_EXTRA_X509_SMALL) || defined(KEEP_PEER_CERT) || \
6238 defined(SESSION_CERTS)
6239/* Smaller subset of X509 compatibility functions. Avoid increasing the size of
6240 * this subset and its memory usage */
6241
6242/* returns a pointer to a new WOLFSSL_X509 structure on success and NULL on
6243 * fail
6244 */
6245WOLFSSL_X509* wolfSSL_X509_new_ex(void* heap)
6246{
6247 WOLFSSL_X509* x509;
6248
6249 x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), heap,
6250 DYNAMIC_TYPE_X509);
6251 if (x509 != NULL) {
6252 InitX509(x509, 1, heap);
6253 }
6254
6255 return x509;
6256}
6257
6258WOLFSSL_X509* wolfSSL_X509_new(void)
6259{
6260 return wolfSSL_X509_new_ex(NULL);
6261}
6262
6263WOLFSSL_ABI
6264WOLFSSL_X509_NAME* wolfSSL_X509_get_subject_name(WOLFSSL_X509* cert)
6265{
6266 WOLFSSL_ENTER("wolfSSL_X509_get_subject_name");
6267 if (cert)
6268 return &cert->subject;
6269 return NULL;
6270}
6271
6272WOLFSSL_ABI
6273WOLFSSL_X509_NAME* wolfSSL_X509_get_issuer_name(WOLFSSL_X509* cert)
6274{
6275 WOLFSSL_ENTER("wolfSSL_X509_get_issuer_name");
6276 if (cert)
6277 return &cert->issuer;
6278 return NULL;
6279}
6280
6281
6282int wolfSSL_X509_get_signature_type(WOLFSSL_X509* x509)
6283{
6284 int type = 0;
6285
6286 WOLFSSL_ENTER("wolfSSL_X509_get_signature_type");
6287
6288 if (x509 != NULL)
6289 type = x509->sigOID;
6290
6291 return type;
6292}
6293
6294#if defined(OPENSSL_EXTRA_X509_SMALL)
6295
6296int wolfSSL_X509_NAME_get_sz(WOLFSSL_X509_NAME* name)
6297{
6298 WOLFSSL_ENTER("wolfSSL_X509_NAME_get_sz");
6299 if (!name)
6300 return WOLFSSL_FATAL_ERROR;
6301 return name->sz;
6302}
6303
6304/* Searches for the first ENTRY of type NID
6305 * idx is the location to start searching from, the value at when the entry was
6306 * found is stored into idx
6307 * returns a pointer to the entry on success and null on fail */
6308static WOLFSSL_X509_NAME_ENTRY* GetEntryByNID(WOLFSSL_X509_NAME* name, int nid,
6309 int* idx)
6310{
6311 int i;
6312 WOLFSSL_X509_NAME_ENTRY* ret = NULL;
6313
6314 for (i = *idx; i < MAX_NAME_ENTRIES; i++) {
6315 if (name->entry[i].nid == nid) {
6316 ret = &name->entry[i];
6317 *idx = i;
6318 break;
6319 }
6320 }
6321 return ret;
6322}
6323
6324
6325/* Used to get a string from the WOLFSSL_X509_NAME structure that
6326 * corresponds with the NID value passed in. This finds the first entry with
6327 * matching NID value, if searching for the case where there is multiple
6328 * entries with the same NID value than other functions should be used
6329 * (i.e. wolfSSL_X509_NAME_get_index_by_NID, wolfSSL_X509_NAME_get_entry)
6330 *
6331 * name structure to get string from
6332 * nid NID value to search for
6333 * buf [out] buffer to hold results. If NULL then the buffer size minus the
6334 * null char is returned.
6335 * len size of "buf" passed in
6336 *
6337 * returns the length of string found, not including the NULL terminator.
6338 * It's possible the function could return a negative value in the
6339 * case that len is less than or equal to 0. A negative value is
6340 * considered an error case.
6341 */
6342int wolfSSL_X509_NAME_get_text_by_NID(WOLFSSL_X509_NAME* name,
6343 int nid, char* buf, int len)
6344{
6345 WOLFSSL_X509_NAME_ENTRY* e;
6346 unsigned char *text = NULL;
6347 int textSz = 0;
6348 int idx = 0;
6349
6350 WOLFSSL_ENTER("wolfSSL_X509_NAME_get_text_by_NID");
6351
6352 if (name == NULL) {
6353 WOLFSSL_MSG("NULL argument passed in");
6354 return WOLFSSL_FATAL_ERROR;
6355 }
6356
6357 e = GetEntryByNID(name, nid, &idx);
6358 if (e == NULL) {
6359 WOLFSSL_MSG("Entry type not found");
6360 return WOLFSSL_FATAL_ERROR;
6361 }
6362 text = wolfSSL_ASN1_STRING_data(e->value);
6363 textSz = wolfSSL_ASN1_STRING_length(e->value);
6364
6365 if (text == NULL) {
6366 WOLFSSL_MSG("Unable to get entry text");
6367 return WOLFSSL_FATAL_ERROR;
6368 }
6369
6370 /* if buf is NULL return size of buffer needed (minus null char) */
6371 if (buf == NULL) {
6372 WOLFSSL_MSG("Buffer is NULL, returning buffer size only");
6373 return textSz;
6374 }
6375 if (len <= 0) {
6376 return 0;
6377 }
6378
6379 /* + 1 to account for null char */
6380 textSz = (int)min((word32)textSz + 1, (word32)len);
6381 if (textSz > 0) {
6382 XMEMCPY(buf, text, textSz - 1);
6383 buf[textSz - 1] = '\0';
6384 }
6385
6386 WOLFSSL_LEAVE("wolfSSL_X509_NAME_get_text_by_NID", textSz);
6387 return (textSz - 1); /* do not include null character in size */
6388}
6389
6390/* Creates a new WOLFSSL_EVP_PKEY structure that has the public key from x509
6391 *
6392 * returns a pointer to the created WOLFSSL_EVP_PKEY on success and NULL on fail
6393 */
6394WOLFSSL_EVP_PKEY* wolfSSL_X509_get_pubkey(WOLFSSL_X509* x509)
6395{
6396 WOLFSSL_EVP_PKEY* key = NULL;
6397 int ret = 0;
6398
6399 (void)ret;
6400
6401 WOLFSSL_ENTER("wolfSSL_X509_get_pubkey");
6402 if (x509 != NULL) {
6403 key = wolfSSL_EVP_PKEY_new_ex(x509->heap);
6404 if (key != NULL) {
6405 if (x509->pubKeyOID == RSAk) {
6406 key->type = WC_EVP_PKEY_RSA;
6407 }
6408 else if (x509->pubKeyOID == DSAk) {
6409 key->type = WC_EVP_PKEY_DSA;
6410 }
6411 #ifdef HAVE_DILITHIUM
6412 else if (x509->pubKeyOID == ML_DSA_LEVEL2k ||
6413 x509->pubKeyOID == ML_DSA_LEVEL3k ||
6414 x509->pubKeyOID == ML_DSA_LEVEL5k) {
6415 key->type = WC_EVP_PKEY_DILITHIUM;
6416 }
6417 #endif
6418 else {
6419 key->type = WC_EVP_PKEY_EC;
6420 }
6421 key->save_type = 0;
6422 key->pkey.ptr = (char*)XMALLOC(
6423 x509->pubKey.length, x509->heap,
6424 DYNAMIC_TYPE_PUBLIC_KEY);
6425 if (key->pkey.ptr == NULL) {
6426 wolfSSL_EVP_PKEY_free(key);
6427 return NULL;
6428 }
6429 XMEMCPY(key->pkey.ptr, x509->pubKey.buffer, x509->pubKey.length);
6430 key->pkey_sz = (int)x509->pubKey.length;
6431
6432 #ifdef HAVE_ECC
6433 key->pkey_curve = (int)x509->pkCurveOID;
6434 #endif /* HAVE_ECC */
6435
6436 /* decode RSA key */
6437 #ifndef NO_RSA
6438 if (key->type == WC_EVP_PKEY_RSA) {
6439 key->ownRsa = 1;
6440 key->rsa = wolfSSL_RSA_new();
6441 if (key->rsa == NULL) {
6442 wolfSSL_EVP_PKEY_free(key);
6443 return NULL;
6444 }
6445
6446 if (wolfSSL_RSA_LoadDer_ex(key->rsa,
6447 (const unsigned char*)key->pkey.ptr, key->pkey_sz,
6448 WOLFSSL_RSA_LOAD_PUBLIC) != WOLFSSL_SUCCESS) {
6449 wolfSSL_EVP_PKEY_free(key);
6450 return NULL;
6451 }
6452 }
6453 #endif /* NO_RSA */
6454
6455 /* decode ECC key */
6456 #if defined(HAVE_ECC) && defined(OPENSSL_EXTRA)
6457 if (key->type == WC_EVP_PKEY_EC) {
6458 word32 idx = 0;
6459
6460 key->ownEcc = 1;
6461 key->ecc = wolfSSL_EC_KEY_new();
6462 if (key->ecc == NULL || key->ecc->internal == NULL) {
6463 wolfSSL_EVP_PKEY_free(key);
6464 return NULL;
6465 }
6466
6467 /* not using wolfSSL_EC_KEY_LoadDer because public key in x509
6468 * is in the format of x963 (no sequence at start of buffer) */
6469 ret = wc_EccPublicKeyDecode((const unsigned char*)key->pkey.ptr,
6470 &idx, (ecc_key*)key->ecc->internal,
6471 key->pkey_sz);
6472 if (ret < 0) {
6473 WOLFSSL_ERROR_VERBOSE(ret);
6474 WOLFSSL_MSG("wc_EccPublicKeyDecode failed");
6475 wolfSSL_EVP_PKEY_free(key);
6476 return NULL;
6477 }
6478
6479 if (SetECKeyExternal(key->ecc) != WOLFSSL_SUCCESS) {
6480 WOLFSSL_MSG("SetECKeyExternal failed");
6481 wolfSSL_EVP_PKEY_free(key);
6482 return NULL;
6483 }
6484
6485 key->ecc->inSet = 1;
6486 }
6487 #endif /* HAVE_ECC && OPENSSL_EXTRA */
6488
6489 #ifndef NO_DSA
6490 if (key->type == WC_EVP_PKEY_DSA) {
6491 key->ownDsa = 1;
6492 key->dsa = wolfSSL_DSA_new();
6493 if (key->dsa == NULL) {
6494 wolfSSL_EVP_PKEY_free(key);
6495 return NULL;
6496 }
6497
6498 if (wolfSSL_DSA_LoadDer_ex(key->dsa,
6499 (const unsigned char*)key->pkey.ptr, key->pkey_sz, \
6500 WOLFSSL_DSA_LOAD_PUBLIC) != WOLFSSL_SUCCESS) {
6501 wolfSSL_DSA_free(key->dsa);
6502 key->dsa = NULL;
6503 wolfSSL_EVP_PKEY_free(key);
6504 return NULL;
6505 }
6506 }
6507 #endif /* NO_DSA */
6508 }
6509 }
6510 return key;
6511}
6512#endif /* OPENSSL_EXTRA_X509_SMALL */
6513
6514/* End of smaller subset of X509 compatibility functions. Avoid increasing the
6515 * size of this subset and its memory usage */
6516#endif /* OPENSSL_EXTRA_X509_SMALL || KEEP_PEER_CERT || SESSION_CERTS */
6517
6518#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)
6519/*
6520 * Converts a and b to DER and then does an XMEMCMP to check if they match.
6521 * Returns 0 when certificates match and WOLFSSL_FATAL_ERROR when they don't.
6522 */
6523int wolfSSL_X509_cmp(const WOLFSSL_X509 *a, const WOLFSSL_X509 *b)
6524{
6525 const byte* derA;
6526 const byte* derB;
6527 int outSzA = 0;
6528 int outSzB = 0;
6529
6530 if (a == NULL || b == NULL) {
6531 return BAD_FUNC_ARG;
6532 }
6533
6534 derA = wolfSSL_X509_get_der((WOLFSSL_X509*)a, &outSzA);
6535 if (derA == NULL) {
6536 WOLFSSL_MSG("wolfSSL_X509_get_der - certificate A has failed");
6537 return WOLFSSL_FATAL_ERROR;
6538 }
6539 derB = wolfSSL_X509_get_der((WOLFSSL_X509*)b, &outSzB);
6540 if (derB == NULL) {
6541 WOLFSSL_MSG("wolfSSL_X509_get_der - certificate B has failed");
6542 return WOLFSSL_FATAL_ERROR;
6543 }
6544
6545 if (outSzA != outSzB || XMEMCMP(derA, derB, outSzA) != 0) {
6546 WOLFSSL_LEAVE("wolfSSL_X509_cmp", WOLFSSL_FATAL_ERROR);
6547 return WOLFSSL_FATAL_ERROR;
6548 }
6549
6550 WOLFSSL_LEAVE("wolfSSL_X509_cmp", 0);
6551
6552 return 0;
6553 }
6554#endif /* OPENSSL_ALL */
6555
6556#if defined(OPENSSL_EXTRA)
6557 int wolfSSL_X509_ext_isSet_by_NID(WOLFSSL_X509* x509, int nid)
6558 {
6559 int isSet = 0;
6560
6561 WOLFSSL_ENTER("wolfSSL_X509_ext_isSet_by_NID");
6562
6563 if (x509 != NULL) {
6564 switch (nid) {
6565 case WC_NID_basic_constraints:
6566 isSet = x509->basicConstSet; break;
6567 case WC_NID_subject_alt_name:
6568 isSet = x509->subjAltNameSet; break;
6569 case WC_NID_authority_key_identifier:
6570 isSet = x509->authKeyIdSet; break;
6571 case WC_NID_subject_key_identifier:
6572 isSet = x509->subjKeyIdSet; break;
6573 case WC_NID_key_usage:
6574 isSet = x509->keyUsageSet; break;
6575 case WC_NID_crl_distribution_points:
6576 isSet = x509->CRLdistSet; break;
6577 case WC_NID_ext_key_usage:
6578 isSet = ((x509->extKeyUsageSrc) ? 1 : 0); break;
6579 case WC_NID_info_access:
6580 isSet = x509->authInfoSet; break;
6581 #if defined(WOLFSSL_SEP) || defined(WOLFSSL_QT)
6582 case WC_NID_certificate_policies:
6583 isSet = x509->certPolicySet; break;
6584 #endif /* WOLFSSL_SEP || WOLFSSL_QT */
6585 default:
6586 WOLFSSL_MSG("NID not in table");
6587 }
6588 }
6589
6590 WOLFSSL_LEAVE("wolfSSL_X509_ext_isSet_by_NID", isSet);
6591
6592 return isSet;
6593 }
6594
6595
6596 int wolfSSL_X509_ext_get_critical_by_NID(WOLFSSL_X509* x509, int nid)
6597 {
6598 int crit = 0;
6599
6600 WOLFSSL_ENTER("wolfSSL_X509_ext_get_critical_by_NID");
6601
6602 if (x509 != NULL) {
6603 switch (nid) {
6604 case WC_NID_basic_constraints:
6605 crit = x509->basicConstCrit; break;
6606 case WC_NID_subject_alt_name:
6607 crit = x509->subjAltNameCrit; break;
6608 case WC_NID_authority_key_identifier:
6609 crit = x509->authKeyIdCrit; break;
6610 case WC_NID_subject_key_identifier:
6611 crit = x509->subjKeyIdCrit; break;
6612 case WC_NID_key_usage:
6613 crit = x509->keyUsageCrit; break;
6614 case WC_NID_crl_distribution_points:
6615 crit= x509->CRLdistCrit; break;
6616 case WC_NID_ext_key_usage:
6617 crit= x509->extKeyUsageCrit; break;
6618 #ifdef WOLFSSL_SEP
6619 case WC_NID_certificate_policies:
6620 crit = x509->certPolicyCrit; break;
6621 #endif /* WOLFSSL_SEP */
6622 }
6623 }
6624
6625 WOLFSSL_LEAVE("wolfSSL_X509_ext_get_critical_by_NID", crit);
6626
6627 return crit;
6628 }
6629
6630
6631 int wolfSSL_X509_get_isSet_pathLength(WOLFSSL_X509* x509)
6632 {
6633 int isSet = 0;
6634
6635 WOLFSSL_ENTER("wolfSSL_X509_get_isSet_pathLength");
6636
6637 if (x509 != NULL)
6638 isSet = x509->basicConstPlSet;
6639
6640 WOLFSSL_LEAVE("wolfSSL_X509_get_isSet_pathLength", isSet);
6641
6642 return isSet;
6643 }
6644
6645
6646 word32 wolfSSL_X509_get_pathLength(WOLFSSL_X509* x509)
6647 {
6648 word32 pathLength = 0;
6649
6650 WOLFSSL_ENTER("wolfSSL_X509_get_pathLength");
6651
6652 if (x509 != NULL)
6653 pathLength = x509->pathLength;
6654
6655 WOLFSSL_LEAVE("wolfSSL_X509_get_pathLength", pathLength);
6656
6657 return pathLength;
6658 }
6659
6660
6661 unsigned int wolfSSL_X509_get_keyUsage(WOLFSSL_X509* x509)
6662 {
6663 word16 usage = 0;
6664
6665 WOLFSSL_ENTER("wolfSSL_X509_get_keyUsage");
6666
6667 if (x509 != NULL)
6668 usage = x509->keyUsage;
6669
6670 WOLFSSL_LEAVE("wolfSSL_X509_get_keyUsage", usage);
6671
6672 return usage;
6673 }
6674
6675
6676 byte* wolfSSL_X509_get_authorityKeyID(WOLFSSL_X509* x509,
6677 byte* dst, int* dstLen)
6678 {
6679 byte *id = NULL;
6680 int copySz = 0;
6681
6682 WOLFSSL_ENTER("wolfSSL_X509_get_authorityKeyID");
6683
6684 if (x509 != NULL) {
6685 if (x509->authKeyIdSet) {
6686 copySz = (int)min(dstLen != NULL ? (word32)*dstLen : 0,
6687 x509->authKeyIdSz);
6688 id = x509->authKeyId;
6689 }
6690
6691 if (dst != NULL && dstLen != NULL && id != NULL && copySz > 0) {
6692 XMEMCPY(dst, id, copySz);
6693 id = dst;
6694 *dstLen = copySz;
6695 }
6696 }
6697
6698 WOLFSSL_LEAVE("wolfSSL_X509_get_authorityKeyID", copySz);
6699
6700 return id;
6701 }
6702
6703 byte* wolfSSL_X509_get_subjectKeyID(WOLFSSL_X509* x509,
6704 byte* dst, int* dstLen)
6705 {
6706 byte *id = NULL;
6707 int copySz = 0;
6708
6709 WOLFSSL_ENTER("wolfSSL_X509_get_subjectKeyID");
6710
6711 if (x509 != NULL) {
6712 if (x509->subjKeyIdSet) {
6713 copySz = (int)min(dstLen != NULL ? (word32) *dstLen : 0,
6714 x509->subjKeyIdSz);
6715 id = x509->subjKeyId;
6716 }
6717
6718 if (dst != NULL && dstLen != NULL && id != NULL && copySz > 0) {
6719 XMEMCPY(dst, id, copySz);
6720 id = dst;
6721 *dstLen = copySz;
6722 }
6723 }
6724
6725 WOLFSSL_LEAVE("wolfSSL_X509_get_subjectKeyID", copySz);
6726
6727 return id;
6728 }
6729
6730 const WOLFSSL_ASN1_STRING *wolfSSL_X509_get0_subject_key_id(
6731 WOLFSSL_X509 *x509)
6732 {
6733 WOLFSSL_ASN1_STRING* ret = NULL;
6734
6735 WOLFSSL_ENTER("wolfSSL_X509_get0_subject_key_id");
6736
6737 if (x509 != NULL && x509->subjKeyIdSet) {
6738 if (x509->subjKeyIdStr == NULL) {
6739 x509->subjKeyIdStr = wolfSSL_ASN1_STRING_new();
6740 if (x509->subjKeyIdStr != NULL) {
6741 if (wolfSSL_ASN1_STRING_set(x509->subjKeyIdStr,
6742 x509->subjKeyId, x509->subjKeyIdSz) == 1) {
6743 }
6744 else {
6745 wolfSSL_ASN1_STRING_free(x509->subjKeyIdStr);
6746 x509->subjKeyIdStr = NULL;
6747 }
6748 }
6749 }
6750 ret = x509->subjKeyIdStr;
6751 }
6752
6753 WOLFSSL_LEAVE("wolfSSL_X509_get0_subject_key_id", ret != NULL);
6754
6755 return ret;
6756 }
6757#endif /* OPENSSL_EXTRA */
6758
6759#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \
6760 defined(OPENSSL_EXTRA_X509_SMALL)
6761
6762 /* Looks up the index of the first entry encountered with matching NID
6763 * The search starts from index 'pos'
6764 * returns a negative value on failure and positive index value on success*/
6765 int wolfSSL_X509_NAME_get_index_by_NID(WOLFSSL_X509_NAME* name,
6766 int nid, int pos)
6767 {
6768 int value = nid, i;
6769
6770 WOLFSSL_ENTER("wolfSSL_X509_NAME_get_index_by_NID");
6771
6772 if (name == NULL) {
6773 return BAD_FUNC_ARG;
6774 }
6775
6776 i = pos + 1; /* start search after index passed in */
6777 if (i < 0) {
6778 i = 0;
6779 }
6780
6781 for (;i < name->entrySz && i < MAX_NAME_ENTRIES; i++) {
6782 if (name->entry[i].nid == value) {
6783 return i;
6784 }
6785 }
6786 return WOLFSSL_FATAL_ERROR;
6787 }
6788
6789
6790 WOLFSSL_ASN1_STRING* wolfSSL_X509_NAME_ENTRY_get_data(
6791 WOLFSSL_X509_NAME_ENTRY* in)
6792 {
6793 WOLFSSL_ENTER("wolfSSL_X509_NAME_ENTRY_get_data");
6794 if (in == NULL)
6795 return NULL;
6796
6797 return in->value;
6798 }
6799
6800#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
6801
6802#ifdef OPENSSL_EXTRA
6803#ifndef NO_BIO
6804
6805#ifndef MAX_WIDTH
6806 #define MAX_WIDTH 80
6807#endif
6808
6809#define ACERT_NUM_DIR_TAGS 4
6810
6811/* Convenience struct and function for printing the Holder sub fields
6812 * of an X509 Attribute struct. */
6813struct acert_dir_print_t {
6814 const char * pfx;
6815 const byte tag[3];
6816};
6817
6818static struct acert_dir_print_t acert_dir_print[ACERT_NUM_DIR_TAGS] =
6819{
6820 { "C=", {0x55, 0x04, ASN_COUNTRY_NAME} },
6821 { "O=", {0x55, 0x04, ASN_ORG_NAME} },
6822 { "OU=", {0x55, 0x04, ASN_ORGUNIT_NAME} },
6823 { "CN=", {0x55, 0x04, ASN_COMMON_NAME} },
6824};
6825
6826/* Print an entry of ASN_DIR_TYPE into dst of length max_len.
6827 *
6828 * Returns total_len of str on success.
6829 * Returns < 0 on failure.
6830 * */
6831static int X509PrintDirType(char * dst, int max_len, const DNS_entry * entry)
6832{
6833 word32 k = 0;
6834 word32 i = 0;
6835 const char * src = entry->name;
6836 word32 src_len = (word32)XSTRLEN(src);
6837 int total_len = 0;
6838 int bytes_left = max_len;
6839 int fld_len = 0;
6840 int match_found = 0;
6841
6842 XMEMSET(dst, 0, max_len);
6843
6844 /* loop over printable DIR tags. */
6845 for (k = 0; k < ACERT_NUM_DIR_TAGS; ++k) {
6846 const char * pfx = acert_dir_print[k].pfx;
6847 const byte * tag = acert_dir_print[k].tag;
6848 byte asn_tag;
6849
6850 /* walk through entry looking for matches. */
6851 for (i = 0; i < src_len - 5; ++i) {
6852 if (XMEMCMP(tag, &src[i], 3) == 0) {
6853 if (bytes_left < 5) {
6854 /* Not enough space left for name oid + tag + len. */
6855 break;
6856 }
6857
6858 if (match_found) {
6859 /* append a {',', ' '} before doing anything else. */
6860 *dst++ = ',';
6861 *dst++ = ' ';
6862 total_len += 2;
6863 bytes_left -= 2;
6864 }
6865
6866 i += 3;
6867
6868 /* Get the ASN Tag. */
6869 if (GetASNTag((const byte *)src, &i, &asn_tag, src_len) < 0) {
6870 WOLFSSL_MSG("error: GetASNTag failed");
6871 break;
6872 }
6873
6874 /* Check it is printable. */
6875 if ((asn_tag != ASN_PRINTABLE_STRING) &&
6876 (asn_tag != ASN_IA5_STRING) &&
6877 (asn_tag != ASN_UTF8STRING)) {
6878 /* Don't know what this is but we can't print it. */
6879 WOLFSSL_MSG("error: asn tag not printable string");
6880 break;
6881 }
6882
6883 /* Now get the length of the printable string. */
6884 if (GetLength((const byte *)src, &i, &fld_len, src_len) < 0) {
6885 break;
6886 }
6887
6888 /* Make sure we have space to fit it. */
6889 if ((int) XSTRLEN(pfx) > bytes_left) {
6890 /* Not enough space left. */
6891 break;
6892 }
6893
6894 /* Copy it in, decrement available space. */
6895 XSTRNCPY(dst, pfx, bytes_left);
6896 dst += XSTRLEN(pfx);
6897 total_len += (int)XSTRLEN(pfx);
6898 bytes_left -= (int)XSTRLEN(pfx);
6899
6900 if (fld_len > bytes_left) {
6901 /* Not enough space left. */
6902 break;
6903 }
6904
6905 XMEMCPY(dst, &src[i], fld_len);
6906 i += fld_len;
6907 dst += fld_len;
6908 total_len += fld_len;
6909 bytes_left -= fld_len;
6910
6911 match_found = 1;
6912 }
6913 }
6914 }
6915
6916 return total_len;
6917}
6918static int X509_print_name_entry(WOLFSSL_BIO* bio,
6919 const DNS_entry* entry, int indent)
6920{
6921 int ret = WOLFSSL_SUCCESS;
6922 int nameCount = 0;
6923 char scratch[MAX_WIDTH];
6924 int len;
6925
6926 if (bio == NULL || entry == NULL) {
6927 return WOLFSSL_FAILURE;
6928 }
6929
6930 len = XSNPRINTF(scratch, MAX_WIDTH, "%*s", indent, "");
6931 if (len >= MAX_WIDTH) {
6932 return WOLFSSL_FAILURE;
6933 }
6934
6935 if (wolfSSL_BIO_write(bio, scratch, (int)XSTRLEN(scratch)) <= 0) {
6936 return WOLFSSL_FAILURE;
6937 }
6938
6939 while (entry != NULL) {
6940 ++nameCount;
6941 if (nameCount > 1) {
6942 if (wolfSSL_BIO_write(bio, ", ", 2) <= 0) {
6943 ret = WOLFSSL_FAILURE;
6944 break;
6945 }
6946 }
6947
6948 if (entry->type == ASN_DNS_TYPE) {
6949 len = XSNPRINTF(scratch, MAX_WIDTH, "DNS:%s", entry->name);
6950 }
6951 #if defined(OPENSSL_ALL) || defined(WOLFSSL_IP_ALT_NAME)
6952 else if (entry->type == ASN_IP_TYPE) {
6953 len = XSNPRINTF(scratch, MAX_WIDTH, "IP Address:%s",
6954 entry->ipString);
6955 }
6956 #else
6957 else if (entry->type == ASN_IP_TYPE) {
6958 /* iPAddress entries are now always parsed into altNames so
6959 * name constraints can be enforced. Without the
6960 * human-readable ipString field, emit a fixed label so this
6961 * print path does not fail. */
6962 len = XSNPRINTF(scratch, MAX_WIDTH, "IP Address:<unavailable>");
6963 }
6964 #endif /* OPENSSL_ALL || WOLFSSL_IP_ALT_NAME */
6965 else if (entry->type == ASN_RFC822_TYPE) {
6966 len = XSNPRINTF(scratch, MAX_WIDTH, "email:%s",
6967 entry->name);
6968 }
6969 else if (entry->type == ASN_DIR_TYPE) {
6970 len = X509PrintDirType(scratch, MAX_WIDTH, entry);
6971 }
6972 else if (entry->type == ASN_URI_TYPE) {
6973 len = XSNPRINTF(scratch, MAX_WIDTH, "URI:%s",
6974 entry->name);
6975 }
6976 #ifdef WOLFSSL_RID_ALT_NAME
6977 else if (entry->type == ASN_RID_TYPE) {
6978 len = XSNPRINTF(scratch, MAX_WIDTH, "Registered ID:%s",
6979 entry->ridString);
6980 }
6981 #else
6982 else if (entry->type == ASN_RID_TYPE) {
6983 /* registeredID entries are now always parsed into altNames
6984 * so name constraints can be enforced. Without the
6985 * human-readable ridString field, emit a fixed label so
6986 * this print path does not fail. */
6987 len = XSNPRINTF(scratch, MAX_WIDTH, "Registered ID:<unavailable>");
6988 }
6989 #endif /* WOLFSSL_RID_ALT_NAME */
6990 else if (entry->type == ASN_OTHER_TYPE) {
6991 len = XSNPRINTF(scratch, MAX_WIDTH,
6992 "othername <unsupported>");
6993 }
6994 else {
6995 WOLFSSL_MSG("Bad alt name type.");
6996 ret = WOLFSSL_FAILURE;
6997 break;
6998 }
6999 if (len >= MAX_WIDTH) {
7000 ret = WOLFSSL_FAILURE;
7001 break;
7002 }
7003 if (wolfSSL_BIO_write(bio, scratch, (int)XSTRLEN(scratch))
7004 <= 0) {
7005 ret = WOLFSSL_FAILURE;
7006 break;
7007 }
7008
7009 entry = entry->next;
7010 }
7011
7012 if (ret == WOLFSSL_SUCCESS && wolfSSL_BIO_write(bio, "\n", 1) <= 0) {
7013 ret = WOLFSSL_FAILURE;
7014 }
7015
7016 return ret;
7017}
7018
7019#ifdef XSNPRINTF
7020static int X509PrintKeyUsage(WOLFSSL_BIO* bio, WOLFSSL_X509* x509, int indent)
7021{
7022 int ret = WOLFSSL_SUCCESS;
7023 const int usages[] = {
7024 KEYUSE_DIGITAL_SIG,
7025 KEYUSE_CONTENT_COMMIT,
7026 KEYUSE_KEY_ENCIPHER,
7027 KEYUSE_DATA_ENCIPHER,
7028 KEYUSE_KEY_AGREE,
7029 KEYUSE_KEY_CERT_SIGN,
7030 KEYUSE_CRL_SIGN,
7031 KEYUSE_ENCIPHER_ONLY,
7032 KEYUSE_DECIPHER_ONLY
7033 };
7034 const char* usageStrs[] = {
7035 "Digital Signature",
7036 "Non Repudiation",
7037 "Key Encipherment",
7038 "Data Encipherment",
7039 "Key Agreement",
7040 "Certificate Sign",
7041 "CRL Sign",
7042 "Encipher Only",
7043 "Decipher Only"
7044 };
7045
7046 if (indent < 0) indent = 0;
7047 if (indent > MAX_INDENT) indent = MAX_INDENT;
7048
7049 if (bio == NULL || x509 == NULL) {
7050 ret = WOLFSSL_FAILURE;
7051 }
7052
7053 if (ret == WOLFSSL_SUCCESS && x509->keyUsageSet && x509->keyUsage != 0) {
7054 char scratch[MAX_WIDTH];
7055 int len;
7056 word32 i = 0;
7057 int usageCount = 0;
7058
7059 len = XSNPRINTF(scratch, MAX_WIDTH, "%*s", indent, "");
7060 if (len >= MAX_WIDTH)
7061 ret = WOLFSSL_FAILURE;
7062 if (ret == WOLFSSL_SUCCESS) {
7063 if (wolfSSL_BIO_write(bio, scratch, (int)XSTRLEN(scratch)) <= 0) {
7064 ret = WOLFSSL_FAILURE;
7065 }
7066 }
7067 for (; ret == WOLFSSL_SUCCESS && i < sizeof(usages) / sizeof(usages[i]);
7068 i++) {
7069 if (x509->keyUsage & usages[i]) {
7070 ++usageCount;
7071 if (usageCount > 1 && wolfSSL_BIO_write(bio, ", ", 2) <= 0) {
7072 ret = WOLFSSL_FAILURE;
7073 break;
7074 }
7075 if (wolfSSL_BIO_write(bio, usageStrs[i],
7076 (int)XSTRLEN(usageStrs[i])) <= 0) {
7077 ret = WOLFSSL_FAILURE;
7078 break;
7079 }
7080 }
7081 }
7082 if (ret == WOLFSSL_SUCCESS && wolfSSL_BIO_write(bio, "\n", 1) <= 0) {
7083 ret = WOLFSSL_FAILURE;
7084 }
7085 }
7086
7087 return ret;
7088}
7089
7090static int X509PrintExtendedKeyUsage(WOLFSSL_BIO* bio, WOLFSSL_X509* x509,
7091 int indent)
7092{
7093 int ret = WOLFSSL_SUCCESS;
7094 const int usages[] = {
7095 EXTKEYUSE_OCSP_SIGN,
7096 EXTKEYUSE_TIMESTAMP,
7097 EXTKEYUSE_EMAILPROT,
7098 EXTKEYUSE_CODESIGN,
7099 EXTKEYUSE_CLIENT_AUTH,
7100 EXTKEYUSE_SERVER_AUTH
7101 };
7102 const char* usageStrs[] = {
7103 "OCSP Signing",
7104 "Time Stamping",
7105 "E-mail Protection",
7106 "Code Signing",
7107 "TLS Web Client Authentication",
7108 "TLS Web Server Authentication"
7109 };
7110
7111 if (bio == NULL || x509 == NULL) {
7112 ret = WOLFSSL_FAILURE;
7113 }
7114
7115 if (ret == WOLFSSL_SUCCESS && x509->extKeyUsageCount > 0
7116 && x509->extKeyUsage != 0) {
7117 char scratch[MAX_WIDTH];
7118 int len;
7119 word32 i = 0;
7120 int usageCount = 0;
7121
7122 len = XSNPRINTF(scratch, MAX_WIDTH, "%*s", indent, "");
7123 if (len >= MAX_WIDTH)
7124 ret = WOLFSSL_FAILURE;
7125 if (ret == WOLFSSL_SUCCESS) {
7126 if (wolfSSL_BIO_write(bio, scratch, (int)XSTRLEN(scratch)) <= 0) {
7127 ret = WOLFSSL_FAILURE;
7128 }
7129 }
7130 for (; ret == WOLFSSL_SUCCESS && i < sizeof(usages) / sizeof(usages[i]);
7131 i++) {
7132 if (x509->extKeyUsage & usages[i]) {
7133 ++usageCount;
7134 if (usageCount > 1 && wolfSSL_BIO_write(bio, ", ", 2) <= 0) {
7135 ret = WOLFSSL_FAILURE;
7136 break;
7137 }
7138 if (wolfSSL_BIO_write(bio, usageStrs[i],
7139 (int)XSTRLEN(usageStrs[i])) <= 0) {
7140 ret = WOLFSSL_FAILURE;
7141 break;
7142 }
7143 }
7144 }
7145 if (ret == WOLFSSL_SUCCESS && wolfSSL_BIO_write(bio, "\n", 1) <= 0) {
7146 ret = WOLFSSL_FAILURE;
7147 }
7148 }
7149
7150 return ret;
7151}
7152
7153
7154/* print serial number out
7155 * return WOLFSSL_SUCCESS on success
7156 */
7157static int X509PrintSerial_ex(WOLFSSL_BIO* bio, byte* serial, int sz,
7158 int delimiter, int indent)
7159{
7160 char scratch[MAX_WIDTH];
7161 const int scratchSz = sizeof(scratch);
7162 int scratchLen;
7163
7164 if ((scratchLen = XSNPRINTF(scratch, MAX_WIDTH, "%*sSerial Number:",
7165 indent, "")) >= MAX_WIDTH) {
7166 WOLFSSL_MSG("buffer overrun");
7167 return WOLFSSL_FAILURE;
7168 }
7169 if (wolfSSL_BIO_write(bio, scratch, scratchLen) <= 0) {
7170 return WOLFSSL_FAILURE;
7171 }
7172
7173 if (sz > (int)sizeof(byte)) {
7174 int i;
7175
7176 /* serial is larger than int size so print off hex values */
7177 if ((scratchLen = XSNPRINTF(
7178 scratch, MAX_WIDTH, "\n%*s", indent + 4, ""))
7179 >= MAX_WIDTH) {
7180 WOLFSSL_MSG("buffer overrun");
7181 return WOLFSSL_FAILURE;
7182 }
7183 for (i = 0; i < sz; i++) {
7184 int valLen;
7185
7186 if ((valLen = XSNPRINTF(
7187 scratch + scratchLen, scratchSz - scratchLen,
7188 "%02x%s", serial[i], (i < sz - 1) ?
7189 (delimiter ? ":" : "") : "\n"))
7190 >= scratchSz - scratchLen) {
7191 WOLFSSL_MSG("buffer overrun");
7192 return WOLFSSL_FAILURE;
7193 }
7194 scratchLen += valLen;
7195 }
7196 if (wolfSSL_BIO_write(bio, scratch, scratchLen) <= 0) {
7197 return WOLFSSL_FAILURE;
7198 }
7199 }
7200
7201 /* if serial can fit into byte then print on the same line */
7202 else {
7203 if ((scratchLen = XSNPRINTF(scratch, MAX_WIDTH, " %d (0x%x)\n",
7204 (char)serial[0], serial[0])) >= MAX_WIDTH) {
7205 WOLFSSL_MSG("buffer overrun");
7206 return WOLFSSL_FAILURE;
7207 }
7208 if (wolfSSL_BIO_write(bio, scratch, scratchLen) <= 0) {
7209 return WOLFSSL_FAILURE;
7210 }
7211 }
7212 return WOLFSSL_SUCCESS;
7213}
7214
7215static int X509PrintSerial(WOLFSSL_BIO* bio, WOLFSSL_X509* x509, int indent)
7216{
7217 unsigned char serial[32];
7218 int sz = sizeof(serial);
7219
7220 if (indent < 0) indent = 0;
7221 if (indent > MAX_INDENT) indent = MAX_INDENT;
7222
7223 XMEMSET(serial, 0, sz);
7224 if (wolfSSL_X509_get_serial_number(x509, serial, &sz) == WOLFSSL_SUCCESS) {
7225 X509PrintSerial_ex(bio, serial, sz, 1, indent);
7226 }
7227 return WOLFSSL_SUCCESS;
7228}
7229
7230#ifndef NO_ASN_TIME
7231static int X509PrintValidity(WOLFSSL_BIO* bio, WOLFSSL_ASN1_TIME * notBefore,
7232 WOLFSSL_ASN1_TIME * notAfter, int indent)
7233{
7234 char tmp[80];
7235 (void) indent;
7236
7237 if (wolfSSL_BIO_write(bio, " Validity\n",
7238 (int)XSTRLEN(" Validity\n")) <= 0) {
7239 return WOLFSSL_FAILURE;
7240 }
7241
7242 if (wolfSSL_BIO_write(bio, " Not Before: ",
7243 (int)XSTRLEN(" Not Before: ")) <= 0) {
7244 return WOLFSSL_FAILURE;
7245 }
7246 if (notBefore->length > 0) {
7247 if (GetTimeString(notBefore->data, ASN_UTC_TIME,
7248 tmp, sizeof(tmp), notBefore->length) != WOLFSSL_SUCCESS) {
7249 if (GetTimeString(notBefore->data, ASN_GENERALIZED_TIME,
7250 tmp, sizeof(tmp), notBefore->length) != WOLFSSL_SUCCESS) {
7251 WOLFSSL_MSG("Error getting not before date");
7252 return WOLFSSL_FAILURE;
7253 }
7254 }
7255 }
7256 else {
7257 XSTRNCPY(tmp, "Not Set", sizeof(tmp)-1);
7258 }
7259 tmp[sizeof(tmp) - 1] = '\0'; /* make sure null terminated */
7260 if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
7261 return WOLFSSL_FAILURE;
7262 }
7263
7264 if (wolfSSL_BIO_write(bio, "\n Not After : ",
7265 (int)XSTRLEN("\n Not After : ")) <= 0) {
7266 return WOLFSSL_FAILURE;
7267 }
7268 if (notAfter->length > 0) {
7269 if (GetTimeString(notAfter->data, ASN_UTC_TIME,
7270 tmp, sizeof(tmp), notAfter->length) != WOLFSSL_SUCCESS) {
7271 if (GetTimeString(notAfter->data, ASN_GENERALIZED_TIME,
7272 tmp, sizeof(tmp), notAfter->length) != WOLFSSL_SUCCESS) {
7273 WOLFSSL_MSG("Error getting not after date");
7274 return WOLFSSL_FAILURE;
7275 }
7276 }
7277 }
7278 else {
7279 XSTRNCPY(tmp, "Not Set", sizeof(tmp)-1);
7280 }
7281 tmp[sizeof(tmp) - 1] = '\0'; /* make sure null terminated */
7282 if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
7283 return WOLFSSL_FAILURE;
7284 }
7285
7286 if (wolfSSL_BIO_write(bio, "\n\0", (int)XSTRLEN("\n\0")) <= 0) {
7287 return WOLFSSL_FAILURE;
7288 }
7289
7290 return WOLFSSL_SUCCESS;
7291}
7292#endif /* ifndef NO_ASN_TIME */
7293
7294static int X509PrintSubjAltName(WOLFSSL_BIO* bio, WOLFSSL_X509* x509,
7295 int indent)
7296{
7297 if (!x509 || !x509->altNames || !x509->subjAltNameSet)
7298 return WOLFSSL_FAILURE;
7299 return X509_print_name_entry(bio, x509->altNames, indent);
7300}
7301
7302/* iterate through certificate extensions printing them out in human readable
7303 * form
7304 * return WOLFSSL_SUCCESS on success
7305 */
7306static int X509PrintExtensions(WOLFSSL_BIO* bio, WOLFSSL_X509* x509, int indent)
7307{
7308 int ret = WOLFSSL_SUCCESS;
7309 char scratch[MAX_WIDTH];
7310 const int scratchSz = sizeof(scratch);
7311 int scratchLen;
7312 int count, i;
7313 char* buf = NULL;
7314
7315 if (indent < 0) indent = 0;
7316 if (indent > MAX_INDENT) indent = MAX_INDENT;
7317
7318 count = wolfSSL_X509_get_ext_count(x509);
7319 if (count <= 0)
7320 return WOLFSSL_SUCCESS;
7321
7322#ifdef WOLFSSL_CERT_REQ
7323 if (x509->isCSR) {
7324 if ((scratchLen = XSNPRINTF(scratch, MAX_WIDTH, "%*s%s\n", indent, "",
7325 "Requested extensions:")) >= MAX_WIDTH) {
7326 return WOLFSSL_FAILURE;
7327 }
7328 }
7329 else
7330#endif
7331 {
7332 if ((scratchLen = XSNPRINTF(scratch, MAX_WIDTH, "%*s%s\n", indent, "",
7333 "X509v3 extensions:")) >= MAX_WIDTH) {
7334 return WOLFSSL_FAILURE;
7335 }
7336 }
7337 if (wolfSSL_BIO_write(bio, scratch, scratchLen) <= 0) {
7338 return WOLFSSL_FAILURE;
7339 }
7340
7341 buf = (char*)XMALLOC(MAX_WIDTH, x509->heap, DYNAMIC_TYPE_TMP_BUFFER);
7342 if (buf == NULL) {
7343 return WOLFSSL_FAILURE;
7344 }
7345
7346 for (i = 0; (i < count) && (ret != WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); i++) {
7347 WOLFSSL_X509_EXTENSION* ext;
7348
7349 ext = wolfSSL_X509_get_ext(x509, i);
7350 if (ext != NULL) {
7351 WOLFSSL_ASN1_OBJECT* obj;
7352 int nid;
7353 char val[6];
7354 int valLen;
7355 word32 j;
7356
7357 obj = wolfSSL_X509_EXTENSION_get_object(ext);
7358 if (obj == NULL) {
7359 ret = WOLFSSL_FAILURE;
7360 break;
7361 }
7362 if (wolfSSL_OBJ_obj2txt(buf, MAX_WIDTH, obj, 0)
7363 == WC_NO_ERR_TRACE(WOLFSSL_FAILURE))
7364 {
7365 ret = WOLFSSL_FAILURE;
7366 break;
7367 }
7368 if ((scratchLen = XSNPRINTF(
7369 scratch, MAX_WIDTH, "%*s%s%s\n", indent + 4, "",
7370 buf,
7371 (wolfSSL_X509_EXTENSION_get_critical(ext)
7372 ? ": critical"
7373 : ": ")))
7374 >= MAX_WIDTH)
7375 {
7376 ret = WOLFSSL_FAILURE;
7377 break;
7378 }
7379
7380 if (wolfSSL_BIO_write(bio, scratch, scratchLen) <= 0) {
7381 ret = WOLFSSL_FAILURE;
7382 break;
7383 }
7384 nid = wolfSSL_OBJ_obj2nid(obj);
7385 switch (nid) {
7386 case WC_NID_subject_alt_name:
7387 ret = X509PrintSubjAltName(bio, x509, indent + 8);
7388 break;
7389
7390 case WC_NID_subject_key_identifier:
7391 if (!x509->subjKeyIdSet || x509->subjKeyId == NULL ||
7392 x509->subjKeyIdSz == 0)
7393 {
7394 ret = WOLFSSL_FAILURE;
7395 break;
7396 }
7397
7398 if ((scratchLen = XSNPRINTF(
7399 scratch, scratchSz,
7400 "%*s", indent + 8, "")) >= scratchSz)
7401 {
7402 ret = WOLFSSL_FAILURE;
7403 break;
7404 }
7405 for (j = 0; j < x509->subjKeyIdSz; j++) {
7406 if ((valLen = XSNPRINTF(
7407 val, sizeof(val), "%02X%s",
7408 x509->subjKeyId[j],
7409 (j < x509->subjKeyIdSz - 1) ? ":" : "\n"))
7410 >= (int)sizeof(val))
7411 {
7412 ret = WOLFSSL_FAILURE;
7413 break;
7414 }
7415 if (scratchLen + valLen >= scratchSz) {
7416 if (wolfSSL_BIO_write(bio, scratch,
7417 scratchLen) <= 0) {
7418 ret = WOLFSSL_FAILURE;
7419 break;
7420 }
7421 scratchLen = 0;
7422 }
7423 XMEMCPY(scratch + scratchLen, val, valLen);
7424 scratchLen += valLen;
7425 }
7426 if (ret == WC_NO_ERR_TRACE(WOLFSSL_FAILURE))
7427 break;
7428 if (wolfSSL_BIO_write(bio, scratch,
7429 scratchLen) <= 0) {
7430 ret = WOLFSSL_FAILURE;
7431 break;
7432 }
7433 break;
7434
7435 case WC_NID_authority_key_identifier:
7436 if (!x509->authKeyIdSet || x509->authKeyId == NULL ||
7437 x509->authKeyIdSz == 0) {
7438 ret = WOLFSSL_FAILURE;
7439 break;
7440 }
7441
7442 if ((scratchLen = XSNPRINTF(
7443 scratch, scratchSz, "%*s%s",
7444 indent + 8, "", "keyid:")) >= scratchSz)
7445 {
7446 ret = WOLFSSL_FAILURE;
7447 break;
7448 }
7449 for (j = 0; j < x509->authKeyIdSz; j++) {
7450 if ((valLen = XSNPRINTF(
7451 val, sizeof(val), "%02X%s",
7452 x509->authKeyId[j],
7453 (j < x509->authKeyIdSz - 1) ? ":" : "\n\n"))
7454 >= (int)sizeof(val))
7455 {
7456 ret = WOLFSSL_FAILURE;
7457 break;
7458 }
7459 if (scratchLen >= scratchSz - valLen) {
7460 if (wolfSSL_BIO_write(bio, scratch,
7461 scratchLen) <= 0)
7462 {
7463 ret = WOLFSSL_FAILURE;
7464 break;
7465 }
7466 scratchLen = 0;
7467 }
7468 if (scratchLen + valLen >= scratchSz) {
7469 ret = WOLFSSL_FAILURE;
7470 break;
7471 }
7472 XMEMCPY(scratch + scratchLen, val, valLen);
7473 scratchLen += valLen;
7474 }
7475 if (ret == WC_NO_ERR_TRACE(WOLFSSL_FAILURE))
7476 break;
7477 if (wolfSSL_BIO_write(bio, scratch,
7478 scratchLen) <= 0) {
7479 ret = WOLFSSL_FAILURE;
7480 break;
7481 }
7482 break;
7483
7484 case WC_NID_basic_constraints:
7485 if (!x509->basicConstSet) {
7486 ret = WOLFSSL_FAILURE;
7487 break;
7488 }
7489 if ((scratchLen = XSNPRINTF(
7490 scratch, scratchSz,
7491 "%*sCA:%s\n",
7492 indent + 8, "", (x509->isCa)? "TRUE": "FALSE"))
7493 >= scratchSz)
7494 {
7495 ret = WOLFSSL_FAILURE;
7496 break;
7497 }
7498 if (wolfSSL_BIO_write(bio, scratch,
7499 scratchLen) <= 0) {
7500 ret = WOLFSSL_FAILURE;
7501 break;
7502 }
7503 break;
7504
7505 case WC_NID_key_usage:
7506 ret = X509PrintKeyUsage(bio, x509, indent + 8);
7507 break;
7508
7509 case WC_NID_ext_key_usage:
7510 ret = X509PrintExtendedKeyUsage(bio, x509, indent + 8);
7511 break;
7512
7513 default:
7514 /* extension nid not yet supported */
7515 if ((scratchLen = XSNPRINTF(
7516 scratch, MAX_WIDTH,
7517 "%*sNID %d print not yet supported\n",
7518 indent + 8, "", nid)) >= MAX_WIDTH)
7519 {
7520 ret = WOLFSSL_FAILURE;
7521 break;
7522 }
7523
7524 if (wolfSSL_BIO_write(bio, scratch, scratchLen) <= 0) {
7525 ret = WOLFSSL_FAILURE;
7526 break;
7527 }
7528 }
7529 }
7530 }
7531
7532 XFREE(buf, x509->heap, DYNAMIC_TYPE_TMP_BUFFER);
7533
7534 return ret;
7535}
7536
7537
7538/* print out the signature in human readable format for use with
7539 * wolfSSL_X509_print()
7540 * return WOLFSSL_SUCCESS on success
7541 */
7542static int X509PrintSignature_ex(WOLFSSL_BIO* bio, byte* sig,
7543 int sigSz, int sigNid, int algOnly, int indent)
7544{
7545 char scratch[MAX_WIDTH];
7546 int scratchLen;
7547 WOLFSSL_ASN1_OBJECT* obj = NULL;
7548 int ret = WOLFSSL_SUCCESS;
7549 char tmp[100];
7550 int tmpLen = 0;
7551
7552 if (sigSz <= 0) {
7553 return WOLFSSL_SUCCESS;
7554 }
7555
7556 if ((scratchLen = XSNPRINTF(scratch, MAX_WIDTH, "%*s%s", indent, "",
7557 "Signature Algorithm: ")) >= MAX_WIDTH) {
7558 ret = WOLFSSL_FAILURE;
7559 }
7560
7561 if (ret == WOLFSSL_SUCCESS) {
7562 if (wolfSSL_BIO_write(bio, scratch, scratchLen) <= 0)
7563 ret = WOLFSSL_FAILURE;
7564 }
7565
7566 if (ret == WOLFSSL_SUCCESS) {
7567 obj = wolfSSL_OBJ_nid2obj(sigNid);
7568 if (obj == NULL)
7569 ret = WOLFSSL_FAILURE;
7570 }
7571 if (ret == WOLFSSL_SUCCESS) {
7572 if (wolfSSL_OBJ_obj2txt(scratch, MAX_WIDTH, obj, 0)
7573 == WC_NO_ERR_TRACE(WOLFSSL_FAILURE))
7574 {
7575 ret = WOLFSSL_FAILURE;
7576 }
7577 }
7578
7579 if (ret == WOLFSSL_SUCCESS) {
7580 if ((tmpLen = XSNPRINTF(tmp, sizeof(tmp),"%s\n", scratch))
7581 >= (int)sizeof(tmp))
7582 {
7583 ret = WOLFSSL_FAILURE;
7584 }
7585 }
7586 if (ret == WOLFSSL_SUCCESS) {
7587 if (wolfSSL_BIO_write(bio, tmp, tmpLen) <= 0)
7588 ret = WOLFSSL_FAILURE;
7589 }
7590
7591 /* Leave function if the desired content to print
7592 * is only the signature algorithm */
7593 if (algOnly) {
7594 if (obj != NULL)
7595 wolfSSL_ASN1_OBJECT_free(obj);
7596
7597 return ret;
7598 }
7599
7600 if (ret == WOLFSSL_SUCCESS) {
7601 if ((tmpLen = XSNPRINTF(tmp, sizeof(tmp), "%*s", indent + 5, ""))
7602 >= (int)sizeof(tmp))
7603 {
7604 ret = WOLFSSL_FAILURE;
7605 }
7606 }
7607
7608 if (ret == WOLFSSL_SUCCESS) {
7609 int i;
7610
7611 for (i = 0; i < sigSz; i++) {
7612 char val[6];
7613 int valLen;
7614
7615 if (i == 0) {
7616 if ((valLen = XSNPRINTF(val, sizeof(val), "%02x", sig[i]))
7617 >= (int)sizeof(val))
7618 {
7619 ret = WOLFSSL_FAILURE;
7620 break;
7621 }
7622 }
7623 else if (((i % 18) == 0)) {
7624 if (wolfSSL_BIO_write(bio, tmp, tmpLen)
7625 <= 0) {
7626 ret = WOLFSSL_FAILURE;
7627 break;
7628 }
7629 if ((tmpLen = XSNPRINTF(tmp, sizeof(tmp), ":\n%*s",
7630 indent + 5, ""))
7631 >= (int)sizeof(tmp))
7632 {
7633 ret = WOLFSSL_FAILURE;
7634 break;
7635 }
7636 if ((valLen = XSNPRINTF(val, sizeof(val), "%02x", sig[i]))
7637 >= (int)sizeof(val))
7638 {
7639 ret = WOLFSSL_FAILURE;
7640 break;
7641 }
7642 }
7643 else {
7644 if ((valLen = XSNPRINTF(val, sizeof(val), ":%02x", sig[i]))
7645 >= (int)sizeof(val))
7646 {
7647 ret = WOLFSSL_FAILURE;
7648 break;
7649 }
7650 }
7651 if ((tmpLen < 0) || (valLen < 0) ||
7652 (valLen >= ((int)sizeof(tmp) - tmpLen - 1))) {
7653 ret = WOLFSSL_FAILURE;
7654 break;
7655 }
7656 XMEMCPY(tmp + tmpLen, val, valLen);
7657 tmpLen += valLen;
7658 tmp[tmpLen] = 0;
7659 }
7660 }
7661
7662 /* print out remaining sig values */
7663 if (ret == WOLFSSL_SUCCESS) {
7664 if (tmpLen > 0) {
7665 if (wolfSSL_BIO_write(bio, tmp, tmpLen)
7666 <= 0)
7667 {
7668 ret = WOLFSSL_FAILURE;
7669 }
7670 }
7671 }
7672
7673 if (obj != NULL)
7674 wolfSSL_ASN1_OBJECT_free(obj);
7675
7676 return ret;
7677}
7678
7679static int X509PrintSignature(WOLFSSL_BIO* bio, WOLFSSL_X509* x509,
7680 int algOnly, int indent)
7681{
7682 int sigSz = 0;
7683 if (wolfSSL_X509_get_signature(x509, NULL, &sigSz) <= 0) {
7684 return WOLFSSL_FAILURE;
7685 }
7686
7687 if (sigSz > 0) {
7688 unsigned char* sig;
7689 int sigNid;
7690
7691 sigNid = wolfSSL_X509_get_signature_nid(x509);
7692 if (sigNid <= 0) {
7693 return WOLFSSL_FAILURE;
7694 }
7695
7696 sig = (unsigned char*)XMALLOC(sigSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
7697 if (sig == NULL) {
7698 return WOLFSSL_FAILURE;
7699 }
7700
7701 if (wolfSSL_X509_get_signature(x509, sig, &sigSz) <= 0) {
7702 XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
7703 return WOLFSSL_FAILURE;
7704 }
7705
7706 if (X509PrintSignature_ex(bio, sig, sigSz, sigNid, algOnly, indent)
7707 != WOLFSSL_SUCCESS) {
7708 XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
7709 return WOLFSSL_FAILURE;
7710 }
7711
7712 XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
7713
7714 }
7715
7716 return WOLFSSL_SUCCESS;
7717}
7718
7719
7720/* print out the public key in human readable format for use with
7721 * wolfSSL_X509_print()
7722 * return WOLFSSL_SUCCESS on success
7723 */
7724static int X509PrintPubKey(WOLFSSL_BIO* bio, WOLFSSL_X509* x509, int indent)
7725{
7726 char scratch[MAX_WIDTH];
7727 WOLFSSL_EVP_PKEY* pubKey;
7728 int len;
7729 int ret = WOLFSSL_SUCCESS;
7730
7731 if (indent < 0) indent = 0;
7732 if (indent > MAX_INDENT) indent = MAX_INDENT;
7733
7734 if (bio == NULL || x509 == NULL)
7735 return BAD_FUNC_ARG;
7736
7737 len = XSNPRINTF(scratch, MAX_WIDTH, "%*sSubject Public Key Info:\n", indent,
7738 "");
7739 if (len >= MAX_WIDTH)
7740 return WOLFSSL_FAILURE;
7741 if (wolfSSL_BIO_write(bio, scratch, len) <= 0)
7742 return WOLFSSL_FAILURE;
7743
7744 switch (x509->pubKeyOID) {
7745 #ifndef NO_RSA
7746 case RSAk:
7747 len = XSNPRINTF(scratch, MAX_WIDTH,
7748 "%*sPublic Key Algorithm: rsaEncryption\n", indent + 4, "");
7749 if (len >= MAX_WIDTH)
7750 return WOLFSSL_FAILURE;
7751 if (wolfSSL_BIO_write(bio, scratch, len) <= 0)
7752 return WOLFSSL_FAILURE;
7753 break;
7754 #endif
7755 #ifdef HAVE_ECC
7756 case ECDSAk:
7757 len = XSNPRINTF(scratch, MAX_WIDTH,
7758 "%*sPublic Key Algorithm: EC\n", indent + 4, "");
7759 if ((len < 0) || (len >= MAX_WIDTH))
7760 return WOLFSSL_FAILURE;
7761 if (wolfSSL_BIO_write(bio, scratch, len) <= 0)
7762 return WOLFSSL_FAILURE;
7763 break;
7764 #endif
7765 default:
7766 WOLFSSL_MSG("Unknown key type");
7767 return WOLFSSL_FAILURE;
7768 }
7769
7770 pubKey = wolfSSL_X509_get_pubkey(x509);
7771 if (pubKey == NULL)
7772 return WOLFSSL_FAILURE;
7773
7774 ret = wolfSSL_EVP_PKEY_print_public(bio, pubKey, indent + 8, NULL);
7775
7776 wolfSSL_EVP_PKEY_free(pubKey);
7777
7778 return ret;
7779}
7780
7781
7782/* human readable print out of x509 name formatted for use with
7783 * wolfSSL_X509_print()
7784 * return WOLFSSL_SUCCESS on success
7785 */
7786static int X509PrintName(WOLFSSL_BIO* bio, WOLFSSL_X509_NAME* name,
7787 char* type, int indent)
7788{
7789 if (name != NULL) {
7790 char scratch[MAX_WIDTH];
7791 int scratchLen;
7792
7793 if ((scratchLen = XSNPRINTF(scratch, MAX_WIDTH,
7794 "%*s%s", indent, "", type))
7795 >= MAX_WIDTH)
7796 {
7797 return WOLFSSL_FAILURE;
7798 }
7799 if (wolfSSL_BIO_write(bio, scratch, scratchLen) <= 0) {
7800 return WOLFSSL_FAILURE;
7801 }
7802 if (wolfSSL_X509_NAME_print_ex(bio, name, 1, 0) <= 0) {
7803 return WOLFSSL_FAILURE;
7804 }
7805 if (wolfSSL_BIO_write(bio, "\n", (int)XSTRLEN("\n")) <= 0) {
7806 return WOLFSSL_FAILURE;
7807 }
7808 }
7809 return WOLFSSL_SUCCESS;
7810}
7811
7812
7813/* human readable print out of x509 version
7814 * return WOLFSSL_SUCCESS on success
7815 */
7816static int X509PrintVersion(WOLFSSL_BIO* bio, int version, int indent)
7817{
7818 char scratch[MAX_WIDTH];
7819 int scratchLen;
7820
7821 if (indent < 0) indent = 0;
7822 if (indent > MAX_INDENT) indent = MAX_INDENT;
7823
7824 scratchLen = XSNPRINTF(scratch, MAX_WIDTH, "%*s%s", indent, "", "Version:");
7825 if ((scratchLen < 0) || (scratchLen >= MAX_WIDTH)) {
7826 return WOLFSSL_FAILURE;
7827 }
7828
7829 if (wolfSSL_BIO_write(bio, scratch, scratchLen) <= 0) {
7830 return WOLFSSL_FAILURE;
7831 }
7832
7833 scratchLen = XSNPRINTF(scratch, MAX_WIDTH, " %d (0x%x)\n",
7834 version, (byte)version-1);
7835 if ((scratchLen < 0) || (scratchLen >= MAX_WIDTH)) {
7836 return WOLFSSL_FAILURE;
7837 }
7838
7839 if (wolfSSL_BIO_write(bio, scratch, scratchLen) <= 0) {
7840 return WOLFSSL_FAILURE;
7841 }
7842 return WOLFSSL_SUCCESS;
7843}
7844
7845#ifdef WOLFSSL_CERT_REQ
7846/* Print out of REQ attributes
7847 * return WOLFSSL_SUCCESS on success
7848 */
7849static int X509PrintReqAttributes(WOLFSSL_BIO* bio, WOLFSSL_X509* x509,
7850 int indent)
7851{
7852 WOLFSSL_X509_ATTRIBUTE* attr;
7853 char scratch[MAX_WIDTH];
7854 int scratchLen;
7855 int i = 0;
7856
7857 if (indent < 0) indent = 0;
7858 if (indent > MAX_INDENT) indent = MAX_INDENT;
7859
7860 if ((scratchLen = XSNPRINTF(scratch, MAX_WIDTH,
7861 "%*s%s", indent, "", "Attributes: \n"))
7862 >= MAX_WIDTH)
7863 {
7864 return WOLFSSL_FAILURE;
7865 }
7866 if (wolfSSL_BIO_write(bio, scratch, scratchLen) <= 0) {
7867 return WOLFSSL_FAILURE;
7868 }
7869 do {
7870 attr = wolfSSL_X509_REQ_get_attr(x509, i);
7871 if (attr != NULL) {
7872 char lName[NAME_SZ/4]; /* NAME_SZ default is 80 */
7873 int lNameSz = NAME_SZ/4;
7874 const byte* data;
7875
7876 if (wolfSSL_OBJ_obj2txt(lName, lNameSz, attr->object, 0)
7877 == WC_NO_ERR_TRACE(WOLFSSL_FAILURE))
7878 {
7879 return WOLFSSL_FAILURE;
7880 }
7881 lNameSz = (int)XSTRLEN(lName);
7882 data = wolfSSL_ASN1_STRING_get0_data(
7883 attr->value->value.asn1_string);
7884 if (data == NULL) {
7885 WOLFSSL_MSG("No REQ attribute found when expected");
7886 return WOLFSSL_FAILURE;
7887 }
7888 if ((scratchLen = XSNPRINTF(scratch, MAX_WIDTH,
7889 "%*s%s%*s:%s\n", indent+4, "",
7890 lName, (NAME_SZ/4)-lNameSz, "", data))
7891 >= MAX_WIDTH)
7892 {
7893 return WOLFSSL_FAILURE;
7894 }
7895 if (wolfSSL_BIO_write(bio, scratch, scratchLen) <= 0) {
7896 WOLFSSL_MSG("Error writing REQ attribute");
7897 return WOLFSSL_FAILURE;
7898 }
7899 }
7900 i++;
7901 } while (attr != NULL);
7902
7903 return WOLFSSL_SUCCESS;
7904}
7905
7906
7907/*
7908 * return WOLFSSL_SUCCESS on success
7909 */
7910int wolfSSL_X509_REQ_print(WOLFSSL_BIO* bio, WOLFSSL_X509* x509)
7911{
7912 char subjType[] = "Subject: ";
7913
7914 if (bio == NULL || x509 == NULL) {
7915 return WOLFSSL_FAILURE;
7916 }
7917
7918 if (wolfSSL_BIO_write(bio, "Certificate Request:\n",
7919 (int)XSTRLEN("Certificate Request:\n")) <= 0) {
7920 return WOLFSSL_FAILURE;
7921 }
7922
7923 if (wolfSSL_BIO_write(bio, " Data:\n",
7924 (int)XSTRLEN(" Data:\n")) <= 0) {
7925 return WOLFSSL_FAILURE;
7926 }
7927
7928 /* print version of cert. Note that we increment by 1 because for REQs,
7929 * the value stored in x509->version is the actual value of the field; not
7930 * the version. */
7931 if (X509PrintVersion(bio, (int)wolfSSL_X509_REQ_get_version(x509) + 1, 8)
7932 != WOLFSSL_SUCCESS) {
7933 return WOLFSSL_FAILURE;
7934 }
7935
7936 if (X509PrintSerial(bio, x509, 8) != WOLFSSL_SUCCESS) {
7937 return WOLFSSL_FAILURE;
7938 }
7939
7940 /* print subject */
7941 if (X509PrintName(bio, wolfSSL_X509_get_subject_name(x509), subjType, 8)
7942 != WOLFSSL_SUCCESS) {
7943 return WOLFSSL_FAILURE;
7944 }
7945
7946 /* get and print public key */
7947 if (X509PrintPubKey(bio, x509, 8) != WOLFSSL_SUCCESS) {
7948 return WOLFSSL_FAILURE;
7949 }
7950
7951 /* print out extensions */
7952 if (X509PrintExtensions(bio, x509, 4) != WOLFSSL_SUCCESS) {
7953 return WOLFSSL_FAILURE;
7954 }
7955
7956 /* print out req attributes */
7957 if (X509PrintReqAttributes(bio, x509, 4) != WOLFSSL_SUCCESS) {
7958 return WOLFSSL_FAILURE;
7959 }
7960
7961 /* print out signature */
7962 if (X509PrintSignature(bio, x509, 0, 4) != WOLFSSL_SUCCESS) {
7963 return WOLFSSL_FAILURE;
7964 }
7965
7966 /* done with print out */
7967 if (wolfSSL_BIO_write(bio, "\n\0", (int)XSTRLEN("\n\0")) <= 0) {
7968 return WOLFSSL_FAILURE;
7969 }
7970
7971 return WOLFSSL_SUCCESS;
7972}
7973#endif /* WOLFSSL_CERT_REQ */
7974
7975
7976/* Writes the human readable form of x509 to bio.
7977 *
7978 * bio WOLFSSL_BIO to write to.
7979 * x509 Certificate to write.
7980 *
7981 * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure
7982 */
7983int wolfSSL_X509_print_ex(WOLFSSL_BIO* bio, WOLFSSL_X509* x509,
7984 unsigned long nmflags, unsigned long cflag)
7985{
7986 char issuType[] = "Issuer:";
7987 char subjType[] = "Subject:";
7988
7989 WOLFSSL_ENTER("wolfSSL_X509_print_ex");
7990
7991 /* flags currently not supported */
7992 (void)nmflags;
7993 (void)cflag;
7994
7995 if (bio == NULL || x509 == NULL) {
7996 return WOLFSSL_FAILURE;
7997 }
7998
7999 if (wolfSSL_BIO_write(bio, "Certificate:\n",
8000 (int)XSTRLEN("Certificate:\n")) <= 0) {
8001 return WOLFSSL_FAILURE;
8002 }
8003
8004 if (wolfSSL_BIO_write(bio, " Data:\n",
8005 (int)XSTRLEN(" Data:\n")) <= 0) {
8006 return WOLFSSL_FAILURE;
8007 }
8008
8009 /* print version of cert */
8010 if (X509PrintVersion(bio, wolfSSL_X509_version(x509), 8)
8011 != WOLFSSL_SUCCESS) {
8012 return WOLFSSL_FAILURE;
8013 }
8014
8015 /* print serial number out */
8016 if (X509PrintSerial(bio, x509, 8) != WOLFSSL_SUCCESS) {
8017 return WOLFSSL_FAILURE;
8018 }
8019
8020 /* print out signature algo*/
8021 if (X509PrintSignature(bio, x509, 1, 8) != WOLFSSL_SUCCESS) {
8022 return WOLFSSL_FAILURE;
8023 }
8024
8025 /* print issuer */
8026 if (X509PrintName(bio, wolfSSL_X509_get_issuer_name(x509), issuType, 8)
8027 != WOLFSSL_SUCCESS) {
8028 return WOLFSSL_FAILURE;
8029 }
8030
8031 #ifndef NO_ASN_TIME
8032 /* print validity */
8033 if (X509PrintValidity(bio, &x509->notBefore, &x509->notAfter, 8)
8034 != WOLFSSL_SUCCESS) {
8035 return WOLFSSL_FAILURE;
8036 }
8037 #endif /* NO_ASN_TIME */
8038
8039 /* print subject */
8040 if (X509PrintName(bio, wolfSSL_X509_get_subject_name(x509), subjType, 8)
8041 != WOLFSSL_SUCCESS) {
8042 return WOLFSSL_FAILURE;
8043 }
8044
8045 /* get and print public key */
8046 if (X509PrintPubKey(bio, x509, 8) != WOLFSSL_SUCCESS) {
8047 return WOLFSSL_FAILURE;
8048 }
8049
8050 /* print out extensions */
8051 if (X509PrintExtensions(bio, x509, 8) != WOLFSSL_SUCCESS) {
8052 return WOLFSSL_FAILURE;
8053 }
8054
8055 /* print out signature */
8056 if (X509PrintSignature(bio, x509, 0, 4) != WOLFSSL_SUCCESS) {
8057 return WOLFSSL_FAILURE;
8058 }
8059
8060 /* done with print out */
8061 if (wolfSSL_BIO_write(bio, "\n\0", (int)XSTRLEN("\n\0")) <= 0) {
8062 return WOLFSSL_FAILURE;
8063 }
8064
8065 return WOLFSSL_SUCCESS;
8066}
8067int wolfSSL_X509_print(WOLFSSL_BIO* bio, WOLFSSL_X509* x509)
8068{
8069 return wolfSSL_X509_print_ex(bio, x509, 0, 0);
8070}
8071
8072#if defined(WOLFSSL_ACERT)
8073/* Retrieve sig NID from an ACERT.
8074 *
8075 * returns NID on success
8076 * returns 0 on failure
8077 */
8078int wolfSSL_X509_ACERT_get_signature_nid(const WOLFSSL_X509_ACERT *x509)
8079{
8080 if (x509 == NULL) {
8081 return 0;
8082 }
8083
8084 return oid2nid((word32)x509->sigOID, oidSigType);
8085}
8086
8087static int X509AcertPrintSignature(WOLFSSL_BIO* bio, WOLFSSL_X509_ACERT* x509,
8088 int algOnly, int indent)
8089{
8090 int sigSz = 0;
8091 if (wolfSSL_X509_ACERT_get_signature(x509, NULL, &sigSz) <= 0) {
8092 return WOLFSSL_FAILURE;
8093 }
8094
8095 if (sigSz > 0) {
8096 unsigned char* sig;
8097 int sigNid;
8098
8099 sigNid = wolfSSL_X509_ACERT_get_signature_nid(x509);
8100 if (sigNid <= 0) {
8101 return WOLFSSL_FAILURE;
8102 }
8103
8104 sig = (unsigned char*)XMALLOC(sigSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
8105 if (sig == NULL) {
8106 return WOLFSSL_FAILURE;
8107 }
8108
8109 if (wolfSSL_X509_ACERT_get_signature(x509, sig, &sigSz) <= 0) {
8110 XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
8111 return WOLFSSL_FAILURE;
8112 }
8113
8114 if (X509PrintSignature_ex(bio, sig, sigSz, sigNid, algOnly, indent)
8115 != WOLFSSL_SUCCESS) {
8116 XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
8117 return WOLFSSL_FAILURE;
8118 }
8119
8120 if (sig != NULL) {
8121 XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
8122 }
8123
8124 }
8125
8126 return WOLFSSL_SUCCESS;
8127}
8128
8129static int X509AcertPrintSerial(WOLFSSL_BIO* bio, WOLFSSL_X509_ACERT* x509,
8130 int indent)
8131{
8132 unsigned char serial[32];
8133 int sz = sizeof(serial);
8134
8135 XMEMSET(serial, 0, sz);
8136 if (wolfSSL_X509_ACERT_get_serial_number(x509, serial, &sz)
8137 == WOLFSSL_SUCCESS) {
8138 X509PrintSerial_ex(bio, serial, sz, 1, indent);
8139 }
8140 return WOLFSSL_SUCCESS;
8141}
8142
8143int wolfSSL_X509_ACERT_print(WOLFSSL_BIO* bio, WOLFSSL_X509_ACERT* x509)
8144{
8145 const char * hdr = "Attribute Certificate:\n";
8146 const char * data_hdr = " Data:\n";
8147 const char * holder_hdr = " Holder:\n";
8148 const char * holder_issuer_hdr = " Issuer:";
8149 const char * holder_name_hdr = " Name:";
8150 const char * attcert_issuer_hdr = " Issuer:";
8151
8152 if (bio == NULL || x509 == NULL) {
8153 return WOLFSSL_FAILURE;
8154 }
8155
8156 /* print acert header */
8157 if (wolfSSL_BIO_write(bio, hdr, (int)XSTRLEN(hdr)) <= 0) {
8158 return WOLFSSL_FAILURE;
8159 }
8160
8161 /* print data header */
8162 if (wolfSSL_BIO_write(bio, data_hdr, (int)XSTRLEN(data_hdr)) <= 0) {
8163 return WOLFSSL_FAILURE;
8164 }
8165
8166 /* print version of cert */
8167 if (X509PrintVersion(bio, wolfSSL_X509_ACERT_version(x509), 8)
8168 != WOLFSSL_SUCCESS) {
8169 return WOLFSSL_FAILURE;
8170 }
8171
8172 /* print serial number out */
8173 if (X509AcertPrintSerial(bio, x509, 8) != WOLFSSL_SUCCESS) {
8174 return WOLFSSL_FAILURE;
8175 }
8176
8177 /* print holder field */
8178 if (wolfSSL_BIO_write(bio, holder_hdr, (int)XSTRLEN(holder_hdr)) <= 0) {
8179 return WOLFSSL_FAILURE;
8180 }
8181
8182 if (x509->holderEntityName != NULL) {
8183 /* print issuer header */
8184 if (wolfSSL_BIO_write(bio, holder_name_hdr,
8185 (int)XSTRLEN(holder_name_hdr)) <= 0) {
8186 return WOLFSSL_FAILURE;
8187 }
8188
8189 if (X509_print_name_entry(bio, x509->holderEntityName, 1)
8190 != WOLFSSL_SUCCESS) {
8191 return WOLFSSL_FAILURE;
8192 }
8193 }
8194
8195 if (x509->holderIssuerName != NULL) {
8196 /* print issuer header */
8197 if (wolfSSL_BIO_write(bio, holder_issuer_hdr,
8198 (int)XSTRLEN(holder_issuer_hdr)) <= 0) {
8199 return WOLFSSL_FAILURE;
8200 }
8201
8202 if (X509_print_name_entry(bio, x509->holderIssuerName, 1)
8203 != WOLFSSL_SUCCESS) {
8204 return WOLFSSL_FAILURE;
8205 }
8206 }
8207
8208 if (x509->holderSerialSz > 0) {
8209 X509PrintSerial_ex(bio, x509->holderSerial, x509->holderSerialSz,
8210 1, 12);
8211 }
8212
8213 /* print issuer header */
8214 if (wolfSSL_BIO_write(bio, attcert_issuer_hdr,
8215 (int)XSTRLEN(attcert_issuer_hdr)) <= 0) {
8216 return WOLFSSL_FAILURE;
8217 }
8218
8219 if (x509->AttCertIssuerName != NULL) {
8220 if (X509_print_name_entry(bio, x509->AttCertIssuerName, 1)
8221 != WOLFSSL_SUCCESS) {
8222 return WOLFSSL_FAILURE;
8223 }
8224 }
8225 else {
8226 const char * msg = " Issuer type not supported.\n";
8227 if (wolfSSL_BIO_write(bio, msg, (int)XSTRLEN(msg)) <= 0) {
8228 return WOLFSSL_FAILURE;
8229 }
8230 }
8231
8232 #ifndef NO_ASN_TIME
8233 /* print validity */
8234 if (X509PrintValidity(bio, &x509->notBefore, &x509->notAfter, 8)
8235 != WOLFSSL_SUCCESS) {
8236 return WOLFSSL_FAILURE;
8237 }
8238 #endif /* NO_ASN_TIME */
8239
8240 /* print raw attributes */
8241 if (x509->rawAttr && x509->rawAttrLen > 0) {
8242 char attr_hdr[128]; /* buffer for XSNPRINTF */
8243
8244 if (XSNPRINTF(attr_hdr, 128, "%*s%s: %d bytes\n", 8, "",
8245 "Attributes", x509->rawAttrLen) >= 128) {
8246 return WOLFSSL_FAILURE;
8247 }
8248
8249 if (wolfSSL_BIO_write(bio, attr_hdr, (int)XSTRLEN(attr_hdr)) <= 0) {
8250 return WOLFSSL_FAILURE;
8251 }
8252 }
8253
8254 /* print out sig algo and signature */
8255 if (X509AcertPrintSignature(bio, x509, 0, 8) != WOLFSSL_SUCCESS) {
8256 return WOLFSSL_FAILURE;
8257 }
8258
8259 /* done with print out */
8260 if (wolfSSL_BIO_write(bio, "\n\0", (int)XSTRLEN("\n\0")) <= 0) {
8261 return WOLFSSL_FAILURE;
8262 }
8263
8264 return WOLFSSL_SUCCESS;
8265}
8266#endif /* WOLFSSL_ACERT */
8267
8268#ifndef NO_FILESYSTEM
8269int wolfSSL_X509_print_fp(XFILE fp, WOLFSSL_X509 *x509)
8270{
8271 WOLFSSL_BIO* bio;
8272 int ret;
8273
8274 WOLFSSL_ENTER("wolfSSL_X509_print_fp");
8275
8276 if (!fp || !x509) {
8277 WOLFSSL_MSG("Bad parameter");
8278 return WOLFSSL_FAILURE;
8279 }
8280
8281 if (!(bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file()))) {
8282 WOLFSSL_MSG("wolfSSL_BIO_new wolfSSL_BIO_s_file error");
8283 return WOLFSSL_FAILURE;
8284 }
8285
8286 if (wolfSSL_BIO_set_fp(bio, fp, WOLFSSL_BIO_NOCLOSE) != WOLFSSL_SUCCESS) {
8287 WOLFSSL_MSG("wolfSSL_BIO_set_fp error");
8288 wolfSSL_BIO_free(bio);
8289 return WOLFSSL_FAILURE;
8290 }
8291
8292 ret = wolfSSL_X509_print(bio, x509);
8293
8294 wolfSSL_BIO_free(bio);
8295
8296 return ret;
8297}
8298#endif /* NO_FILESYSTEM */
8299
8300#endif /* XSNPRINTF */
8301
8302int wolfSSL_X509_signature_print(WOLFSSL_BIO *bp,
8303 const WOLFSSL_X509_ALGOR *sigalg, const WOLFSSL_ASN1_STRING *sig)
8304{
8305 int length = 0;
8306 word32 idx = 0;
8307 int i;
8308
8309 (void)sig;
8310
8311 WOLFSSL_ENTER("wolfSSL_X509_signature_print");
8312
8313 if (!bp || !sigalg) {
8314 WOLFSSL_MSG("Bad parameter");
8315 return WOLFSSL_FAILURE;
8316 }
8317
8318 if ((sigalg->algorithm->obj == NULL) ||
8319 (sigalg->algorithm->obj[idx] != ASN_OBJECT_ID)) {
8320 WOLFSSL_MSG("Bad ASN1 Object");
8321 return WOLFSSL_FAILURE;
8322 }
8323 idx++; /* skip object id */
8324
8325 if (GetLength((const byte*)sigalg->algorithm->obj, &idx, &length,
8326 sigalg->algorithm->objSz) < 0 || length < 0) {
8327 return WOLFSSL_FAILURE;
8328 }
8329
8330 if (wolfSSL_BIO_puts(bp, " Raw Signature Algorithm:") <= 0) {
8331 WOLFSSL_MSG("wolfSSL_BIO_puts error");
8332 return WOLFSSL_FAILURE;
8333 }
8334
8335 for (i = 0; i < length; ++i) {
8336 char hex_digits[4];
8337 if (XSNPRINTF(hex_digits, sizeof(hex_digits), "%c%02X", i>0 ? ':' : ' ',
8338 (unsigned int)sigalg->algorithm->obj[idx+i])
8339 >= (int)sizeof(hex_digits))
8340 {
8341 WOLFSSL_MSG("buffer overrun");
8342 return WOLFSSL_FAILURE;
8343 }
8344 if (wolfSSL_BIO_puts(bp, hex_digits) <= 0)
8345 return WOLFSSL_FAILURE;
8346 }
8347
8348 if (wolfSSL_BIO_puts(bp, "\n") <= 0)
8349 return WOLFSSL_FAILURE;
8350
8351 return WOLFSSL_SUCCESS;
8352}
8353#endif /* !NO_BIO */
8354
8355#ifndef NO_WOLFSSL_STUB
8356void wolfSSL_X509_get0_signature(const WOLFSSL_ASN1_BIT_STRING **psig,
8357 const WOLFSSL_X509_ALGOR **palg, const WOLFSSL_X509 *x509)
8358{
8359 (void)psig;
8360 (void)palg;
8361 (void)x509;
8362 WOLFSSL_STUB("wolfSSL_X509_get0_signature");
8363}
8364#endif
8365
8366#endif /* OPENSSL_EXTRA */
8367
8368#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
8369const char* wolfSSL_X509_verify_cert_error_string(long err)
8370{
8371 return wolfSSL_ERR_reason_error_string((unsigned long)err);
8372}
8373#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
8374
8375#ifdef OPENSSL_EXTRA
8376
8377/* Add directory path that will be used for loading certs and CRLs
8378 * which have the <hash>.rn name format.
8379 * type may be WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
8380 * returns WOLFSSL_SUCCESS on successful, otherwise negative or zero. */
8381int wolfSSL_X509_LOOKUP_add_dir(WOLFSSL_X509_LOOKUP* lookup, const char* dir,
8382 long type)
8383{
8384 return wolfSSL_X509_LOOKUP_ctrl(lookup, WOLFSSL_X509_L_ADD_DIR, dir, type,
8385 NULL);
8386}
8387
8388int wolfSSL_X509_LOOKUP_load_file(WOLFSSL_X509_LOOKUP* lookup,
8389 const char* file, long type)
8390{
8391#if !defined(NO_FILESYSTEM) && \
8392 (defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM))
8393 int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
8394 XFILE fp;
8395 long sz;
8396 byte* pem = NULL;
8397 byte* curr = NULL;
8398 byte* prev = NULL;
8399 const char* header = NULL;
8400 const char* footer = NULL;
8401
8402 if (type != WOLFSSL_FILETYPE_PEM)
8403 return WS_RETURN_CODE(BAD_FUNC_ARG, (int)WOLFSSL_FAILURE);
8404
8405 fp = XFOPEN(file, "rb");
8406 if (fp == XBADFILE)
8407 return WS_RETURN_CODE(BAD_FUNC_ARG, (int)WOLFSSL_FAILURE);
8408
8409 if (XFSEEK(fp, 0, XSEEK_END) != 0) {
8410 XFCLOSE(fp);
8411 return WS_RETURN_CODE(WOLFSSL_BAD_FILE,WOLFSSL_FAILURE);
8412 }
8413 sz = XFTELL(fp);
8414 if (XFSEEK(fp, 0, XSEEK_SET) != 0) {
8415 XFCLOSE(fp);
8416 return WS_RETURN_CODE(WOLFSSL_BAD_FILE,WOLFSSL_FAILURE);
8417 }
8418
8419 if (sz > MAX_WOLFSSL_FILE_SIZE || sz <= 0) {
8420 WOLFSSL_MSG("X509_LOOKUP_load_file size error");
8421 goto end;
8422 }
8423
8424 pem = (byte*)XMALLOC(sz, 0, DYNAMIC_TYPE_PEM);
8425 if (pem == NULL) {
8426 ret = MEMORY_ERROR;
8427 goto end;
8428 }
8429
8430 /* Read in file which may be CRLs or certificates. */
8431 if (XFREAD(pem, (size_t)sz, 1, fp) != 1)
8432 goto end;
8433
8434 prev = curr = pem;
8435 do {
8436 /* get PEM header and footer based on type */
8437 if (wc_PemGetHeaderFooter(CRL_TYPE, &header, &footer) == 0 &&
8438 XSTRNSTR((char*)curr, header, sz) != NULL) {
8439#ifdef HAVE_CRL
8440 WOLFSSL_CERT_MANAGER* cm = lookup->store->cm;
8441
8442 if (cm->crl == NULL) {
8443 if (wolfSSL_CertManagerEnableCRL(cm, WOLFSSL_CRL_CHECK)
8444 != WOLFSSL_SUCCESS) {
8445 WOLFSSL_MSG("Enable CRL failed");
8446 goto end;
8447 }
8448 }
8449
8450 ret = BufferLoadCRL(cm->crl, curr, sz, WOLFSSL_FILETYPE_PEM,
8451 NO_VERIFY);
8452 if (ret != WOLFSSL_SUCCESS)
8453 goto end;
8454#endif
8455 curr = (byte*)XSTRNSTR((char*)curr, footer, sz);
8456 }
8457 else if (wc_PemGetHeaderFooter(CERT_TYPE, &header, &footer) == 0 &&
8458 XSTRNSTR((char*)curr, header, sz) != NULL) {
8459 ret = X509StoreLoadCertBuffer(lookup->store, curr,
8460 (word32)sz, WOLFSSL_FILETYPE_PEM);
8461 if (ret != WOLFSSL_SUCCESS)
8462 goto end;
8463 curr = (byte*)XSTRNSTR((char*)curr, footer, sz);
8464 }
8465 else
8466 goto end;
8467
8468 if (curr == NULL)
8469 goto end;
8470
8471 curr++;
8472 sz -= (long)(curr - prev);
8473 prev = curr;
8474 }
8475 while (ret == WOLFSSL_SUCCESS);
8476
8477end:
8478 XFREE(pem, 0, DYNAMIC_TYPE_PEM);
8479 XFCLOSE(fp);
8480 return WS_RETURN_CODE(ret, (int)WOLFSSL_FAILURE);
8481#else
8482 (void)lookup;
8483 (void)file;
8484 (void)type;
8485 return WS_RETURN_CODE(WOLFSSL_FAILURE,WOLFSSL_FAILURE);
8486#endif
8487}
8488
8489WOLFSSL_X509_LOOKUP_METHOD* wolfSSL_X509_LOOKUP_hash_dir(void)
8490{
8491 /* Method implementation in functions. */
8492 static WOLFSSL_X509_LOOKUP_METHOD meth = { 1 };
8493 return &meth;
8494}
8495
8496WOLFSSL_X509_LOOKUP_METHOD* wolfSSL_X509_LOOKUP_file(void)
8497{
8498 /* Method implementation in functions. */
8499 static WOLFSSL_X509_LOOKUP_METHOD meth = { 0 };
8500 return &meth;
8501}
8502
8503/* set directory path to load certificate or CRL which have the hash.N form */
8504/* for late use */
8505/* @param ctx a pointer to WOLFSSL_BY_DIR structure */
8506/* @param argc directory path */
8507/* @param argl file type, either WOLFSSL_FILETYPE_PEM or */
8508/* WOLFSSL_FILETYPE_ASN1 */
8509/* @return WOLFSSL_SUCCESS on successful, otherwise negative or zero */
8510static int x509AddCertDir(WOLFSSL_BY_DIR *ctx, const char *argc, long argl)
8511{
8512#if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR)
8513 WOLFSSL_BY_DIR_entry *entry;
8514 size_t pathLen;
8515 int i, num;
8516 const char* c;
8517 WC_DECLARE_VAR(buf, char, MAX_FILENAME_SZ, 0);
8518
8519 WOLFSSL_ENTER("x509AddCertDir");
8520
8521 pathLen = 0;
8522 c = argc;
8523 /* sanity check, zero length */
8524 if (ctx == NULL || c == NULL || *c == '\0')
8525 return WOLFSSL_FAILURE;
8526
8527#ifdef WOLFSSL_SMALL_STACK
8528 buf = (char*)XMALLOC(MAX_FILENAME_SZ, NULL, DYNAMIC_TYPE_OPENSSL);
8529 if (buf == NULL) {
8530 WOLFSSL_LEAVE("x509AddCertDir", MEMORY_E);
8531 return MEMORY_E;
8532 }
8533#endif
8534
8535 XMEMSET(buf, 0, MAX_FILENAME_SZ);
8536
8537 do {
8538 if (*c == SEPARATOR_CHAR || *c == '\0') {
8539
8540 num = wolfSSL_sk_BY_DIR_entry_num(ctx->dir_entry);
8541
8542 for (i=0; i<num; i++) {
8543
8544 entry = wolfSSL_sk_BY_DIR_entry_value(ctx->dir_entry, i);
8545
8546 if (XSTRLEN(entry->dir_name) == pathLen &&
8547 XSTRNCMP(entry->dir_name, buf, pathLen) == 0) {
8548 WOLFSSL_MSG("dir entry found");
8549 break;
8550 }
8551 }
8552
8553 if (num == -1 || i == num) {
8554 WOLFSSL_MSG("no entry found");
8555
8556 if (ctx->dir_entry == NULL) {
8557 ctx->dir_entry = wolfSSL_sk_BY_DIR_entry_new_null();
8558
8559 if (ctx->dir_entry == NULL) {
8560 WOLFSSL_MSG("failed to allocate dir_entry");
8561 WC_FREE_VAR_EX(buf, 0, DYNAMIC_TYPE_OPENSSL);
8562 return 0;
8563 }
8564 }
8565
8566 entry = wolfSSL_BY_DIR_entry_new();
8567 if (entry == NULL) {
8568 WOLFSSL_MSG("failed to allocate dir entry");
8569 WC_FREE_VAR_EX(buf, 0, DYNAMIC_TYPE_OPENSSL);
8570 return 0;
8571 }
8572 entry->dir_type = (int)argl;
8573 entry->dir_name = (char*)XMALLOC(pathLen + 1/* \0 termination*/
8574 , NULL, DYNAMIC_TYPE_OPENSSL);
8575 entry->hashes = wolfSSL_sk_BY_DIR_HASH_new_null();
8576 if (entry->dir_name == NULL || entry->hashes == NULL) {
8577 WOLFSSL_MSG("failed to allocate dir name");
8578 wolfSSL_BY_DIR_entry_free(entry);
8579 WC_FREE_VAR_EX(buf, 0, DYNAMIC_TYPE_OPENSSL);
8580 return 0;
8581 }
8582
8583 XSTRNCPY(entry->dir_name, buf, pathLen);
8584 entry->dir_name[pathLen] = '\0';
8585
8586 if (wolfSSL_sk_BY_DIR_entry_push(ctx->dir_entry, entry) <= 0) {
8587 wolfSSL_BY_DIR_entry_free(entry);
8588 WC_FREE_VAR_EX(buf, 0, DYNAMIC_TYPE_OPENSSL);
8589 return 0;
8590 }
8591 }
8592 /* skip separator */
8593 if (*c == SEPARATOR_CHAR) c++;
8594
8595 pathLen = 0;
8596 XMEMSET(buf, 0, MAX_FILENAME_SZ);
8597 }
8598 buf[pathLen++] = *c;
8599
8600 } while(*c++ != '\0');
8601
8602 WC_FREE_VAR_EX(buf, 0, DYNAMIC_TYPE_OPENSSL);
8603
8604 return WOLFSSL_SUCCESS;
8605#else
8606 (void)ctx;
8607 (void)argc;
8608 (void)argl;
8609 return WOLFSSL_NOT_IMPLEMENTED;
8610#endif
8611}
8612
8613/* set additional data to X509_LOOKUP */
8614/* @param ctx a pointer to X509_LOOKUP structure */
8615/* @param cmd control command : */
8616/* X509_L_FILE_LOAD, X509_L_ADD_DIR X509_L_ADD_STORE or */
8617/* X509_L_LOAD_STORE */
8618/* @param argc arguments for the control command */
8619/* @param argl arguments for the control command */
8620/* @param **ret return value of the control command */
8621/* @return WOLFSSL_SUCCESS on successful, otherwise WOLFSSL_FAILURE */
8622/* note: WOLFSSL_X509_L_ADD_STORE and WOLFSSL_X509_L_LOAD_STORE have not*/
8623/* yet implemented. It returns WOLFSSL_NOT_IMPLEMENTED */
8624/* when those control commands are passed. */
8625int wolfSSL_X509_LOOKUP_ctrl(WOLFSSL_X509_LOOKUP *ctx, int cmd,
8626 const char *argc, long argl, char **ret)
8627{
8628 int lret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
8629
8630 WOLFSSL_ENTER("wolfSSL_X509_LOOKUP_ctrl");
8631#if !defined(NO_FILESYSTEM)
8632 if (ctx != NULL) {
8633 switch (cmd) {
8634 case WOLFSSL_X509_L_FILE_LOAD:
8635 /* expects to return a number of processed cert or crl file */
8636 lret = wolfSSL_X509_load_cert_crl_file(ctx, argc, (int)argl) > 0 ?
8637 WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
8638 break;
8639 case WOLFSSL_X509_L_ADD_DIR:
8640 /* store directory location to use it later */
8641#if !defined(NO_WOLFSSL_DIR)
8642 lret = x509AddCertDir(ctx->dirs, argc, argl);
8643#else
8644 (void)x509AddCertDir;
8645 lret = WOLFSSL_NOT_IMPLEMENTED;
8646#endif
8647 break;
8648 case WOLFSSL_X509_L_ADD_STORE:
8649 case WOLFSSL_X509_L_LOAD_STORE:
8650 return WOLFSSL_NOT_IMPLEMENTED;
8651
8652 default:
8653 break;
8654 }
8655 }
8656 (void)ret;
8657#else
8658 (void)ctx;
8659 (void)argc;
8660 (void)argl;
8661 (void)ret;
8662 (void)cmd;
8663 (void)x509AddCertDir;
8664 lret = WOLFSSL_NOT_IMPLEMENTED;
8665#endif
8666 return lret;
8667}
8668
8669
8670#if defined(WOLFSSL_CERT_GEN)
8671static int wolfssl_x509_make_der(WOLFSSL_X509* x509, int req,
8672 unsigned char* der, int* derSz, int includeSig);
8673#endif
8674
8675#ifdef WOLFSSL_CERT_GEN
8676#ifndef NO_BIO
8677/* Converts the X509 to DER format and outputs it into bio.
8678 *
8679 * bio is the structure to hold output DER
8680 * x509 certificate to create DER from
8681 * req if set then a CSR is generated
8682 *
8683 * returns WOLFSSL_SUCCESS on success
8684 */
8685static int loadX509orX509REQFromBio(WOLFSSL_BIO* bio, WOLFSSL_X509* x509,
8686 int req)
8687{
8688 int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
8689 /* Get large buffer to hold cert der */
8690 int derSz = X509_BUFFER_SZ;
8691 WC_DECLARE_VAR(der, byte, X509_BUFFER_SZ, 0);
8692 WOLFSSL_ENTER("wolfSSL_i2d_X509_bio");
8693
8694 if (bio == NULL || x509 == NULL) {
8695 return WOLFSSL_FAILURE;
8696 }
8697
8698#ifdef WOLFSSL_SMALL_STACK
8699 der = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
8700 if (!der) {
8701 WOLFSSL_MSG("malloc failed");
8702 return WOLFSSL_FAILURE;
8703 }
8704#endif
8705
8706 if (wolfssl_x509_make_der(x509, req, der, &derSz, 1) != WOLFSSL_SUCCESS) {
8707 goto cleanup;
8708 }
8709
8710 if (wolfSSL_BIO_write(bio, der, derSz) != derSz) {
8711 goto cleanup;
8712 }
8713
8714 ret = WOLFSSL_SUCCESS;
8715cleanup:
8716 WC_FREE_VAR_EX(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
8717
8718 return ret;
8719}
8720
8721/* Converts the X509 to DER format and outputs it into bio.
8722 *
8723 * bio is the structure to hold output DER
8724 * x509 certificate to create DER from
8725 *
8726 * returns WOLFSSL_SUCCESS on success
8727 */
8728int wolfSSL_i2d_X509_bio(WOLFSSL_BIO* bio, WOLFSSL_X509* x509)
8729{
8730 return loadX509orX509REQFromBio(bio, x509, 0);
8731}
8732
8733#ifdef WOLFSSL_CERT_REQ
8734int wolfSSL_i2d_X509_REQ_bio(WOLFSSL_BIO* bio, WOLFSSL_X509* x509)
8735{
8736 return loadX509orX509REQFromBio(bio, x509, 1);
8737}
8738#endif /* WOLFSSL_CERT_REQ */
8739#endif /* !NO_BIO */
8740#endif /* WOLFSSL_CERT_GEN */
8741
8742/* Converts an internal structure to a DER buffer
8743 *
8744 * x509 structure to get DER buffer from
8745 * out buffer to hold result. If NULL then *out is NULL then a new buffer is
8746 * created.
8747 *
8748 * returns the size of the DER result on success
8749 */
8750int wolfSSL_i2d_X509(WOLFSSL_X509* x509, unsigned char** out)
8751{
8752 const unsigned char* der;
8753 int derSz = 0;
8754 int advance = 1;
8755
8756 WOLFSSL_ENTER("wolfSSL_i2d_X509");
8757
8758 if (x509 == NULL) {
8759 WOLFSSL_LEAVE("wolfSSL_i2d_X509", BAD_FUNC_ARG);
8760 return BAD_FUNC_ARG;
8761 }
8762
8763 der = wolfSSL_X509_get_der(x509, &derSz);
8764 if (der == NULL) {
8765 WOLFSSL_LEAVE("wolfSSL_i2d_X509", MEMORY_E);
8766 return MEMORY_E;
8767 }
8768
8769 if (out != NULL && *out == NULL) {
8770 *out = (unsigned char*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_OPENSSL);
8771 if (*out == NULL) {
8772 WOLFSSL_LEAVE("wolfSSL_i2d_X509", MEMORY_E);
8773 return MEMORY_E;
8774 }
8775 advance = 0;
8776 }
8777
8778 if (out != NULL) {
8779 XMEMCPY(*out, der, derSz);
8780 if (advance)
8781 *out += derSz;
8782 }
8783
8784 WOLFSSL_LEAVE("wolfSSL_i2d_X509", derSz);
8785 return derSz;
8786}
8787
8788#ifdef WOLFSSL_DUAL_ALG_CERTS
8789/* Generate a der preTBS from a decoded cert, and write
8790 * to buffer.
8791 *
8792 * @param [in] cert The decoded cert to parse.
8793 * @param [out] der The der buffer to write in.
8794 * @param [in] derSz The der buffer size.
8795 *
8796 * @return preTBS der size on success.
8797 * */
8798int wc_GeneratePreTBS(DecodedCert* cert, byte *der, int derSz) {
8799 int ret = 0;
8800 WOLFSSL_X509 *x = NULL;
8801 byte certIsCSR = 0;
8802
8803 WOLFSSL_ENTER("wc_GeneratePreTBS");
8804
8805 if ((cert == NULL) || (der == NULL) || (derSz <= 0)) {
8806 return BAD_FUNC_ARG;
8807 }
8808
8809#ifdef WOLFSSL_CERT_REQ
8810 certIsCSR = cert->isCSR;
8811#endif
8812
8813 x = wolfSSL_X509_new();
8814 if (x == NULL) {
8815 ret = MEMORY_E;
8816 }
8817 else {
8818 ret = CopyDecodedToX509(x, cert);
8819 }
8820
8821 if (ret == 0) {
8822 /* Remove the altsigval extension. */
8823 XFREE(x->altSigValDer, x->heap, DYNAMIC_TYPE_X509_EXT);
8824 x->altSigValDer = NULL;
8825 x->altSigValLen = 0;
8826 /* Remove sigOID so it won't be encoded. */
8827 x->sigOID = 0;
8828 /* We now have a PreTBS. Encode it. */
8829 ret = wolfssl_x509_make_der(x, certIsCSR, der, &derSz, 0);
8830 if (ret == WOLFSSL_SUCCESS) {
8831 ret = derSz;
8832 }
8833 }
8834
8835 if (x != NULL) {
8836 wolfSSL_X509_free(x);
8837 x = NULL;
8838 }
8839
8840 return ret;
8841}
8842#endif /* WOLFSSL_DUAL_ALG_CERTS */
8843
8844#ifndef NO_BIO
8845/**
8846 * Converts the DER from bio and creates a WOLFSSL_X509 structure from it.
8847 * @param bio is the structure holding DER
8848 * @param x509 certificate to create from DER. Can be NULL
8849 * @param req 1 for a CSR and 0 for a x509 cert
8850 * @return pointer to WOLFSSL_X509 structure on success and NULL on fail
8851 */
8852static WOLFSSL_X509* d2i_X509orX509REQ_bio(WOLFSSL_BIO* bio,
8853 WOLFSSL_X509** x509, int req)
8854{
8855 WOLFSSL_X509* localX509 = NULL;
8856 byte* mem = NULL;
8857 int size;
8858
8859 WOLFSSL_ENTER("wolfSSL_d2i_X509_bio");
8860
8861 if (bio == NULL) {
8862 WOLFSSL_MSG("Bad Function Argument bio is NULL");
8863 return NULL;
8864 }
8865
8866 size = wolfSSL_BIO_get_len(bio);
8867 if (size <= 0) {
8868 WOLFSSL_MSG("wolfSSL_BIO_get_len error. Possibly no pending data.");
8869 WOLFSSL_ERROR(WOLFSSL_ASN1_R_HEADER_TOO_LONG_E);
8870 return NULL;
8871 }
8872
8873 if (!(mem = (byte*)XMALLOC(size, NULL, DYNAMIC_TYPE_OPENSSL))) {
8874 WOLFSSL_MSG("malloc error");
8875 return NULL;
8876 }
8877
8878 if ((size = wolfSSL_BIO_read(bio, mem, size)) == 0) {
8879 WOLFSSL_MSG("wolfSSL_BIO_read error");
8880 XFREE(mem, NULL, DYNAMIC_TYPE_OPENSSL);
8881 return NULL;
8882 }
8883
8884 if (req) {
8885#ifdef WOLFSSL_CERT_REQ
8886 localX509 = wolfSSL_X509_REQ_d2i(NULL, mem, size);
8887#else
8888 WOLFSSL_MSG("CSR not compiled in");
8889#endif
8890 }
8891 else {
8892 localX509 = wolfSSL_X509_d2i_ex(NULL, mem, size, bio->heap);
8893 }
8894 if (localX509 == NULL) {
8895 WOLFSSL_MSG("wolfSSL_X509_d2i error");
8896 XFREE(mem, NULL, DYNAMIC_TYPE_OPENSSL);
8897 return NULL;
8898 }
8899
8900 if (x509 != NULL) {
8901 *x509 = localX509;
8902 }
8903
8904 XFREE(mem, NULL, DYNAMIC_TYPE_OPENSSL);
8905 return localX509;
8906}
8907
8908WOLFSSL_X509* wolfSSL_d2i_X509_bio(WOLFSSL_BIO* bio, WOLFSSL_X509** x509)
8909{
8910 return d2i_X509orX509REQ_bio(bio, x509, 0);
8911}
8912
8913#ifdef WOLFSSL_CERT_REQ
8914WOLFSSL_X509* wolfSSL_d2i_X509_REQ_bio(WOLFSSL_BIO* bio, WOLFSSL_X509** x509)
8915{
8916 return d2i_X509orX509REQ_bio(bio, x509, 1);
8917}
8918#endif
8919#endif /* !NO_BIO */
8920
8921#endif /* OPENSSL_EXTRA */
8922
8923#ifdef OPENSSL_EXTRA
8924/* Use the public key to verify the signature. Note: this only verifies
8925 * the certificate signature.
8926 * returns WOLFSSL_SUCCESS on successful signature verification */
8927static int verifyX509orX509REQ(WOLFSSL_X509* x509, WOLFSSL_EVP_PKEY* pkey,
8928 int req)
8929{
8930 int ret;
8931 const byte* der;
8932 int derSz = 0;
8933 int type;
8934
8935 (void)req;
8936
8937 if (x509 == NULL || pkey == NULL) {
8938 return WOLFSSL_FATAL_ERROR;
8939 }
8940
8941 der = wolfSSL_X509_get_der(x509, &derSz);
8942 if (der == NULL) {
8943 WOLFSSL_MSG("Error getting WOLFSSL_X509 DER");
8944 return WOLFSSL_FATAL_ERROR;
8945 }
8946
8947 switch (pkey->type) {
8948 case WC_EVP_PKEY_RSA:
8949 type = RSAk;
8950 break;
8951
8952 case WC_EVP_PKEY_EC:
8953 type = ECDSAk;
8954 break;
8955
8956 case WC_EVP_PKEY_DSA:
8957 type = DSAk;
8958 break;
8959
8960 default:
8961 WOLFSSL_MSG("Unknown pkey key type");
8962 return WOLFSSL_FATAL_ERROR;
8963 }
8964
8965#ifdef WOLFSSL_CERT_REQ
8966 if (req)
8967 ret = CheckCSRSignaturePubKey(der, (word32)derSz, x509->heap,
8968 (unsigned char*)pkey->pkey.ptr, pkey->pkey_sz, type);
8969 else
8970#endif
8971 ret = CheckCertSignaturePubKey(der, (word32)derSz, x509->heap,
8972 (unsigned char*)pkey->pkey.ptr, pkey->pkey_sz, type);
8973 if (ret == 0) {
8974 return WOLFSSL_SUCCESS;
8975 }
8976 return WOLFSSL_FAILURE;
8977}
8978
8979int wolfSSL_X509_verify(WOLFSSL_X509* x509, WOLFSSL_EVP_PKEY* pkey)
8980{
8981 return verifyX509orX509REQ(x509, pkey, 0);
8982}
8983
8984#ifdef WOLFSSL_CERT_REQ
8985int wolfSSL_X509_REQ_verify(WOLFSSL_X509* x509, WOLFSSL_EVP_PKEY* pkey)
8986{
8987 return verifyX509orX509REQ(x509, pkey, 1);
8988}
8989#endif /* WOLFSSL_CERT_REQ */
8990
8991#if !defined(NO_FILESYSTEM)
8992static void *wolfSSL_d2i_X509_fp_ex(XFILE file, void **x509, int type)
8993{
8994 void *newx509 = NULL;
8995 byte *fileBuffer = NULL;
8996 long sz = 0;
8997
8998 /* init variable */
8999 if (x509)
9000 *x509 = NULL;
9001
9002 /* argument check */
9003 if (file == XBADFILE) {
9004 return NULL;
9005 }
9006
9007 /* determine file size */
9008 if (XFSEEK(file, 0, XSEEK_END) != 0) {
9009 return NULL;
9010 }
9011 sz = XFTELL(file);
9012 if (XFSEEK(file, 0, XSEEK_SET) != 0) {
9013 return NULL;
9014 }
9015
9016 if (sz > MAX_WOLFSSL_FILE_SIZE || sz <= 0) {
9017 WOLFSSL_MSG("d2i_X509_fp_ex file size error");
9018 return NULL;
9019 }
9020
9021 fileBuffer = (byte *)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE);
9022 if (fileBuffer != NULL) {
9023 if ((long)XFREAD(fileBuffer, 1, (size_t)sz, file) != sz) {
9024 WOLFSSL_MSG("File read failed");
9025 goto err_exit;
9026 }
9027 if (type == CERT_TYPE) {
9028 newx509 = (void *)wolfSSL_X509_d2i(NULL, fileBuffer, (int)sz);
9029 }
9030 #ifdef HAVE_CRL
9031 else if (type == CRL_TYPE) {
9032 newx509 = (void *)wolfSSL_d2i_X509_CRL(NULL, fileBuffer, (int)sz);
9033 }
9034 #endif
9035 #ifdef WOLFSSL_CERT_REQ
9036 else if (type == CERTREQ_TYPE) {
9037 newx509 = (void *)wolfSSL_X509_REQ_d2i(NULL, fileBuffer, (int)sz);
9038 }
9039 #endif
9040 #if !defined(NO_ASN) && !defined(NO_PWDBASED) && defined(HAVE_PKCS12)
9041 else if (type == PKCS12_TYPE) {
9042 if ((newx509 = wc_PKCS12_new()) == NULL) {
9043 goto err_exit;
9044 }
9045 if (wc_d2i_PKCS12(fileBuffer, (word32)sz,
9046 (WC_PKCS12*)newx509) < 0) {
9047 goto err_exit;
9048 }
9049 }
9050 #endif
9051 else {
9052 goto err_exit;
9053 }
9054 if (newx509 == NULL) {
9055 WOLFSSL_MSG("X509 failed");
9056 goto err_exit;
9057 }
9058 }
9059
9060 if (x509)
9061 *x509 = newx509;
9062
9063 goto _exit;
9064
9065err_exit:
9066#if !defined(NO_ASN) && !defined(NO_PWDBASED) && defined(HAVE_PKCS12)
9067 if ((newx509 != NULL) && (type == PKCS12_TYPE)) {
9068 wc_PKCS12_free((WC_PKCS12*)newx509);
9069 newx509 = NULL;
9070 }
9071#endif
9072_exit:
9073 XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE);
9074
9075 return newx509;
9076}
9077
9078#ifdef WOLFSSL_CERT_REQ
9079WOLFSSL_X509* wolfSSL_d2i_X509_REQ_fp(XFILE fp, WOLFSSL_X509 **req)
9080{
9081 return (WOLFSSL_X509 *)wolfSSL_d2i_X509_fp_ex(fp, (void **)req,
9082 CERTREQ_TYPE);
9083}
9084#endif /* WOLFSSL_CERT_REQ */
9085
9086WOLFSSL_X509 *wolfSSL_d2i_X509_fp(XFILE fp, WOLFSSL_X509 **x509)
9087{
9088 WOLFSSL_ENTER("wolfSSL_d2i_X509_fp");
9089 return (WOLFSSL_X509 *)wolfSSL_d2i_X509_fp_ex(fp, (void **)x509, CERT_TYPE);
9090}
9091
9092/* load certificate or CRL file, and add it to the STORE */
9093/* @param ctx a pointer to X509_LOOKUP structure */
9094/* @param file file name to load */
9095/* @param type WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1 */
9096/* @return a number of loading CRL or certificate, otherwise zero */
9097int wolfSSL_X509_load_cert_crl_file(WOLFSSL_X509_LOOKUP *ctx,
9098 const char *file, int type)
9099{
9100 WOLFSSL_X509 *x509 = NULL;
9101
9102 int cnt = 0;
9103
9104 WOLFSSL_ENTER("wolfSSL_X509_load_cert_crl_file");
9105
9106 /* stanity check */
9107 if (ctx == NULL || file == NULL) {
9108 WOLFSSL_MSG("bad arguments");
9109 return 0;
9110 }
9111
9112 if (type != WOLFSSL_FILETYPE_PEM) {
9113 x509 = wolfSSL_X509_load_certificate_file(file, type);
9114 if (x509 != NULL) {
9115 if (wolfSSL_X509_STORE_add_cert(ctx->store, x509)
9116 == WOLFSSL_SUCCESS) {
9117 cnt++;
9118 }
9119 else {
9120 WOLFSSL_MSG("wolfSSL_X509_STORE_add_cert error");
9121 }
9122 wolfSSL_X509_free(x509);
9123 x509 = NULL;
9124 }
9125 else {
9126 WOLFSSL_MSG("wolfSSL_X509_load_certificate_file error");
9127 }
9128
9129 }
9130 else {
9131#if defined(OPENSSL_ALL)
9132 #if !defined(NO_BIO)
9133 STACK_OF(WOLFSSL_X509_INFO) *info;
9134 WOLFSSL_X509_INFO *info_tmp;
9135 int i;
9136 int num = 0;
9137 WOLFSSL_BIO *bio = wolfSSL_BIO_new_file(file, "rb");
9138 if (!bio) {
9139 WOLFSSL_MSG("wolfSSL_BIO_new error");
9140 return cnt;
9141 }
9142
9143 info = wolfSSL_PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL);
9144
9145 wolfSSL_BIO_free(bio);
9146
9147 if (!info) {
9148 WOLFSSL_MSG("wolfSSL_PEM_X509_INFO_read_bio error");
9149 return cnt;
9150 }
9151 num = wolfSSL_sk_X509_INFO_num(info);
9152 for (i=0; i < num; i++) {
9153 info_tmp = wolfSSL_sk_X509_INFO_value(info, i);
9154
9155 if (info_tmp == NULL)
9156 continue;
9157
9158 if (info_tmp->x509) {
9159 if (wolfSSL_X509_STORE_add_cert(ctx->store, info_tmp->x509) ==
9160 WOLFSSL_SUCCESS) {
9161 cnt ++;
9162 }
9163 else {
9164 WOLFSSL_MSG("wolfSSL_X509_STORE_add_cert failed");
9165 }
9166 }
9167#ifdef HAVE_CRL
9168 if (info_tmp->crl) {
9169 if (wolfSSL_X509_STORE_add_crl(ctx->store, info_tmp->crl) ==
9170 WOLFSSL_SUCCESS) {
9171 cnt ++;
9172 }
9173 else {
9174 WOLFSSL_MSG("wolfSSL_X509_STORE_add_crl failed");
9175 }
9176 }
9177#endif
9178 }
9179 wolfSSL_sk_X509_INFO_pop_free(info, wolfSSL_X509_INFO_free);
9180 #elif defined(HAVE_CRL)
9181 /* Only supports one certificate or CRL in the file. */
9182 WOLFSSL_X509_CRL* crl = NULL;
9183 XFILE fp = XFOPEN(file, "rb");
9184 if (fp == XBADFILE) {
9185 WOLFSSL_MSG("XFOPEN error");
9186 return cnt;
9187 }
9188
9189 x509 = wolfSSL_PEM_read_X509(fp, NULL, NULL, NULL);
9190 if (x509 != NULL) {
9191 if (wolfSSL_X509_STORE_add_cert(ctx->store, x509) ==
9192 WOLFSSL_SUCCESS) {
9193 cnt++;
9194 }
9195 else {
9196 WOLFSSL_MSG("wolfSSL_X509_STORE_add_cert failed");
9197 }
9198 }
9199 else {
9200 if (XFSEEK(fp, 0, XSEEK_SET) != 0) {
9201 WOLFSSL_MSG("XFSEEK error");
9202 return cnt;
9203 }
9204 crl = wolfSSL_PEM_read_X509_CRL(fp, NULL, NULL, NULL);
9205 if (crl != NULL) {
9206 if (wolfSSL_X509_STORE_add_crl(ctx->store, crl) ==
9207 WOLFSSL_SUCCESS) {
9208 cnt++;
9209 }
9210 else {
9211 WOLFSSL_MSG("wolfSSL_X509_STORE_add_crl failed");
9212 }
9213 }
9214 else {
9215 WOLFSSL_MSG("Certificate and CRL not recognized");
9216 return cnt;
9217 }
9218 }
9219
9220 wolfSSL_X509_free(x509);
9221 wolfSSL_X509_CRL_free(crl);
9222 #endif
9223#else
9224 (void)cnt;
9225#endif /* OPENSSL_ALL && !NO_BIO */
9226 }
9227
9228 WOLFSSL_LEAVE("wolfSSL_X509_load_ceretificate_crl_file", cnt);
9229 return cnt;
9230}
9231#endif /* !NO_FILESYSTEM */
9232
9233
9234#ifdef HAVE_CRL
9235
9236#ifndef NO_BIO
9237WOLFSSL_X509_CRL *wolfSSL_d2i_X509_CRL_bio(WOLFSSL_BIO *bp,
9238 WOLFSSL_X509_CRL **x)
9239{
9240 int derSz;
9241 byte* der = NULL;
9242 WOLFSSL_X509_CRL* crl = NULL;
9243
9244 if (bp == NULL)
9245 return NULL;
9246
9247 if ((derSz = wolfSSL_BIO_get_len(bp)) > 0) {
9248 der = (byte*)XMALLOC(derSz, 0, DYNAMIC_TYPE_DER);
9249 if (der != NULL) {
9250 if (wolfSSL_BIO_read(bp, der, derSz) == derSz) {
9251 crl = wolfSSL_d2i_X509_CRL(x, der, derSz);
9252 }
9253 }
9254 }
9255
9256 XFREE(der, 0, DYNAMIC_TYPE_DER);
9257
9258 return crl;
9259}
9260#endif
9261
9262#if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM)
9263WOLFSSL_X509_CRL *wolfSSL_d2i_X509_CRL_fp(XFILE fp, WOLFSSL_X509_CRL **crl)
9264{
9265 WOLFSSL_ENTER("wolfSSL_d2i_X509_CRL_fp");
9266 return (WOLFSSL_X509_CRL *)wolfSSL_d2i_X509_fp_ex(fp, (void **)crl,
9267 CRL_TYPE);
9268}
9269
9270/* Read CRL file, and add it to store and corresponding cert manager */
9271/* @param ctx a pointer of X509_LOOKUP back to the X509_STORE */
9272/* @param file a file to read */
9273/* @param type WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1 */
9274/* @return WOLFSSL_SUCCESS(1) on successful, otherwise WOLFSSL_FAILURE(0)*/
9275int wolfSSL_X509_load_crl_file(WOLFSSL_X509_LOOKUP *ctx,
9276 const char *file, int type)
9277{
9278#ifndef NO_BIO
9279 int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
9280 int count = 0;
9281 WOLFSSL_BIO *bio = NULL;
9282 WOLFSSL_X509_CRL *crl = NULL;
9283
9284 WOLFSSL_ENTER("wolfSSL_X509_load_crl_file");
9285
9286 if (ctx == NULL || file == NULL)
9287 return ret;
9288
9289 if ((bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file())) == NULL)
9290 return ret;
9291
9292 if (wolfSSL_BIO_read_filename(bio, file) <= 0) {
9293 wolfSSL_BIO_free(bio);
9294 return ret;
9295 }
9296
9297 if (wolfSSL_BIO_read_filename(bio, file) <= 0) {
9298 wolfSSL_BIO_free(bio);
9299 return ret;
9300 }
9301
9302 if (type == WOLFSSL_FILETYPE_PEM) {
9303 do {
9304 crl = wolfSSL_PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL);
9305 if (crl == NULL) {
9306 if (count <= 0) {
9307 WOLFSSL_MSG("Load crl failed");
9308 }
9309 break;
9310 }
9311
9312 ret = wolfSSL_X509_STORE_add_crl(ctx->store, crl);
9313 if (ret == WC_NO_ERR_TRACE(WOLFSSL_FAILURE)) {
9314 WOLFSSL_MSG("Adding crl failed");
9315 break;
9316 }
9317 count++;
9318 wolfSSL_X509_CRL_free(crl);
9319 crl = NULL;
9320 } while(crl == NULL);
9321
9322 ret = count;
9323 }
9324 else if (type == WOLFSSL_FILETYPE_ASN1) {
9325 crl = wolfSSL_d2i_X509_CRL_bio(bio, NULL);
9326 if (crl == NULL) {
9327 WOLFSSL_MSG("Load crl failed");
9328 }
9329 else {
9330 ret = wolfSSL_X509_STORE_add_crl(ctx->store, crl);
9331 if (ret == WC_NO_ERR_TRACE(WOLFSSL_FAILURE)) {
9332 WOLFSSL_MSG("Adding crl failed");
9333 }
9334 else {
9335 ret = 1;/* handled a file */
9336 }
9337 }
9338 }
9339 else {
9340 WOLFSSL_MSG("Invalid file type");
9341 }
9342
9343 wolfSSL_X509_CRL_free(crl);
9344 wolfSSL_BIO_free(bio);
9345
9346 WOLFSSL_LEAVE("wolfSSL_X509_load_crl_file", ret);
9347 return ret;
9348#else
9349 int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
9350 int count = 0;
9351 XFILE fp;
9352 WOLFSSL_X509_CRL *crl = NULL;
9353
9354 WOLFSSL_ENTER("wolfSSL_X509_load_crl_file");
9355
9356 if (ctx == NULL || file == NULL)
9357 return ret;
9358
9359 if ((fp = XFOPEN(file, "rb")) == XBADFILE)
9360 return ret;
9361
9362 if (type == WOLFSSL_FILETYPE_PEM) {
9363 do {
9364 crl = wolfSSL_PEM_read_X509_CRL(fp, NULL, NULL, NULL);
9365 if (crl == NULL) {
9366 if (count <= 0) {
9367 WOLFSSL_MSG("Load crl failed");
9368 }
9369 break;
9370 }
9371
9372 ret = wolfSSL_X509_STORE_add_crl(ctx->store, crl);
9373 if (ret == WC_NO_ERR_TRACE(WOLFSSL_FAILURE)) {
9374 WOLFSSL_MSG("Adding crl failed");
9375 break;
9376 }
9377 count++;
9378 wolfSSL_X509_CRL_free(crl);
9379 crl = NULL;
9380 }
9381 while(crl == NULL);
9382
9383 ret = count;
9384 }
9385 else if (type == WOLFSSL_FILETYPE_ASN1) {
9386 crl = wolfSSL_d2i_X509_CRL_fp(fp, NULL);
9387 if (crl == NULL) {
9388 WOLFSSL_MSG("Load crl failed");
9389 }
9390 else {
9391 ret = wolfSSL_X509_STORE_add_crl(ctx->store, crl);
9392 if (ret == WC_NO_ERR_TRACE(WOLFSSL_FAILURE)) {
9393 WOLFSSL_MSG("Adding crl failed");
9394 }
9395 else {
9396 ret = 1;/* handled a file */
9397 }
9398 }
9399 }
9400 else {
9401 WOLFSSL_MSG("Invalid file type");
9402 }
9403
9404 wolfSSL_X509_CRL_free(crl);
9405 XFCLOSE(fp);
9406
9407 WOLFSSL_LEAVE("wolfSSL_X509_load_crl_file", ret);
9408 return ret;
9409#endif /* !NO_BIO */
9410}
9411#endif /* !NO_FILESYSTEM */
9412
9413
9414WOLFSSL_X509_CRL* wolfSSL_d2i_X509_CRL(WOLFSSL_X509_CRL** crl,
9415 const unsigned char* in, int len)
9416{
9417 WOLFSSL_X509_CRL *newcrl = NULL;
9418 int ret = WOLFSSL_SUCCESS;
9419
9420 WOLFSSL_ENTER("wolfSSL_d2i_X509_CRL");
9421
9422 if (in == NULL) {
9423 WOLFSSL_MSG("Bad argument value");
9424 }
9425 else {
9426 newcrl =(WOLFSSL_X509_CRL*)XMALLOC(sizeof(WOLFSSL_X509_CRL), NULL,
9427 DYNAMIC_TYPE_CRL);
9428 if (newcrl == NULL) {
9429 WOLFSSL_MSG("New CRL allocation failed");
9430 }
9431 else {
9432 ret = InitCRL(newcrl, NULL);
9433 if (ret < 0) {
9434 WOLFSSL_MSG("Init tmp CRL failed");
9435 }
9436 else {
9437 ret = BufferLoadCRL(newcrl, in, len, WOLFSSL_FILETYPE_ASN1,
9438 NO_VERIFY);
9439 if (ret != WOLFSSL_SUCCESS) {
9440 WOLFSSL_MSG("Buffer Load CRL failed");
9441 }
9442 else {
9443 if (crl) {
9444 *crl = newcrl;
9445 }
9446 }
9447 }
9448 }
9449 }
9450
9451 if ((ret != WOLFSSL_SUCCESS) && (newcrl != NULL)) {
9452 wolfSSL_X509_CRL_free(newcrl);
9453 newcrl = NULL;
9454 }
9455
9456 return newcrl;
9457}
9458
9459/* Retrieve issuer X509_NAME from CRL
9460 * return X509_NAME* on success
9461 * return NULL on failure
9462 */
9463WOLFSSL_X509_NAME* wolfSSL_X509_CRL_get_issuer_name(const WOLFSSL_X509_CRL* crl)
9464{
9465 if (crl == NULL || crl->crlList == NULL)
9466 return NULL;
9467
9468 return crl->crlList->issuer;
9469}
9470
9471/* Set issuer name of CRL
9472 * return WOLFSSL_SUCCESS on success
9473 * return WOLFSSL_FAILURE on failure
9474 */
9475int wolfSSL_X509_CRL_set_issuer_name(WOLFSSL_X509_CRL* crl,
9476 const WOLFSSL_X509_NAME* name)
9477{
9478 WOLFSSL_X509_NAME* newName;
9479
9480 if (crl == NULL || crl->crlList == NULL || name == NULL)
9481 return WOLFSSL_FAILURE;
9482
9483 newName = wolfSSL_X509_NAME_dup(name);
9484 if (newName == NULL)
9485 return WOLFSSL_FAILURE;
9486
9487 if (crl->crlList->issuer != NULL) {
9488 FreeX509Name(crl->crlList->issuer);
9489 XFREE(crl->crlList->issuer, crl->heap, DYNAMIC_TYPE_X509);
9490 }
9491 crl->crlList->issuer = newName;
9492
9493 return WOLFSSL_SUCCESS;
9494}
9495
9496/* Retrieve version from CRL
9497 * return version on success
9498 * return 0 on failure
9499 */
9500int wolfSSL_X509_CRL_version(WOLFSSL_X509_CRL* crl)
9501{
9502 if (crl == NULL || crl->crlList == NULL)
9503 return 0;
9504
9505 return crl->crlList->version;
9506}
9507
9508/* Set version of CRL
9509 * Caller passes the RFC 5280 value: 0 for v1, 1 for v2.
9510 * Internally wolfSSL stores version + 1 (v1 = 1, v2 = 2) to match
9511 * what ParseCRL produces, so apply the same normalization here.
9512 * return WOLFSSL_SUCCESS on success
9513 * return WOLFSSL_FAILURE on failure
9514 */
9515int wolfSSL_X509_CRL_set_version(WOLFSSL_X509_CRL* crl, long version)
9516{
9517 if (crl == NULL || crl->crlList == NULL)
9518 return WOLFSSL_FAILURE;
9519
9520 /* Only v1 (0) and v2 (1) are defined by RFC 5280. */
9521 if (version < 0 || version > 1)
9522 return WOLFSSL_FAILURE;
9523
9524 /* Store as version + 1 to match internal convention. */
9525 crl->crlList->version = (int)version + 1;
9526 return WOLFSSL_SUCCESS;
9527}
9528
9529/* Retrieve sig OID from CRL
9530 * return OID on success
9531 * return 0 on failure
9532 */
9533int wolfSSL_X509_CRL_get_signature_type(WOLFSSL_X509_CRL* crl)
9534{
9535 if (crl == NULL || crl->crlList == NULL)
9536 return 0;
9537
9538 return crl->crlList->signatureOID;
9539}
9540
9541/* Set signature type of CRL
9542 * return WOLFSSL_SUCCESS on success
9543 * return WOLFSSL_FAILURE on failure
9544 */
9545int wolfSSL_X509_CRL_set_signature_type(WOLFSSL_X509_CRL* crl,
9546 int signatureType)
9547{
9548 if (crl == NULL || crl->crlList == NULL)
9549 return WOLFSSL_FAILURE;
9550
9551 crl->crlList->signatureOID = signatureType;
9552 return WOLFSSL_SUCCESS;
9553}
9554
9555/* Retrieve sig NID from CRL
9556 * return NID on success
9557 * return 0 on failure
9558 */
9559int wolfSSL_X509_CRL_get_signature_nid(const WOLFSSL_X509_CRL* crl)
9560{
9561 if (crl == NULL || crl->crlList == NULL)
9562 return 0;
9563
9564 return oid2nid(crl->crlList->signatureOID, oidSigType);
9565}
9566
9567/* Set signature NID of CRL
9568 * return WOLFSSL_SUCCESS on success
9569 * return negative value on failure
9570 */
9571int wolfSSL_X509_CRL_set_signature_nid(WOLFSSL_X509_CRL* crl, int nid)
9572{
9573 int ret = WOLFSSL_SUCCESS;
9574 word32 oid;
9575
9576 if (crl == NULL || crl->crlList == NULL || nid <= 0) {
9577 ret = BAD_FUNC_ARG;
9578 }
9579
9580 if (ret == WOLFSSL_SUCCESS) {
9581 oid = nid2oid(nid, oidSigType);
9582 if (oid == (word32)-1 || oid == (word32)WOLFSSL_FATAL_ERROR) {
9583 ret = WOLFSSL_FATAL_ERROR;
9584 }
9585 else {
9586 crl->crlList->signatureOID = oid;
9587 }
9588 }
9589
9590 return ret;
9591}
9592
9593/* Retrieve signature from CRL
9594 * return WOLFSSL_SUCCESS on success and negative values on failure
9595 */
9596int wolfSSL_X509_CRL_get_signature(WOLFSSL_X509_CRL* crl,
9597 unsigned char* buf, int* bufSz)
9598{
9599 WOLFSSL_ENTER("wolfSSL_X509_CRL_get_signature");
9600
9601 if (crl == NULL || crl->crlList == NULL ||
9602 crl->crlList->signature == NULL || bufSz == NULL)
9603 return BAD_FUNC_ARG;
9604
9605 if (buf != NULL) {
9606 if (*bufSz < (int)crl->crlList->signatureSz) {
9607 WOLFSSL_MSG("Signature buffer too small");
9608 return BUFFER_E;
9609 }
9610 else {
9611 XMEMCPY(buf, crl->crlList->signature, crl->crlList->signatureSz);
9612 }
9613 }
9614 *bufSz = (int)crl->crlList->signatureSz;
9615
9616 return WOLFSSL_SUCCESS;
9617}
9618
9619int wolfSSL_X509_CRL_set_signature(WOLFSSL_X509_CRL* crl,
9620 unsigned char* buf, int bufSz)
9621{
9622 byte* newSig;
9623
9624 if (crl == NULL || crl->crlList == NULL || buf == NULL || bufSz <= 0) {
9625 return BAD_FUNC_ARG;
9626 }
9627
9628 /* Ensure signature buffer is allocated and large enough. */
9629 if (crl->crlList->signature == NULL) {
9630 crl->crlList->signature = (byte*)XMALLOC((word32)bufSz, crl->heap,
9631 DYNAMIC_TYPE_CRL_ENTRY);
9632 if (crl->crlList->signature == NULL) {
9633 return MEMORY_E;
9634 }
9635 crl->crlList->signatureSz = (word32)bufSz;
9636 }
9637 else if ((word32)bufSz > crl->crlList->signatureSz) {
9638 newSig = (byte*)XMALLOC((word32)bufSz, crl->heap,
9639 DYNAMIC_TYPE_CRL_ENTRY);
9640 if (newSig == NULL) {
9641 return MEMORY_E;
9642 }
9643 XFREE(crl->crlList->signature, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
9644 crl->crlList->signature = newSig;
9645 crl->crlList->signatureSz = (word32)bufSz;
9646 }
9647 else {
9648 /* Reuse existing buffer, clear contents in case new signature
9649 * is smaller. Note that we do not shrink the buffer. */
9650 XMEMSET(crl->crlList->signature, 0, crl->crlList->signatureSz);
9651 }
9652
9653 XMEMCPY(crl->crlList->signature, buf, bufSz);
9654 crl->crlList->signatureSz = (word32)bufSz;
9655 return WOLFSSL_SUCCESS;
9656}
9657
9658/* Retrieve serial number from RevokedCert
9659 * return WOLFSSL_SUCCESS on success and negative values on failure
9660 */
9661int wolfSSL_X509_REVOKED_get_serial_number(RevokedCert* rev,
9662 byte* in, int* inOutSz)
9663{
9664 WOLFSSL_ENTER("wolfSSL_X509_REVOKED_get_serial_number");
9665 if (rev == NULL || inOutSz == NULL) {
9666 return BAD_FUNC_ARG;
9667 }
9668
9669 if (in != NULL) {
9670 if (*inOutSz < rev->serialSz) {
9671 WOLFSSL_MSG("Serial buffer too small");
9672 return BUFFER_E;
9673 }
9674 XMEMCPY(in, rev->serialNumber, rev->serialSz);
9675 }
9676 *inOutSz = rev->serialSz;
9677
9678 return WOLFSSL_SUCCESS;
9679}
9680
9681const WOLFSSL_ASN1_INTEGER* wolfSSL_X509_REVOKED_get0_serial_number(const
9682 WOLFSSL_X509_REVOKED *rev)
9683{
9684 WOLFSSL_ENTER("wolfSSL_X509_REVOKED_get0_serial_number");
9685
9686 if (rev != NULL) {
9687 return rev->serialNumber;
9688 }
9689 else
9690 return NULL;
9691}
9692
9693const WOLFSSL_ASN1_TIME* wolfSSL_X509_REVOKED_get0_revocation_date(const
9694 WOLFSSL_X509_REVOKED *rev)
9695{
9696 WOLFSSL_ENTER("wolfSSL_X509_REVOKED_get0_revocation_date");
9697
9698 if (rev != NULL) {
9699 return rev->revocationDate;
9700 }
9701 return NULL;
9702}
9703
9704
9705#ifndef NO_BIO
9706/* print serial number out
9707* return WOLFSSL_SUCCESS on success
9708*/
9709static int X509RevokedPrintSerial(WOLFSSL_BIO* bio, RevokedCert* rev,
9710 int indent)
9711{
9712 unsigned char serial[32];
9713 int sz = sizeof(serial);
9714
9715 if (indent < 0) indent = 0;
9716 if (indent > MAX_INDENT) indent = MAX_INDENT;
9717
9718 XMEMSET(serial, 0, sz);
9719 if (wolfSSL_X509_REVOKED_get_serial_number(rev, serial, &sz)
9720 == WOLFSSL_SUCCESS) {
9721 X509PrintSerial_ex(bio, serial, sz, 0, indent);
9722 }
9723 return WOLFSSL_SUCCESS;
9724}
9725
9726
9727/* print out the signature in human readable format for use with
9728* wolfSSL_X509_CRL_print()
9729 * return WOLFSSL_SUCCESS on success
9730 */
9731static int X509CRLPrintSignature(WOLFSSL_BIO* bio, WOLFSSL_X509_CRL* crl,
9732 int algOnly, int indent)
9733{
9734 int sigSz = 0;
9735
9736 if (wolfSSL_X509_CRL_get_signature(crl, NULL, &sigSz) <= 0) {
9737 return WOLFSSL_FAILURE;
9738 }
9739
9740 if (sigSz > 0) {
9741 unsigned char* sig;
9742 int sigNid = wolfSSL_X509_CRL_get_signature_nid(crl);
9743
9744 sig = (unsigned char*)XMALLOC(sigSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
9745 if (sig == NULL) {
9746 return WOLFSSL_FAILURE;
9747 }
9748
9749 if (wolfSSL_X509_CRL_get_signature(crl, sig, &sigSz) <= 0) {
9750 XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
9751 return WOLFSSL_FAILURE;
9752 }
9753
9754 if (X509PrintSignature_ex(bio, sig, sigSz, sigNid, algOnly, indent)
9755 != WOLFSSL_SUCCESS) {
9756 XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
9757 return WOLFSSL_FAILURE;
9758 }
9759
9760 XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
9761
9762 }
9763
9764 return WOLFSSL_SUCCESS;
9765}
9766#endif /* !NO_BIO */
9767
9768#if !defined(NO_BIO) && defined(XSNPRINTF)
9769/* print out the extensions in human readable format for use with
9770 * wolfSSL_X509_CRL_print()
9771 * return WOLFSSL_SUCCESS on success
9772 */
9773static int X509CRLPrintExtensions(WOLFSSL_BIO* bio, WOLFSSL_X509_CRL* crl,
9774 int indent)
9775{
9776 char tmp[MAX_WIDTH]; /* buffer for XSNPRINTF */
9777 int ret = 0;
9778
9779 if (indent < 0) indent = 0;
9780 if (indent > MAX_INDENT) indent = MAX_INDENT;
9781
9782 if (XSNPRINTF(tmp, MAX_WIDTH, "%*s%s\n", indent, "",
9783 "CRL extensions:") >= MAX_WIDTH) {
9784 ret = WOLFSSL_FAILURE;
9785 }
9786
9787 if (ret == 0 && wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
9788 ret = WOLFSSL_FAILURE;
9789 }
9790
9791 if (ret == 0 && crl->crlList->crlNumberSet) {
9792 char dec_string[49]; /* 20 octets can express numbers up to approx
9793 49 decimal digits */
9794 int freeMp = 0;
9795 #ifdef WOLFSSL_SMALL_STACK
9796 mp_int* dec_num = (mp_int*)XMALLOC(sizeof(*dec_num), NULL,
9797 DYNAMIC_TYPE_BIGINT);
9798 if (dec_num == NULL) {
9799 ret = MEMORY_E;
9800 }
9801 #else
9802 mp_int dec_num[1];
9803 #endif
9804
9805 if (ret == 0 && (mp_init(dec_num) != MP_OKAY)) {
9806 ret = MP_INIT_E;
9807 }
9808 else if (ret == 0) {
9809 freeMp = 1;
9810 }
9811
9812 if (ret == 0 && mp_read_radix(dec_num, (char *)crl->crlList->crlNumber,
9813 MP_RADIX_HEX) != MP_OKAY) {
9814 ret = WOLFSSL_FAILURE;
9815 }
9816
9817 if (ret == 0 && mp_toradix(dec_num, dec_string, MP_RADIX_DEC)
9818 != MP_OKAY) {
9819 ret = WOLFSSL_FAILURE;
9820 }
9821
9822 if (ret == 0 && XSNPRINTF(tmp, MAX_WIDTH, "%*s%s\n", indent + 4, "",
9823 "X509v3 CRL Number:") >= MAX_WIDTH) {
9824 ret = WOLFSSL_FAILURE;
9825 }
9826
9827 if (ret == 0 && wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
9828 ret = WOLFSSL_FAILURE;
9829 }
9830
9831 if (ret == 0 && XSNPRINTF(tmp, MAX_WIDTH, "%*s%s\n", indent + 8, "",
9832 dec_string) >= MAX_WIDTH) {
9833 ret = WOLFSSL_FAILURE;
9834 }
9835
9836 if (ret == 0 && wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
9837 ret = WOLFSSL_FAILURE;
9838 }
9839
9840 XMEMSET(tmp, 0, sizeof(tmp));
9841
9842 if (freeMp) {
9843 mp_free(dec_num);
9844 }
9845
9846 WC_FREE_VAR_EX(dec_num, NULL, DYNAMIC_TYPE_BIGINT);
9847 }
9848
9849#if !defined(NO_SKID)
9850 if (ret == 0 && crl->crlList->extAuthKeyIdSet &&
9851 crl->crlList->extAuthKeyId[0] != 0) {
9852 word32 i;
9853 char val[5];
9854 int valSz = 5;
9855
9856 if (XSNPRINTF(tmp, MAX_WIDTH, "%*s%s", indent + 4, "",
9857 "X509v3 Authority Key Identifier:") >= MAX_WIDTH) {
9858 ret = WOLFSSL_FAILURE;
9859 }
9860
9861 if (ret == 0) {
9862 XSTRNCAT(tmp, "\n", MAX_WIDTH - XSTRLEN(tmp) - 1);
9863 }
9864
9865 if (ret == 0 && wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
9866 ret = WOLFSSL_FAILURE;
9867 }
9868 XMEMSET(tmp, 0, MAX_WIDTH);
9869
9870 if (ret == 0 && XSNPRINTF(tmp, MAX_WIDTH - 1, "%*s%s",
9871 indent + 8, "", "keyid") >= MAX_WIDTH) {
9872 ret = WOLFSSL_FAILURE;
9873 }
9874
9875
9876 for (i = 0; i < XSTRLEN((char*)crl->crlList->extAuthKeyId); i++) {
9877 /* check if buffer is almost full */
9878 if (ret == 0 && XSTRLEN(tmp) >= sizeof(tmp) - valSz) {
9879 if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
9880 ret = WOLFSSL_FAILURE;
9881 }
9882 tmp[0] = '\0';
9883 }
9884 if (ret == 0 && XSNPRINTF(val, (size_t)valSz, ":%02X",
9885 crl->crlList->extAuthKeyId[i]) >= valSz) {
9886 WOLFSSL_MSG("buffer overrun");
9887 ret = WOLFSSL_FAILURE;
9888 }
9889 if (ret == 0) {
9890 XSTRNCAT(tmp, val, valSz);
9891 }
9892 }
9893 if (ret == 0) {
9894 XSTRNCAT(tmp, "\n", XSTRLEN("\n") + 1);
9895 }
9896 if (ret == 0 && wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
9897 ret = WOLFSSL_FAILURE;
9898 }
9899 }
9900#endif
9901
9902 if (ret == 0) {
9903 ret = WOLFSSL_SUCCESS;
9904 }
9905
9906 return ret;
9907}
9908
9909/* iterate through a CRL's Revoked Certs and print out in human
9910 * readable format for use with wolfSSL_X509_CRL_print()
9911 * return WOLFSSL_SUCCESS on success
9912 */
9913static int X509CRLPrintRevoked(WOLFSSL_BIO* bio, WOLFSSL_X509_CRL* crl,
9914 int indent)
9915{
9916 char tmp[MAX_WIDTH]; /* buffer for XSNPRINTF */
9917 int i;
9918
9919 if (crl->crlList->totalCerts > 0) {
9920 RevokedCert* revoked = crl->crlList->certs;
9921
9922 if (XSNPRINTF(tmp, MAX_WIDTH, "%*s%s\n", indent, "",
9923 "Revoked Certificates:") >= MAX_WIDTH) {
9924 return WOLFSSL_FAILURE;
9925 }
9926
9927 if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
9928 return WOLFSSL_FAILURE;
9929 }
9930 XMEMSET(tmp, 0, MAX_WIDTH);
9931
9932 for (i = 0; i < crl->crlList->totalCerts; i++) {
9933 if (revoked->serialSz > 0) {
9934 if (X509RevokedPrintSerial(bio, revoked, indent + 4)
9935 != WOLFSSL_SUCCESS) {
9936 return WOLFSSL_FAILURE;
9937 }
9938 }
9939 #ifndef NO_ASN_TIME
9940 if (XSNPRINTF(tmp, MAX_WIDTH, "%*s%s", indent + 8, "",
9941 "Revocation Date: ") >= MAX_WIDTH) {
9942 return WOLFSSL_FAILURE;
9943 }
9944
9945 if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
9946 return WOLFSSL_FAILURE;
9947 }
9948
9949 if (revoked->revDate[0] != 0) {
9950 if (GetTimeString(revoked->revDate, ASN_UTC_TIME,
9951 tmp, MAX_WIDTH, MAX_DATE_SIZE) != WOLFSSL_SUCCESS) {
9952 if (GetTimeString(revoked->revDate, ASN_GENERALIZED_TIME,
9953 tmp, MAX_WIDTH, MAX_DATE_SIZE) != WOLFSSL_SUCCESS) {
9954 WOLFSSL_MSG("Error getting revocation date");
9955 return WOLFSSL_FAILURE;
9956 }
9957 }
9958 }
9959 else {
9960 XSTRNCPY(tmp, "Not Set", MAX_WIDTH-1);
9961 }
9962 tmp[MAX_WIDTH - 1] = '\0'; /* make sure null terminated */
9963 if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
9964 return WOLFSSL_FAILURE;
9965 }
9966
9967 if (wolfSSL_BIO_write(bio, "\n", (int)XSTRLEN("\n")) <= 0) {
9968 return WOLFSSL_FAILURE;
9969 }
9970 #endif
9971 revoked = revoked->next;
9972 }
9973 }
9974 else {
9975 if (wolfSSL_BIO_write(bio, "No Revoked Certificates.\n",
9976 (int)XSTRLEN("No Revoked Certificates.\n")) <= 0) {
9977 return WOLFSSL_FAILURE;
9978 }
9979 }
9980
9981 return WOLFSSL_SUCCESS;
9982}
9983
9984#ifndef NO_ASN_TIME
9985/* print out the last/next update times in human readable
9986 * format for use with wolfSSL_X509_CRL_print()
9987 * return WOLFSSL_SUCCESS on success
9988 */
9989static int X509CRLPrintDates(WOLFSSL_BIO* bio, WOLFSSL_X509_CRL* crl,
9990 int indent)
9991{
9992 char tmp[MAX_WIDTH]; /* buffer for XSNPRINTF */
9993
9994 if (XSNPRINTF(tmp, MAX_WIDTH, "%*s%s", indent, "",
9995 "Last Update: ") >= MAX_WIDTH) {
9996 return WOLFSSL_FAILURE;
9997 }
9998
9999 if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
10000 return WOLFSSL_FAILURE;
10001 }
10002
10003 if (crl->crlList->lastDate[0] != 0) {
10004 if (GetTimeString(crl->crlList->lastDate, crl->crlList->lastDateFormat,
10005 tmp, MAX_WIDTH, MAX_DATE_SIZE) != WOLFSSL_SUCCESS) {
10006 WOLFSSL_MSG("Error getting last update date");
10007 return WOLFSSL_FAILURE;
10008 }
10009 }
10010 else {
10011 XSTRNCPY(tmp, "Not Set", sizeof(tmp)-1);
10012 }
10013 tmp[sizeof(tmp) - 1] = '\0'; /* make sure null terminated */
10014 if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
10015 return WOLFSSL_FAILURE;
10016 }
10017
10018 if (wolfSSL_BIO_write(bio, "\n", (int)XSTRLEN("\n")) <= 0) {
10019 return WOLFSSL_FAILURE;
10020 }
10021
10022 if (XSNPRINTF(tmp, MAX_WIDTH, "%*s%s", indent, "",
10023 "Next Update: ") >= MAX_WIDTH) {
10024 return WOLFSSL_FAILURE;
10025 }
10026
10027 if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
10028 return WOLFSSL_FAILURE;
10029 }
10030
10031 if (crl->crlList->nextDate[0] != 0) {
10032 if (GetTimeString(crl->crlList->nextDate, crl->crlList->nextDateFormat,
10033 tmp, MAX_WIDTH, MAX_DATE_SIZE) != WOLFSSL_SUCCESS) {
10034 WOLFSSL_MSG("Error getting next update date");
10035 return WOLFSSL_FAILURE;
10036 }
10037 }
10038 else {
10039 XSTRNCPY(tmp, "Not Set", sizeof(tmp)-1);
10040 }
10041 tmp[sizeof(tmp) - 1] = '\0'; /* make sure null terminated */
10042 if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) {
10043 return WOLFSSL_FAILURE;
10044 }
10045
10046 if (wolfSSL_BIO_write(bio, "\n", (int)XSTRLEN("\n")) <= 0) {
10047 return WOLFSSL_FAILURE;
10048 }
10049
10050 return WOLFSSL_SUCCESS;
10051}
10052#endif
10053
10054/* Writes the human readable form of x509 to bio.
10055 *
10056 * bio WOLFSSL_BIO to write to.
10057 * crl Certificate revocation list to write.
10058 *
10059 * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure
10060 */
10061int wolfSSL_X509_CRL_print(WOLFSSL_BIO* bio, WOLFSSL_X509_CRL* crl)
10062{
10063 char issuType[] = "Issuer: ";
10064
10065 if (bio == NULL || crl == NULL || crl->crlList == NULL) {
10066 return WOLFSSL_FAILURE;
10067 }
10068
10069 if (wolfSSL_BIO_write(bio, "Certificate Revocation List (CRL):\n",
10070 (int)XSTRLEN("Certificate Revocation List (CRL):\n")) <= 0) {
10071 return WOLFSSL_FAILURE;
10072 }
10073
10074 /* print version */
10075 if (X509PrintVersion(bio, wolfSSL_X509_CRL_version(crl), 8)
10076 != WOLFSSL_SUCCESS) {
10077 return WOLFSSL_FAILURE;
10078 }
10079
10080 /* print signature algo */
10081 if (X509CRLPrintSignature(bio, crl, 1, 8) != WOLFSSL_SUCCESS) {
10082 return WOLFSSL_FAILURE;
10083 }
10084
10085 /* print issuer name */
10086 if (X509PrintName(bio, wolfSSL_X509_CRL_get_issuer_name(crl), issuType, 8)
10087 != WOLFSSL_SUCCESS) {
10088 return WOLFSSL_FAILURE;
10089 }
10090
10091#ifndef NO_ASN_TIME
10092 /* print last and next update times */
10093 if (X509CRLPrintDates(bio, crl, 8) != WOLFSSL_SUCCESS) {
10094 return WOLFSSL_FAILURE;
10095 }
10096#endif
10097
10098 /* print CRL extensions */
10099 if (X509CRLPrintExtensions(bio, crl, 8) != WOLFSSL_SUCCESS) {
10100 return WOLFSSL_FAILURE;
10101 }
10102
10103 /* print CRL Revoked Certs */
10104 if (X509CRLPrintRevoked(bio, crl, 0) != WOLFSSL_SUCCESS) {
10105 return WOLFSSL_FAILURE;
10106 }
10107
10108 if (X509CRLPrintSignature(bio, crl, 0, 4) != WOLFSSL_SUCCESS) {
10109 return WOLFSSL_FAILURE;
10110 }
10111
10112 if (wolfSSL_BIO_write(bio, "\n\0", (int)XSTRLEN("\n\0")) <= 0) {
10113 return WOLFSSL_FAILURE;
10114 }
10115
10116 return WOLFSSL_SUCCESS;
10117}
10118#endif /* !NO_BIO && XSNPRINTF */
10119#endif /* HAVE_CRL */
10120#endif /* OPENSSL_EXTRA */
10121
10122#if defined(HAVE_CRL) && (defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL))
10123void wolfSSL_X509_CRL_free(WOLFSSL_X509_CRL *crl)
10124{
10125 WOLFSSL_ENTER("wolfSSL_X509_CRL_free");
10126
10127 if (crl)
10128 FreeCRL(crl, 1);
10129}
10130#endif /* HAVE_CRL && (OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL) */
10131
10132#if defined(HAVE_CRL) && defined(OPENSSL_EXTRA)
10133WOLFSSL_ASN1_TIME* wolfSSL_X509_CRL_get_lastUpdate(WOLFSSL_X509_CRL* crl)
10134{
10135 if ((crl != NULL) && (crl->crlList != NULL) &&
10136 (crl->crlList->lastDateAsn1.data[0] != 0)) {
10137 return &crl->crlList->lastDateAsn1;
10138 }
10139 return NULL;
10140}
10141
10142int wolfSSL_X509_CRL_set_lastUpdate(WOLFSSL_X509_CRL* crl,
10143 const WOLFSSL_ASN1_TIME* time)
10144{
10145 if (crl != NULL && crl->crlList != NULL && time != NULL) {
10146 crl->crlList->lastDateAsn1 = *time;
10147 return WOLFSSL_SUCCESS;
10148 }
10149 return WOLFSSL_FAILURE;
10150}
10151
10152WOLFSSL_ASN1_TIME* wolfSSL_X509_CRL_get_nextUpdate(WOLFSSL_X509_CRL* crl)
10153{
10154 if ((crl != NULL) && (crl->crlList != NULL) &&
10155 (crl->crlList->nextDateAsn1.data[0] != 0)) {
10156 return &crl->crlList->nextDateAsn1;
10157 }
10158 return NULL;
10159}
10160
10161int wolfSSL_X509_CRL_set_nextUpdate(WOLFSSL_X509_CRL* crl,
10162 const WOLFSSL_ASN1_TIME* time)
10163{
10164 if (crl != NULL && crl->crlList != NULL && time != NULL) {
10165 crl->crlList->nextDateAsn1 = *time;
10166 return WOLFSSL_SUCCESS;
10167 }
10168 return WOLFSSL_FAILURE;
10169}
10170
10171#ifndef NO_WOLFSSL_STUB
10172int wolfSSL_X509_CRL_verify(WOLFSSL_X509_CRL* crl, WOLFSSL_EVP_PKEY* key)
10173{
10174 (void)crl;
10175 (void)key;
10176 WOLFSSL_STUB("X509_CRL_verify");
10177 return 0;
10178}
10179#endif
10180
10181/* Encode CRL to DER format in memory.
10182 *
10183 * If *out is NULL, allocates memory and returns it via *out.
10184 * If *out is not NULL, writes DER data starting at *out.
10185 *
10186 * @param crl CRL to encode
10187 * @param out Pointer to output buffer pointer
10188 * @return Size of DER encoding on success, WOLFSSL_FAILURE on failure
10189 */
10190int wolfSSL_i2d_X509_CRL(WOLFSSL_X509_CRL* crl, unsigned char** out)
10191{
10192 int ret;
10193 long derSz = 0;
10194 byte* der = NULL;
10195 int alloced = 0;
10196
10197 WOLFSSL_ENTER("wolfSSL_i2d_X509_CRL");
10198
10199 if (crl == NULL) {
10200 return BAD_FUNC_ARG;
10201 }
10202
10203 /* Get required size */
10204 ret = BufferStoreCRL(crl, NULL, &derSz, WOLFSSL_FILETYPE_ASN1);
10205 if (ret != WOLFSSL_SUCCESS || derSz <= 0) {
10206 WOLFSSL_MSG("BufferStoreCRL failed to get size");
10207 return WOLFSSL_FAILURE;
10208 }
10209
10210 if (out == NULL) {
10211 /* Just return size */
10212 return (int)derSz;
10213 }
10214
10215 if (*out == NULL) {
10216 /* Allocate output buffer */
10217 der = (byte*)XMALLOC((size_t)derSz, NULL, DYNAMIC_TYPE_OPENSSL);
10218 if (der == NULL) {
10219 WOLFSSL_MSG("Memory allocation failed");
10220 return MEMORY_E;
10221 }
10222 alloced = 1;
10223 }
10224 else {
10225 der = *out;
10226 }
10227
10228 /* Encode CRL to DER */
10229 ret = BufferStoreCRL(crl, der, &derSz, WOLFSSL_FILETYPE_ASN1);
10230 if (ret != WOLFSSL_SUCCESS) {
10231 WOLFSSL_MSG("BufferStoreCRL failed to encode");
10232 if (alloced) {
10233 XFREE(der, NULL, DYNAMIC_TYPE_OPENSSL);
10234 }
10235 return WOLFSSL_FAILURE;
10236 }
10237
10238 if (alloced) {
10239 *out = der;
10240 }
10241 else {
10242 *out += derSz;
10243 }
10244
10245 return (int)derSz;
10246}
10247#endif /* HAVE_CRL && OPENSSL_EXTRA */
10248
10249#if defined(WOLFSSL_CERT_EXT) && \
10250 (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
10251/* Set CRL Distribution Points from pre-encoded DER.
10252 *
10253 * x509 - Certificate to modify
10254 * der - Pre-encoded CRLDistributionPoints DER
10255 * derSz - Size of DER in bytes
10256 *
10257 * Returns WOLFSSL_SUCCESS or WOLFSSL_FAILURE
10258 */
10259int wolfSSL_X509_CRL_set_dist_points(WOLFSSL_X509* x509,
10260 const unsigned char* der, int derSz)
10261{
10262 WOLFSSL_ENTER("wolfSSL_X509_CRL_set_dist_points");
10263
10264 if (x509 == NULL || der == NULL || derSz <= 0) {
10265 return WOLFSSL_FAILURE;
10266 }
10267
10268 if (x509->rawCRLInfo != NULL) {
10269 XFREE(x509->rawCRLInfo, x509->heap, DYNAMIC_TYPE_X509_EXT);
10270 }
10271 x509->rawCRLInfo = (byte*)XMALLOC((word32)derSz, x509->heap,
10272 DYNAMIC_TYPE_X509_EXT);
10273 if (x509->rawCRLInfo == NULL) {
10274 return WOLFSSL_FAILURE;
10275 }
10276
10277 XMEMCPY(x509->rawCRLInfo, der, (word32)derSz);
10278 x509->rawCRLInfoSz = derSz;
10279 x509->CRLdistSet = 1;
10280
10281 return WOLFSSL_SUCCESS;
10282}
10283
10284/* Add CRL Distribution Point URI.
10285 * Encodes URI into proper CRLDistributionPoints DER format.
10286 *
10287 * x509 - Certificate to modify
10288 * uri - URI string (e.g., "http://crl.example.com/ca.crl")
10289 * critical - Whether extension is critical
10290 *
10291 * Returns WOLFSSL_SUCCESS or WOLFSSL_FAILURE
10292 */
10293int wolfSSL_X509_CRL_add_dist_point(WOLFSSL_X509* x509,
10294 const char* uri, int critical)
10295{
10296 word32 uriLen;
10297 byte* derBuf = NULL;
10298 word32 derSz;
10299 word32 idx;
10300 word32 uriTagLen; /* [6] tag + length + URI */
10301 word32 genNamesLen; /* [0] IMPLICIT GeneralNames wrapper */
10302 word32 distPtNmLen; /* [0] EXPLICIT distributionPoint wrapper */
10303 word32 distPtSeqLen; /* SEQUENCE for DistributionPoint */
10304 word32 outerSeqLen; /* SEQUENCE for CRLDistributionPoints */
10305 int ret = WOLFSSL_SUCCESS;
10306
10307 WOLFSSL_ENTER("wolfSSL_X509_CRL_add_dist_point");
10308
10309 if (x509 == NULL || uri == NULL) {
10310 return WOLFSSL_FAILURE;
10311 }
10312
10313 uriLen = (word32)XSTRLEN(uri);
10314 if (uriLen == 0) {
10315 WOLFSSL_MSG("URI empty");
10316 return WOLFSSL_FAILURE;
10317 }
10318
10319 /*
10320 * Encode CRL Distribution Points in DER format:
10321 * CRLDistributionPoints ::= SEQUENCE OF DistributionPoint
10322 * DistributionPoint ::= SEQUENCE {
10323 * distributionPoint [0] EXPLICIT DistributionPointName OPTIONAL
10324 * }
10325 * DistributionPointName ::= CHOICE {
10326 * fullName [0] IMPLICIT GeneralNames
10327 * }
10328 * GeneralNames ::= SEQUENCE OF GeneralName
10329 * GeneralName ::= [6] IMPLICIT IA5String (uniformResourceIdentifier)
10330 */
10331
10332 /* Calculate sizes from innermost to outermost */
10333 /* [6] tag (1 byte) + length encoding + URI data */
10334 uriTagLen = ASN_TAG_SZ + SetLength(uriLen, NULL) + uriLen;
10335 /* [0] CONSTRUCTED tag (1 byte) + length encoding + uriTagLen */
10336 genNamesLen = ASN_TAG_SZ + SetLength(uriTagLen, NULL) + uriTagLen;
10337 /* [0] CONSTRUCTED tag (1 byte) + length encoding + genNamesLen */
10338 distPtNmLen = ASN_TAG_SZ + SetLength(genNamesLen, NULL) + genNamesLen;
10339 /* SEQUENCE header + distPtNmLen */
10340 distPtSeqLen = SetSequence(distPtNmLen, NULL) + distPtNmLen;
10341 /* Outer SEQUENCE header + distPtSeqLen */
10342 outerSeqLen = SetSequence(distPtSeqLen, NULL) + distPtSeqLen;
10343
10344 derSz = outerSeqLen;
10345
10346 /* Allocate buffer for DER encoding */
10347 derBuf = (byte*)XMALLOC(derSz, x509->heap, DYNAMIC_TYPE_X509_EXT);
10348 if (derBuf == NULL) {
10349 return WOLFSSL_FAILURE;
10350 }
10351
10352 /* Build forward using SetSequence/SetHeader/SetLength */
10353 idx = 0;
10354
10355 /* SEQUENCE for CRLDistributionPoints (outer) */
10356 idx += SetSequence(distPtSeqLen, derBuf + idx);
10357
10358 /* SEQUENCE for DistributionPoint */
10359 idx += SetSequence(distPtNmLen, derBuf + idx);
10360
10361 /* [0] EXPLICIT wrapper for distributionPoint */
10362 derBuf[idx++] = (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED);
10363 idx += SetLength(genNamesLen, derBuf + idx);
10364
10365 /* [0] IMPLICIT wrapper for GeneralNames (constructed) */
10366 derBuf[idx++] = (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED);
10367 idx += SetLength(uriTagLen, derBuf + idx);
10368
10369 /* [6] IMPLICIT IA5String tag for URI (context-specific, primitive) */
10370 derBuf[idx++] = (ASN_CONTEXT_SPECIFIC | 6); /* [6] tag */
10371 idx += SetLength(uriLen, derBuf + idx);
10372
10373 /* Copy URI string */
10374 XMEMCPY(derBuf + idx, uri, uriLen);
10375 idx += uriLen;
10376
10377 /* Store the encoded CRL info in x509 */
10378 {
10379 ret = wolfSSL_X509_CRL_set_dist_points(x509, derBuf, (int)idx);
10380 if (ret == WOLFSSL_SUCCESS && critical) {
10381 x509->CRLdistCrit = 1;
10382 }
10383 }
10384
10385 XFREE(derBuf, x509->heap, DYNAMIC_TYPE_X509_EXT);
10386
10387 return ret;
10388}
10389#endif /* WOLFSSL_CERT_EXT && (OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL) */
10390
10391#ifdef OPENSSL_EXTRA
10392
10393
10394WOLFSSL_X509_VERIFY_PARAM* wolfSSL_X509_VERIFY_PARAM_new(void)
10395{
10396 WOLFSSL_X509_VERIFY_PARAM *param = NULL;
10397 param = (WOLFSSL_X509_VERIFY_PARAM*)XMALLOC(
10398 sizeof(WOLFSSL_X509_VERIFY_PARAM), NULL, DYNAMIC_TYPE_OPENSSL);
10399 if (param != NULL)
10400 XMEMSET(param, 0, sizeof(WOLFSSL_X509_VERIFY_PARAM ));
10401
10402 return(param);
10403}
10404
10405
10406void wolfSSL_X509_VERIFY_PARAM_free(WOLFSSL_X509_VERIFY_PARAM *param)
10407{
10408 XFREE(param, NULL, DYNAMIC_TYPE_OPENSSL);
10409}
10410
10411
10412/* Sets flags by OR'ing with existing value. */
10413int wolfSSL_X509_VERIFY_PARAM_set_flags(WOLFSSL_X509_VERIFY_PARAM *param,
10414 unsigned long flags)
10415{
10416 int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
10417
10418 if (param != NULL) {
10419 param->flags |= flags;
10420 ret = WOLFSSL_SUCCESS;
10421 }
10422
10423 return ret;
10424}
10425
10426
10427int wolfSSL_X509_VERIFY_PARAM_get_flags(WOLFSSL_X509_VERIFY_PARAM *param)
10428{
10429 int ret = 0;
10430
10431 if (param != NULL) {
10432 ret = (int)param->flags;
10433 }
10434
10435 return ret;
10436}
10437
10438
10439int wolfSSL_X509_VERIFY_PARAM_clear_flags(WOLFSSL_X509_VERIFY_PARAM *param,
10440 unsigned long flags)
10441{
10442 int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
10443
10444 if (param != NULL) {
10445 param->flags &= ~flags;
10446 ret = WOLFSSL_SUCCESS;
10447 }
10448
10449 return ret;
10450}
10451
10452/* note WOLFSSL_X509_VERIFY_PARAM does not record purpose, trust, depth, or
10453 * auth_level.
10454 */
10455static const WOLFSSL_X509_VERIFY_PARAM x509_verify_param_builtins[] = {
10456 {
10457 "ssl_client", /* name */
10458 0, /* check_time */
10459 0, /* inherit_flags */
10460 0, /* flags */
10461 "", /* hostname */
10462 0, /* hostFlags */
10463 "" /* ipasc */
10464 },
10465 {
10466 "ssl_server", /* name */
10467 0, /* check_time */
10468 0, /* inherit_flags */
10469 0, /* flags */
10470 "", /* hostname */
10471 0, /* hostFlags */
10472 "" /* ipasc */
10473 }
10474};
10475
10476const WOLFSSL_X509_VERIFY_PARAM *wolfSSL_X509_VERIFY_PARAM_lookup(
10477 const char *name)
10478{
10479 const WOLFSSL_X509_VERIFY_PARAM *param = &x509_verify_param_builtins[0],
10480 *param_end = &x509_verify_param_builtins[
10481 XELEM_CNT(x509_verify_param_builtins)];
10482
10483 if (name == NULL) {
10484 return NULL;
10485 }
10486 while (param < param_end) {
10487 if (XSTRCMP(name, param->name) == 0)
10488 return param;
10489 ++param;
10490 }
10491 return NULL;
10492}
10493
10494/* inherits properties of param "to" to param "from"
10495*
10496* WOLFSSL_VPARAM_DEFAULT any values in "src" is copied
10497* if "src" value is new for "to".
10498* WOLFSSL_VPARAM_OVERWRITE all values of "form" are copied to "to"
10499* WOLFSSL_VPARAM_RESET_FLAGS the flag values are copied, not Ored
10500* WOLFSSL_VPARAM_LOCKED don't copy any values
10501* WOLFSSL_VPARAM_ONCE the current inherit_flags is zerroed
10502*/
10503int wolfSSL_X509_VERIFY_PARAM_inherit(WOLFSSL_X509_VERIFY_PARAM *to,
10504 const WOLFSSL_X509_VERIFY_PARAM *from)
10505{
10506 int ret = WOLFSSL_SUCCESS;
10507 int isOverWrite = 0;
10508 int isDefault = 0;
10509 unsigned int flags;
10510
10511 /* sanity check */
10512 if (!to || !from) {
10513 /* be compatible to openssl return value */
10514 return WOLFSSL_SUCCESS;
10515 }
10516 flags = to->inherit_flags | from->inherit_flags;
10517
10518 if (flags & WOLFSSL_VPARAM_LOCKED) {
10519 return WOLFSSL_SUCCESS;
10520 }
10521
10522 if (flags & WOLFSSL_VPARAM_ONCE) {
10523 to->inherit_flags = 0;
10524 }
10525
10526 isOverWrite = (flags & WOLFSSL_VPARAM_OVERWRITE);
10527 isDefault = (flags & WOLFSSL_VPARAM_DEFAULT);
10528
10529 /* copy check_time if check time is not set */
10530 if ((to->flags & WOLFSSL_USE_CHECK_TIME) == 0 || isOverWrite) {
10531 to->check_time = from->check_time;
10532 to->flags &= ~WOLFSSL_USE_CHECK_TIME;
10533 }
10534 /* host name */
10535 if (isOverWrite ||
10536 (from->hostName[0] != 0 && (to->hostName[0] == 0 || isDefault))) {
10537 if (!(ret = wolfSSL_X509_VERIFY_PARAM_set1_host(to, from->hostName,
10538 (unsigned int)XSTRLEN(from->hostName))))
10539 return ret;
10540 to->hostFlags = from->hostFlags;
10541 }
10542 /* ip ascii */
10543 if (isOverWrite ||
10544 (from->ipasc[0] != 0 && (to->ipasc[0] == 0 || isDefault))) {
10545
10546 if (!(ret = wolfSSL_X509_VERIFY_PARAM_set1_ip_asc(to, from->ipasc)))
10547 return ret;
10548 }
10549
10550 if (flags & WOLFSSL_VPARAM_RESET_FLAGS)
10551 to->flags = 0;
10552
10553 to->flags |= from->flags;
10554
10555 return ret;
10556}
10557
10558/******************************************************************************
10559* wolfSSL_X509_VERIFY_PARAM_set1_host - sets the DNS hostname to name
10560* hostnames is cleared if name is NULL or empty.
10561*
10562* RETURNS:
10563*
10564*/
10565int wolfSSL_X509_VERIFY_PARAM_set1_host(WOLFSSL_X509_VERIFY_PARAM* pParam,
10566 const char* name,
10567 unsigned int nameSz)
10568{
10569 WOLFSSL_ENTER("wolfSSL_X509_VERIFY_PARAM_set1_host");
10570
10571 if (pParam == NULL)
10572 return WOLFSSL_FAILURE;
10573
10574 /* If name is NULL, clear hostname. */
10575 if (name == NULL) {
10576 XMEMSET(pParam->hostName, 0, WOLFSSL_HOST_NAME_MAX);
10577 return WOLFSSL_SUCCESS;
10578 }
10579
10580 /* If name is NULL-terminated, namelen can be set to zero. */
10581 if (nameSz == 0) {
10582 nameSz = (unsigned int)XSTRLEN(name);
10583 }
10584
10585 if (nameSz > 0 && name[nameSz - 1] == '\0')
10586 nameSz--;
10587
10588 if (nameSz > WOLFSSL_HOST_NAME_MAX-1) {
10589 WOLFSSL_MSG("Truncating name");
10590 nameSz = WOLFSSL_HOST_NAME_MAX-1;
10591 }
10592
10593 if (nameSz > 0) {
10594 XMEMCPY(pParam->hostName, name, nameSz);
10595 XMEMSET(pParam->hostName + nameSz, 0,
10596 WOLFSSL_HOST_NAME_MAX - nameSz);
10597 }
10598
10599 pParam->hostName[nameSz] = '\0';
10600
10601 return WOLFSSL_SUCCESS;
10602}
10603
10604/* Set VERIFY PARAM from "from" pointer to "to" pointer */
10605int wolfSSL_X509_VERIFY_PARAM_set1(WOLFSSL_X509_VERIFY_PARAM *to,
10606 const WOLFSSL_X509_VERIFY_PARAM *from)
10607{
10608 int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
10609 unsigned int _inherit_flags;
10610
10611 if (!to) {
10612 return ret;
10613 }
10614 /* keeps the inherit flags for save */
10615 _inherit_flags = to->inherit_flags;
10616
10617 /* Ored DEFAULT inherit flag property to copy "from" contents to "to"
10618 * contents
10619 */
10620 to->inherit_flags |= WOLFSSL_VPARAM_DEFAULT;
10621
10622 ret = wolfSSL_X509_VERIFY_PARAM_inherit(to, from);
10623
10624 /* restore inherit flag */
10625 to->inherit_flags = _inherit_flags;
10626
10627 return ret;
10628}
10629
10630/* Set the host flag in the X509_VERIFY_PARAM structure */
10631void wolfSSL_X509_VERIFY_PARAM_set_hostflags(WOLFSSL_X509_VERIFY_PARAM* param,
10632 unsigned int flags)
10633{
10634 if (param != NULL) {
10635 param->hostFlags = flags;
10636 }
10637}
10638
10639/* Sets the expected IP address to ipasc.
10640 *
10641 * param is a pointer to the X509_VERIFY_PARAM structure
10642 * ipasc is a NULL-terminated string with N.N.N.N for IPv4 and
10643 * HH:HH ... HH:HH for IPv6. There is no validation performed on the
10644 * parameter, and it must be an exact match with the IP in the cert.
10645 *
10646 * return 1 for success and 0 for failure*/
10647int wolfSSL_X509_VERIFY_PARAM_set1_ip_asc(WOLFSSL_X509_VERIFY_PARAM *param,
10648 const char *ipasc)
10649{
10650 int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
10651
10652 if (param != NULL) {
10653 if (ipasc == NULL) {
10654 param->ipasc[0] = '\0';
10655 }
10656 else {
10657 XSTRLCPY(param->ipasc, ipasc, WOLFSSL_MAX_IPSTR);
10658 param->ipasc[WOLFSSL_MAX_IPSTR-1] = '\0';
10659 }
10660 ret = WOLFSSL_SUCCESS;
10661 }
10662
10663 return ret;
10664}
10665/* Sets the expected IP address to ip(asc)
10666 * by re-constructing IP address in ascii
10667 * @param param is a pointer to the X509_VERIFY_PARAM structure
10668 * @param ip in binary format of ip address
10669 * @param iplen size of ip, 4 for ipv4, 16 for ipv6
10670 * @return 1 for success and 0 for failure
10671 */
10672int wolfSSL_X509_VERIFY_PARAM_set1_ip(WOLFSSL_X509_VERIFY_PARAM* param,
10673 const unsigned char* ip, size_t iplen)
10674{
10675 int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
10676#ifndef NO_FILESYSTEM
10677 char* buf = NULL;
10678 char* p = NULL;
10679 word32 val = 0;
10680 int i;
10681 const size_t max_ipv6_len = 40;
10682 byte write_zero = 0;
10683#endif
10684
10685 /* sanity check */
10686 if (param == NULL || (iplen != 0 && iplen != 4 && iplen != 16)) {
10687 WOLFSSL_MSG("bad function arg");
10688 return ret;
10689 }
10690 if (ip == NULL && iplen != 0) {
10691 WOLFSSL_MSG("bad function arg");
10692 return ret;
10693 }
10694#ifndef NO_FILESYSTEM
10695 if (iplen == 4) {
10696 /* ipv4 www.xxx.yyy.zzz max 15 length + Null termination */
10697 buf = (char*)XMALLOC(16, NULL, DYNAMIC_TYPE_TMP_BUFFER);
10698 if (!buf) {
10699 WOLFSSL_MSG("failed malloc");
10700 return ret;
10701 }
10702
10703 (void)XSNPRINTF(buf, 16, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
10704 buf[15] = '\0'; /* null terminate */
10705 }
10706 else if (iplen == 16) {
10707 /* ipv6 normal address scheme
10708 * y1:y2:y3:y4:y5:y6:y7:y8, len(yx):4, len(y1-y8):32. len(":"):7
10709 * Max len is 32 + 7 + 1(Termination) = 40 bytes
10710 *
10711 * ipv6 dual address
10712 * Or y1:y2:y3:y4:y:y6:x.x.x.x yx is 4, y1-y6 is 24, ":" is 6
10713 * x.x.x.x is 15.
10714 * Max len is 24 + 6 + 15 + 1(Termination) = 46 bytes
10715 *
10716 * Expect data in ip[16]
10717 * e.g (aaaa):(bbbb):(cccc):....(hhhh)
10718 * (aaaa) = (ip[0<<8)|ip[1]
10719 * ......
10720 * (hhhh) = (ip[14]<<8)|(ip[15])
10721 *
10722 * e.g ::(gggg):(hhhh)
10723 * ip[0]-[11] = 0
10724 * (gggg) = (ip[12]<<8) |(ip[13])
10725 * (hhhh) = (ip[14]<<8) |(ip[15])
10726 *
10727 * Because it is not able to know which ivp6 scheme uses from data to
10728 * reconstruct IP address, this function assumes
10729 * ivp6 normal address scheme, not dual address scheme,
10730 * to re-construct IP address in ascii.
10731 */
10732 buf = (char*)XMALLOC(max_ipv6_len, NULL, DYNAMIC_TYPE_TMP_BUFFER);
10733 if (!buf) {
10734 WOLFSSL_MSG("failed malloc");
10735 return ret;
10736 }
10737 p = buf;
10738 for (i = 0; i < 16; i += 2) {
10739 val = (((word32)(ip[i]<<8)) | (ip[i+1])) & 0xFFFF;
10740 if (val == 0) {
10741 if (!write_zero) {
10742 *p = ':';
10743 }
10744 p++;
10745 *p = '\0';
10746 write_zero = 1;
10747 }
10748 else {
10749 if (i != 0) {
10750 *p++ = ':';
10751 }
10752 (void)XSNPRINTF(p, max_ipv6_len - (size_t)(p - buf), "%x", val);
10753 }
10754 /* sanity check */
10755 if (XSTRLEN(buf) > max_ipv6_len) {
10756 WOLFSSL_MSG("The target ip address exceeds buffer length(40)");
10757 XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
10758 buf = NULL;
10759 break;
10760 }
10761 /* move the pointer to the last */
10762 /* XSTRLEN includes NULL because of XSPRINTF use */
10763 p = buf + (XSTRLEN(buf));
10764 }
10765 /* termination */
10766 if (i == 16 && buf) {
10767 p--;
10768 if ((*p) == ':') {
10769 /* when the last character is :, the following segments are zero
10770 * Therefore, adding : and null termination */
10771 p++;
10772 *p++ = ':';
10773 *p = '\0';
10774 }
10775 }
10776 }
10777 else {
10778 WOLFSSL_MSG("iplen is zero, do nothing");
10779 return WOLFSSL_SUCCESS;
10780 }
10781
10782 if (buf) {
10783 /* set address to ip asc */
10784 ret = wolfSSL_X509_VERIFY_PARAM_set1_ip_asc(param, buf);
10785 XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
10786 }
10787#else
10788 (void)param;
10789 (void)ip;
10790 (void)iplen;
10791#endif
10792
10793 return ret;
10794}
10795
10796#ifndef NO_WOLFSSL_STUB
10797void wolfSSL_X509_OBJECT_free_contents(WOLFSSL_X509_OBJECT* obj)
10798{
10799 (void)obj;
10800 WOLFSSL_STUB("X509_OBJECT_free_contents");
10801}
10802#endif
10803
10804#ifndef NO_ASN_TIME
10805int wolfSSL_X509_cmp_current_time(const WOLFSSL_ASN1_TIME* asnTime)
10806{
10807 return wolfSSL_X509_cmp_time(asnTime, NULL);
10808}
10809
10810/* return WOLFSSL_FATAL_ERROR if asnTime is earlier than or equal to cmpTime,
10811 * and 1 otherwise
10812 * return 0 on error
10813 */
10814int wolfSSL_X509_cmp_time(const WOLFSSL_ASN1_TIME* asnTime, time_t* cmpTime)
10815{
10816 int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
10817 time_t tmpTime, *pTime = &tmpTime;
10818 struct tm ts, *tmpTs, *ct;
10819#if defined(NEED_TMP_TIME)
10820 /* for use with gmtime_r */
10821 struct tm tmpTimeStorage;
10822
10823 tmpTs = &tmpTimeStorage;
10824#else
10825 tmpTs = NULL;
10826#endif
10827 (void)tmpTs;
10828
10829 if (asnTime == NULL) {
10830 return WOLFSSL_FAILURE;
10831 }
10832
10833 if (cmpTime == NULL) {
10834 /* Use current time */
10835 *pTime = wc_Time(0);
10836 }
10837 else {
10838 pTime = cmpTime;
10839 }
10840
10841 if (wolfSSL_ASN1_TIME_to_tm((WOLFSSL_ASN1_TIME*)asnTime, &ts) !=
10842 WOLFSSL_SUCCESS) {
10843 WOLFSSL_MSG("Failed to convert WOLFSSL_ASN1_TIME to struct tm.");
10844 return WOLFSSL_FAILURE;
10845 }
10846
10847 /* Convert to time struct*/
10848 ct = XGMTIME(pTime, tmpTs);
10849
10850 if (ct == NULL)
10851 return GETTIME_ERROR;
10852
10853 /* DateGreaterThan returns 1 for >; 0 for <= */
10854 ret = DateGreaterThan(&ts, ct) ? 1 : -1;
10855
10856 return ret;
10857}
10858#endif /* !NO_ASN_TIME */
10859
10860#if (defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)) && \
10861 !defined(NO_ASN_TIME) && !defined(USER_TIME) && !defined(TIME_OVERRIDES)
10862WOLFSSL_ASN1_TIME *wolfSSL_X509_time_adj_ex(WOLFSSL_ASN1_TIME *asnTime,
10863 int offset_day, long offset_sec, time_t *in_tm)
10864{
10865 /* get current time if in_tm is null */
10866 time_t t = in_tm ? *in_tm : wc_Time(0);
10867 return wolfSSL_ASN1_TIME_adj(asnTime, t, offset_day, offset_sec);
10868}
10869
10870WOLFSSL_ASN1_TIME *wolfSSL_X509_time_adj(WOLFSSL_ASN1_TIME *asnTime,
10871 long offset_sec, time_t *in_tm)
10872{
10873 return wolfSSL_X509_time_adj_ex(asnTime, 0, offset_sec, in_tm);
10874}
10875
10876WOLFSSL_ASN1_TIME* wolfSSL_X509_gmtime_adj(WOLFSSL_ASN1_TIME *s, long adj)
10877{
10878 return wolfSSL_X509_time_adj(s, adj, NULL);
10879}
10880#endif
10881
10882int wolfSSL_sk_X509_REVOKED_num(WOLFSSL_STACK* sk)
10883{
10884 WOLFSSL_ENTER("wolfSSL_sk_X509_REVOKED_num");
10885 if (sk != NULL) {
10886 return (int)sk->num;
10887 }
10888 return 0;
10889}
10890
10891/* Free a WOLFSSL_X509_REVOKED and all its owned memory. */
10892void wolfSSL_X509_REVOKED_free(WOLFSSL_X509_REVOKED* rev)
10893{
10894 if (rev == NULL) {
10895 return;
10896 }
10897
10898 wolfSSL_ASN1_INTEGER_free(rev->serialNumber);
10899 wolfSSL_ASN1_TIME_free(rev->revocationDate);
10900
10901 if (rev->extensions != NULL) {
10902 wolfSSL_sk_pop_free(rev->extensions, NULL);
10903 }
10904 if (rev->issuer != NULL) {
10905 wolfSSL_sk_pop_free(rev->issuer, NULL);
10906 }
10907
10908 XFREE(rev, NULL, DYNAMIC_TYPE_OPENSSL);
10909}
10910
10911#ifdef HAVE_CRL
10912/* Build a WOLFSSL_X509_REVOKED from an internal RevokedCert.
10913 * Caller takes ownership of the returned object. */
10914static WOLFSSL_X509_REVOKED* RevokedCertToRevoked(RevokedCert* rc, int seq)
10915{
10916 WOLFSSL_X509_REVOKED* rev;
10917 WOLFSSL_ASN1_INTEGER* serial;
10918
10919 if (rc == NULL) {
10920 return NULL;
10921 }
10922
10923 rev = (WOLFSSL_X509_REVOKED*)XMALLOC(sizeof(WOLFSSL_X509_REVOKED), NULL,
10924 DYNAMIC_TYPE_OPENSSL);
10925 if (rev == NULL) {
10926 return NULL;
10927 }
10928 XMEMSET(rev, 0, sizeof(WOLFSSL_X509_REVOKED));
10929
10930 /* Serial number */
10931 serial = wolfSSL_ASN1_INTEGER_new();
10932 if (serial == NULL) {
10933 XFREE(rev, NULL, DYNAMIC_TYPE_OPENSSL);
10934 return NULL;
10935 }
10936 if (rc->serialSz > 0 && rc->serialSz <= EXTERNAL_SERIAL_SIZE) {
10937 serial->data = (unsigned char*)XMALLOC((size_t)rc->serialSz, NULL,
10938 DYNAMIC_TYPE_OPENSSL);
10939 if (serial->data == NULL) {
10940 wolfSSL_ASN1_INTEGER_free(serial);
10941 XFREE(rev, NULL, DYNAMIC_TYPE_OPENSSL);
10942 return NULL;
10943 }
10944 XMEMCPY(serial->data, rc->serialNumber, (size_t)rc->serialSz);
10945 serial->length = rc->serialSz;
10946 serial->dataMax = rc->serialSz;
10947 serial->isDynamic = 1;
10948 }
10949 rev->serialNumber = serial;
10950
10951 /* Revocation date */
10952 {
10953 WOLFSSL_ASN1_TIME* revDate = wolfSSL_ASN1_TIME_new();
10954 if (revDate != NULL) {
10955 int dateLen = 0;
10956 /* Determine date length from the format byte */
10957 if (rc->revDateFormat == ASN_UTC_TIME ||
10958 rc->revDateFormat == ASN_GENERALIZED_TIME) {
10959 /* Find actual length: dates are null-terminated strings in
10960 * revDate buffer up to MAX_DATE_SIZE */
10961 while (dateLen < MAX_DATE_SIZE && rc->revDate[dateLen] != 0)
10962 dateLen++;
10963 }
10964 if (dateLen > 0 && dateLen < MAX_DATE_SIZE) {
10965 XMEMCPY(revDate->data, rc->revDate, (size_t)dateLen);
10966 revDate->length = dateLen;
10967 revDate->type = rc->revDateFormat;
10968 }
10969 }
10970 rev->revocationDate = revDate;
10971 }
10972
10973 /* Reason code */
10974 rev->reason = rc->reasonCode;
10975
10976 /* Sequence (load order) */
10977 rev->sequence = seq;
10978
10979 /* issuer: left as NULL (indirect CRL not yet supported) */
10980 /* extensions: left as NULL for now (raw DER available in RevokedCert
10981 * but decoded STACK_OF(X509_EXTENSION) build not yet implemented) */
10982
10983 return rev;
10984}
10985#endif /* HAVE_CRL */
10986
10987WOLFSSL_STACK* wolfSSL_X509_CRL_get_REVOKED(WOLFSSL_X509_CRL* crl)
10988{
10989 WOLFSSL_ENTER("wolfSSL_X509_CRL_get_REVOKED");
10990
10991 if (crl == NULL) {
10992 return NULL;
10993 }
10994
10995#if defined(OPENSSL_EXTRA) && defined(HAVE_CRL)
10996 /* Return cached stack if already built */
10997 if (crl->revokedStack != NULL) {
10998 return crl->revokedStack;
10999 }
11000
11001 /* Build the stack from the internal RevokedCert linked list */
11002 if (crl->crlList != NULL) {
11003 WOLFSSL_STACK* sk;
11004 RevokedCert* rc;
11005 int seq = 0;
11006
11007 sk = wolfSSL_sk_new_null();
11008 if (sk == NULL) {
11009 return NULL;
11010 }
11011 sk->type = STACK_TYPE_X509_REVOKED;
11012
11013 for (rc = crl->crlList->certs; rc != NULL; rc = rc->next) {
11014 WOLFSSL_X509_REVOKED* rev = RevokedCertToRevoked(rc, seq);
11015 if (rev == NULL) {
11016 /* Clean up on failure */
11017 wolfSSL_sk_pop_free(sk, NULL);
11018 return NULL;
11019 }
11020 /* Push to stack. wolfSSL_sk_push returns total count on success. */
11021 if (wolfSSL_sk_push(sk, rev) <= 0) {
11022 wolfSSL_X509_REVOKED_free(rev);
11023 wolfSSL_sk_pop_free(sk, NULL);
11024 return NULL;
11025 }
11026 seq++;
11027 }
11028
11029 crl->revokedStack = sk;
11030 return sk;
11031 }
11032#endif /* OPENSSL_EXTRA && HAVE_CRL */
11033
11034 return NULL;
11035}
11036
11037WOLFSSL_X509_REVOKED* wolfSSL_sk_X509_REVOKED_value(
11038 WOLFSSL_STACK* sk, int idx)
11039{
11040 WOLFSSL_ENTER("wolfSSL_sk_X509_REVOKED_value");
11041
11042 if (sk == NULL) {
11043 return NULL;
11044 }
11045
11046 return (WOLFSSL_X509_REVOKED*)wolfSSL_sk_value(sk, idx);
11047}
11048
11049/* Extension accessors for WOLFSSL_X509_REVOKED */
11050int wolfSSL_X509_REVOKED_get_ext_count(const WOLFSSL_X509_REVOKED* rev)
11051{
11052 WOLFSSL_ENTER("wolfSSL_X509_REVOKED_get_ext_count");
11053 if (rev != NULL && rev->extensions != NULL) {
11054 return (int)rev->extensions->num;
11055 }
11056 return 0;
11057}
11058
11059WOLFSSL_X509_EXTENSION* wolfSSL_X509_REVOKED_get_ext(
11060 const WOLFSSL_X509_REVOKED* rev, int loc)
11061{
11062 WOLFSSL_ENTER("wolfSSL_X509_REVOKED_get_ext");
11063 if (rev != NULL && rev->extensions != NULL) {
11064 return (WOLFSSL_X509_EXTENSION*)wolfSSL_sk_value(rev->extensions, loc);
11065 }
11066 return NULL;
11067}
11068
11069#endif /* OPENSSL_EXTRA */
11070
11071#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
11072
11073WOLFSSL_ASN1_INTEGER* wolfSSL_X509_get_serialNumber(WOLFSSL_X509* x509)
11074{
11075 WOLFSSL_ASN1_INTEGER* a;
11076 int i = 0;
11077
11078 WOLFSSL_ENTER("wolfSSL_X509_get_serialNumber");
11079
11080 if (x509 == NULL) {
11081 WOLFSSL_MSG("NULL function argument");
11082 return NULL;
11083 }
11084
11085 if (x509->serialNumber != NULL)
11086 return x509->serialNumber;
11087
11088 if (x509->serialSz < 0) {
11089 WOLFSSL_MSG("Invalid serial number size");
11090 return NULL;
11091 }
11092
11093 a = wolfSSL_ASN1_INTEGER_new();
11094 if (a == NULL)
11095 return NULL;
11096
11097 /* Make sure there is space for the data, ASN.1 type and length. */
11098 if (x509->serialSz > (WOLFSSL_ASN1_INTEGER_MAX - 2)) {
11099 /* dynamically create data buffer, +2 for type and length */
11100 a->data = (unsigned char*)XMALLOC(x509->serialSz + 2, NULL,
11101 DYNAMIC_TYPE_OPENSSL);
11102 if (a->data == NULL) {
11103 wolfSSL_ASN1_INTEGER_free(a);
11104 return NULL;
11105 }
11106 a->dataMax = (unsigned int)x509->serialSz + 2;
11107 a->isDynamic = 1;
11108 }
11109 else {
11110 /* Use array instead of dynamic memory */
11111 a->data = a->intData;
11112 a->dataMax = WOLFSSL_ASN1_INTEGER_MAX;
11113 }
11114
11115 #if defined(WOLFSSL_QT) || defined(WOLFSSL_HAPROXY)
11116 XMEMCPY(&a->data[i], x509->serial, x509->serialSz);
11117 a->length = x509->serialSz;
11118 #else
11119 a->data[i++] = ASN_INTEGER;
11120 i += SetLength(x509->serialSz, a->data + i);
11121 XMEMCPY(&a->data[i], x509->serial, x509->serialSz);
11122 a->length = x509->serialSz + 2;
11123 #endif
11124
11125 x509->serialNumber = a;
11126
11127 return a;
11128}
11129
11130#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
11131
11132#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
11133
11134#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || \
11135 defined(WOLFSSL_APACHE_HTTPD) || defined(WOLFSSL_HAPROXY) || \
11136 defined(WOLFSSL_WPAS)
11137WOLFSSL_X509_ALGOR* wolfSSL_X509_ALGOR_new(void)
11138{
11139 WOLFSSL_X509_ALGOR* ret;
11140 ret = (WOLFSSL_X509_ALGOR*)XMALLOC(sizeof(WOLFSSL_X509_ALGOR), NULL,
11141 DYNAMIC_TYPE_OPENSSL);
11142 if (ret) {
11143 XMEMSET(ret, 0, sizeof(WOLFSSL_X509_ALGOR));
11144 }
11145 return ret;
11146}
11147
11148void wolfSSL_X509_ALGOR_free(WOLFSSL_X509_ALGOR *alg)
11149{
11150 if (alg) {
11151 wolfSSL_ASN1_OBJECT_free(alg->algorithm);
11152 wolfSSL_ASN1_TYPE_free(alg->parameter);
11153 XFREE(alg, NULL, DYNAMIC_TYPE_OPENSSL);
11154 }
11155}
11156
11157/* Returns X509_ALGOR struct with signature algorithm */
11158const WOLFSSL_X509_ALGOR* wolfSSL_X509_get0_tbs_sigalg(const WOLFSSL_X509 *x509)
11159{
11160 WOLFSSL_ENTER("wolfSSL_X509_get0_tbs_sigalg");
11161
11162 if (x509 == NULL) {
11163 WOLFSSL_MSG("x509 struct NULL error");
11164 return NULL;
11165 }
11166
11167 return &x509->algor;
11168}
11169
11170/* Sets paobj pointer to X509_ALGOR signature algorithm */
11171void wolfSSL_X509_ALGOR_get0(const WOLFSSL_ASN1_OBJECT **paobj, int *pptype,
11172 const void **ppval, const WOLFSSL_X509_ALGOR *algor)
11173{
11174 WOLFSSL_ENTER("wolfSSL_X509_ALGOR_get0");
11175
11176 if (!algor) {
11177 WOLFSSL_MSG("algor object is NULL");
11178 return;
11179 }
11180
11181 if (paobj)
11182 *paobj = algor->algorithm;
11183 if (ppval && algor->parameter)
11184 *ppval = algor->parameter->value.ptr;
11185 if (pptype) {
11186 if (algor->parameter) {
11187 *pptype = algor->parameter->type;
11188 }
11189 else {
11190 /* Default to WOLFSSL_V_ASN1_OBJECT */
11191 *pptype = WOLFSSL_V_ASN1_OBJECT;
11192 }
11193 }
11194}
11195
11196/**
11197 * Populate algor members.
11198 *
11199 * @param algor The object to be set
11200 * @param aobj The value to be set in algor->algorithm
11201 * @param ptype The type of algor->parameter
11202 * @param pval The value of algor->parameter
11203 * @return WOLFSSL_SUCCESS on success
11204 * WOLFSSL_FAILURE on missing parameters or bad malloc
11205 */
11206int wolfSSL_X509_ALGOR_set0(WOLFSSL_X509_ALGOR *algor,
11207 WOLFSSL_ASN1_OBJECT *aobj, int ptype, void *pval)
11208{
11209 if (!algor) {
11210 return WOLFSSL_FAILURE;
11211 }
11212
11213 if (!algor->parameter) {
11214 algor->parameter = wolfSSL_ASN1_TYPE_new();
11215 if (!algor->parameter) {
11216 return WOLFSSL_FAILURE;
11217 }
11218 }
11219
11220 if (aobj) {
11221 algor->algorithm = aobj;
11222 }
11223 wolfSSL_ASN1_TYPE_set(algor->parameter, ptype, pval);
11224
11225 return WOLFSSL_SUCCESS;
11226}
11227
11228/**
11229 * Serialize object to DER encoding
11230 *
11231 * @param alg Object to serialize
11232 * @param pp Output
11233 * @return Length on success
11234 * Negative number on failure
11235 */
11236int wolfSSL_i2d_X509_ALGOR(const WOLFSSL_X509_ALGOR* alg,
11237 unsigned char** pp)
11238{
11239 int len;
11240 word32 oid = 0;
11241 word32 idx = 0;
11242 unsigned char* buf = NULL;
11243
11244 if (alg == NULL || alg->algorithm == 0) {
11245 WOLFSSL_MSG("alg is NULL or algorithm not set");
11246 return WOLFSSL_FATAL_ERROR;
11247 }
11248
11249 if (GetObjectId(alg->algorithm->obj, &idx, &oid,
11250 (word32)alg->algorithm->grp, alg->algorithm->objSz) < 0) {
11251 WOLFSSL_MSG("Issue getting OID of object");
11252 return WOLFSSL_FATAL_ERROR;
11253 }
11254
11255 len = (int)SetAlgoID((int)oid, NULL, alg->algorithm->grp, 0);
11256 if (len == 0) {
11257 WOLFSSL_MSG("SetAlgoID error");
11258 return WOLFSSL_FATAL_ERROR;
11259 }
11260
11261 if (pp != NULL) {
11262 if (*pp != NULL)
11263 buf = *pp;
11264 else {
11265 buf = (byte*)XMALLOC((size_t)len, NULL, DYNAMIC_TYPE_ASN1);
11266 if (buf == NULL)
11267 return WOLFSSL_FATAL_ERROR;
11268 }
11269
11270 len = (int)SetAlgoID((int)oid, buf, alg->algorithm->grp, 0);
11271 if (len == 0) {
11272 WOLFSSL_MSG("SetAlgoID error");
11273 if (*pp == NULL)
11274 XFREE(buf, NULL, DYNAMIC_TYPE_ASN1);
11275 return WOLFSSL_FATAL_ERROR;
11276 }
11277
11278 if (*pp != NULL)
11279 *pp += len;
11280 else
11281 *pp = buf;
11282 }
11283
11284 return len;
11285}
11286
11287WOLFSSL_X509_ALGOR* wolfSSL_d2i_X509_ALGOR(WOLFSSL_X509_ALGOR** out,
11288 const byte** src, long len)
11289{
11290 WOLFSSL_X509_ALGOR* ret = NULL;
11291 word32 idx = 0;
11292 word32 oid = 0;
11293 int grp;
11294
11295 WOLFSSL_ENTER("wolfSSL_d2i_X509_ALGOR");
11296
11297 if (src == NULL || *src == NULL || len == 0)
11298 return NULL;
11299
11300 if (GetAlgoId(*src, &idx, &oid, oidIgnoreType, (word32)len) != 0)
11301 return NULL;
11302
11303 /* Try to guess the type */
11304 for (grp = 0; grp < oidIgnoreType; grp++) {
11305 word32 oidSz;
11306 if (OidFromId(oid, (word32)grp, &oidSz) != NULL)
11307 break;
11308 }
11309 if (grp == oidIgnoreType)
11310 return NULL;
11311
11312 ret = wolfSSL_X509_ALGOR_new();
11313 if (ret == NULL)
11314 return NULL;
11315
11316 ret->algorithm = wolfSSL_OBJ_nid2obj(oid2nid(oid, grp));
11317 if (ret->algorithm == NULL) {
11318 wolfSSL_X509_ALGOR_free(ret);
11319 return NULL;
11320 }
11321 *src += idx;
11322
11323 if (out != NULL) {
11324 if (*out != NULL)
11325 wolfSSL_X509_ALGOR_free(*out);
11326 *out = ret;
11327 }
11328
11329 return ret;
11330}
11331
11332/**
11333 * Allocate a new WOLFSSL_X509_PUBKEY object.
11334 *
11335 * @return New zero'ed WOLFSSL_X509_PUBKEY object
11336 */
11337WOLFSSL_X509_PUBKEY *wolfSSL_X509_PUBKEY_new(void)
11338{
11339 WOLFSSL_X509_PUBKEY *ret;
11340 ret = (WOLFSSL_X509_PUBKEY*)XMALLOC(sizeof(WOLFSSL_X509_PUBKEY), NULL,
11341 DYNAMIC_TYPE_OPENSSL);
11342 if (!ret) {
11343 return NULL;
11344 }
11345 XMEMSET(ret, 0, sizeof(WOLFSSL_X509_PUBKEY));
11346 ret->algor = wolfSSL_X509_ALGOR_new();
11347 if (!ret->algor) {
11348 wolfSSL_X509_PUBKEY_free(ret);
11349 return NULL;
11350 }
11351 return ret;
11352}
11353
11354/**
11355 * Free WOLFSSL_X509_PUBKEY and all its members.
11356 *
11357 * @param at Object to free
11358 */
11359void wolfSSL_X509_PUBKEY_free(WOLFSSL_X509_PUBKEY *x)
11360{
11361 if (x) {
11362 if (x->algor) {
11363 wolfSSL_X509_ALGOR_free(x->algor);
11364 }
11365 if (x->pkey) {
11366 wolfSSL_EVP_PKEY_free(x->pkey);
11367 }
11368 XFREE(x, NULL, DYNAMIC_TYPE_OPENSSL);
11369 }
11370}
11371
11372/* Returns X509_PUBKEY structure containing X509_ALGOR and EVP_PKEY */
11373WOLFSSL_X509_PUBKEY* wolfSSL_X509_get_X509_PUBKEY(const WOLFSSL_X509* x509)
11374{
11375 WOLFSSL_ENTER("wolfSSL_X509_get_X509_PUBKEY");
11376
11377 if (x509 == NULL) {
11378 WOLFSSL_MSG("x509 struct NULL error");
11379 return NULL;
11380 }
11381
11382 return (WOLFSSL_X509_PUBKEY*)&x509->key;
11383}
11384
11385/* Sets ppkalg pointer to X509_PUBKEY algorithm. Returns WOLFSSL_SUCCESS on
11386 success or WOLFSSL_FAILURE on error. */
11387int wolfSSL_X509_PUBKEY_get0_param(WOLFSSL_ASN1_OBJECT **ppkalg,
11388 const unsigned char **pk, int *ppklen, WOLFSSL_X509_ALGOR **pa,
11389 WOLFSSL_X509_PUBKEY *pub)
11390{
11391 WOLFSSL_ENTER("wolfSSL_X509_PUBKEY_get0_param");
11392
11393 if (!pub || !pub->pubKeyOID) {
11394 WOLFSSL_MSG("X509_PUBKEY struct not populated");
11395 return WOLFSSL_FAILURE;
11396 }
11397
11398 if (!pub->algor) {
11399 if (!(pub->algor = wolfSSL_X509_ALGOR_new())) {
11400 return WOLFSSL_FAILURE;
11401 }
11402 pub->algor->algorithm = wolfSSL_OBJ_nid2obj(pub->pubKeyOID);
11403 if (pub->algor->algorithm == NULL) {
11404 WOLFSSL_MSG("Failed to create object from NID");
11405 return WOLFSSL_FAILURE;
11406 }
11407 }
11408
11409 if (pa)
11410 *pa = pub->algor;
11411 if (ppkalg)
11412 *ppkalg = pub->algor->algorithm;
11413 if (pk)
11414 *pk = (unsigned char*)pub->pkey->pkey.ptr;
11415 if (ppklen)
11416 *ppklen = pub->pkey->pkey_sz;
11417
11418 return WOLFSSL_SUCCESS;
11419}
11420
11421/* Returns a pointer to the pkey when passed a key */
11422WOLFSSL_EVP_PKEY* wolfSSL_X509_PUBKEY_get(WOLFSSL_X509_PUBKEY* key)
11423{
11424 WOLFSSL_ENTER("wolfSSL_X509_PUBKEY_get");
11425 if (key == NULL || key->pkey == NULL) {
11426 WOLFSSL_LEAVE("wolfSSL_X509_PUBKEY_get", BAD_FUNC_ARG);
11427 return NULL;
11428 }
11429 if (wolfSSL_EVP_PKEY_up_ref(key->pkey) != WOLFSSL_SUCCESS) {
11430 WOLFSSL_LEAVE("wolfSSL_X509_PUBKEY_get", BAD_MUTEX_E);
11431 return NULL;
11432 }
11433 WOLFSSL_LEAVE("wolfSSL_X509_PUBKEY_get", WOLFSSL_SUCCESS);
11434 return key->pkey;
11435}
11436
11437int wolfSSL_X509_PUBKEY_set(WOLFSSL_X509_PUBKEY **x, WOLFSSL_EVP_PKEY *key)
11438{
11439 WOLFSSL_X509_PUBKEY *pk = NULL;
11440 int ptype;
11441 void *pval;
11442#ifndef NO_DSA
11443 WOLFSSL_ASN1_STRING *str;
11444#endif
11445#ifdef HAVE_ECC
11446 int nid;
11447 const WOLFSSL_EC_GROUP *group;
11448#endif
11449 WOLFSSL_ASN1_OBJECT *keyTypeObj;
11450
11451 WOLFSSL_ENTER("wolfSSL_X509_PUBKEY_set");
11452
11453 if (!x || !key) {
11454 return WOLFSSL_FAILURE;
11455 }
11456
11457 if (!(pk = wolfSSL_X509_PUBKEY_new())) {
11458 return WOLFSSL_FAILURE;
11459 }
11460
11461 switch (key->type) {
11462#ifndef NO_RSA
11463 case WC_EVP_PKEY_RSA:
11464 pval = NULL;
11465 ptype = WOLFSSL_V_ASN1_NULL;
11466 pk->pubKeyOID = RSAk;
11467 break;
11468#endif
11469#ifndef NO_DSA
11470 case WC_EVP_PKEY_DSA:
11471 if (!key->dsa->p || !key->dsa->q || !key->dsa->g)
11472 goto error;
11473
11474 str = wolfSSL_ASN1_STRING_new();
11475 if (str == NULL)
11476 goto error;
11477
11478 str->length = wolfSSL_i2d_DSAparams(key->dsa,
11479 (unsigned char **)&str->data);
11480 if (str->length <= 0) {
11481 wolfSSL_ASN1_STRING_free(str);
11482 goto error;
11483 }
11484 str->isDynamic = 1;
11485
11486 pval = str;
11487 ptype = WOLFSSL_V_ASN1_SEQUENCE;
11488 pk->pubKeyOID = DSAk;
11489 break;
11490#endif
11491#ifdef HAVE_ECC
11492 case WC_EVP_PKEY_EC:
11493 group = wolfSSL_EC_KEY_get0_group(key->ecc);
11494 if (!group)
11495 goto error;
11496
11497 nid = wolfSSL_EC_GROUP_get_curve_name(group);
11498 if (nid <= 0) {
11499 /* TODO: Add support for no nid case */
11500 WOLFSSL_MSG("nid not found");
11501 goto error;
11502 }
11503
11504 pval = wolfSSL_OBJ_nid2obj(nid);
11505 if (!pval)
11506 goto error;
11507
11508 ptype = WOLFSSL_V_ASN1_OBJECT;
11509 pk->pubKeyOID = ECDSAk;
11510 break;
11511#endif
11512 default:
11513 WOLFSSL_MSG("Unknown key type");
11514 goto error;
11515 }
11516
11517 keyTypeObj = wolfSSL_OBJ_nid2obj(key->type);
11518 if (keyTypeObj == NULL) {
11519 if (ptype == WOLFSSL_V_ASN1_OBJECT)
11520 wolfSSL_ASN1_OBJECT_free((WOLFSSL_ASN1_OBJECT *)pval);
11521 else
11522 wolfSSL_ASN1_STRING_free((WOLFSSL_ASN1_STRING *)pval);
11523 goto error;
11524 }
11525 if (!wolfSSL_X509_ALGOR_set0(pk->algor, keyTypeObj, ptype, pval)) {
11526 WOLFSSL_MSG("Failed to create algorithm object");
11527 wolfSSL_ASN1_OBJECT_free(keyTypeObj);
11528 if (ptype == WOLFSSL_V_ASN1_OBJECT)
11529 wolfSSL_ASN1_OBJECT_free((WOLFSSL_ASN1_OBJECT *)pval);
11530 else
11531 wolfSSL_ASN1_STRING_free((WOLFSSL_ASN1_STRING *)pval);
11532 goto error;
11533 }
11534
11535 if (!wolfSSL_EVP_PKEY_up_ref(key)) {
11536 WOLFSSL_MSG("Failed to up key reference");
11537 goto error;
11538 }
11539 pk->pkey = key;
11540
11541 wolfSSL_X509_PUBKEY_free(*x);
11542 *x = pk;
11543 return WOLFSSL_SUCCESS;
11544error:
11545 if (pk) {
11546 wolfSSL_X509_PUBKEY_free(pk);
11547 }
11548 return WOLFSSL_FAILURE;
11549}
11550
11551#endif /* OPENSSL_ALL || OPENSSL_EXTRA || WOLFSSL_APACHE_HTTPD ||
11552 * WOLFSSL_HAPROXY || WOLFSSL_WPAS */
11553
11554#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && !defined(NO_ASN) && \
11555 !defined(NO_PWDBASED)
11556
11557int wolfSSL_i2d_X509_PUBKEY(WOLFSSL_X509_PUBKEY* x509_PubKey,
11558 unsigned char** der)
11559{
11560 if (x509_PubKey == NULL)
11561 return WOLFSSL_FATAL_ERROR;
11562 return wolfSSL_i2d_PublicKey(x509_PubKey->pkey, der);
11563}
11564
11565#endif /* OPENSSL_EXTRA && !NO_CERTS && !NO_ASN && !NO_PWDBASED */
11566
11567#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
11568
11569#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
11570WOLFSSL_BASIC_CONSTRAINTS* wolfSSL_BASIC_CONSTRAINTS_new(void)
11571{
11572 WOLFSSL_BASIC_CONSTRAINTS* bc;
11573 bc = (WOLFSSL_BASIC_CONSTRAINTS*)
11574 XMALLOC(sizeof(WOLFSSL_BASIC_CONSTRAINTS), NULL,
11575 DYNAMIC_TYPE_X509_EXT);
11576 if (bc == NULL) {
11577 WOLFSSL_MSG("Failed to malloc basic constraints");
11578 return NULL;
11579 }
11580 XMEMSET(bc, 0, sizeof(WOLFSSL_BASIC_CONSTRAINTS));
11581 return bc;
11582}
11583
11584/* frees the wolfSSL_BASIC_CONSTRAINTS object */
11585void wolfSSL_BASIC_CONSTRAINTS_free(WOLFSSL_BASIC_CONSTRAINTS *bc)
11586{
11587 WOLFSSL_ENTER("wolfSSL_BASIC_CONSTRAINTS_free");
11588 if (bc == NULL) {
11589 WOLFSSL_MSG("Argument is NULL");
11590 return;
11591 }
11592 if (bc->pathlen) {
11593 wolfSSL_ASN1_INTEGER_free(bc->pathlen);
11594 }
11595 XFREE(bc, NULL, DYNAMIC_TYPE_OPENSSL);
11596}
11597
11598WOLFSSL_AUTHORITY_KEYID* wolfSSL_AUTHORITY_KEYID_new(void)
11599{
11600 WOLFSSL_AUTHORITY_KEYID* akey = (WOLFSSL_AUTHORITY_KEYID*)XMALLOC(
11601 sizeof(WOLFSSL_AUTHORITY_KEYID), NULL, DYNAMIC_TYPE_OPENSSL);
11602 if (!akey) {
11603 WOLFSSL_MSG("Issue creating WOLFSSL_AUTHORITY_KEYID struct");
11604 return NULL;
11605 }
11606 XMEMSET(akey, 0, sizeof(WOLFSSL_AUTHORITY_KEYID));
11607 return akey;
11608}
11609
11610/* frees the wolfSSL_AUTHORITY_KEYID object */
11611void wolfSSL_AUTHORITY_KEYID_free(WOLFSSL_AUTHORITY_KEYID *id)
11612{
11613 WOLFSSL_ENTER("wolfSSL_AUTHORITY_KEYID_free");
11614 if (id == NULL) {
11615 WOLFSSL_MSG("Argument is NULL");
11616 return;
11617 }
11618 if (id->keyid) {
11619 wolfSSL_ASN1_STRING_free(id->keyid);
11620 }
11621 if (id->issuer) {
11622 wolfSSL_ASN1_OBJECT_free(id->issuer);
11623 }
11624 if (id->serial) {
11625 wolfSSL_ASN1_INTEGER_free(id->serial);
11626 }
11627 XFREE(id, NULL, DYNAMIC_TYPE_OPENSSL);
11628}
11629
11630#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
11631
11632#ifdef KEEP_PEER_CERT
11633char* wolfSSL_X509_get_subjectCN(WOLFSSL_X509* x509)
11634{
11635 if (x509 == NULL)
11636 return NULL;
11637
11638 return x509->subjectCN;
11639}
11640#endif /* KEEP_PEER_CERT */
11641
11642#if defined(OPENSSL_EXTRA_X509_SMALL) || defined(OPENSSL_EXTRA)
11643/* increments ref count of WOLFSSL_X509. Return 1 on success, 0 on error */
11644int wolfSSL_X509_up_ref(WOLFSSL_X509* x509)
11645{
11646 if (x509) {
11647 int ret;
11648 wolfSSL_RefInc(&x509->ref, &ret);
11649 if (ret != 0) {
11650 WOLFSSL_MSG("Failed to lock x509 mutex");
11651 return WOLFSSL_FAILURE;
11652 }
11653
11654 return WOLFSSL_SUCCESS;
11655 }
11656
11657 return WOLFSSL_FAILURE;
11658}
11659#endif /* OPENSSL_EXTRA_X509_SMALL || OPENSSL_EXTRA */
11660
11661#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
11662WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_chain_up_ref(
11663 WOLF_STACK_OF(WOLFSSL_X509)* chain)
11664{
11665 /* wolfSSL_sk_dup takes care of doing a deep copy */
11666 return wolfSSL_sk_dup(chain);
11667}
11668#endif
11669
11670#if defined(OPENSSL_EXTRA)
11671
11672WOLF_STACK_OF(WOLFSSL_X509_OBJECT)* wolfSSL_sk_X509_OBJECT_deep_copy(
11673 const WOLF_STACK_OF(WOLFSSL_X509_OBJECT)* sk,
11674 WOLFSSL_X509_OBJECT* (*c)(const WOLFSSL_X509_OBJECT*),
11675 void (*f)(WOLFSSL_X509_OBJECT*))
11676{
11677 (void)f; /* free function */
11678 (void)c; /* copy function */
11679 return wolfSSL_sk_dup((WOLFSSL_STACK*)sk);
11680}
11681#endif
11682
11683#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
11684 void wolfSSL_X509_NAME_free(WOLFSSL_X509_NAME *name)
11685 {
11686 WOLFSSL_ENTER("wolfSSL_X509_NAME_free");
11687 FreeX509Name(name);
11688 if (name != NULL) {
11689 XFREE(name, name->heap, DYNAMIC_TYPE_X509);
11690 }
11691 }
11692
11693
11694 /* Malloc's a new WOLFSSL_X509_NAME structure
11695 *
11696 * returns NULL on failure, otherwise returns a new structure.
11697 */
11698 WOLFSSL_X509_NAME* wolfSSL_X509_NAME_new_ex(void *heap)
11699 {
11700 WOLFSSL_X509_NAME* name;
11701
11702 WOLFSSL_ENTER("wolfSSL_X509_NAME_new_ex");
11703
11704 name = (WOLFSSL_X509_NAME*)XMALLOC(sizeof(WOLFSSL_X509_NAME), heap,
11705 DYNAMIC_TYPE_X509);
11706 if (name != NULL) {
11707 InitX509Name(name, 1, heap);
11708 }
11709 return name;
11710 }
11711
11712 WOLFSSL_X509_NAME* wolfSSL_X509_NAME_new(void) {
11713 return wolfSSL_X509_NAME_new_ex(NULL);
11714 }
11715
11716 /* Creates a duplicate of a WOLFSSL_X509_NAME structure.
11717 Returns a new WOLFSSL_X509_NAME structure or NULL on failure */
11718 WOLFSSL_X509_NAME* wolfSSL_X509_NAME_dup(const WOLFSSL_X509_NAME *name)
11719 {
11720 WOLFSSL_X509_NAME* copy = NULL;
11721
11722 WOLFSSL_ENTER("wolfSSL_X509_NAME_dup");
11723
11724 if (name == NULL) {
11725 WOLFSSL_MSG("NULL parameter");
11726 return NULL;
11727 }
11728
11729 if (!(copy = wolfSSL_X509_NAME_new_ex(name->heap))) {
11730 return NULL;
11731 }
11732
11733 /* copy contents */
11734 InitX509Name(copy, 1, name->heap);
11735 if (wolfSSL_X509_NAME_copy(name, copy) != WOLFSSL_SUCCESS) {
11736 wolfSSL_X509_NAME_free(copy);
11737 return NULL;
11738 }
11739
11740 return copy;
11741 }
11742
11743#ifdef WOLFSSL_CERT_GEN
11744
11745#if defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT) || \
11746 defined(OPENSSL_EXTRA)
11747 /* Helper function to copy cert name from a WOLFSSL_X509_NAME structure to
11748 * a Cert structure.
11749 *
11750 * returns length of DER on success and a negative error value on failure
11751 */
11752 static int CopyX509NameToCert(WOLFSSL_X509_NAME* n, byte* out)
11753 {
11754 unsigned char* der = NULL;
11755 int length = WC_NO_ERR_TRACE(BAD_FUNC_ARG), ret;
11756 word32 idx = 0;
11757
11758 ret = wolfSSL_i2d_X509_NAME(n, &der);
11759 if (ret > (int)sizeof(CertName) || ret < 0) {
11760 WOLFSSL_MSG("Name conversion error");
11761 ret = MEMORY_E;
11762 }
11763
11764 if (ret > 0) {
11765 /* strip off sequence, this gets added on certificate creation */
11766 ret = GetSequence(der, &idx, &length, (word32)ret);
11767 }
11768
11769 if (ret > 0) {
11770 XMEMCPY(out, der + idx, length);
11771 }
11772
11773 XFREE(der, NULL, DYNAMIC_TYPE_OPENSSL);
11774
11775 return length;
11776 }
11777#endif
11778
11779#ifdef WOLFSSL_CERT_REQ
11780 static int ReqCertFromX509(Cert* cert, WOLFSSL_X509* req)
11781 {
11782 int ret;
11783
11784 if (wc_InitCert(cert) != 0)
11785 return WOLFSSL_FAILURE;
11786
11787
11788 ret = CopyX509NameToCert(&req->subject, cert->sbjRaw);
11789 if (ret < 0) {
11790 WOLFSSL_MSG("REQ subject conversion error");
11791 ret = MEMORY_E;
11792 }
11793 else {
11794 ret = WOLFSSL_SUCCESS;
11795 }
11796
11797 if (ret == WOLFSSL_SUCCESS) {
11798 cert->version = req->version;
11799 cert->isCA = req->isCa;
11800 cert->basicConstSet = req->basicConstSet;
11801 #ifdef WOLFSSL_CERT_EXT
11802 if (req->subjKeyIdSz != 0) {
11803 if (req->subjKeyIdSz > CTC_MAX_SKID_SIZE) {
11804 WOLFSSL_MSG("Subject Key ID too large");
11805 WOLFSSL_ERROR_VERBOSE(BUFFER_E);
11806 ret = WOLFSSL_FAILURE;
11807 }
11808 else if (req->subjKeyId == NULL) {
11809 WOLFSSL_MSG("Subject Key ID missing");
11810 WOLFSSL_ERROR_VERBOSE(BAD_FUNC_ARG);
11811 ret = WOLFSSL_FAILURE;
11812 }
11813 else {
11814 XMEMCPY(cert->skid, req->subjKeyId,
11815 req->subjKeyIdSz);
11816 cert->skidSz = (int)req->subjKeyIdSz;
11817 }
11818 }
11819 if (req->keyUsageSet)
11820 cert->keyUsage = req->keyUsage;
11821
11822 cert->extKeyUsage = req->extKeyUsage;
11823 #endif
11824 }
11825
11826 if (ret == WOLFSSL_SUCCESS) {
11827 #if defined(OPENSSL_ALL)
11828 int idx;
11829 #endif
11830
11831 XMEMCPY(cert->challengePw, req->challengePw, CTC_NAME_SIZE);
11832 cert->challengePwPrintableString = req->challengePw[0] != 0;
11833
11834 #if defined(OPENSSL_ALL)
11835 idx = wolfSSL_X509_REQ_get_attr_by_NID(req,
11836 WC_NID_pkcs9_unstructuredName, -1);
11837 if (idx != WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)) {
11838 WOLFSSL_X509_ATTRIBUTE *attr;
11839 attr = wolfSSL_X509_REQ_get_attr(req, idx);
11840 if (attr != NULL) {
11841 const unsigned char *attrData;
11842 int attrDataSz;
11843
11844 attrData = wolfSSL_ASN1_STRING_get0_data(
11845 attr->value->value.asn1_string);
11846 attrDataSz = wolfSSL_ASN1_STRING_length(
11847 attr->value->value.asn1_string);
11848
11849 /* +1 to make sure is terminated string */
11850 if (attrDataSz + 1 > CTC_NAME_SIZE) {
11851 WOLFSSL_MSG("attribute size was too large to copy");
11852 ret = REQ_ATTRIBUTE_E;
11853 }
11854 else {
11855 XMEMCPY(cert->unstructuredName, attrData, attrDataSz);
11856 cert->unstructuredName[attrDataSz] = '\0';
11857 }
11858 }
11859 }
11860
11861 #ifdef WOLFSSL_CUSTOM_OID
11862 if (ret == WOLFSSL_SUCCESS) {
11863 if ((req->customExtCount < 0) ||
11864 (req->customExtCount >= NUM_CUSTOM_EXT)) {
11865 WOLFSSL_MSG("Bad value for customExtCount.");
11866 ret = WOLFSSL_FAILURE;
11867 }
11868
11869 if (ret == WOLFSSL_SUCCESS) {
11870 for (idx = 0; idx < req->customExtCount; idx++) {
11871 /* Note that ownership is NOT transferred.
11872 * req->custom_exts buffers still need to be cleaned
11873 * up. */
11874 cert->customCertExt[idx] = req->custom_exts[idx];
11875 }
11876 cert->customCertExtCount = req->customExtCount;
11877 }
11878 }
11879 #endif /* WOLFSSL_CUSTOM_OID */
11880 #endif /* OPENSSL_ALL */
11881
11882 #ifdef WOLFSSL_ALT_NAMES
11883 if (ret == WOLFSSL_SUCCESS) {
11884 cert->altNamesSz = FlattenAltNames(cert->altNames,
11885 sizeof(cert->altNames), req->altNames);
11886 }
11887 #endif /* WOLFSSL_ALT_NAMES */
11888 }
11889
11890 return ret;
11891 }
11892#endif /* WOLFSSL_CERT_REQ */
11893
11894/* converts WOLFSSL_AN1_TIME to Cert form, returns positive size on
11895 * success */
11896static int CertDateFromX509(byte* out, int outSz, WOLFSSL_ASN1_TIME* t)
11897{
11898 int sz, i;
11899
11900 if (t->length + 1 >= outSz) {
11901 return BUFFER_E;
11902 }
11903
11904 out[0] = (byte) t->type;
11905 sz = (int)SetLength((word32)t->length, out + 1) + 1; /* gen tag */
11906 for (i = 0; i < t->length; i++) {
11907 out[sz + i] = t->data[i];
11908 }
11909 return t->length + sz;
11910}
11911
11912/* convert a WOLFSSL_X509 to a Cert structure for writing out */
11913static int CertFromX509(Cert* cert, WOLFSSL_X509* x509)
11914{
11915 int ret;
11916#ifdef WOLFSSL_CERT_EXT
11917 int i;
11918#endif
11919
11920 WOLFSSL_ENTER("wolfSSL_X509_to_Cert");
11921
11922 if (x509 == NULL || cert == NULL) {
11923 return BAD_FUNC_ARG;
11924 }
11925
11926 wc_InitCert(cert);
11927
11928 cert->version = (int)wolfSSL_X509_get_version(x509);
11929
11930 if (x509->notBefore.length > 0) {
11931 cert->beforeDateSz = CertDateFromX509(cert->beforeDate,
11932 CTC_DATE_SIZE, &x509->notBefore);
11933 if (cert->beforeDateSz <= 0) {
11934 WOLFSSL_MSG("Error converting WOLFSSL_X509 not before date");
11935 return WOLFSSL_FAILURE;
11936 }
11937 }
11938 else {
11939 cert->beforeDateSz = 0;
11940 }
11941
11942 if (x509->notAfter.length > 0) {
11943 cert->afterDateSz = CertDateFromX509(cert->afterDate,
11944 CTC_DATE_SIZE, &x509->notAfter);
11945 if (cert->afterDateSz <= 0) {
11946 WOLFSSL_MSG("Error converting WOLFSSL_X509 not after date");
11947 return WOLFSSL_FAILURE;
11948 }
11949 }
11950 else {
11951 cert->afterDateSz = 0;
11952 }
11953
11954#ifdef WOLFSSL_ALT_NAMES
11955 cert->altNamesSz = FlattenAltNames(cert->altNames,
11956 sizeof(cert->altNames), x509->altNames);
11957#endif /* WOLFSSL_ALT_NAMES */
11958
11959 cert->sigType = wolfSSL_X509_get_signature_type(x509);
11960 cert->keyType = x509->pubKeyOID;
11961 cert->isCA = wolfSSL_X509_get_isCA(x509);
11962 cert->basicConstCrit = x509->basicConstCrit;
11963 cert->basicConstSet = x509->basicConstSet;
11964 cert->pathLen = (byte)x509->pathLength;
11965 cert->pathLenSet = x509->pathLengthSet;
11966
11967#ifdef WOLFSSL_CERT_EXT
11968 if (x509->subjKeyIdSz <= CTC_MAX_SKID_SIZE) {
11969 if (x509->subjKeyId) {
11970 XMEMCPY(cert->skid, x509->subjKeyId, x509->subjKeyIdSz);
11971 }
11972 cert->skidSz = (int)x509->subjKeyIdSz;
11973 }
11974 else {
11975 WOLFSSL_MSG("Subject Key ID too large");
11976 WOLFSSL_ERROR_VERBOSE(BUFFER_E);
11977 return WOLFSSL_FAILURE;
11978 }
11979
11980 #ifdef WOLFSSL_AKID_NAME
11981 cert->rawAkid = 0;
11982 if (x509->authKeyIdSrc) {
11983 if (x509->authKeyIdSrcSz > sizeof(cert->akid)) {
11984 WOLFSSL_MSG("Auth Key ID too large");
11985 WOLFSSL_ERROR_VERBOSE(BUFFER_E);
11986 return WOLFSSL_FAILURE;
11987 }
11988 XMEMCPY(cert->akid, x509->authKeyIdSrc, x509->authKeyIdSrcSz);
11989 cert->akidSz = (int)x509->authKeyIdSrcSz;
11990 cert->rawAkid = 1;
11991 }
11992 else
11993 #endif
11994 if (x509->authKeyId) {
11995 if (x509->authKeyIdSz > sizeof(cert->akid)) {
11996 WOLFSSL_MSG("Auth Key ID too large");
11997 WOLFSSL_ERROR_VERBOSE(BUFFER_E);
11998 return WOLFSSL_FAILURE;
11999 }
12000 XMEMCPY(cert->akid, x509->authKeyId, x509->authKeyIdSz);
12001 cert->akidSz = (int)x509->authKeyIdSz;
12002 }
12003
12004 for (i = 0; i < x509->certPoliciesNb; i++) {
12005 /* copy the smaller of MAX macros, by default they are currently equal*/
12006 if ((int)CTC_MAX_CERTPOL_SZ <= (int)MAX_CERTPOL_SZ) {
12007 XMEMCPY(cert->certPolicies[i], x509->certPolicies[i],
12008 CTC_MAX_CERTPOL_SZ);
12009 }
12010 else {
12011 XMEMCPY(cert->certPolicies[i], x509->certPolicies[i],
12012 MAX_CERTPOL_SZ);
12013 }
12014 }
12015 cert->certPoliciesNb = (word16)x509->certPoliciesNb;
12016
12017 cert->keyUsage = x509->keyUsage;
12018 cert->extKeyUsage = x509->extKeyUsage;
12019 cert->nsCertType = x509->nsCertType;
12020
12021 if (x509->rawCRLInfo != NULL) {
12022 if (x509->rawCRLInfoSz > CTC_MAX_CRLINFO_SZ) {
12023 WOLFSSL_MSG("CRL Info too large");
12024 WOLFSSL_ERROR_VERBOSE(BUFFER_E);
12025 return WOLFSSL_FAILURE;
12026 }
12027 XMEMCPY(cert->crlInfo, x509->rawCRLInfo, x509->rawCRLInfoSz);
12028 cert->crlInfoSz = x509->rawCRLInfoSz;
12029 }
12030
12031#ifdef WOLFSSL_DUAL_ALG_CERTS
12032 /* We point to instance in x509 so DON'T need to be free'd. */
12033 cert->sapkiDer = x509->sapkiDer;
12034 cert->sapkiLen = x509->sapkiLen;
12035 cert->sapkiCrit = x509->sapkiCrit;
12036 cert->altSigAlgDer = x509->altSigAlgDer;
12037 cert->altSigAlgLen = x509->altSigAlgLen;
12038 cert->altSigAlgCrit = x509->altSigAlgCrit;
12039 cert->altSigValDer = x509->altSigValDer;
12040 cert->altSigValLen = x509->altSigValLen;
12041 cert->altSigValCrit = x509->altSigValCrit;
12042#endif /* WOLFSSL_DUAL_ALG_CERTS */
12043
12044#if defined(WOLFSSL_ASN_TEMPLATE) && defined(WOLFSSL_CUSTOM_OID) && \
12045 defined(HAVE_OID_ENCODING)
12046
12047 if ((x509->customExtCount < 0) ||
12048 (x509->customExtCount >= NUM_CUSTOM_EXT)) {
12049 WOLFSSL_MSG("Bad value for customExtCount.");
12050 return WOLFSSL_FAILURE;
12051 }
12052
12053 for (i = 0; i < x509->customExtCount; i++) {
12054 if (wc_SetCustomExtension(cert, x509->custom_exts[i].crit,
12055 x509->custom_exts[i].oid, x509->custom_exts[i].val,
12056 x509->custom_exts[i].valSz))
12057 {
12058 return WOLFSSL_FAILURE;
12059 }
12060 }
12061#endif /* WOLFSSL_ASN_TEMPLATE && WOLFSSL_CUSTOM_OID && HAVE_OID_ENCODING */
12062
12063#endif /* WOLFSSL_CERT_EXT */
12064
12065#ifdef WOLFSSL_CERT_REQ
12066 /* copy over challenge password for REQ certs */
12067 XMEMCPY(cert->challengePw, x509->challengePw, CTC_NAME_SIZE);
12068#endif
12069
12070 /* Only makes sense to do this for OPENSSL_EXTRA because without
12071 * this define the function will error out below */
12072 #ifdef OPENSSL_EXTRA
12073 if (x509->serialSz == 0 && x509->serialNumber != NULL &&
12074 /* Check if the buffer contains more than just the
12075 * ASN tag and length */
12076 x509->serialNumber->length > 2) {
12077 if (wolfSSL_X509_set_serialNumber(x509, x509->serialNumber)
12078 != WOLFSSL_SUCCESS) {
12079 WOLFSSL_MSG("Failed to set serial number");
12080 return WOLFSSL_FAILURE;
12081 }
12082 }
12083 #endif
12084
12085 /* set serial number */
12086 if (x509->serialSz > 0) {
12087 #if defined(OPENSSL_EXTRA)
12088 byte serial[EXTERNAL_SERIAL_SIZE];
12089 int serialSz = EXTERNAL_SERIAL_SIZE;
12090
12091 ret = wolfSSL_X509_get_serial_number(x509, serial, &serialSz);
12092 if (ret != WOLFSSL_SUCCESS) {
12093 WOLFSSL_MSG("Serial size error");
12094 return WOLFSSL_FAILURE;
12095 }
12096
12097 if (serialSz > EXTERNAL_SERIAL_SIZE ||
12098 serialSz > CTC_SERIAL_SIZE) {
12099 WOLFSSL_MSG("Serial size too large error");
12100 WOLFSSL_ERROR_VERBOSE(BUFFER_E);
12101 return WOLFSSL_FAILURE;
12102 }
12103 XMEMCPY(cert->serial, serial, serialSz);
12104 cert->serialSz = serialSz;
12105 #else
12106 WOLFSSL_MSG("Getting X509 serial number not supported");
12107 return WOLFSSL_FAILURE;
12108 #endif
12109 }
12110
12111 /* copy over Name structures */
12112 if (x509->issuerSet)
12113 cert->selfSigned = 0;
12114
12115#if defined(WOLFSSL_CERT_EXT) || defined(OPENSSL_EXTRA)
12116 ret = CopyX509NameToCert(&x509->subject, cert->sbjRaw);
12117 if (ret < 0) {
12118 WOLFSSL_MSG("Subject conversion error");
12119 return MEMORY_E;
12120 }
12121 if (cert->selfSigned) {
12122 XMEMCPY(cert->issRaw, cert->sbjRaw, sizeof(CertName));
12123 }
12124 else {
12125 ret = CopyX509NameToCert(&x509->issuer, cert->issRaw);
12126 if (ret < 0) {
12127 WOLFSSL_MSG("Issuer conversion error");
12128 return MEMORY_E;
12129 }
12130 }
12131#endif
12132
12133 cert->heap = x509->heap;
12134
12135 (void)ret;
12136 return WOLFSSL_SUCCESS;
12137}
12138
12139
12140 /* returns the sig type to use on success i.e CTC_SHAwRSA and WOLFSSL_FALURE
12141 * on fail case */
12142 static int wolfSSL_sigTypeFromPKEY(WOLFSSL_EVP_MD* md,
12143 WOLFSSL_EVP_PKEY* pkey)
12144 {
12145 #if !defined(NO_PWDBASED) && defined(OPENSSL_EXTRA)
12146 int hashType;
12147 int sigType = WOLFSSL_FAILURE;
12148
12149 /* Convert key type and hash algorithm to a signature algorithm */
12150 if (wolfSSL_EVP_get_hashinfo(md, &hashType, NULL)
12151 == WC_NO_ERR_TRACE(WOLFSSL_FAILURE))
12152 {
12153 return WOLFSSL_FAILURE;
12154 }
12155
12156 if (pkey->type == WC_EVP_PKEY_RSA) {
12157 switch (hashType) {
12158 case WC_HASH_TYPE_SHA:
12159 sigType = CTC_SHAwRSA;
12160 break;
12161 case WC_HASH_TYPE_SHA224:
12162 sigType = CTC_SHA224wRSA;
12163 break;
12164 case WC_HASH_TYPE_SHA256:
12165 sigType = CTC_SHA256wRSA;
12166 break;
12167 case WC_HASH_TYPE_SHA384:
12168 sigType = CTC_SHA384wRSA;
12169 break;
12170 case WC_HASH_TYPE_SHA512:
12171 sigType = CTC_SHA512wRSA;
12172 break;
12173 #ifdef WOLFSSL_SHA3
12174 case WC_HASH_TYPE_SHA3_224:
12175 sigType = CTC_SHA3_224wRSA;
12176 break;
12177 case WC_HASH_TYPE_SHA3_256:
12178 sigType = CTC_SHA3_256wRSA;
12179 break;
12180 case WC_HASH_TYPE_SHA3_384:
12181 sigType = CTC_SHA3_384wRSA;
12182 break;
12183 case WC_HASH_TYPE_SHA3_512:
12184 sigType = CTC_SHA3_512wRSA;
12185 break;
12186 #endif
12187 default:
12188 return WOLFSSL_FAILURE;
12189 }
12190 }
12191 else if (pkey->type == WC_EVP_PKEY_EC) {
12192 switch (hashType) {
12193 case WC_HASH_TYPE_SHA:
12194 sigType = CTC_SHAwECDSA;
12195 break;
12196 case WC_HASH_TYPE_SHA224:
12197 sigType = CTC_SHA224wECDSA;
12198 break;
12199 case WC_HASH_TYPE_SHA256:
12200 sigType = CTC_SHA256wECDSA;
12201 break;
12202 case WC_HASH_TYPE_SHA384:
12203 sigType = CTC_SHA384wECDSA;
12204 break;
12205 case WC_HASH_TYPE_SHA512:
12206 sigType = CTC_SHA512wECDSA;
12207 break;
12208 #ifdef WOLFSSL_SHA3
12209 case WC_HASH_TYPE_SHA3_224:
12210 sigType = CTC_SHA3_224wECDSA;
12211 break;
12212 case WC_HASH_TYPE_SHA3_256:
12213 sigType = CTC_SHA3_256wECDSA;
12214 break;
12215 case WC_HASH_TYPE_SHA3_384:
12216 sigType = CTC_SHA3_384wECDSA;
12217 break;
12218 case WC_HASH_TYPE_SHA3_512:
12219 sigType = CTC_SHA3_512wECDSA;
12220 break;
12221 #endif
12222 default:
12223 return WOLFSSL_FAILURE;
12224 }
12225 }
12226 else
12227 return WOLFSSL_FAILURE;
12228 return sigType;
12229#else
12230 (void)md;
12231 (void)pkey;
12232 WOLFSSL_MSG("Cannot get hashinfo when NO_PWDBASED is defined");
12233 return WOLFSSL_FAILURE;
12234#endif /* !NO_PWDBASED && OPENSSL_EXTRA */
12235 }
12236
12237
12238 /* generates DER buffer from WOLFSSL_X509
12239 * If req == 1 then creates a request DER buffer
12240 *
12241 * updates derSz with certificate body size on success
12242 * return WOLFSSL_SUCCESS on success
12243 */
12244 static int wolfssl_x509_make_der(WOLFSSL_X509* x509, int req,
12245 unsigned char* der, int* derSz, int includeSig)
12246 {
12247 int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
12248 int totalLen;
12249 Cert* cert = NULL;
12250 void* key = NULL;
12251 int type = -1;
12252 #ifndef NO_RSA
12253 RsaKey* rsa = NULL;
12254 #endif
12255 #ifdef HAVE_ECC
12256 ecc_key* ecc = NULL;
12257 #endif
12258 #ifndef NO_DSA
12259 DsaKey* dsa = NULL;
12260 #endif
12261 #if defined(HAVE_FALCON)
12262 falcon_key* falcon = NULL;
12263 #endif
12264 #if defined(HAVE_DILITHIUM)
12265 dilithium_key* dilithium = NULL;
12266 #endif
12267 #if defined(WOLFSSL_HAVE_SLHDSA)
12268 SlhDsaKey* slhdsa = NULL;
12269 #endif
12270 WC_RNG rng;
12271 word32 idx = 0;
12272
12273 if (x509 == NULL || der == NULL || derSz == NULL)
12274 return BAD_FUNC_ARG;
12275
12276 #ifndef WOLFSSL_CERT_REQ
12277 if (req) {
12278 WOLFSSL_MSG("WOLFSSL_CERT_REQ needed for certificate request");
12279 return WOLFSSL_FAILURE;
12280 }
12281 #endif
12282
12283 /* allocate Cert struct on heap since it is large */
12284 cert = (Cert*)XMALLOC(sizeof(Cert), NULL, DYNAMIC_TYPE_CERT);
12285 if (cert == NULL) {
12286 WOLFSSL_MSG("Failed to allocate memory for Cert struct");
12287 return WOLFSSL_FAILURE;
12288 }
12289 XMEMSET(cert, 0, sizeof(Cert));
12290
12291 #ifdef WOLFSSL_CERT_REQ
12292 if (req) {
12293 if (ReqCertFromX509(cert, x509) != WOLFSSL_SUCCESS) {
12294 XFREE(cert, NULL, DYNAMIC_TYPE_CERT);
12295 return WOLFSSL_FAILURE;
12296 }
12297 }
12298 else
12299 #endif
12300 {
12301 /* Create a Cert that has the certificate fields. */
12302 if (CertFromX509(cert, x509) != WOLFSSL_SUCCESS) {
12303 XFREE(cert, NULL, DYNAMIC_TYPE_CERT);
12304 return WOLFSSL_FAILURE;
12305 }
12306 }
12307
12308 /* Create a public key object from requests public key. */
12309 #ifndef NO_RSA
12310 if (x509->pubKeyOID == RSAk) {
12311
12312 rsa = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_RSA);
12313 if (rsa == NULL) {
12314 WOLFSSL_MSG("Failed to allocate memory for RsaKey");
12315 XFREE(cert, NULL, DYNAMIC_TYPE_CERT);
12316 return WOLFSSL_FAILURE;
12317 }
12318
12319 type = RSA_TYPE;
12320 ret = wc_InitRsaKey(rsa, x509->heap);
12321 if (ret != 0) {
12322 XFREE(rsa, NULL, DYNAMIC_TYPE_RSA);
12323 XFREE(cert, NULL, DYNAMIC_TYPE_CERT);
12324 return ret;
12325 }
12326 ret = wc_RsaPublicKeyDecode(x509->pubKey.buffer, &idx, rsa,
12327 x509->pubKey.length);
12328 if (ret != 0) {
12329 WOLFSSL_ERROR_VERBOSE(ret);
12330 wc_FreeRsaKey(rsa);
12331 XFREE(rsa, NULL, DYNAMIC_TYPE_RSA);
12332 XFREE(cert, NULL, DYNAMIC_TYPE_CERT);
12333 return ret;
12334 }
12335 key = (void*)rsa;
12336 }
12337 #endif
12338 #ifdef HAVE_ECC
12339 if (x509->pubKeyOID == ECDSAk) {
12340
12341 ecc = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL, DYNAMIC_TYPE_ECC);
12342 if (ecc == NULL) {
12343 WOLFSSL_MSG("Failed to allocate memory for ecc_key");
12344 XFREE(cert, NULL, DYNAMIC_TYPE_CERT);
12345 return WOLFSSL_FAILURE;
12346 }
12347
12348 type = ECC_TYPE;
12349 ret = wc_ecc_init(ecc);
12350 if (ret != 0) {
12351 XFREE(ecc, NULL, DYNAMIC_TYPE_ECC);
12352 XFREE(cert, NULL, DYNAMIC_TYPE_CERT);
12353 return ret;
12354 }
12355 ret = wc_EccPublicKeyDecode(x509->pubKey.buffer, &idx, ecc,
12356 x509->pubKey.length);
12357 if (ret != 0) {
12358 WOLFSSL_ERROR_VERBOSE(ret);
12359 wc_ecc_free(ecc);
12360 XFREE(ecc, NULL, DYNAMIC_TYPE_ECC);
12361 XFREE(cert, NULL, DYNAMIC_TYPE_CERT);
12362 return ret;
12363 }
12364 key = (void*)ecc;
12365 }
12366 #endif
12367 #ifndef NO_DSA
12368 if (x509->pubKeyOID == DSAk) {
12369
12370 dsa = (DsaKey*)XMALLOC(sizeof(DsaKey), NULL, DYNAMIC_TYPE_DSA);
12371 if (dsa == NULL) {
12372 WOLFSSL_MSG("Failed to allocate memory for DsaKey");
12373 XFREE(cert, NULL, DYNAMIC_TYPE_CERT);
12374 return WOLFSSL_FAILURE;
12375 }
12376
12377 type = DSA_TYPE;
12378 ret = wc_InitDsaKey(dsa);
12379 if (ret != 0) {
12380 XFREE(dsa, NULL, DYNAMIC_TYPE_DSA);
12381 XFREE(cert, NULL, DYNAMIC_TYPE_CERT);
12382 return ret;
12383 }
12384 ret = wc_DsaPublicKeyDecode(x509->pubKey.buffer, &idx, dsa,
12385 x509->pubKey.length);
12386 if (ret != 0) {
12387 WOLFSSL_ERROR_VERBOSE(ret);
12388 wc_FreeDsaKey(dsa);
12389 XFREE(dsa, NULL, DYNAMIC_TYPE_DSA);
12390 XFREE(cert, NULL, DYNAMIC_TYPE_CERT);
12391 return ret;
12392 }
12393 key = (void*)dsa;
12394 }
12395 #endif
12396 #if defined(HAVE_FALCON)
12397 if ((x509->pubKeyOID == FALCON_LEVEL1k) ||
12398 (x509->pubKeyOID == FALCON_LEVEL5k)) {
12399 falcon = (falcon_key*)XMALLOC(sizeof(falcon_key), NULL,
12400 DYNAMIC_TYPE_FALCON);
12401 if (falcon == NULL) {
12402 WOLFSSL_MSG("Failed to allocate memory for falcon_key");
12403 XFREE(cert, NULL, DYNAMIC_TYPE_CERT);
12404 return WOLFSSL_FAILURE;
12405 }
12406
12407 ret = wc_falcon_init(falcon);
12408 if (ret != 0) {
12409 XFREE(falcon, NULL, DYNAMIC_TYPE_FALCON);
12410 XFREE(cert, NULL, DYNAMIC_TYPE_CERT);
12411 return ret;
12412 }
12413
12414 if (x509->pubKeyOID == FALCON_LEVEL1k) {
12415 type = FALCON_LEVEL1_TYPE;
12416 wc_falcon_set_level(falcon, 1);
12417 }
12418 else if (x509->pubKeyOID == FALCON_LEVEL5k) {
12419 type = FALCON_LEVEL5_TYPE;
12420 wc_falcon_set_level(falcon, 5);
12421 }
12422
12423 ret = wc_Falcon_PublicKeyDecode(x509->pubKey.buffer, &idx, falcon,
12424 x509->pubKey.length);
12425 if (ret != 0) {
12426 WOLFSSL_ERROR_VERBOSE(ret);
12427 wc_falcon_free(falcon);
12428 XFREE(falcon, NULL, DYNAMIC_TYPE_FALCON);
12429 XFREE(cert, NULL, DYNAMIC_TYPE_CERT);
12430 return ret;
12431 }
12432 key = (void*)falcon;
12433 }
12434 #endif
12435 #if defined(HAVE_DILITHIUM)
12436 if ((x509->pubKeyOID == ML_DSA_LEVEL2k) ||
12437 (x509->pubKeyOID == ML_DSA_LEVEL3k) ||
12438 (x509->pubKeyOID == ML_DSA_LEVEL5k)
12439 #ifdef WOLFSSL_DILITHIUM_FIPS204_DRAFT
12440 || (x509->pubKeyOID == DILITHIUM_LEVEL2k)
12441 || (x509->pubKeyOID == DILITHIUM_LEVEL3k)
12442 || (x509->pubKeyOID == DILITHIUM_LEVEL5k)
12443 #endif /* WOLFSSL_DILITHIUM_FIPS204_DRAFT */
12444 ) {
12445 dilithium = (dilithium_key*)XMALLOC(sizeof(dilithium_key), NULL,
12446 DYNAMIC_TYPE_DILITHIUM);
12447 if (dilithium == NULL) {
12448 WOLFSSL_MSG("Failed to allocate memory for dilithium_key");
12449 XFREE(cert, NULL, DYNAMIC_TYPE_CERT);
12450 return WOLFSSL_FAILURE;
12451 }
12452
12453 ret = wc_dilithium_init(dilithium);
12454 if (ret != 0) {
12455 XFREE(dilithium, NULL, DYNAMIC_TYPE_DILITHIUM);
12456 XFREE(cert, NULL, DYNAMIC_TYPE_CERT);
12457 return ret;
12458 }
12459
12460 if (x509->pubKeyOID == ML_DSA_LEVEL2k) {
12461 type = ML_DSA_LEVEL2_TYPE;
12462 wc_dilithium_set_level(dilithium, WC_ML_DSA_44);
12463 }
12464 else if (x509->pubKeyOID == ML_DSA_LEVEL3k) {
12465 type = ML_DSA_LEVEL3_TYPE;
12466 wc_dilithium_set_level(dilithium, WC_ML_DSA_65);
12467 }
12468 else if (x509->pubKeyOID == ML_DSA_LEVEL5k) {
12469 type = ML_DSA_LEVEL5_TYPE;
12470 wc_dilithium_set_level(dilithium, WC_ML_DSA_87);
12471 }
12472 #ifdef WOLFSSL_DILITHIUM_FIPS204_DRAFT
12473 else if (x509->pubKeyOID == DILITHIUM_LEVEL2k) {
12474 type = DILITHIUM_LEVEL2_TYPE;
12475 wc_dilithium_set_level(dilithium, WC_ML_DSA_44_DRAFT);
12476 }
12477 else if (x509->pubKeyOID == DILITHIUM_LEVEL3k) {
12478 type = DILITHIUM_LEVEL3_TYPE;
12479 wc_dilithium_set_level(dilithium, WC_ML_DSA_65_DRAFT);
12480 }
12481 else if (x509->pubKeyOID == DILITHIUM_LEVEL5k) {
12482 type = DILITHIUM_LEVEL5_TYPE;
12483 wc_dilithium_set_level(dilithium, WC_ML_DSA_87_DRAFT);
12484 }
12485 #endif /* WOLFSSL_DILITHIUM_FIPS204_DRAFT */
12486
12487 ret = wc_Dilithium_PublicKeyDecode(x509->pubKey.buffer, &idx,
12488 dilithium, x509->pubKey.length);
12489 if (ret != 0) {
12490 WOLFSSL_ERROR_VERBOSE(ret);
12491 wc_dilithium_free(dilithium);
12492 XFREE(dilithium, NULL, DYNAMIC_TYPE_DILITHIUM);
12493 XFREE(cert, NULL, DYNAMIC_TYPE_CERT);
12494 return ret;
12495 }
12496 key = (void*)dilithium;
12497 }
12498 #endif
12499 #if defined(WOLFSSL_HAVE_SLHDSA)
12500 if (wc_IsSlhDsaOid(x509->pubKeyOID)) {
12501 int paramInt = wc_SlhDsaOidToParam(x509->pubKeyOID);
12502 int certType = wc_SlhDsaOidToCertType(x509->pubKeyOID);
12503
12504 /* The OID is a recognised SLH-DSA OID but the parameter set
12505 * isn't built in; surface NOT_COMPILED_IN directly so
12506 * callers can render an accurate diagnostic. */
12507 if (paramInt == WC_NO_ERR_TRACE(NOT_COMPILED_IN) ||
12508 certType == WC_NO_ERR_TRACE(NOT_COMPILED_IN)) {
12509 WOLFSSL_MSG("SLH-DSA variant not compiled in");
12510 XFREE(cert, NULL, DYNAMIC_TYPE_CERT);
12511 return NOT_COMPILED_IN;
12512 }
12513 /* Defensive: wc_IsSlhDsaOid already implies both lookups
12514 * succeed, but check explicitly so any future drift between the
12515 * three OID helpers surfaces as a clean failure rather than
12516 * undefined behaviour from casting -1 to enum SlhDsaParam. */
12517 if (paramInt < 0 || certType < 0) {
12518 WOLFSSL_MSG("SLH-DSA OID helper mismatch");
12519 XFREE(cert, NULL, DYNAMIC_TYPE_CERT);
12520 return WOLFSSL_FAILURE;
12521 }
12522
12523 slhdsa = (SlhDsaKey*)XMALLOC(sizeof(SlhDsaKey), NULL,
12524 DYNAMIC_TYPE_SLHDSA);
12525 if (slhdsa == NULL) {
12526 WOLFSSL_MSG("Failed to allocate memory for SlhDsaKey");
12527 XFREE(cert, NULL, DYNAMIC_TYPE_CERT);
12528 return WOLFSSL_FAILURE;
12529 }
12530
12531 type = certType;
12532
12533 ret = wc_SlhDsaKey_Init(slhdsa, (enum SlhDsaParam)paramInt, NULL,
12534 INVALID_DEVID);
12535 if (ret != 0) {
12536 XFREE(slhdsa, NULL, DYNAMIC_TYPE_SLHDSA);
12537 XFREE(cert, NULL, DYNAMIC_TYPE_CERT);
12538 return ret;
12539 }
12540
12541 ret = wc_SlhDsaKey_PublicKeyDecode(x509->pubKey.buffer, &idx,
12542 slhdsa, x509->pubKey.length);
12543 if (ret != 0) {
12544 WOLFSSL_ERROR_VERBOSE(ret);
12545 wc_SlhDsaKey_Free(slhdsa);
12546 XFREE(slhdsa, NULL, DYNAMIC_TYPE_SLHDSA);
12547 XFREE(cert, NULL, DYNAMIC_TYPE_CERT);
12548 return ret;
12549 }
12550 key = (void*)slhdsa;
12551 }
12552 #endif
12553 if (key == NULL) {
12554 WOLFSSL_MSG("No public key found for certificate");
12555 XFREE(cert, NULL, DYNAMIC_TYPE_CERT);
12556 return WOLFSSL_FAILURE;
12557 }
12558
12559 /* Make the body of the certificate request. */
12560 #ifdef WOLFSSL_CERT_REQ
12561 if (req) {
12562 ret = wc_MakeCertReq_ex(cert, der, *derSz, type, key);
12563 }
12564 else
12565 #endif
12566 {
12567 ret = wc_InitRng(&rng);
12568 if (ret != 0) {
12569 ret = WOLFSSL_FAILURE;
12570 goto cleanup;
12571 }
12572
12573 ret = wc_MakeCert_ex(cert, der, *derSz, type, key, &rng);
12574 wc_FreeRng(&rng);
12575 }
12576 if (ret <= 0) {
12577 WOLFSSL_ERROR_VERBOSE(ret);
12578 ret = WOLFSSL_FAILURE;
12579 goto cleanup;
12580 }
12581
12582 if ((x509->serialSz == 0) &&
12583 (cert->serialSz <= EXTERNAL_SERIAL_SIZE) &&
12584 (cert->serialSz > 0)) {
12585 #if defined(OPENSSL_EXTRA)
12586 WOLFSSL_ASN1_INTEGER *i = wolfSSL_ASN1_INTEGER_new();
12587
12588 if (i == NULL) {
12589 WOLFSSL_MSG("wolfSSL_ASN1_INTEGER_new error");
12590 ret = WOLFSSL_FAILURE;
12591 goto cleanup;
12592 }
12593 else {
12594 i->length = cert->serialSz + 2;
12595 i->data[0] = ASN_INTEGER;
12596 i->data[1] = (unsigned char)cert->serialSz;
12597 XMEMCPY(i->data + 2, cert->serial, cert->serialSz);
12598 if (wolfSSL_X509_set_serialNumber(x509, i) != WOLFSSL_SUCCESS) {
12599 WOLFSSL_MSG("Issue setting generated serial number");
12600 wolfSSL_ASN1_INTEGER_free(i);
12601 ret = WOLFSSL_FAILURE;
12602 goto cleanup;
12603 }
12604 wolfSSL_ASN1_INTEGER_free(i);
12605 }
12606 #else
12607 WOLFSSL_MSG("ASN1_INTEGER API not in build");
12608
12609 ret = WOLFSSL_FAILURE;
12610 goto cleanup;
12611 #endif /* OPENSSL_EXTRA */
12612 }
12613
12614 if (includeSig) {
12615 if (!x509->sig.buffer) {
12616 WOLFSSL_MSG("No signature buffer");
12617 ret = WOLFSSL_FAILURE;
12618 goto cleanup;
12619 }
12620 totalLen = AddSignature(NULL, ret, NULL, x509->sig.length,
12621 x509->sigOID);
12622 if (totalLen > *derSz) {
12623 WOLFSSL_MSG("Output der buffer too short");
12624 ret = WOLFSSL_FAILURE;
12625 goto cleanup;
12626 }
12627 ret = AddSignature(der, ret, x509->sig.buffer,
12628 x509->sig.length, x509->sigOID);
12629 }
12630
12631 *derSz = ret;
12632 ret = WOLFSSL_SUCCESS;
12633cleanup:
12634 /* Dispose of the public key object. */
12635 #ifndef NO_RSA
12636 if (x509->pubKeyOID == RSAk) {
12637 wc_FreeRsaKey(rsa);
12638 XFREE(rsa, NULL, DYNAMIC_TYPE_RSA);
12639 }
12640 #endif
12641 #ifdef HAVE_ECC
12642 if (x509->pubKeyOID == ECDSAk) {
12643 wc_ecc_free(ecc);
12644 XFREE(ecc, NULL, DYNAMIC_TYPE_ECC);
12645 }
12646 #endif
12647 #ifndef NO_DSA
12648 if (x509->pubKeyOID == DSAk) {
12649 wc_FreeDsaKey(dsa);
12650 XFREE(dsa, NULL, DYNAMIC_TYPE_DSA);
12651 }
12652 #endif
12653 #if defined(HAVE_FALCON)
12654 if ((x509->pubKeyOID == FALCON_LEVEL1k) ||
12655 (x509->pubKeyOID == FALCON_LEVEL5k)) {
12656 wc_falcon_free(falcon);
12657 XFREE(falcon, NULL, DYNAMIC_TYPE_FALCON);
12658 }
12659 #endif
12660 #if defined(HAVE_DILITHIUM)
12661 if ((x509->pubKeyOID == ML_DSA_LEVEL2k) ||
12662 (x509->pubKeyOID == ML_DSA_LEVEL3k) ||
12663 (x509->pubKeyOID == ML_DSA_LEVEL5k)
12664 #ifdef WOLFSSL_DILITHIUM_FIPS204_DRAFT
12665 || (x509->pubKeyOID == DILITHIUM_LEVEL2k)
12666 || (x509->pubKeyOID == DILITHIUM_LEVEL3k)
12667 || (x509->pubKeyOID == DILITHIUM_LEVEL5k)
12668 #endif
12669 ) {
12670 wc_dilithium_free(dilithium);
12671 XFREE(dilithium, NULL, DYNAMIC_TYPE_DILITHIUM);
12672 }
12673 #endif
12674 #if defined(WOLFSSL_HAVE_SLHDSA)
12675 /* wc_IsSlhDsaOid returns 1 even for OIDs whose backend is
12676 * NOT_COMPILED_IN; the early-return at the top of the SLH-DSA
12677 * branch keeps slhdsa==NULL in that case. Guard the cleanup so
12678 * future restructuring (a goto cleanup from inside the
12679 * unbuilt-variant handler) cannot dereference a NULL key. */
12680 if (wc_IsSlhDsaOid(x509->pubKeyOID) && slhdsa != NULL) {
12681 wc_SlhDsaKey_Free(slhdsa);
12682 XFREE(slhdsa, NULL, DYNAMIC_TYPE_SLHDSA);
12683 }
12684 #endif
12685 XFREE(cert, NULL, DYNAMIC_TYPE_CERT);
12686
12687 return ret;
12688 }
12689
12690
12691 /* signs a der buffer for the WOLFSSL_X509 structure using the PKEY and MD
12692 * hash passed in
12693 *
12694 * WARNING: this free's and replaces the existing DER buffer in the
12695 * WOLFSSL_X509 with the newly signed buffer.
12696 * returns size of signed buffer on success and negative values on fail
12697 */
12698 static int wolfSSL_X509_resign_cert(WOLFSSL_X509* x509, int req,
12699 unsigned char* der, int derSz, int certBodySz, WOLFSSL_EVP_MD* md,
12700 WOLFSSL_EVP_PKEY* pkey)
12701 {
12702 int ret;
12703 void* key = NULL;
12704 int type = -1;
12705 int sigType;
12706 WC_RNG rng;
12707
12708 (void)req;
12709 WOLFSSL_ENTER("wolfSSL_X509_resign_cert");
12710
12711 sigType = wolfSSL_sigTypeFromPKEY(md, pkey);
12712 if (sigType == WC_NO_ERR_TRACE(WOLFSSL_FAILURE)) {
12713 WOLFSSL_MSG("Error getting signature type from pkey");
12714 return WOLFSSL_FATAL_ERROR;
12715 }
12716
12717
12718 /* Get the private key object and type from pkey. */
12719 #ifndef NO_RSA
12720 if (pkey->type == WC_EVP_PKEY_RSA) {
12721 type = RSA_TYPE;
12722 key = pkey->rsa->internal;
12723 }
12724 #endif
12725 #ifdef HAVE_ECC
12726 if (pkey->type == WC_EVP_PKEY_EC) {
12727 type = ECC_TYPE;
12728 key = pkey->ecc->internal;
12729 }
12730 #endif
12731
12732 /* Sign the certificate (request) body. */
12733 ret = wc_InitRng(&rng);
12734 if (ret != 0)
12735 return ret;
12736 ret = wc_SignCert_ex(certBodySz, sigType, der, (word32)derSz, type, key,
12737 &rng);
12738 wc_FreeRng(&rng);
12739 if (ret < 0) {
12740 WOLFSSL_LEAVE("wolfSSL_X509_resign_cert", ret);
12741 return ret;
12742 }
12743 derSz = ret;
12744
12745 /* Extract signature from buffer */
12746 {
12747 word32 idx = 0;
12748 int len = 0;
12749
12750 /* Read top level sequence */
12751 if (GetSequence(der, &idx, &len, (word32)derSz) < 0) {
12752 WOLFSSL_MSG("GetSequence error");
12753 return WOLFSSL_FATAL_ERROR;
12754 }
12755 /* Move idx to signature */
12756 idx += certBodySz;
12757 /* Read signature algo sequence */
12758 if (GetSequence(der, &idx, &len, (word32)derSz) < 0) {
12759 WOLFSSL_MSG("GetSequence error");
12760 return WOLFSSL_FATAL_ERROR;
12761 }
12762 idx += len;
12763 /* Read signature bit string */
12764 if (CheckBitString(der, &idx, &len, (word32)derSz, 0, NULL) != 0) {
12765 WOLFSSL_MSG("CheckBitString error");
12766 return WOLFSSL_FATAL_ERROR;
12767 }
12768 /* Sanity check */
12769 if (idx + len != (word32)derSz) {
12770 WOLFSSL_MSG("unexpected asn1 structure");
12771 return WOLFSSL_FATAL_ERROR;
12772 }
12773 x509->sig.length = 0;
12774 if (x509->sig.buffer)
12775 XFREE(x509->sig.buffer, x509->heap, DYNAMIC_TYPE_SIGNATURE);
12776 x509->sig.buffer = (byte*)XMALLOC(len, x509->heap,
12777 DYNAMIC_TYPE_SIGNATURE);
12778 if (!x509->sig.buffer) {
12779 WOLFSSL_MSG("malloc error");
12780 return WOLFSSL_FATAL_ERROR;
12781 }
12782 XMEMCPY(x509->sig.buffer, der + idx, len);
12783 x509->sig.length = (unsigned int)len;
12784 }
12785
12786 /* Put in the new certificate encoding into the x509 object. */
12787 FreeDer(&x509->derCert);
12788 type = CERT_TYPE;
12789 #ifdef WOLFSSL_CERT_REQ
12790 if (req) {
12791 type = CERTREQ_TYPE;
12792 }
12793 #endif
12794 if (AllocDer(&x509->derCert, (word32)derSz, type, NULL) != 0)
12795 return WOLFSSL_FATAL_ERROR;
12796 XMEMCPY(x509->derCert->buffer, der, derSz);
12797 x509->derCert->length = (word32)derSz;
12798
12799 return ret;
12800 }
12801
12802
12803#ifndef WC_MAX_X509_GEN
12804 /* able to override max size until dynamic buffer created */
12805 #define WC_MAX_X509_GEN 4096
12806#endif
12807
12808/* returns the size of signature on success */
12809int wolfSSL_X509_sign(WOLFSSL_X509* x509, WOLFSSL_EVP_PKEY* pkey,
12810 const WOLFSSL_EVP_MD* md)
12811{
12812 int ret;
12813 /* @TODO dynamic set based on expected cert size */
12814 byte *der = (byte *)XMALLOC(WC_MAX_X509_GEN, NULL, DYNAMIC_TYPE_TMP_BUFFER);
12815 int derSz = WC_MAX_X509_GEN;
12816
12817 WOLFSSL_ENTER("wolfSSL_X509_sign");
12818
12819 if (x509 == NULL || pkey == NULL || md == NULL) {
12820 ret = WOLFSSL_FAILURE;
12821 goto out;
12822 }
12823
12824 x509->sigOID = wolfSSL_sigTypeFromPKEY((WOLFSSL_EVP_MD*)md, pkey);
12825 if ((ret = wolfssl_x509_make_der(x509, 0, der, &derSz, 0)) !=
12826 WOLFSSL_SUCCESS) {
12827 WOLFSSL_MSG("Unable to make DER for X509");
12828 WOLFSSL_LEAVE("wolfSSL_X509_sign", ret);
12829 (void)ret;
12830 ret = WOLFSSL_FAILURE;
12831 goto out;
12832 }
12833
12834 ret = wolfSSL_X509_resign_cert(x509, 0, der, WC_MAX_X509_GEN, derSz,
12835 (WOLFSSL_EVP_MD*)md, pkey);
12836 if (ret <= 0) {
12837 WOLFSSL_LEAVE("wolfSSL_X509_sign", ret);
12838 ret = WOLFSSL_FAILURE;
12839 goto out;
12840 }
12841
12842out:
12843 XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
12844
12845 return ret;
12846}
12847
12848#if defined(OPENSSL_EXTRA)
12849int wolfSSL_X509_sign_ctx(WOLFSSL_X509 *x509, WOLFSSL_EVP_MD_CTX *ctx)
12850{
12851 WOLFSSL_ENTER("wolfSSL_X509_sign_ctx");
12852
12853 if (!x509 || !ctx || !ctx->pctx || !ctx->pctx->pkey) {
12854 WOLFSSL_MSG("Bad parameter");
12855 return WOLFSSL_FAILURE;
12856 }
12857
12858 return wolfSSL_X509_sign(x509, ctx->pctx->pkey,
12859 wolfSSL_EVP_MD_CTX_md(ctx));
12860}
12861#endif /* OPENSSL_EXTRA */
12862#endif /* WOLFSSL_CERT_GEN */
12863
12864
12865#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || \
12866 defined(OPENSSL_EXTRA_X509_SMALL) || defined(WOLFSSL_WPAS_SMALL)
12867/* Converts from WC_NID_* value to wolfSSL value if needed.
12868 *
12869 * @param [in] nid Numeric Id of a domain name component.
12870 * @return Domain name tag values - wolfSSL internal values.
12871 * @return -1 when nid isn't known.
12872 */
12873static int ConvertNIDToWolfSSL(int nid)
12874{
12875 switch (nid) {
12876 case WC_NID_commonName : return ASN_COMMON_NAME;
12877 #ifdef WOLFSSL_CERT_NAME_ALL
12878 case WC_NID_name : return ASN_NAME;
12879 case WC_NID_givenName: return ASN_GIVEN_NAME;
12880 case WC_NID_dnQualifier : return ASN_DNQUALIFIER;
12881 case WC_NID_initials: return ASN_INITIALS;
12882 #endif /* WOLFSSL_CERT_NAME_ALL */
12883 case WC_NID_surname : return ASN_SUR_NAME;
12884 case WC_NID_countryName: return ASN_COUNTRY_NAME;
12885 case WC_NID_localityName: return ASN_LOCALITY_NAME;
12886 case WC_NID_stateOrProvinceName: return ASN_STATE_NAME;
12887 case WC_NID_streetAddress: return ASN_STREET_ADDR;
12888 case WC_NID_organizationName: return ASN_ORG_NAME;
12889 case WC_NID_organizationalUnitName: return ASN_ORGUNIT_NAME;
12890 case WC_NID_emailAddress: return ASN_EMAIL_NAME;
12891 case WC_NID_pkcs9_contentType: return ASN_CONTENT_TYPE;
12892 case WC_NID_serialNumber: return ASN_SERIAL_NUMBER;
12893 case WC_NID_userId: return ASN_USER_ID;
12894 case WC_NID_businessCategory: return ASN_BUS_CAT;
12895 case WC_NID_domainComponent: return ASN_DOMAIN_COMPONENT;
12896 case WC_NID_postalCode: return ASN_POSTAL_CODE;
12897 case WC_NID_rfc822Mailbox: return ASN_RFC822_MAILBOX;
12898 case WC_NID_favouriteDrink: return ASN_FAVOURITE_DRINK;
12899 default:
12900 WOLFSSL_MSG("Attribute NID not found");
12901 return WOLFSSL_FATAL_ERROR;
12902 }
12903}
12904#endif /* OPENSSL_ALL || OPENSSL_EXTRA ||
12905 OPENSSL_EXTRA_X509_SMALL || WOLFSSL_WPAS_SMALL*/
12906
12907#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || \
12908 defined(OPENSSL_EXTRA_X509_SMALL)
12909/* This is to convert the x509 name structure into canonical DER format */
12910/* , which has the following rules: */
12911/* convert to UTF8 */
12912/* convert to lower case */
12913/* multi-spaces collapsed */
12914/* leading SEQUENCE header is skipped */
12915/* @param name a pointer to X509_NAME that is to be converted */
12916/* @param out a pointer to converted data */
12917/* @return a number of converted bytes, otherwise <=0 error code */
12918int wolfSSL_i2d_X509_NAME_canon(WOLFSSL_X509_NAME* name, unsigned char** out)
12919{
12920 int totalBytes = 0, i, idx;
12921 byte *output, *local = NULL;
12922 WC_DECLARE_VAR(names, EncodedName, MAX_NAME_ENTRIES, 0);
12923
12924 if (name == NULL)
12925 return BAD_FUNC_ARG;
12926
12927 WC_ALLOC_VAR_EX(names, EncodedName, MAX_NAME_ENTRIES, NULL,
12928 DYNAMIC_TYPE_TMP_BUFFER, return MEMORY_E);
12929
12930 XMEMSET(names, 0, sizeof(EncodedName) * MAX_NAME_ENTRIES);
12931
12932 for (i = 0; i < MAX_NAME_ENTRIES; i++) {
12933 WOLFSSL_X509_NAME_ENTRY* entry;
12934 int ret;
12935
12936 entry = wolfSSL_X509_NAME_get_entry(name, i);
12937 if (entry != NULL && entry->set >= 1) {
12938 const char* nameStr;
12939 WOLFSSL_ASN1_STRING* data;
12940 WOLFSSL_ASN1_STRING* cano_data;
12941
12942 cano_data = wolfSSL_ASN1_STRING_new();
12943 if (cano_data == NULL) {
12944 WC_FREE_VAR_EX(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
12945 return MEMORY_E;
12946 }
12947
12948 data = wolfSSL_X509_NAME_ENTRY_get_data(entry);
12949 if (data == NULL) {
12950 WC_FREE_VAR_EX(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
12951 wolfSSL_ASN1_STRING_free(cano_data);
12952 WOLFSSL_MSG("Error getting entry data");
12953 return WOLFSSL_FATAL_ERROR;
12954 }
12955 if (wolfSSL_ASN1_STRING_canon(cano_data, data) != WOLFSSL_SUCCESS) {
12956 WC_FREE_VAR_EX(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
12957 wolfSSL_ASN1_STRING_free(cano_data);
12958 return WOLFSSL_FAILURE;
12959 }
12960 nameStr = (const char*)wolfSSL_ASN1_STRING_data(cano_data);
12961
12962 /* allow for blank values in the name structure, eg OU= */
12963 if (nameStr)
12964 {
12965 ret = wc_EncodeNameCanonical(&names[i], nameStr, CTC_UTF8,
12966 (byte)ConvertNIDToWolfSSL(entry->nid));
12967 if (ret < 0) {
12968 WC_FREE_VAR_EX(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
12969 wolfSSL_ASN1_STRING_free(cano_data);
12970 WOLFSSL_MSG("EncodeName failed");
12971 return WOLFSSL_FATAL_ERROR;
12972 }
12973 totalBytes += ret;
12974 }
12975
12976 wolfSSL_ASN1_STRING_free(cano_data);
12977 }
12978 }
12979
12980 if (out == NULL) {
12981 /* If out is NULL, caller just wants length. */
12982 WC_FREE_VAR_EX(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
12983 return totalBytes;
12984 }
12985
12986 /* skip header */
12987 /* check if using buffer passed in */
12988 if (*out == NULL) {
12989 *out = local = (unsigned char*)XMALLOC(totalBytes, NULL,
12990 DYNAMIC_TYPE_OPENSSL);
12991 if (*out == NULL) {
12992 return MEMORY_E;
12993 }
12994 }
12995 output = *out;
12996 idx = 0;
12997
12998 for (i = 0; i < MAX_NAME_ENTRIES; i++) {
12999 if (names[i].used) {
13000 XMEMCPY(output + idx, names[i].encoded, names[i].totalLen);
13001 idx += names[i].totalLen;
13002 }
13003 }
13004
13005 WC_FREE_VAR_EX(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
13006
13007 /* used existing buffer passed in, so increment pointer */
13008 if (local == NULL) {
13009 *out += totalBytes;
13010 }
13011 return totalBytes;
13012}
13013#endif /* OPENSSL_ALL || OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
13014
13015#ifdef WOLFSSL_CERT_GEN
13016/* Guarded by either
13017 * A) WOLFSSL_WPAS_SMALL is on or
13018 * B) (OPENSSL_EXTRA or OPENSSL_EXTRA_X509_SMALL) + WOLFSSL_CERT_GEN +
13019 * (WOLFSSL_CERT_REQ or WOLFSSL_CERT_EXT or OPENSSL_EXTRA) has been
13020 * defined
13021 */
13022#if defined(WOLFSSL_WPAS_SMALL) || \
13023 (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
13024 defined(WOLFSSL_CERT_GEN) && \
13025 (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT) || \
13026 defined(OPENSSL_EXTRA))
13027
13028/* Converts the x509 name structure into DER format.
13029 *
13030 * out pointer to either a pre setup buffer or a pointer to null for
13031 * creating a dynamic buffer. In the case that a pre-existing buffer is
13032 * used out will be incremented the size of the DER buffer on success. If
13033 * out is NULL, the function returns the necessary output buffer length.
13034 *
13035 * returns the size of the buffer on success, or negative value with failure
13036 */
13037int wolfSSL_i2d_X509_NAME(WOLFSSL_X509_NAME* name, unsigned char** out)
13038{
13039 int totalBytes = 0, i, idx;
13040 byte temp[MAX_SEQ_SZ];
13041 byte *output, *local = NULL;
13042 WC_DECLARE_VAR(names, EncodedName, MAX_NAME_ENTRIES, 0);
13043
13044 if (name == NULL)
13045 return BAD_FUNC_ARG;
13046
13047 WC_ALLOC_VAR_EX(names, EncodedName, MAX_NAME_ENTRIES, NULL,
13048 DYNAMIC_TYPE_TMP_BUFFER, return MEMORY_E);
13049
13050 XMEMSET(names, 0, sizeof(EncodedName) * MAX_NAME_ENTRIES);
13051
13052 for (i = 0; i < MAX_NAME_ENTRIES; i++) {
13053 WOLFSSL_X509_NAME_ENTRY* entry;
13054 int ret;
13055
13056 entry = wolfSSL_X509_NAME_get_entry(name, i);
13057 if (entry != NULL && entry->set >= 1) {
13058 const char* nameStr;
13059 int type;
13060 WOLFSSL_ASN1_STRING* data;
13061
13062 data = wolfSSL_X509_NAME_ENTRY_get_data(entry);
13063 if (data == NULL) {
13064 WC_FREE_VAR_EX(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
13065 WOLFSSL_MSG("Error getting entry data");
13066 return WOLFSSL_FATAL_ERROR;
13067 }
13068
13069 nameStr = (const char*)wolfSSL_ASN1_STRING_data(data);
13070 type = wolfSSL_ASN1_STRING_type(data);
13071
13072 switch (type) {
13073 case WOLFSSL_MBSTRING_UTF8:
13074 type = CTC_UTF8;
13075 break;
13076 case WOLFSSL_MBSTRING_ASC:
13077 case WOLFSSL_V_ASN1_PRINTABLESTRING:
13078 type = CTC_PRINTABLE;
13079 break;
13080 default:
13081 WOLFSSL_MSG(
13082 "Unknown encoding type conversion UTF8 by default");
13083 type = CTC_UTF8;
13084 }
13085 ret = wc_EncodeName(&names[i], nameStr, (char)type,
13086 (byte)ConvertNIDToWolfSSL(entry->nid));
13087 if (ret < 0) {
13088 WC_FREE_VAR_EX(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
13089 WOLFSSL_MSG("EncodeName failed");
13090 return WOLFSSL_FATAL_ERROR;
13091 }
13092 totalBytes += ret;
13093 }
13094 }
13095
13096 /* header */
13097 idx = (int)SetSequence((word32)totalBytes, temp);
13098 if (totalBytes + idx > ASN_NAME_MAX) {
13099 WC_FREE_VAR_EX(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
13100 WOLFSSL_MSG("Total Bytes is greater than ASN_NAME_MAX");
13101 return BUFFER_E;
13102 }
13103
13104 if (out == NULL) {
13105 /* If out is NULL, caller just wants length. */
13106 totalBytes += idx;
13107 WC_FREE_VAR_EX(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
13108 return totalBytes;
13109 }
13110
13111 /* check if using buffer passed in */
13112 if (*out == NULL) {
13113 *out = local = (unsigned char*)XMALLOC(totalBytes + idx, name->heap,
13114 DYNAMIC_TYPE_OPENSSL);
13115 if (*out == NULL) {
13116 return MEMORY_E;
13117 }
13118 }
13119 output = *out;
13120
13121 idx = (int)SetSequence((word32)totalBytes, output);
13122 totalBytes += idx;
13123 for (i = 0; i < MAX_NAME_ENTRIES; i++) {
13124 if (names[i].used) {
13125 XMEMCPY(output + idx, names[i].encoded, names[i].totalLen);
13126 idx += names[i].totalLen;
13127 }
13128 }
13129
13130 WC_FREE_VAR_EX(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
13131
13132 /* used existing buffer passed in, so increment pointer */
13133 if (local == NULL) {
13134 *out += totalBytes;
13135 }
13136 return totalBytes;
13137}
13138#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
13139#endif /* WOLFSSL_CERT_GEN */
13140
13141#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) || \
13142 defined (WOLFSSL_WPAS_SMALL)
13143
13144 WOLFSSL_X509_NAME *wolfSSL_d2i_X509_NAME(WOLFSSL_X509_NAME **name,
13145 unsigned char **in, long length)
13146 {
13147 WOLFSSL_X509_NAME* tmp = NULL;
13148 WC_DECLARE_VAR(cert, DecodedCert, 1, 0);
13149
13150 WOLFSSL_ENTER("wolfSSL_d2i_X509_NAME");
13151
13152 if (!in || !*in || length <= 0) {
13153 WOLFSSL_MSG("Bad argument");
13154 return NULL;
13155 }
13156
13157 WC_ALLOC_VAR_EX(cert, DecodedCert, 1, NULL, DYNAMIC_TYPE_DCERT,
13158 return NULL);
13159
13160 /* Set the X509_NAME buffer as the input data for cert.
13161 * in is NOT a full certificate. Just the name. */
13162 InitDecodedCert(cert, *in, (word32)length, NULL);
13163
13164 /* Parse the X509 subject name */
13165 if (GetName(cert, ASN_SUBJECT, (int)length) != 0) {
13166 WOLFSSL_MSG("WOLFSSL_X509_NAME parse error");
13167 goto cleanup;
13168 }
13169
13170 if (!(tmp = wolfSSL_X509_NAME_new_ex(cert->heap))) {
13171 WOLFSSL_MSG("wolfSSL_X509_NAME_new_ex error");
13172 goto cleanup;
13173 }
13174
13175 if (wolfSSL_X509_NAME_copy((WOLFSSL_X509_NAME*)cert->subjectName,
13176 tmp) != WOLFSSL_SUCCESS) {
13177 wolfSSL_X509_NAME_free(tmp);
13178 tmp = NULL;
13179 goto cleanup;
13180 }
13181
13182 if (name)
13183 *name = tmp;
13184cleanup:
13185 FreeDecodedCert(cert);
13186 WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_DCERT);
13187 return tmp;
13188 }
13189#endif /* OPENSSL_EXTRA || OPENSSL_ALL || WOLFSSL_WPAS_SMALL */
13190
13191
13192#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
13193
13194 /* Compares the two X509 names. If the size of x is larger then y then a
13195 * positive value is returned if x is smaller a negative value is returned.
13196 * In the case that the sizes are equal a the value of strcmp between the
13197 * two names is returned.
13198 *
13199 * x First name for comparison
13200 * y Second name to compare with x
13201 */
13202 int wolfSSL_X509_NAME_cmp(const WOLFSSL_X509_NAME* x,
13203 const WOLFSSL_X509_NAME* y)
13204 {
13205 const char* _x;
13206 const char* _y;
13207 WOLFSSL_ENTER("wolfSSL_X509_NAME_cmp");
13208
13209 if (x == NULL || y == NULL) {
13210 WOLFSSL_MSG("Bad argument passed in");
13211 return -2;
13212 }
13213
13214 if (x == y) {
13215 return 0; /* match */
13216 }
13217
13218 if (x->sz != y->sz) {
13219 return x->sz - y->sz;
13220 }
13221
13222 /*
13223 * If the name member is not set or is immediately null terminated then
13224 * compare the staticName member
13225 */
13226 _x = (x->name && *x->name) ? x->name : x->staticName;
13227 _y = (y->name && *y->name) ? y->name : y->staticName;
13228
13229 return XSTRNCASECMP(_x, _y, x->sz); /* y sz is the same */
13230 }
13231
13232#ifndef NO_BIO
13233
13234static WOLFSSL_X509 *loadX509orX509REQFromPemBio(WOLFSSL_BIO *bp,
13235 WOLFSSL_X509 **x, wc_pem_password_cb *cb, void *u, int type)
13236{
13237 WOLFSSL_X509* x509 = NULL;
13238#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)
13239 unsigned char* pem = NULL;
13240 int pemSz;
13241 long i = 0, l, footerSz;
13242 const char* footer = NULL;
13243 int streaming = 0; /* Flag to indicate if source is streaming (FIFO) */
13244 const char* altFooter = NULL;
13245 long altFooterSz = 0;
13246
13247 WOLFSSL_ENTER("loadX509orX509REQFromPemBio");
13248
13249 if (bp == NULL || (type != CERT_TYPE && type != CERTREQ_TYPE &&
13250 type != TRUSTED_CERT_TYPE)) {
13251 WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_X509", BAD_FUNC_ARG);
13252 return NULL;
13253 }
13254
13255 if ((l = wolfSSL_BIO_get_len(bp)) <= 0) {
13256 /* No certificate size available - could be FIFO or other streaming
13257 * source. Use MAX_X509_SIZE as initial buffer, will resize if needed. */
13258 l = MAX_X509_SIZE;
13259 streaming = 1;
13260 }
13261
13262 pemSz = (int)l;
13263 pem = (unsigned char*)XMALLOC(pemSz, 0, DYNAMIC_TYPE_PEM);
13264 if (pem == NULL)
13265 return NULL;
13266 XMEMSET(pem, 0, pemSz);
13267
13268 i = 0;
13269 if (wc_PemGetHeaderFooter(type, NULL, &footer) != 0) {
13270 XFREE(pem, 0, DYNAMIC_TYPE_PEM);
13271 return NULL;
13272 }
13273 footerSz = (long)XSTRLEN(footer);
13274
13275 /* For TRUSTED_CERT_TYPE, also prepare to check for regular CERT footer
13276 * as the file might contain regular certificates instead of TRUSTED
13277 * format */
13278 if (type == TRUSTED_CERT_TYPE) {
13279 wc_PemGetHeaderFooter(CERT_TYPE, NULL, &altFooter);
13280 if (altFooter != NULL) {
13281 altFooterSz = (long)XSTRLEN(altFooter);
13282 }
13283 }
13284
13285 /* TODO: Inefficient
13286 * reading in one byte at a time until see the footer
13287 */
13288 while ((l = wolfSSL_BIO_read(bp, (char *)&pem[i], 1)) == 1) {
13289 int foundFooter = 0;
13290 i++;
13291 /* Check if buffer is full and we're reading from streaming source */
13292 if (i >= pemSz && streaming) {
13293 /* Double the buffer size for streaming sources */
13294 int newSz = pemSz * 2;
13295 unsigned char* newPem;
13296
13297 /* Sanity check: don't grow beyond reasonable limit */
13298 if (newSz > MAX_BIO_READ_BUFFER) {
13299 WOLFSSL_MSG("PEM data too large for streaming source");
13300 XFREE(pem, 0, DYNAMIC_TYPE_PEM);
13301 return NULL;
13302 }
13303
13304 newPem = (unsigned char*)XREALLOC(pem, newSz, 0, DYNAMIC_TYPE_PEM);
13305 if (newPem == NULL) {
13306 WOLFSSL_MSG("Failed to resize PEM buffer");
13307 XFREE(pem, 0, DYNAMIC_TYPE_PEM);
13308 return NULL;
13309 }
13310
13311 pem = newPem;
13312 pemSz = newSz;
13313 }
13314 else if (i >= pemSz) {
13315 /* Buffer full for non-streaming source - this shouldn't happen */
13316 break;
13317 }
13318
13319 /* Check for the expected footer OR alternate footer (for
13320 * TRUSTED_CERT_TYPE) */
13321 if (i > footerSz &&
13322 XMEMCMP((char *)&pem[i-footerSz], footer, footerSz) == 0) {
13323 foundFooter = 1;
13324 }
13325 else if (i > altFooterSz && altFooter != NULL &&
13326 XMEMCMP((char *)&pem[i-altFooterSz], altFooter, altFooterSz) == 0) {
13327 foundFooter = 1;
13328 }
13329
13330 if (foundFooter) {
13331 if (i < pemSz && wolfSSL_BIO_read(bp, (char *)&pem[i], 1) == 1) {
13332 /* attempt to read newline following footer */
13333 i++;
13334 if (i < pemSz && pem[i-1] == '\r') {
13335 /* found \r , Windows line ending is \r\n so try to read one
13336 * more byte for \n, ignoring return value */
13337 (void)wolfSSL_BIO_read(bp, (char *)&pem[i++], 1);
13338 }
13339 }
13340 break;
13341 }
13342 }
13343 if (l == 0 && i == 0) {
13344 WOLFSSL_ERROR(ASN_NO_PEM_HEADER);
13345 }
13346 if (i > pemSz) {
13347 WOLFSSL_MSG("Error parsing PEM");
13348 }
13349 else {
13350 pemSz = (int)i;
13351 #ifdef WOLFSSL_CERT_REQ
13352 if (type == CERTREQ_TYPE)
13353 x509 = loadX509orX509REQFromBuffer(pem, pemSz, WOLFSSL_FILETYPE_PEM,
13354 CERTREQ_TYPE, cb, u);
13355 else
13356 #endif
13357 /* Use TRUSTED_CERT_TYPE if input was TRUSTED CERTIFICATE format,
13358 * otherwise use CERT_TYPE for regular certificates */
13359 if (type == TRUSTED_CERT_TYPE)
13360 x509 = loadX509orX509REQFromBuffer(pem, pemSz, WOLFSSL_FILETYPE_PEM,
13361 TRUSTED_CERT_TYPE, cb, u);
13362 else
13363 x509 = loadX509orX509REQFromBuffer(pem, pemSz, WOLFSSL_FILETYPE_PEM,
13364 CERT_TYPE, cb, u);
13365 }
13366
13367 if (x != NULL) {
13368 *x = x509;
13369 }
13370
13371 XFREE(pem, NULL, DYNAMIC_TYPE_PEM);
13372
13373#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */
13374 (void)bp;
13375 (void)x;
13376 (void)cb;
13377 (void)u;
13378
13379 return x509;
13380}
13381
13382
13383WC_MAYBE_UNUSED
13384static unsigned char* ReadPemFromBioToBuffer(WOLFSSL_BIO *bp, int *pemSz)
13385{
13386 unsigned char* pem = NULL;
13387
13388 WOLFSSL_ENTER("ReadPemFromBioToBuffer");
13389
13390 if (bp == NULL || pemSz == NULL) {
13391 WOLFSSL_LEAVE("ReadPemFromBioToBuffer", BAD_FUNC_ARG);
13392 return NULL;
13393 }
13394
13395 if ((*pemSz = wolfSSL_BIO_get_len(bp)) <= 0) {
13396 /* No certificate size available - could be FIFO or other streaming
13397 * source. Use MAX_X509_SIZE as initial buffer, read in loop. */
13398 int totalRead = 0;
13399 int readSz;
13400
13401 *pemSz = MAX_X509_SIZE;
13402 pem = (unsigned char*)XMALLOC(*pemSz, 0, DYNAMIC_TYPE_PEM);
13403 if (pem == NULL) {
13404 return NULL;
13405 }
13406
13407 /* Read from streaming source until EOF or buffer full */
13408 while ((readSz = wolfSSL_BIO_read(bp, pem + totalRead,
13409 *pemSz - totalRead)) > 0) {
13410 totalRead += readSz;
13411
13412 /* If buffer is full, try to grow it */
13413 if (totalRead >= *pemSz) {
13414 int newSz = *pemSz * 2;
13415 unsigned char* newPem;
13416
13417 /* Sanity check */
13418 if (newSz > MAX_BIO_READ_BUFFER) {
13419 WOLFSSL_MSG("PEM data too large for streaming source");
13420 XFREE(pem, NULL, DYNAMIC_TYPE_PEM);
13421 return NULL;
13422 }
13423
13424 newPem = (unsigned char*)XREALLOC(pem, newSz, 0,
13425 DYNAMIC_TYPE_PEM);
13426 if (newPem == NULL) {
13427 XFREE(pem, NULL, DYNAMIC_TYPE_PEM);
13428 return NULL;
13429 }
13430 pem = newPem;
13431 *pemSz = newSz;
13432 }
13433 }
13434
13435 *pemSz = totalRead;
13436 if (*pemSz <= 0) {
13437 XFREE(pem, NULL, DYNAMIC_TYPE_PEM);
13438 return NULL;
13439 }
13440 }
13441 else {
13442 /* Known size - allocate and read */
13443 pem = (unsigned char*)XMALLOC(*pemSz, 0, DYNAMIC_TYPE_PEM);
13444 if (pem == NULL) {
13445 return NULL;
13446 }
13447
13448 XMEMSET(pem, 0, *pemSz);
13449
13450 *pemSz = wolfSSL_BIO_read(bp, pem, *pemSz);
13451 if (*pemSz <= 0) {
13452 XFREE(pem, NULL, DYNAMIC_TYPE_PEM);
13453 return NULL;
13454 }
13455 }
13456
13457 WOLFSSL_LEAVE("ReadPemFromBioToBuffer", 0);
13458 return pem;
13459}
13460
13461
13462
13463#if defined(WOLFSSL_ACERT)
13464 WOLFSSL_X509_ACERT *wolfSSL_PEM_read_bio_X509_ACERT(WOLFSSL_BIO *bp,
13465 WOLFSSL_X509_ACERT **x,
13466 wc_pem_password_cb *cb,
13467 void *u)
13468 {
13469 WOLFSSL_X509_ACERT* x509 = NULL;
13470#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)
13471 unsigned char * pem = NULL;
13472 int pemSz;
13473
13474 WOLFSSL_ENTER("wolfSSL_PEM_read_bio_X509_ACERT");
13475
13476 if (bp == NULL) {
13477 return NULL;
13478 }
13479
13480 pem = ReadPemFromBioToBuffer(bp, &pemSz);
13481 if (pem == NULL) {
13482 return NULL;
13483 }
13484
13485 x509 = wolfSSL_X509_ACERT_load_certificate_buffer(pem, pemSz,
13486 WOLFSSL_FILETYPE_PEM);
13487
13488 if (x != NULL) {
13489 *x = x509;
13490 }
13491
13492 XFREE(pem, NULL, DYNAMIC_TYPE_PEM);
13493
13494#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */
13495 (void)bp;
13496 (void)x;
13497 (void)cb;
13498 (void)u;
13499
13500 return x509;
13501
13502 }
13503#endif /* WOLFSSL_ACERT */
13504
13505 WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509(WOLFSSL_BIO *bp, WOLFSSL_X509 **x,
13506 wc_pem_password_cb *cb, void *u)
13507 {
13508 return loadX509orX509REQFromPemBio(bp, x, cb, u, CERT_TYPE);
13509 }
13510
13511 /*
13512 * bp : bio to read X509 from
13513 * x : x509 to write to
13514 * cb : password call back for reading PEM
13515 * u : password
13516 * _AUX is for working with a trusted X509 certificate
13517 */
13518 WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509_AUX(WOLFSSL_BIO *bp,
13519 WOLFSSL_X509 **x, wc_pem_password_cb *cb,
13520 void *u)
13521 {
13522 WOLFSSL_ENTER("wolfSSL_PEM_read_bio_X509_AUX");
13523
13524 /* AUX info is; trusted/rejected uses, friendly name, private key id,
13525 * and potentially a stack of "other" info. wolfSSL does not store
13526 * friendly name or private key id yet in WOLFSSL_X509 for human
13527 * readability and does not support extra trusted/rejected uses for
13528 * root CA. Use TRUSTED_CERT_TYPE to properly parse TRUSTED CERTIFICATE
13529 * format and strip auxiliary data. */
13530 return loadX509orX509REQFromPemBio(bp, x, cb, u, TRUSTED_CERT_TYPE);
13531 }
13532
13533#ifdef WOLFSSL_CERT_REQ
13534WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509_REQ(WOLFSSL_BIO *bp, WOLFSSL_X509 **x,
13535 wc_pem_password_cb *cb, void *u)
13536{
13537 return loadX509orX509REQFromPemBio(bp, x, cb, u, CERTREQ_TYPE);
13538}
13539
13540#ifndef NO_FILESYSTEM
13541 WOLFSSL_X509* wolfSSL_PEM_read_X509_REQ(XFILE fp, WOLFSSL_X509** x,
13542 wc_pem_password_cb* cb, void* u)
13543 {
13544 int err = 0;
13545 WOLFSSL_X509* ret = NULL;
13546 WOLFSSL_BIO* bio = NULL;
13547
13548 WOLFSSL_ENTER("wolfSSL_PEM_read_X509_REQ");
13549
13550 if (fp == XBADFILE) {
13551 WOLFSSL_MSG("Invalid file.");
13552 err = 1;
13553 }
13554
13555 if (err == 0) {
13556 bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file());
13557 if (bio == NULL) {
13558 WOLFSSL_MSG("Failed to create new BIO with input file.");
13559 err = 1;
13560 }
13561 }
13562 if (err == 0 && wolfSSL_BIO_set_fp(bio, fp, WOLFSSL_BIO_CLOSE)
13563 != WOLFSSL_SUCCESS) {
13564 WOLFSSL_MSG("Failed to set BIO file pointer.");
13565 err = 1;
13566 }
13567 if (err == 0) {
13568 ret = wolfSSL_PEM_read_bio_X509_REQ(bio, x, cb, u);
13569 }
13570
13571 wolfSSL_BIO_free(bio);
13572
13573 return ret;
13574 }
13575#endif /* !NO_FILESYSTEM */
13576#endif /* WOLFSSL_CERT_REQ */
13577
13578 WOLFSSL_X509_CRL *wolfSSL_PEM_read_bio_X509_CRL(WOLFSSL_BIO *bp,
13579 WOLFSSL_X509_CRL **x, wc_pem_password_cb *cb, void *u)
13580 {
13581#if defined(WOLFSSL_PEM_TO_DER) && defined(HAVE_CRL)
13582 WOLFSSL_X509_CRL* crl = NULL;
13583
13584 WOLFSSL_ENTER("wolfSSL_PEM_read_bio_X509_CRL");
13585
13586 /* OpenSSL's PEM_read_bio_X509_CRL skips intervening cert/key blocks
13587 * and returns the next CRL in the stream (NULL only at EOF). Mirror
13588 * that by looping over the per-block reader until we get a CRL or
13589 * the BIO has nothing left to parse. */
13590 for (;;) {
13591 WOLFSSL_X509* x509 = NULL;
13592 WOLFSSL_X509_PKEY* x_pkey = NULL;
13593 if (wolfSSL_PEM_X509_X509_CRL_X509_PKEY_read_bio(bp, cb,
13594 &x509, &crl, &x_pkey) != WOLFSSL_SUCCESS) {
13595 break;
13596 }
13597 if (crl != NULL) {
13598 break;
13599 }
13600 wolfSSL_X509_free(x509);
13601 wolfSSL_X509_PKEY_free(x_pkey);
13602 }
13603
13604 if (x != NULL) {
13605 if (*x != NULL && *x != crl) {
13606 wolfSSL_X509_CRL_free(*x);
13607 }
13608 *x = crl;
13609 }
13610
13611 (void)u;
13612
13613 return crl;
13614#else
13615 (void)bp;
13616 (void)x;
13617 (void)cb;
13618 (void)u;
13619
13620 return NULL;
13621#endif
13622 }
13623
13624#endif /* !NO_BIO */
13625
13626#if !defined(NO_FILESYSTEM)
13627static void* wolfSSL_PEM_read_X509_ex(XFILE fp, void **x,
13628 wc_pem_password_cb *cb, void *u, int type)
13629{
13630 unsigned char* pem = NULL;
13631 int pemSz;
13632 long i = 0, l;
13633 void *newx509;
13634 int derSz;
13635 DerBuffer* der = NULL;
13636
13637 WOLFSSL_ENTER("wolfSSL_PEM_read_X509");
13638
13639 if (fp == XBADFILE) {
13640 WOLFSSL_LEAVE("wolfSSL_PEM_read_X509", BAD_FUNC_ARG);
13641 return NULL;
13642 }
13643 /* Read cert from file */
13644 i = XFTELL(fp);
13645 if (i < 0) {
13646 WOLFSSL_LEAVE("wolfSSL_PEM_read_X509", BAD_FUNC_ARG);
13647 return NULL;
13648 }
13649
13650 if (XFSEEK(fp, 0, XSEEK_END) != 0)
13651 return NULL;
13652 l = XFTELL(fp);
13653 if (l < 0)
13654 return NULL;
13655 if (XFSEEK(fp, i, SEEK_SET) != 0)
13656 return NULL;
13657 pemSz = (int)(l - i);
13658
13659 /* check calculated length */
13660 if (pemSz > MAX_WOLFSSL_FILE_SIZE || pemSz <= 0) {
13661 WOLFSSL_MSG("PEM_read_X509_ex file size error");
13662 return NULL;
13663 }
13664
13665 /* allocate pem buffer */
13666 pem = (unsigned char*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_PEM);
13667 if (pem == NULL)
13668 return NULL;
13669
13670 if ((int)XFREAD((char *)pem, 1, (size_t)pemSz, fp) != pemSz)
13671 goto err_exit;
13672
13673 switch (type) {
13674 case CERT_TYPE:
13675 newx509 = (void *)wolfSSL_X509_load_certificate_buffer(pem,
13676 pemSz, WOLFSSL_FILETYPE_PEM);
13677 break;
13678
13679 #ifdef HAVE_CRL
13680 case CRL_TYPE:
13681 if ((PemToDer(pem, pemSz, CRL_TYPE, &der, NULL, NULL, NULL)) < 0)
13682 goto err_exit;
13683 derSz = (int)der->length;
13684 newx509 = (void*)wolfSSL_d2i_X509_CRL((WOLFSSL_X509_CRL **)x,
13685 (const unsigned char *)der->buffer, derSz);
13686 if (newx509 == NULL)
13687 goto err_exit;
13688 FreeDer(&der);
13689 break;
13690 #endif
13691
13692 default:
13693 goto err_exit;
13694 }
13695 if (x != NULL) {
13696 *x = newx509;
13697 }
13698 XFREE(pem, NULL, DYNAMIC_TYPE_PEM);
13699 return newx509;
13700
13701err_exit:
13702 XFREE(pem, NULL, DYNAMIC_TYPE_PEM);
13703 if (der != NULL)
13704 FreeDer(&der);
13705
13706 /* unused */
13707 (void)cb;
13708 (void)u;
13709 (void)derSz;
13710
13711 return NULL;
13712}
13713
13714WOLFSSL_X509* wolfSSL_PEM_read_X509(XFILE fp, WOLFSSL_X509 **x,
13715 wc_pem_password_cb *cb, void *u)
13716{
13717 return (WOLFSSL_X509* )wolfSSL_PEM_read_X509_ex(fp, (void **)x, cb, u,
13718 CERT_TYPE);
13719}
13720
13721#if defined(HAVE_CRL)
13722WOLFSSL_X509_CRL* wolfSSL_PEM_read_X509_CRL(XFILE fp,
13723 WOLFSSL_X509_CRL **crl, wc_pem_password_cb *cb, void *u)
13724{
13725 return (WOLFSSL_X509_CRL* )wolfSSL_PEM_read_X509_ex(fp, (void **)crl, cb, u,
13726 CRL_TYPE);
13727}
13728
13729/* Store CRL to file in DER or PEM format.
13730 * Returns WOLFSSL_SUCCESS on success, negative on failure.
13731 */
13732int wolfSSL_write_X509_CRL(WOLFSSL_X509_CRL* crl, const char* path, int type)
13733{
13734 int ret;
13735 WOLFSSL_ENTER("wolfSSL_write_X509_CRL");
13736 ret = StoreCRL(crl, path, type);
13737 WOLFSSL_LEAVE("wolfSSL_write_X509_CRL", ret);
13738 return ret;
13739}
13740#endif
13741
13742#ifdef WOLFSSL_CERT_GEN
13743#ifndef NO_BIO
13744 int wolfSSL_PEM_write_X509(XFILE fp, WOLFSSL_X509* x)
13745 {
13746 int ret;
13747 WOLFSSL_BIO* bio;
13748
13749 if (x == NULL || fp == XBADFILE)
13750 return 0;
13751
13752 bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file());
13753 if (bio == NULL)
13754 return 0;
13755
13756 if (wolfSSL_BIO_set_fp(bio, fp, WOLFSSL_BIO_NOCLOSE) != WOLFSSL_SUCCESS) {
13757 wolfSSL_BIO_free(bio);
13758 bio = NULL;
13759 }
13760
13761 ret = wolfSSL_PEM_write_bio_X509(bio, x);
13762
13763 if (bio != NULL)
13764 wolfSSL_BIO_free(bio);
13765
13766 return ret;
13767 }
13768#endif /* !NO_BIO */
13769#endif /* WOLFSSL_CERT_GEN */
13770#endif /* !NO_FILESYSTEM */
13771
13772#endif /* OPENSSL_EXTRA || OPENSSL_ALL */
13773#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
13774
13775#ifndef NO_BIO
13776 /* create and return a new WOLFSSL_X509_PKEY structure or NULL on failure */
13777 static WOLFSSL_X509_PKEY* wolfSSL_X509_PKEY_new(void* heap)
13778 {
13779 WOLFSSL_X509_PKEY* ret;
13780
13781 ret = (WOLFSSL_X509_PKEY*)XMALLOC(sizeof(WOLFSSL_X509_PKEY), heap,
13782 DYNAMIC_TYPE_KEY);
13783 if (ret != NULL) {
13784 XMEMSET(ret, 0, sizeof(WOLFSSL_X509_PKEY));
13785 ret->heap = heap;
13786 }
13787 return ret;
13788 }
13789#endif /* !NO_BIO */
13790
13791
13792 /* free up all memory used by "xPkey" passed in */
13793 void wolfSSL_X509_PKEY_free(WOLFSSL_X509_PKEY* xPkey)
13794 {
13795 if (xPkey != NULL) {
13796 wolfSSL_EVP_PKEY_free(xPkey->dec_pkey);
13797 XFREE(xPkey, xPkey->heap, DYNAMIC_TYPE_KEY);
13798 }
13799 }
13800
13801
13802#ifndef NO_BIO
13803
13804#define PEM_COMPARE_HEADER(start, end, header) \
13805 ((end) - (start) == XSTR_SIZEOF(header) && XMEMCMP(start, header, \
13806 XSTR_SIZEOF(header)) == 0)
13807
13808 /**
13809 * This read one structure from bio and returns the read structure
13810 * in the appropriate output parameter (x509, crl, x_pkey). The
13811 * output parameters must be set to NULL.
13812 * @param bio Input for reading structures
13813 * @param cb Password callback
13814 * @param x509 Output
13815 * @param crl Output
13816 * @param x_pkey Output
13817 * @return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE otherwise
13818 */
13819 int wolfSSL_PEM_X509_X509_CRL_X509_PKEY_read_bio(
13820 WOLFSSL_BIO* bio, wc_pem_password_cb* cb, WOLFSSL_X509** x509,
13821 WOLFSSL_X509_CRL** crl, WOLFSSL_X509_PKEY** x_pkey)
13822 {
13823
13824#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)
13825 char* pem = NULL;
13826 long i = pem_struct_min_sz, l;
13827 const char* header = NULL;
13828 const char* headerEnd = NULL;
13829 const char* footer = NULL;
13830 const char* footerEnd = NULL;
13831 #ifdef HAVE_CRL
13832 DerBuffer* der = NULL;
13833 #endif
13834 WOLFSSL_BIO* pemBio = NULL;
13835
13836 if (!bio || !x509 || *x509 || !crl || *crl || !x_pkey || *x_pkey) {
13837 WOLFSSL_MSG("Bad input parameter or output parameters "
13838 "not set to a NULL value.");
13839 return WOLFSSL_FAILURE;
13840 }
13841
13842 l = wolfSSL_BIO_get_len(bio);
13843
13844 if (l < 0) {
13845 WOLFSSL_ERROR(BAD_FUNC_ARG);
13846 return WOLFSSL_FAILURE;
13847 }
13848
13849 if (l == 0) {
13850 /* Streaming BIO (pipe/FIFO/socket): size unknown, use the cap. */
13851 l = MAX_BIO_READ_BUFFER;
13852 }
13853 else if (l <= pem_struct_min_sz) {
13854 /* No certificate in buffer */
13855 WOLFSSL_ERROR(ASN_NO_PEM_HEADER);
13856 return WOLFSSL_FAILURE;
13857 }
13858
13859 pem = (char*)XMALLOC(l, 0, DYNAMIC_TYPE_PEM);
13860 if (pem == NULL)
13861 return WOLFSSL_FAILURE;
13862
13863 if (wolfSSL_BIO_read(bio, &pem[0], pem_struct_min_sz) !=
13864 pem_struct_min_sz) {
13865 WOLFSSL_ERROR(ASN_NO_PEM_HEADER);
13866 goto err;
13867 }
13868
13869 /* Read the header and footer */
13870 while (i < l && wolfSSL_BIO_read(bio, &pem[i], 1) == 1) {
13871 i++;
13872 if (!header) {
13873 header = XSTRNSTR(pem, "-----BEGIN ", i);
13874 }
13875 else if (!headerEnd) {
13876 headerEnd = XSTRNSTR(header + XSTR_SIZEOF("-----BEGIN "),
13877 "-----",
13878 i - (header + XSTR_SIZEOF("-----BEGIN ") - pem));
13879 if (headerEnd) {
13880 headerEnd += XSTR_SIZEOF("-----");
13881 /* Read in the newline */
13882 if (wolfSSL_BIO_read(bio, &pem[i], 1) != 1) {
13883 WOLFSSL_MSG("wolfSSL_BIO_read error");
13884 goto err;
13885 }
13886 i++;
13887 if (*headerEnd != '\n' && *headerEnd != '\r') {
13888 WOLFSSL_MSG("Missing newline after header");
13889 goto err;
13890 }
13891 }
13892 }
13893 else if (!footer) {
13894 footer = XSTRNSTR(headerEnd, "-----END ",
13895 i - (headerEnd - pem));
13896 }
13897 else if (!footerEnd) {
13898 footerEnd = XSTRNSTR(footer + XSTR_SIZEOF("-----"),
13899 "-----",
13900 i - (footer + XSTR_SIZEOF("-----") - pem));
13901 if (footerEnd) {
13902 footerEnd += XSTR_SIZEOF("-----");
13903 /* Now check that footer matches header */
13904 if ((headerEnd - (header + XSTR_SIZEOF("-----BEGIN "))) ==
13905 (footerEnd - (footer + XSTR_SIZEOF("-----END "))) &&
13906 XMEMCMP(header + XSTR_SIZEOF("-----BEGIN "),
13907 footer + XSTR_SIZEOF("-----END "),
13908 headerEnd - (header + XSTR_SIZEOF("-----BEGIN ")))
13909 != 0) {
13910 WOLFSSL_MSG("Header and footer don't match");
13911 goto err;
13912 }
13913 /* header and footer match */
13914 break;
13915 }
13916 }
13917 }
13918 if (!footerEnd) {
13919 /* Only check footerEnd since it is set last */
13920 WOLFSSL_ERROR(ASN_NO_PEM_HEADER);
13921 goto err;
13922 }
13923 else {
13924 if (PEM_COMPARE_HEADER(header, headerEnd,
13925 "-----BEGIN CERTIFICATE-----")) {
13926 /* We have a certificate */
13927 WOLFSSL_MSG("Parsing x509 cert");
13928 *x509 = wolfSSL_X509_load_certificate_buffer(
13929 (const unsigned char*) header,
13930 (int)(footerEnd - header), WOLFSSL_FILETYPE_PEM);
13931 if (!*x509) {
13932 WOLFSSL_MSG("wolfSSL_X509_load_certificate_buffer error");
13933 goto err;
13934 }
13935 }
13936 #ifdef HAVE_CRL
13937 else if (PEM_COMPARE_HEADER(header, headerEnd,
13938 "-----BEGIN X509 CRL-----")) {
13939 /* We have a crl */
13940 WOLFSSL_MSG("Parsing crl");
13941 if ((PemToDer((const unsigned char*) header,
13942 (long)(footerEnd - header), CRL_TYPE, &der, NULL, NULL,
13943 NULL)) < 0) {
13944 WOLFSSL_MSG("PemToDer error");
13945 goto err;
13946 }
13947 *crl = wolfSSL_d2i_X509_CRL(NULL, der->buffer, der->length);
13948 if (!*crl) {
13949 WOLFSSL_MSG("wolfSSL_d2i_X509_CRL error");
13950 goto err;
13951 }
13952 }
13953 #endif
13954 else {
13955 WOLFSSL_MSG("Parsing x509 key");
13956
13957 if (!(*x_pkey = wolfSSL_X509_PKEY_new(NULL))) {
13958 WOLFSSL_MSG("wolfSSL_X509_PKEY_new error");
13959 goto err;
13960 }
13961
13962 if (!(pemBio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem()))) {
13963 WOLFSSL_MSG("wolfSSL_BIO_new error");
13964 goto err;
13965 }
13966
13967 if (wolfSSL_BIO_write(pemBio, header,
13968 (int)(footerEnd - header)) != footerEnd - header) {
13969 WOLFSSL_MSG("wolfSSL_BIO_new error");
13970 goto err;
13971 }
13972
13973 if (wolfSSL_PEM_read_bio_PrivateKey(pemBio,
13974 &(*x_pkey)->dec_pkey, cb, NULL) == NULL) {
13975 WOLFSSL_MSG("wolfSSL_PEM_read_bio_PrivateKey error");
13976 goto err;
13977 }
13978
13979 wolfSSL_BIO_free(pemBio);
13980 }
13981 }
13982
13983 XFREE(pem, 0, DYNAMIC_TYPE_PEM);
13984 #ifdef HAVE_CRL
13985 if (der)
13986 FreeDer(&der);
13987 #endif
13988 return WOLFSSL_SUCCESS;
13989err:
13990 XFREE(pem, 0, DYNAMIC_TYPE_PEM);
13991 #ifdef HAVE_CRL
13992 if (der)
13993 FreeDer(&der);
13994 #endif
13995 if (*x_pkey) {
13996 wolfSSL_X509_PKEY_free(*x_pkey);
13997 *x_pkey = NULL;
13998 }
13999 if (pemBio)
14000 wolfSSL_BIO_free(pemBio);
14001 return WOLFSSL_FAILURE;
14002#else /* ! (WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM) */
14003 return WOLFSSL_FAILURE;
14004#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */
14005 }
14006
14007#endif /* OPENSSL_EXTRA || OPENSSL_ALL */
14008#ifdef OPENSSL_ALL
14009
14010#ifndef NO_FILESYSTEM
14011 WOLF_STACK_OF(WOLFSSL_X509_INFO)* wolfSSL_PEM_X509_INFO_read(
14012 XFILE fp, WOLF_STACK_OF(WOLFSSL_X509_INFO)* sk,
14013 pem_password_cb* cb, void* u)
14014 {
14015 WOLFSSL_BIO* fileBio = wolfSSL_BIO_new_fp(fp, WOLFSSL_BIO_NOCLOSE);
14016 WOLF_STACK_OF(WOLFSSL_X509_INFO)* ret = NULL;
14017
14018 WOLFSSL_ENTER("wolfSSL_PEM_X509_INFO_read");
14019 if (fileBio != NULL) {
14020 ret = wolfSSL_PEM_X509_INFO_read_bio(fileBio, sk, cb, u);
14021 wolfSSL_BIO_free(fileBio);
14022 }
14023 return ret;
14024 }
14025#endif /* !NO_FILESYSTEM */
14026
14027 /*
14028 * bio WOLFSSL_BIO to read certificates from
14029 * sk possible stack to push more X509_INFO structs to. Can be NULL
14030 * cb callback password for encrypted PEM certificates
14031 * u user input such as password
14032 *
14033 * returns stack on success and NULL or default stack passed in on fail
14034 */
14035 WOLF_STACK_OF(WOLFSSL_X509_INFO)* wolfSSL_PEM_X509_INFO_read_bio(
14036 WOLFSSL_BIO* bio, WOLF_STACK_OF(WOLFSSL_X509_INFO)* sk,
14037 wc_pem_password_cb* cb, void* u)
14038 {
14039 WOLF_STACK_OF(WOLFSSL_X509_INFO)* localSk = NULL;
14040 int ret = WOLFSSL_SUCCESS;
14041 WOLFSSL_X509_INFO* current = NULL;
14042 WOLFSSL_X509* x509 = NULL;
14043 WOLFSSL_X509_CRL* crl = NULL;
14044 WOLFSSL_X509_PKEY* x_pkey = NULL;
14045
14046 (void)u;
14047
14048 WOLFSSL_ENTER("wolfSSL_PEM_X509_INFO_read_bio");
14049
14050 /* attempt to use passed in stack or create a new one */
14051 if (sk != NULL) {
14052 localSk = sk;
14053 }
14054 else {
14055 localSk = wolfSSL_sk_X509_INFO_new_null();
14056 }
14057 if (localSk == NULL) {
14058 WOLFSSL_LEAVE("wolfSSL_PEM_X509_INFO_read_bio",
14059 MEMORY_E);
14060 return NULL;
14061 }
14062
14063 /* parse through BIO and push new info's found onto stack */
14064 while (1) {
14065 x509 = NULL;
14066 crl = NULL;
14067 x_pkey = NULL;
14068
14069 if (wolfSSL_PEM_X509_X509_CRL_X509_PKEY_read_bio(bio, cb,
14070 &x509, &crl, &x_pkey) == WOLFSSL_SUCCESS) {
14071 if (current == NULL ||
14072 (x509 && current->x509) ||
14073 (crl && current->crl) ||
14074 (x_pkey && current->x_pkey)) {
14075 /* Need to create new current since existing one already
14076 * has the member filled or this is the first successful
14077 * read. */
14078 current = wolfSSL_X509_INFO_new();
14079 if (current == NULL) {
14080 ret = MEMORY_E;
14081 break;
14082 }
14083 if (wolfSSL_sk_X509_INFO_push(localSk, current) <= 0) {
14084 wolfSSL_X509_INFO_free(current);
14085 current = NULL;
14086 ret = WOLFSSL_FAILURE;
14087 break;
14088 }
14089 }
14090
14091 if (x509) {
14092 current->x509 = x509;
14093 }
14094 else if (crl) {
14095 current->crl = crl;
14096 }
14097 else if (x_pkey) {
14098 current->x_pkey = x_pkey;
14099 }
14100 else {
14101 WOLFSSL_MSG("No output parameters set");
14102 ret = WOLFSSL_FAILURE;
14103 break;
14104 }
14105 }
14106 else {
14107#ifdef WOLFSSL_HAVE_ERROR_QUEUE
14108 unsigned long err;
14109 CLEAR_ASN_NO_PEM_HEADER_ERROR(err);
14110 if (ERR_GET_LIB(err) != ERR_LIB_PEM ||
14111 ERR_GET_REASON(err) != PEM_R_NO_START_LINE) {
14112 ret = WOLFSSL_FAILURE;
14113 }
14114#else
14115 if (wolfSSL_sk_X509_INFO_num(localSk) > 0) {
14116 WOLFSSL_MSG("At least one X509_INFO object on stack."
14117 "Assuming error means EOF or no more PEM"
14118 "headers found.");
14119 }
14120 else {
14121 ret = WOLFSSL_FAILURE;
14122 }
14123#endif
14124 break;
14125 }
14126 }
14127 if (ret != WOLFSSL_SUCCESS ||
14128 wolfSSL_sk_X509_INFO_num(localSk) == 0) {
14129 /* current should always be pushed onto the localsk stack at this
14130 * point. The only case when it isn't is when
14131 * wolfSSL_sk_X509_INFO_push fails but in that case the current
14132 * free is handled inside the loop. */
14133 if (localSk != sk) {
14134 wolfSSL_sk_pop_free(localSk, NULL);
14135 }
14136 wolfSSL_X509_free(x509);
14137#ifdef HAVE_CRL
14138 wolfSSL_X509_CRL_free(crl);
14139#endif
14140 wolfSSL_X509_PKEY_free(x_pkey);
14141 localSk = NULL;
14142 }
14143 WOLFSSL_LEAVE("wolfSSL_PEM_X509_INFO_read_bio", ret);
14144 return localSk;
14145 }
14146#endif /* !NO_BIO */
14147#endif /* OPENSSL_EXTRA || OPENSSL_ALL */
14148
14149 void wolfSSL_X509_NAME_ENTRY_free(WOLFSSL_X509_NAME_ENTRY* ne)
14150 {
14151 WOLFSSL_ENTER("wolfSSL_X509_NAME_ENTRY_free");
14152 if (ne != NULL) {
14153 wolfSSL_ASN1_OBJECT_free(ne->object);
14154 if (ne->value != NULL) {
14155 wolfSSL_ASN1_STRING_free(ne->value);
14156 }
14157 XFREE(ne, NULL, DYNAMIC_TYPE_NAME_ENTRY);
14158 }
14159 }
14160
14161
14162 WOLFSSL_X509_NAME_ENTRY* wolfSSL_X509_NAME_ENTRY_new(void)
14163 {
14164 WOLFSSL_X509_NAME_ENTRY* ne;
14165
14166 ne = (WOLFSSL_X509_NAME_ENTRY*)XMALLOC(sizeof(WOLFSSL_X509_NAME_ENTRY),
14167 NULL, DYNAMIC_TYPE_NAME_ENTRY);
14168 if (ne != NULL) {
14169 XMEMSET(ne, 0, sizeof(WOLFSSL_X509_NAME_ENTRY));
14170 }
14171
14172 return ne;
14173 }
14174
14175
14176 static void wolfssl_x509_name_entry_set(WOLFSSL_X509_NAME_ENTRY* ne,
14177 int nid, int type, const unsigned char *data, int dataSz)
14178 {
14179 ne->nid = nid;
14180 /* Reuse the object if already available. */
14181 ne->object = wolfSSL_OBJ_nid2obj_ex(nid, ne->object);
14182 if (ne->value == NULL) {
14183 ne->value = wolfSSL_ASN1_STRING_type_new(type);
14184 }
14185 if (ne->value != NULL) {
14186 if (wolfSSL_ASN1_STRING_set(ne->value, (const void*)data,
14187 dataSz) == WOLFSSL_SUCCESS) {
14188 ne->set = 1;
14189 }
14190 else {
14191 /* Free the ASN1_STRING if it is not set. */
14192 wolfSSL_ASN1_STRING_free(ne->value);
14193 ne->value = NULL;
14194 }
14195 }
14196 }
14197
14198 /* Create a new WOLFSSL_X509_NAME_ENTRY structure based on the text passed
14199 * in. Returns NULL on failure */
14200 WOLFSSL_X509_NAME_ENTRY* wolfSSL_X509_NAME_ENTRY_create_by_txt(
14201 WOLFSSL_X509_NAME_ENTRY **neIn, const char *txt, int type,
14202 const unsigned char *data, int dataSz)
14203 {
14204 int nid = -1;
14205 WOLFSSL_X509_NAME_ENTRY* ne = NULL;
14206
14207 WOLFSSL_ENTER("wolfSSL_X509_NAME_ENTRY_create_by_txt");
14208
14209 if (txt == NULL) {
14210 return NULL;
14211 }
14212
14213 if (neIn != NULL) {
14214 ne = *neIn;
14215 }
14216
14217 nid = wolfSSL_OBJ_txt2nid(txt);
14218 if (nid == WC_NID_undef) {
14219 WOLFSSL_MSG("Unable to find text");
14220 ne = NULL;
14221 }
14222 else {
14223 if (ne == NULL) {
14224 ne = wolfSSL_X509_NAME_ENTRY_new();
14225 if (ne == NULL) {
14226 return NULL;
14227 }
14228 }
14229
14230 wolfssl_x509_name_entry_set(ne, nid, type, data, dataSz);
14231 }
14232
14233 return ne;
14234 }
14235
14236
14237 /* Creates a new entry given the NID, type, and data
14238 * "dataSz" is number of bytes in data, if set to -1 then XSTRLEN is used
14239 * "out" can be used to store the new entry data in an existing structure
14240 * if NULL then a new WOLFSSL_X509_NAME_ENTRY structure is created
14241 * returns a pointer to WOLFSSL_X509_NAME_ENTRY on success and NULL on fail
14242 */
14243 WOLFSSL_X509_NAME_ENTRY* wolfSSL_X509_NAME_ENTRY_create_by_NID(
14244 WOLFSSL_X509_NAME_ENTRY** out, int nid, int type,
14245 const unsigned char* data, int dataSz)
14246 {
14247 WOLFSSL_X509_NAME_ENTRY* ne;
14248
14249#ifdef WOLFSSL_DEBUG_OPENSSL
14250 WOLFSSL_ENTER("wolfSSL_X509_NAME_ENTRY_create_by_NID");
14251#endif
14252
14253 if (!data) {
14254 WOLFSSL_MSG("Bad parameter");
14255 return NULL;
14256 }
14257
14258 if (out == NULL || *out == NULL) {
14259 ne = wolfSSL_X509_NAME_ENTRY_new();
14260 if (ne == NULL) {
14261 return NULL;
14262 }
14263 if (out != NULL) {
14264 *out = ne;
14265 }
14266 }
14267 else {
14268 ne = *out;
14269 }
14270
14271 wolfssl_x509_name_entry_set(ne, nid, type, data, dataSz);
14272
14273 return ne;
14274 }
14275#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
14276
14277#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \
14278 defined(HAVE_LIGHTY) || defined(WOLFSSL_MYSQL_COMPATIBLE) || \
14279 defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \
14280 defined(HAVE_POCO_LIB) || defined(WOLFSSL_HAPROXY)
14281WOLFSSL_ASN1_OBJECT* wolfSSL_X509_NAME_ENTRY_get_object(
14282 WOLFSSL_X509_NAME_ENTRY *ne)
14283{
14284 WOLFSSL_ASN1_OBJECT* object = NULL;
14285
14286#ifdef WOLFSSL_DEBUG_OPENSSL
14287 WOLFSSL_ENTER("wolfSSL_X509_NAME_ENTRY_get_object");
14288#endif
14289
14290 if (ne != NULL) {
14291 /* Create object from nid - reuse existing object if possible. */
14292 object = wolfSSL_OBJ_nid2obj_ex(ne->nid, ne->object);
14293 if (object != NULL) {
14294 /* Set the object when no error. */
14295 ne->object = object;
14296 }
14297 }
14298
14299 return object;
14300}
14301#endif /* OPENSSL_ALL || HAVE_LIGHTY || WOLFSSL_MYSQL_COMPATIBLE ||
14302 * HAVE_STUNNEL || WOLFSSL_NGINX || HAVE_POCO_LIB || WOLFSSL_HAPROXY */
14303
14304#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
14305 /* add all entry of type "nid" to the buffer "fullName" and advance "idx"
14306 * since number of entries is small, a brute force search is used here
14307 * returns the number of entries added
14308 */
14309 static int AddAllEntry(WOLFSSL_X509_NAME* name, char* fullName,
14310 int fullNameSz, int* idx)
14311 {
14312 int i;
14313 int ret = 0;
14314
14315 for (i = 0; i < MAX_NAME_ENTRIES; i++) {
14316 if (name->entry[i].set) {
14317 WOLFSSL_X509_NAME_ENTRY* e;
14318 WOLFSSL_ASN1_OBJECT* obj;
14319
14320 int sz;
14321 unsigned char* data;
14322
14323 e = &name->entry[i];
14324 obj = wolfSSL_X509_NAME_ENTRY_get_object(e);
14325 if (obj == NULL) {
14326 return BAD_FUNC_ARG;
14327 }
14328
14329 XMEMCPY(fullName + *idx, "/", 1); *idx = *idx + 1;
14330 sz = (int)XSTRLEN(obj->sName);
14331 XMEMCPY(fullName + *idx, obj->sName, sz);
14332 *idx += sz;
14333 XMEMCPY(fullName + *idx, "=", 1); *idx = *idx + 1;
14334
14335 data = wolfSSL_ASN1_STRING_data(e->value);
14336 if (data != NULL) {
14337 sz = (int)XSTRLEN((const char*)data);
14338 XMEMCPY(fullName + *idx, data, sz);
14339 *idx += sz;
14340 }
14341
14342 ret++;
14343 }
14344 }
14345 (void)fullNameSz;
14346 return ret;
14347 }
14348
14349
14350 /* Converts a list of entries in WOLFSSL_X509_NAME struct into a string
14351 * returns 0 on success */
14352 static int RebuildFullName(WOLFSSL_X509_NAME* name)
14353 {
14354 int totalLen = 0, i, idx, entryCount = 0;
14355
14356 if (name == NULL)
14357 return BAD_FUNC_ARG;
14358
14359 for (i = 0; i < MAX_NAME_ENTRIES; i++) {
14360 if (name->entry[i].set) {
14361 WOLFSSL_X509_NAME_ENTRY* e;
14362 WOLFSSL_ASN1_OBJECT* obj;
14363
14364 e = &name->entry[i];
14365 obj = wolfSSL_X509_NAME_ENTRY_get_object(e);
14366 if (obj == NULL)
14367 return BAD_FUNC_ARG;
14368
14369 totalLen += (int)XSTRLEN(obj->sName) + 2;/*+2 for '/' and '=' */
14370 totalLen += wolfSSL_ASN1_STRING_length(e->value);
14371 }
14372 }
14373
14374 if (name->dynamicName) {
14375 XFREE(name->name, name->heap, DYNAMIC_TYPE_X509);
14376 name->name = name->staticName;
14377 name->dynamicName = 0;
14378 }
14379
14380 if (totalLen >= ASN_NAME_MAX) {
14381 name->name = (char*)XMALLOC(totalLen + 1, name->heap,
14382 DYNAMIC_TYPE_X509);
14383 if (name->name == NULL)
14384 return MEMORY_E;
14385 name->dynamicName = 1;
14386 }
14387
14388 idx = 0;
14389 entryCount = AddAllEntry(name, name->name, totalLen, &idx);
14390 if (entryCount < 0)
14391 return entryCount;
14392
14393 name->name[idx] = '\0';
14394 name->sz = idx + 1; /* size includes null terminator */
14395 name->entrySz = entryCount;
14396
14397 return 0;
14398 }
14399
14400 /* Copies entry into name. With it being copied freeing entry becomes the
14401 * callers responsibility.
14402 * returns 1 for success and 0 for error */
14403 int wolfSSL_X509_NAME_add_entry(WOLFSSL_X509_NAME* name,
14404 WOLFSSL_X509_NAME_ENTRY* entry, int idx, int set)
14405 {
14406 WOLFSSL_X509_NAME_ENTRY* current = NULL;
14407 int ret, i;
14408
14409#ifdef WOLFSSL_DEBUG_OPENSSL
14410 WOLFSSL_ENTER("wolfSSL_X509_NAME_add_entry");
14411#endif
14412
14413 if (name == NULL || entry == NULL || entry->value == NULL) {
14414 WOLFSSL_MSG("NULL argument passed in");
14415 return WOLFSSL_FAILURE;
14416 }
14417
14418 if (idx >= 0) {
14419 /* place in specific index */
14420
14421 if (idx >= MAX_NAME_ENTRIES) {
14422 WOLFSSL_MSG("Error index to insert entry is larger than array");
14423 return WOLFSSL_FAILURE;
14424 }
14425 i = idx;
14426 }
14427 else {
14428 /* iterate through and find first open spot */
14429 for (i = 0; i < MAX_NAME_ENTRIES; i++) {
14430 if (name->entry[i].set == 0) { /* not set so overwritten */
14431 WOLFSSL_MSG("Found place for name entry");
14432 break;
14433 }
14434 }
14435
14436 if (i == MAX_NAME_ENTRIES) {
14437 WOLFSSL_MSG("No spot found for name entry");
14438 return WOLFSSL_FAILURE;
14439 }
14440 }
14441
14442 current = &name->entry[i];
14443 if (current->set == 0)
14444 name->entrySz++;
14445
14446 if (wolfSSL_X509_NAME_ENTRY_create_by_NID(¤t,
14447 entry->nid,
14448 wolfSSL_ASN1_STRING_type(entry->value),
14449 wolfSSL_ASN1_STRING_data(entry->value),
14450 wolfSSL_ASN1_STRING_length(entry->value)) != NULL)
14451 {
14452 ret = WOLFSSL_SUCCESS;
14453 #ifdef OPENSSL_ALL
14454 if (name->entries == NULL) {
14455 name->entries = wolfSSL_sk_X509_NAME_new(NULL);
14456 }
14457 if (wolfSSL_sk_X509_NAME_ENTRY_push(name->entries, current) <= 0) {
14458 ret = WOLFSSL_FAILURE;
14459 }
14460 #endif
14461 }
14462 else {
14463 ret = WOLFSSL_FAILURE;
14464 }
14465
14466 if (ret != WOLFSSL_SUCCESS) {
14467 WOLFSSL_MSG("Error adding the name entry");
14468 if (current->set == 0)
14469 name->entrySz--;
14470 return WOLFSSL_FAILURE;
14471 }
14472
14473#ifdef WOLFSSL_PYTHON
14474 /* Set name index for OpenSSL stack index position and so Python can
14475 * generate tuples/sets from the list. */
14476 for (i = 0; i < MAX_NAME_ENTRIES; i++) {
14477 if (name->entry[i].set != 0)
14478 name->entry[i].set = i + 1;
14479 }
14480#endif
14481
14482 if (RebuildFullName(name) != 0)
14483 return WOLFSSL_FAILURE;
14484
14485 (void)set;
14486 return WOLFSSL_SUCCESS;
14487 }
14488
14489 int wolfSSL_X509_NAME_add_entry_by_txt(WOLFSSL_X509_NAME *name,
14490 const char *field, int type,
14491 const unsigned char *bytes, int len,
14492 int loc, int set)
14493 {
14494 int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
14495 int nid;
14496 WOLFSSL_X509_NAME_ENTRY* entry;
14497
14498 (void)type;
14499 WOLFSSL_ENTER("wolfSSL_X509_NAME_add_entry_by_txt");
14500
14501 if (name == NULL || field == NULL)
14502 return WOLFSSL_FAILURE;
14503
14504 if ((nid = wolfSSL_OBJ_txt2nid(field)) == WC_NID_undef) {
14505 WOLFSSL_MSG("Unable convert text to NID");
14506 return WOLFSSL_FAILURE;
14507 }
14508
14509 entry = wolfSSL_X509_NAME_ENTRY_create_by_NID(NULL,
14510 nid, type, (unsigned char*)bytes, len);
14511 if (entry == NULL)
14512 return WOLFSSL_FAILURE;
14513
14514 ret = wolfSSL_X509_NAME_add_entry(name, entry, loc, set);
14515 wolfSSL_X509_NAME_ENTRY_free(entry);
14516
14517 return ret;
14518 }
14519
14520 int wolfSSL_X509_NAME_add_entry_by_NID(WOLFSSL_X509_NAME *name, int nid,
14521 int type, const unsigned char *bytes,
14522 int len, int loc, int set)
14523 {
14524 int ret;
14525 WOLFSSL_X509_NAME_ENTRY* entry;
14526 WOLFSSL_ENTER("wolfSSL_X509_NAME_add_entry_by_NID");
14527 entry = wolfSSL_X509_NAME_ENTRY_create_by_NID(NULL, nid, type, bytes,
14528 len);
14529 if (entry == NULL)
14530 return WOLFSSL_FAILURE;
14531 ret = wolfSSL_X509_NAME_add_entry(name, entry, loc, set);
14532 wolfSSL_X509_NAME_ENTRY_free(entry);
14533 return ret;
14534 }
14535
14536 WOLFSSL_X509_NAME_ENTRY *wolfSSL_X509_NAME_delete_entry(
14537 WOLFSSL_X509_NAME *name, int loc)
14538 {
14539 WOLFSSL_X509_NAME_ENTRY* ret;
14540 WOLFSSL_ENTER("wolfSSL_X509_NAME_delete_entry");
14541
14542 if (!name) {
14543 WOLFSSL_MSG("Bad parameter");
14544 return NULL;
14545 }
14546
14547 ret = wolfSSL_X509_NAME_get_entry(name, loc);
14548 if (!ret) {
14549 WOLFSSL_MSG("loc entry not found");
14550 return NULL;
14551 }
14552 name->entry[loc].set = 0;
14553#ifdef WOLFSSL_PYTHON
14554 {
14555 int i;
14556 /* Set name index for OpenSSL stack index position and so Python can
14557 * generate tuples/sets from the list. */
14558 for (i = 0; i < MAX_NAME_ENTRIES; i++) {
14559 if (name->entry[i].set != 0)
14560 name->entry[i].set = i + 1;
14561 }
14562 }
14563#endif
14564 return ret;
14565 }
14566
14567#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
14568
14569#if defined(OPENSSL_EXTRA) && !defined(NO_ASN)
14570 int wolfSSL_X509_NAME_get_index_by_OBJ(WOLFSSL_X509_NAME *name,
14571 const WOLFSSL_ASN1_OBJECT *obj,
14572 int idx) {
14573 if (!name || idx >= MAX_NAME_ENTRIES ||
14574 !obj || !obj->obj) {
14575 return WOLFSSL_FATAL_ERROR;
14576 }
14577
14578 if (idx < 0) {
14579 idx = -1;
14580 }
14581
14582 for (idx++; idx < MAX_NAME_ENTRIES; idx++) {
14583 /* Find index of desired name */
14584 if (name->entry[idx].set) {
14585 if (XSTRLEN(obj->sName) ==
14586 XSTRLEN(name->entry[idx].object->sName) &&
14587 XSTRNCMP((const char*) obj->sName,
14588 name->entry[idx].object->sName, obj->objSz - 1) == 0) {
14589 return idx;
14590 }
14591 }
14592 }
14593 return WOLFSSL_FATAL_ERROR;
14594 }
14595#endif
14596
14597#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \
14598 defined(OPENSSL_EXTRA_X509_SMALL)
14599
14600#ifdef OPENSSL_EXTRA
14601 int wolfSSL_X509_NAME_ENTRY_set(const WOLFSSL_X509_NAME_ENTRY *ne)
14602 {
14603 if (ne != NULL) {
14604 return ne->set;
14605 }
14606 return 0;
14607 }
14608#endif
14609
14610
14611 /* returns a pointer to the internal entry at location 'loc' on success,
14612 * a null pointer is returned in fail cases */
14613 WOLFSSL_X509_NAME_ENTRY *wolfSSL_X509_NAME_get_entry(
14614 const WOLFSSL_X509_NAME *name, int loc)
14615 {
14616#ifdef WOLFSSL_DEBUG_OPENSSL
14617 WOLFSSL_ENTER("wolfSSL_X509_NAME_get_entry");
14618#endif
14619
14620 if (name == NULL) {
14621 return NULL;
14622 }
14623
14624 if (loc < 0 || loc >= MAX_NAME_ENTRIES) {
14625 WOLFSSL_MSG("Bad argument");
14626 return NULL;
14627 }
14628
14629 if (name->entry[loc].set) {
14630 return (WOLFSSL_X509_NAME_ENTRY*)&name->entry[loc];
14631 }
14632 else {
14633 return NULL;
14634 }
14635 }
14636#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
14637
14638#ifdef OPENSSL_EXTRA
14639
14640int wolfSSL_X509_check_private_key(WOLFSSL_X509 *x509, WOLFSSL_EVP_PKEY *key)
14641{
14642 WOLFSSL_ENTER("wolfSSL_X509_check_private_key");
14643
14644 if (!x509 || !key) {
14645 WOLFSSL_MSG("Bad parameter");
14646 return WOLFSSL_FAILURE;
14647 }
14648
14649#ifndef NO_CHECK_PRIVATE_KEY
14650 return wc_CheckPrivateKey((byte*)key->pkey.ptr, key->pkey_sz,
14651 x509->pubKey.buffer, x509->pubKey.length,
14652 (enum Key_Sum)x509->pubKeyOID, key->heap) == 1 ?
14653 WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
14654#else
14655 /* not compiled in */
14656 return WOLFSSL_SUCCESS;
14657#endif
14658}
14659
14660#endif /* OPENSSL_EXTRA */
14661
14662#if defined(HAVE_LIGHTY) || defined(HAVE_STUNNEL) \
14663 || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(OPENSSL_EXTRA)
14664#ifndef NO_BIO
14665
14666#ifdef WOLFSSL_CERT_GEN
14667
14668#ifdef WOLFSSL_CERT_REQ
14669/* writes the x509 from x to the WOLFSSL_BIO bp
14670 *
14671 * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on fail
14672 */
14673int wolfSSL_PEM_write_bio_X509_REQ(WOLFSSL_BIO *bp, WOLFSSL_X509 *x)
14674{
14675 byte* pem;
14676 int pemSz = 0;
14677 const unsigned char* der;
14678 int derSz;
14679 int ret;
14680
14681 WOLFSSL_ENTER("wolfSSL_PEM_write_bio_X509_REQ");
14682
14683 if (x == NULL || bp == NULL) {
14684 return WOLFSSL_FAILURE;
14685 }
14686
14687 der = wolfSSL_X509_get_der(x, &derSz);
14688 if (der == NULL) {
14689 return WOLFSSL_FAILURE;
14690 }
14691
14692 /* get PEM size */
14693 pemSz = wc_DerToPemEx(der, (word32)derSz, NULL, 0, NULL, CERTREQ_TYPE);
14694 if (pemSz < 0) {
14695 return WOLFSSL_FAILURE;
14696 }
14697
14698 /* create PEM buffer and convert from DER */
14699 pem = (byte*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
14700 if (pem == NULL) {
14701 return WOLFSSL_FAILURE;
14702 }
14703 if (wc_DerToPemEx(der, (word32)derSz, pem, pemSz, NULL, CERTREQ_TYPE) < 0) {
14704 XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
14705 return WOLFSSL_FAILURE;
14706 }
14707
14708 /* write the PEM to BIO */
14709 ret = wolfSSL_BIO_write(bp, pem, pemSz);
14710 XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
14711
14712 if (ret <= 0) return WOLFSSL_FAILURE;
14713 return WOLFSSL_SUCCESS;
14714}
14715#endif /* WOLFSSL_CERT_REQ */
14716
14717
14718/* writes the x509 from x to the WOLFSSL_BIO bp
14719 *
14720 * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on fail
14721 */
14722int wolfSSL_PEM_write_bio_X509_AUX(WOLFSSL_BIO *bp, WOLFSSL_X509 *x)
14723{
14724 byte* pem;
14725 int pemSz = 0;
14726 const unsigned char* der;
14727 int derSz;
14728 int ret;
14729
14730 WOLFSSL_ENTER("wolfSSL_PEM_write_bio_X509_AUX");
14731
14732 if (bp == NULL || x == NULL) {
14733 WOLFSSL_MSG("NULL argument passed in");
14734 return WOLFSSL_FAILURE;
14735 }
14736
14737 der = wolfSSL_X509_get_der(x, &derSz);
14738 if (der == NULL) {
14739 return WOLFSSL_FAILURE;
14740 }
14741
14742 /* get PEM size */
14743 pemSz = wc_DerToPemEx(der, (word32)derSz, NULL, 0, NULL, CERT_TYPE);
14744 if (pemSz < 0) {
14745 return WOLFSSL_FAILURE;
14746 }
14747
14748 /* create PEM buffer and convert from DER */
14749 pem = (byte*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
14750 if (pem == NULL) {
14751 return WOLFSSL_FAILURE;
14752 }
14753 if (wc_DerToPemEx(der, (word32)derSz, pem, pemSz, NULL, CERT_TYPE) < 0) {
14754 XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
14755 return WOLFSSL_FAILURE;
14756 }
14757
14758 /* write the PEM to BIO */
14759 ret = wolfSSL_BIO_write(bp, pem, pemSz);
14760 XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
14761
14762 if (ret <= 0) return WOLFSSL_FAILURE;
14763 return WOLFSSL_SUCCESS;
14764}
14765
14766int wolfSSL_PEM_write_bio_X509(WOLFSSL_BIO *bio, WOLFSSL_X509 *cert)
14767{
14768 byte* pem = NULL;
14769 int pemSz = 0;
14770 /* Get large buffer to hold cert der */
14771 const byte* der = NULL;
14772 int derSz = X509_BUFFER_SZ;
14773 int ret;
14774
14775 WOLFSSL_ENTER("wolfSSL_PEM_write_bio_X509");
14776
14777 if (bio == NULL || cert == NULL) {
14778 WOLFSSL_MSG("NULL argument passed in");
14779 return WOLFSSL_FAILURE;
14780 }
14781
14782 /* Do not call wolfssl_x509_make_der() here. If we did, then need to re-sign
14783 * because we don't know the original order of the extensions and so we must
14784 * assume our extensions are in a different order, thus need to re-sign. */
14785 der = wolfSSL_X509_get_der(cert, &derSz);
14786 if (der == NULL) {
14787 goto error;
14788 }
14789
14790 /* get PEM size */
14791 pemSz = wc_DerToPemEx(der, (word32)derSz, NULL, 0, NULL, CERT_TYPE);
14792 if (pemSz < 0) {
14793 goto error;
14794 }
14795
14796 /* create PEM buffer and convert from DER */
14797 pem = (byte*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
14798 if (pem == NULL) {
14799 goto error;
14800 }
14801 if (wc_DerToPemEx(der, (word32)derSz, pem, pemSz, NULL, CERT_TYPE) < 0) {
14802 goto error;
14803 }
14804
14805 /* write the PEM to BIO */
14806 ret = wolfSSL_BIO_write(bio, pem, pemSz);
14807 XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
14808
14809 if (ret <= 0) return WOLFSSL_FAILURE;
14810 return WOLFSSL_SUCCESS;
14811
14812error:
14813 XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
14814 return WOLFSSL_FAILURE;
14815}
14816#endif /* WOLFSSL_CERT_GEN */
14817
14818#endif /* !NO_BIO */
14819#endif /* HAVE_LIGHTY || HAVE_STUNNEL || WOLFSSL_MYSQL_COMPATIBLE */
14820
14821#if defined(OPENSSL_EXTRA) || defined(HAVE_STUNNEL) || \
14822 defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY) || \
14823 defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_OPENSSH) || \
14824 defined(HAVE_SBLIM_SFCB)
14825
14826WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_sk_X509_NAME_new(
14827 WOLF_SK_COMPARE_CB(WOLFSSL_X509_NAME, cb))
14828{
14829 WOLFSSL_STACK* sk;
14830 (void)cb;
14831
14832 WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_new");
14833
14834 sk = wolfSSL_sk_new_node(NULL);
14835 if (sk != NULL) {
14836 sk->type = STACK_TYPE_X509_NAME;
14837 }
14838
14839 return sk;
14840}
14841
14842int wolfSSL_sk_X509_NAME_num(const WOLF_STACK_OF(WOLFSSL_X509_NAME) *sk)
14843{
14844 WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_num");
14845
14846 if (sk == NULL)
14847 return BAD_FUNC_ARG;
14848
14849 return (int)sk->num;
14850}
14851
14852/* Getter function for WOLFSSL_X509_NAME pointer
14853 *
14854 * sk is the stack to retrieve pointer from
14855 * i is the index value in stack
14856 *
14857 * returns a pointer to a WOLFSSL_X509_NAME structure on success and NULL on
14858 * fail
14859 */
14860WOLFSSL_X509_NAME* wolfSSL_sk_X509_NAME_value(
14861 const WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk, int i)
14862{
14863 WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_value");
14864 return (WOLFSSL_X509_NAME*)wolfSSL_sk_value(sk, i);
14865}
14866
14867WOLFSSL_X509_NAME* wolfSSL_sk_X509_NAME_pop(
14868 WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk)
14869{
14870 return (WOLFSSL_X509_NAME*)wolfSSL_sk_pop(sk);
14871}
14872
14873void wolfSSL_sk_X509_NAME_pop_free(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk,
14874 void (*f) (WOLFSSL_X509_NAME*))
14875{
14876 WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_pop_free");
14877 wolfSSL_sk_pop_free(sk, (wolfSSL_sk_freefunc)f);
14878}
14879
14880/* Free only the sk structure, NOT X509_NAME members */
14881void wolfSSL_sk_X509_NAME_free(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk)
14882{
14883 WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_free");
14884 wolfSSL_sk_free(sk);
14885}
14886
14887int wolfSSL_sk_X509_NAME_push(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk,
14888 WOLFSSL_X509_NAME* name)
14889{
14890 WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_push");
14891
14892 return wolfSSL_sk_push(sk, name);
14893}
14894
14895/* return index of found, or negative to indicate not found */
14896int wolfSSL_sk_X509_NAME_find(const WOLF_STACK_OF(WOLFSSL_X509_NAME) *sk,
14897 WOLFSSL_X509_NAME *name)
14898{
14899 int i;
14900
14901 WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_find");
14902
14903 if (sk == NULL)
14904 return BAD_FUNC_ARG;
14905
14906 for (i = 0; sk; i++, sk = sk->next) {
14907 if (wolfSSL_X509_NAME_cmp(sk->data.name, name) == 0) {
14908 return i;
14909 }
14910 }
14911 return WOLFSSL_FATAL_ERROR;
14912}
14913
14914/* Name Entry */
14915WOLF_STACK_OF(WOLFSSL_X509_NAME_ENTRY)* wolfSSL_sk_X509_NAME_ENTRY_new(
14916 WOLF_SK_COMPARE_CB(WOLFSSL_X509_NAME_ENTRY, cb))
14917{
14918 WOLFSSL_STACK* sk = wolfSSL_sk_new_node(NULL);
14919 if (sk != NULL) {
14920 sk->type = STACK_TYPE_X509_NAME_ENTRY;
14921 (void)cb;
14922 }
14923 return sk;
14924}
14925
14926int wolfSSL_sk_X509_NAME_ENTRY_push(WOLF_STACK_OF(WOLFSSL_X509_NAME_ENTRY)* sk,
14927 WOLFSSL_X509_NAME_ENTRY* name_entry)
14928{
14929 return wolfSSL_sk_push(sk, name_entry);
14930}
14931
14932WOLFSSL_X509_NAME_ENTRY* wolfSSL_sk_X509_NAME_ENTRY_value(
14933 const WOLF_STACK_OF(WOLFSSL_X509_NAME_ENTRY)* sk, int i)
14934{
14935 return (WOLFSSL_X509_NAME_ENTRY*)wolfSSL_sk_value(sk, i);
14936}
14937
14938int wolfSSL_sk_X509_NAME_ENTRY_num(
14939 const WOLF_STACK_OF(WOLFSSL_X509_NAME_ENTRY)* sk)
14940{
14941 if (sk == NULL)
14942 return BAD_FUNC_ARG;
14943 return (int)sk->num;
14944}
14945
14946void wolfSSL_sk_X509_NAME_ENTRY_free(WOLF_STACK_OF(WOLFSSL_X509_NAME_ENTRY)* sk)
14947{
14948 wolfSSL_sk_free(sk);
14949}
14950
14951#endif /* OPENSSL_EXTRA || HAVE_STUNNEL || WOLFSSL_NGINX ||
14952 HAVE_LIGHTY || WOLFSSL_HAPROXY ||
14953 WOLFSSL_OPENSSH || HAVE_SBLIM_SFCB */
14954
14955#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || \
14956 (defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \
14957 defined(HAVE_LIGHTY) || defined(WOLFSSL_HAPROXY) || \
14958 defined(WOLFSSL_OPENSSH) || defined(HAVE_SBLIM_SFCB))
14959
14960#if defined(OPENSSL_ALL)
14961WOLFSSL_X509_INFO* wolfSSL_X509_INFO_new(void)
14962{
14963 WOLFSSL_X509_INFO* info;
14964 info = (WOLFSSL_X509_INFO*)XMALLOC(sizeof(WOLFSSL_X509_INFO), NULL,
14965 DYNAMIC_TYPE_X509);
14966 if (info) {
14967 XMEMSET(info, 0, sizeof(*info));
14968 }
14969 return info;
14970}
14971
14972void wolfSSL_X509_INFO_free(WOLFSSL_X509_INFO* info)
14973{
14974 if (info == NULL)
14975 return;
14976
14977 if (info->x509) {
14978 wolfSSL_X509_free(info->x509);
14979 info->x509 = NULL;
14980 }
14981#ifdef HAVE_CRL
14982 if (info->crl) {
14983 wolfSSL_X509_CRL_free(info->crl);
14984 info->crl = NULL;
14985 }
14986#endif
14987 wolfSSL_X509_PKEY_free(info->x_pkey);
14988 info->x_pkey = NULL;
14989
14990 XFREE(info, NULL, DYNAMIC_TYPE_X509);
14991}
14992#endif
14993
14994WOLFSSL_STACK* wolfSSL_sk_X509_INFO_new_null(void)
14995{
14996 WOLFSSL_STACK* sk = wolfSSL_sk_new_node(NULL);
14997 if (sk) {
14998 sk->type = STACK_TYPE_X509_INFO;
14999 }
15000 return sk;
15001}
15002
15003int wolfSSL_sk_X509_INFO_num(const WOLF_STACK_OF(WOLFSSL_X509_INFO) *sk)
15004{
15005 WOLFSSL_ENTER("wolfSSL_sk_X509_INFO_num");
15006
15007 return wolfSSL_sk_num(sk);
15008}
15009
15010WOLFSSL_X509_INFO* wolfSSL_sk_X509_INFO_value(
15011 const WOLF_STACK_OF(WOLFSSL_X509_INFO) *sk, int i)
15012{
15013 WOLFSSL_ENTER("wolfSSL_sk_X509_INFO_value");
15014
15015 return (WOLFSSL_X509_INFO *)wolfSSL_sk_value(sk, i);
15016}
15017
15018WOLFSSL_X509_INFO* wolfSSL_sk_X509_INFO_pop(
15019 WOLF_STACK_OF(WOLFSSL_X509_INFO)* sk)
15020{
15021 return (WOLFSSL_X509_INFO*)wolfSSL_sk_pop(sk);
15022}
15023
15024#if defined(OPENSSL_ALL)
15025void wolfSSL_sk_X509_INFO_pop_free(WOLF_STACK_OF(WOLFSSL_X509_INFO)* sk,
15026 void (*f) (WOLFSSL_X509_INFO*))
15027{
15028 WOLFSSL_ENTER("wolfSSL_sk_X509_INFO_pop_free");
15029 wolfSSL_sk_pop_free(sk, (wolfSSL_sk_freefunc)f);
15030}
15031
15032void wolfSSL_sk_X509_INFO_free(WOLF_STACK_OF(WOLFSSL_X509_INFO) *sk)
15033{
15034 WOLFSSL_ENTER("wolfSSL_sk_X509_INFO_free");
15035 wolfSSL_sk_free(sk);
15036}
15037
15038/* Adds the WOLFSSL_X509_INFO to the stack "sk". "sk" takes control of "in" and
15039 * tries to free it when the stack is free'd.
15040 *
15041 * return number of elements on success 0 on fail
15042 */
15043int wolfSSL_sk_X509_INFO_push(WOLF_STACK_OF(WOLFSSL_X509_INFO)* sk,
15044 WOLFSSL_X509_INFO* in)
15045{
15046 return wolfSSL_sk_push(sk, in);
15047}
15048
15049/* Creates a duplicate of WOLF_STACK_OF(WOLFSSL_X509_NAME).
15050 * Returns a new WOLF_STACK_OF(WOLFSSL_X509_NAME) or NULL on failure */
15051WOLF_STACK_OF(WOLFSSL_X509_NAME) *wolfSSL_dup_CA_list(
15052 WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk)
15053{
15054 int i;
15055 const int num = wolfSSL_sk_X509_NAME_num(sk);
15056 WOLF_STACK_OF(WOLFSSL_X509_NAME) *copy;
15057 WOLFSSL_X509_NAME *name;
15058
15059 WOLFSSL_ENTER("wolfSSL_dup_CA_list");
15060
15061 copy = wolfSSL_sk_X509_NAME_new(NULL);
15062 if (copy == NULL) {
15063 WOLFSSL_MSG("Memory error");
15064 return NULL;
15065 }
15066
15067 for (i = 0; i < num; i++) {
15068 name = wolfSSL_X509_NAME_dup(wolfSSL_sk_X509_NAME_value(sk, i));
15069 if (name == NULL || wolfSSL_sk_X509_NAME_push(copy, name) <= 0) {
15070 WOLFSSL_MSG("Memory error");
15071 wolfSSL_sk_X509_NAME_pop_free(copy, wolfSSL_X509_NAME_free);
15072 wolfSSL_X509_NAME_free(name);
15073 return NULL;
15074 }
15075 }
15076
15077 return copy;
15078}
15079
15080void* wolfSSL_sk_X509_OBJECT_value(WOLF_STACK_OF(WOLFSSL_X509_OBJECT)* sk,
15081 int i)
15082{
15083 WOLFSSL_ENTER("wolfSSL_sk_X509_OBJECT_value");
15084 for (; sk != NULL && i > 0; i--)
15085 sk = sk->next;
15086
15087 if (i != 0 || sk == NULL)
15088 return NULL;
15089 return sk->data.x509_obj;
15090}
15091
15092int wolfSSL_sk_X509_OBJECT_num(const WOLF_STACK_OF(WOLFSSL_X509_OBJECT) *s)
15093{
15094 WOLFSSL_ENTER("wolfSSL_sk_X509_OBJECT_num");
15095 if (s) {
15096 return (int)s->num;
15097 }
15098 else {
15099 return 0;
15100 }
15101}
15102
15103int wolfSSL_sk_X509_NAME_set_cmp_func(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk,
15104 WOLF_SK_COMPARE_CB(WOLFSSL_X509_NAME, cb))
15105{
15106 WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_set_cmp_func");
15107
15108 if (sk == NULL)
15109 return BAD_FUNC_ARG;
15110
15111 WOLFSSL_MSG("Stack comparison not used in wolfSSL");
15112 (void)cb;
15113 return 0;
15114}
15115#endif /* OPENSSL_ALL */
15116
15117#ifndef NO_BIO
15118
15119/* Helper function for X509_NAME_print_ex. Sets *buf to string for domain
15120 name attribute based on NID. Returns size of buf */
15121static int get_dn_attr_by_nid(int n, const char** buf)
15122{
15123 int len = 0;
15124 const char *str;
15125
15126 switch(n)
15127 {
15128 case WC_NID_commonName :
15129 str = "CN";
15130 len = 2;
15131 break;
15132 case WC_NID_countryName:
15133 str = "C";
15134 len = 1;
15135 break;
15136 case WC_NID_localityName:
15137 str = "L";
15138 len = 1;
15139 break;
15140 case WC_NID_stateOrProvinceName:
15141 str = "ST";
15142 len = 2;
15143 break;
15144 case WC_NID_streetAddress:
15145 str = "street";
15146 len = 6;
15147 break;
15148 case WC_NID_organizationName:
15149 str = "O";
15150 len = 1;
15151 break;
15152 case WC_NID_organizationalUnitName:
15153 str = "OU";
15154 len = 2;
15155 break;
15156 case WC_NID_postalCode:
15157 str = "postalCode";
15158 len = 10;
15159 break;
15160 case WC_NID_emailAddress:
15161 str = "emailAddress";
15162 len = 12;
15163 break;
15164 case WC_NID_surname:
15165 str = "SN";
15166 len = 2;
15167 break;
15168 case WC_NID_givenName:
15169 str = "GN";
15170 len = 2;
15171 break;
15172 case WC_NID_dnQualifier:
15173 str = "dnQualifier";
15174 len = 11;
15175 break;
15176 case WC_NID_name:
15177 str = "name";
15178 len = 4;
15179 break;
15180 case WC_NID_initials:
15181 str = "initials";
15182 len = 8;
15183 break;
15184 case WC_NID_domainComponent:
15185 str = "DC";
15186 len = 2;
15187 break;
15188 case WC_NID_pkcs9_contentType:
15189 str = "contentType";
15190 len = 11;
15191 break;
15192 case WC_NID_userId:
15193 str = "UID";
15194 len = 3;
15195 break;
15196 case WC_NID_serialNumber:
15197 str = "serialNumber";
15198 len = 12;
15199 break;
15200 case WC_NID_title:
15201 str = "title";
15202 len = 5;
15203 break;
15204 case WC_NID_rfc822Mailbox:
15205 str = "mail";
15206 len = 4;
15207 break;
15208 default:
15209 WOLFSSL_MSG("Attribute type not found");
15210 str = NULL;
15211
15212 }
15213 if (buf != NULL)
15214 *buf = str;
15215 return len;
15216}
15217
15218/**
15219 * Escape input string for RFC2253 requirements. The following characters
15220 * are escaped with a backslash (\):
15221 *
15222 * 1. A space or '#' at the beginning of the string
15223 * 2. A space at the end of the string
15224 * 3. One of: ",", "+", """, "\", "<", ">", ";"
15225 *
15226 * in - input string to escape
15227 * inSz - length of in, not including the null terminator
15228 * out - buffer for output string to be written, will be null terminated
15229 * outSz - size of out
15230 *
15231 * Returns size of output string (not counting NULL terminator) on success,
15232 * negative on error.
15233 */
15234static int wolfSSL_EscapeString_RFC2253(char* in, word32 inSz,
15235 char* out, word32 outSz)
15236{
15237 word32 inIdx = 0;
15238 word32 outIdx = 0;
15239
15240 if (in == NULL || out == NULL || inSz == 0 || outSz == 0) {
15241 return BAD_FUNC_ARG;
15242 }
15243
15244 for (inIdx = 0; inIdx < inSz; inIdx++) {
15245
15246 char c = in[inIdx];
15247
15248 if (((inIdx == 0) && (c == ' ' || c == '#')) ||
15249 ((inIdx == (inSz-1)) && (c == ' ')) ||
15250 c == ',' || c == '+' || c == '"' || c == '\\' ||
15251 c == '<' || c == '>' || c == ';') {
15252
15253 if (outIdx > (outSz - 1)) {
15254 return BUFFER_E;
15255 }
15256 out[outIdx] = '\\';
15257 outIdx++;
15258 }
15259 if (outIdx > (outSz - 1)) {
15260 return BUFFER_E;
15261 }
15262 out[outIdx] = c;
15263 outIdx++;
15264 }
15265
15266 /* null terminate out */
15267 if (outIdx > (outSz -1)) {
15268 return BUFFER_E;
15269 }
15270 out[outIdx] = '\0';
15271
15272 return (int)outIdx;
15273}
15274
15275/*
15276 * Print human readable version of X509_NAME to provided BIO.
15277 *
15278 * bio - output BIO to place name string. Does not include null terminator.
15279 * name - input name to convert to string
15280 * indent - number of indent spaces to prepend to name string
15281 * flags - flags to control function behavior. Not all flags are currently
15282 * supported/implemented. Currently supported are:
15283 * XN_FLAG_RFC2253 - only the backslash escape requirements from
15284 * RFC22523 currently implemented.
15285 * XN_FLAG_DN_REV - print name reversed. Automatically done by
15286 * XN_FLAG_RFC2253.
15287 * XN_FLAG_SPC_EQ - spaces before and after '=' character
15288 *
15289 * Returns WOLFSSL_SUCCESS (1) on success, WOLFSSL_FAILURE (0) on failure.
15290 */
15291int wolfSSL_X509_NAME_print_ex(WOLFSSL_BIO* bio, WOLFSSL_X509_NAME* name,
15292 int indent, unsigned long flags)
15293{
15294 int i, count = 0, nameStrSz = 0, escapeSz = 0;
15295 int eqSpace = 0;
15296 char eqStr[4];
15297 char* tmp = NULL;
15298 char* nameStr = NULL;
15299 const char *buf = NULL;
15300 WOLFSSL_X509_NAME_ENTRY* ne;
15301 WOLFSSL_ASN1_STRING* str;
15302 char escaped[ASN_NAME_MAX];
15303
15304 WOLFSSL_ENTER("wolfSSL_X509_NAME_print_ex");
15305
15306 if ((name == NULL) || (bio == NULL))
15307 return WOLFSSL_FAILURE;
15308
15309 XMEMSET(eqStr, 0, sizeof(eqStr));
15310 if (flags & WOLFSSL_XN_FLAG_SPC_EQ) {
15311 eqSpace = 2;
15312 XSTRNCPY(eqStr, " = ", 4);
15313 }
15314 else {
15315 XSTRNCPY(eqStr, "=", 4);
15316 }
15317
15318 for (i = 0; i < indent; i++) {
15319 if (wolfSSL_BIO_write(bio, " ", 1) != 1)
15320 return WOLFSSL_FAILURE;
15321 }
15322
15323 count = wolfSSL_X509_NAME_entry_count(name);
15324
15325 for (i = 0; i < count; i++) {
15326 int len;
15327 int tmpSz;
15328
15329 /* reverse name order for RFC2253 and DN_REV */
15330 if ((flags & WOLFSSL_XN_FLAG_RFC2253) ||
15331 (flags & WOLFSSL_XN_FLAG_DN_REV)) {
15332 ne = wolfSSL_X509_NAME_get_entry(name, count - i - 1);
15333 }
15334 else {
15335 ne = wolfSSL_X509_NAME_get_entry(name, i);
15336 }
15337 if (ne == NULL)
15338 return WOLFSSL_FAILURE;
15339
15340 str = wolfSSL_X509_NAME_ENTRY_get_data(ne);
15341 if (str == NULL)
15342 return WOLFSSL_FAILURE;
15343
15344 if (flags & WOLFSSL_XN_FLAG_RFC2253) {
15345 /* escape string for RFC 2253, ret sz not counting null term */
15346 escapeSz = wolfSSL_EscapeString_RFC2253(str->data,
15347 str->length, escaped, sizeof(escaped));
15348 if (escapeSz < 0)
15349 return WOLFSSL_FAILURE;
15350
15351 nameStr = escaped;
15352 nameStrSz = escapeSz;
15353 }
15354 else {
15355 nameStr = str->data;
15356 nameStrSz = str->length;
15357 }
15358
15359 /* len is without null terminator */
15360 len = get_dn_attr_by_nid(ne->nid, &buf);
15361 if (len == 0 || buf == NULL)
15362 return WOLFSSL_FAILURE;
15363
15364 /* + 4 for '=', comma space and '\0'*/
15365 tmpSz = nameStrSz + len + 4 + eqSpace;
15366 tmp = (char*)XMALLOC(tmpSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
15367 if (tmp == NULL) {
15368 return WOLFSSL_FAILURE;
15369 }
15370
15371 if (i < count - 1) {
15372 if (XSNPRINTF(tmp, (size_t)tmpSz, "%s%s%s, ", buf, eqStr, nameStr)
15373 >= tmpSz)
15374 {
15375 WOLFSSL_MSG("buffer overrun");
15376 XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
15377 return WOLFSSL_FAILURE;
15378 }
15379
15380 tmpSz = len + nameStrSz + 3 + eqSpace; /* 3 for '=', comma space */
15381 }
15382 else {
15383 if (XSNPRINTF(tmp, (size_t)tmpSz, "%s%s%s", buf, eqStr, nameStr)
15384 >= tmpSz)
15385 {
15386 WOLFSSL_MSG("buffer overrun");
15387 XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
15388 return WOLFSSL_FAILURE;
15389 }
15390 tmpSz = len + nameStrSz + 1 + eqSpace; /* 1 for '=' */
15391 if (bio->type != WOLFSSL_BIO_FILE &&
15392 bio->type != WOLFSSL_BIO_MEMORY) {
15393 ++tmpSz; /* include the terminating null when not writing to a
15394 * file.
15395 */
15396 }
15397 }
15398
15399 if (wolfSSL_BIO_write(bio, tmp, tmpSz) != tmpSz) {
15400 XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
15401 return WOLFSSL_FAILURE;
15402 }
15403
15404 XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
15405 }
15406
15407 return WOLFSSL_SUCCESS;
15408}
15409
15410#ifndef NO_FILESYSTEM
15411int wolfSSL_X509_NAME_print_ex_fp(XFILE file, WOLFSSL_X509_NAME* name,
15412 int indent, unsigned long flags)
15413{
15414 WOLFSSL_BIO* bio;
15415 int ret;
15416
15417 WOLFSSL_ENTER("wolfSSL_X509_NAME_print_ex_fp");
15418
15419 if (!(bio = wolfSSL_BIO_new_fp(file, WOLFSSL_BIO_NOCLOSE))) {
15420 WOLFSSL_MSG("wolfSSL_BIO_new_fp error");
15421 return WOLFSSL_FAILURE;
15422 }
15423
15424 ret = wolfSSL_X509_NAME_print_ex(bio, name, indent, flags);
15425
15426 wolfSSL_BIO_free(bio);
15427
15428 return ret;
15429}
15430#endif /* NO_FILESYSTEM */
15431#endif /* !NO_BIO */
15432
15433#ifndef NO_WOLFSSL_STUB
15434WOLFSSL_ASN1_BIT_STRING* wolfSSL_X509_get0_pubkey_bitstr(const WOLFSSL_X509* x)
15435{
15436 (void)x;
15437 WOLFSSL_ENTER("wolfSSL_X509_get0_pubkey_bitstr");
15438 WOLFSSL_STUB("X509_get0_pubkey_bitstr");
15439
15440 return NULL;
15441}
15442#endif
15443
15444#ifdef OPENSSL_ALL
15445WOLFSSL_X509_LOOKUP_TYPE wolfSSL_X509_OBJECT_get_type(
15446 const WOLFSSL_X509_OBJECT* obj)
15447{
15448 if (obj == NULL)
15449 return WOLFSSL_X509_LU_NONE;
15450 return obj->type;
15451}
15452
15453WOLFSSL_X509_OBJECT* wolfSSL_X509_OBJECT_new(void)
15454{
15455 WOLFSSL_X509_OBJECT* ret = (WOLFSSL_X509_OBJECT*)
15456 XMALLOC(sizeof(WOLFSSL_X509_OBJECT), NULL, DYNAMIC_TYPE_OPENSSL);
15457 if (ret != NULL)
15458 XMEMSET(ret, 0, sizeof(WOLFSSL_X509_OBJECT));
15459 return ret;
15460}
15461
15462void wolfSSL_X509_OBJECT_free(WOLFSSL_X509_OBJECT *obj)
15463{
15464 WOLFSSL_ENTER("wolfSSL_X509_OBJECT_free");
15465 if (obj != NULL) {
15466 if (obj->type == WOLFSSL_X509_LU_X509) {
15467 wolfSSL_X509_free(obj->data.x509);
15468 }
15469 #ifdef HAVE_CRL
15470 else if (obj->type == WOLFSSL_X509_LU_CRL) {
15471 wolfSSL_X509_CRL_free(obj->data.crl);
15472 }
15473 #endif
15474 else {
15475 /* We don't free as this will point to
15476 * store->cm->crl which we don't own */
15477 WOLFSSL_MSG("Not free'ing CRL in WOLFSSL_X509_OBJECT");
15478 }
15479 XFREE(obj, NULL, DYNAMIC_TYPE_OPENSSL);
15480 }
15481}
15482
15483WOLFSSL_X509_OBJECT *wolfSSL_X509_OBJECT_retrieve_by_subject(
15484 WOLF_STACK_OF(WOLFSSL_X509_OBJECT) *sk,
15485 WOLFSSL_X509_LOOKUP_TYPE type,
15486 WOLFSSL_X509_NAME *name)
15487{
15488 int i;
15489
15490 WOLFSSL_ENTER("wolfSSL_X509_OBJECT_retrieve_by_subject");
15491
15492 if (sk == NULL || name == NULL)
15493 return NULL;
15494
15495 for (i = 0; i < wolfSSL_sk_X509_OBJECT_num(sk); i++) {
15496 WOLFSSL_X509_OBJECT* obj = (WOLFSSL_X509_OBJECT *)
15497 wolfSSL_sk_X509_OBJECT_value(sk, i);
15498 if (obj != NULL && obj->type == type &&
15499 wolfSSL_X509_NAME_cmp(
15500 wolfSSL_X509_get_subject_name(obj->data.x509), name) == 0)
15501 return obj;
15502 }
15503 return NULL;
15504}
15505#endif /* OPENSSL_ALL */
15506
15507#ifndef NO_WOLFSSL_STUB
15508WOLFSSL_X509_OBJECT* wolfSSL_sk_X509_OBJECT_delete(
15509 WOLF_STACK_OF(WOLFSSL_X509_OBJECT)* sk, int i)
15510{
15511 WOLFSSL_ENTER("wolfSSL_sk_X509_OBJECT_delete");
15512 WOLFSSL_STUB("wolfSSL_sk_X509_OBJECT_delete");
15513 (void)sk;
15514 (void)i;
15515 return NULL;
15516}
15517#endif
15518
15519WOLFSSL_X509 *wolfSSL_X509_OBJECT_get0_X509(const WOLFSSL_X509_OBJECT *obj)
15520{
15521 if (obj != NULL && obj->type == WOLFSSL_X509_LU_X509)
15522 return obj->data.x509;
15523 return NULL;
15524}
15525
15526WOLFSSL_X509_CRL *wolfSSL_X509_OBJECT_get0_X509_CRL(WOLFSSL_X509_OBJECT *obj)
15527{
15528 if (obj != NULL && obj->type == WOLFSSL_X509_LU_CRL)
15529 return obj->data.crl;
15530 return NULL;
15531}
15532
15533#endif /* OPENSSL_ALL || (OPENSSL_EXTRA && (HAVE_STUNNEL || WOLFSSL_NGINX ||
15534 * HAVE_LIGHTY || WOLFSSL_HAPROXY || WOLFSSL_OPENSSH ||
15535 * HAVE_SBLIM_SFCB)) */
15536
15537
15538#if defined(OPENSSL_EXTRA)
15539
15540int wolfSSL_sk_X509_num(const WOLF_STACK_OF(WOLFSSL_X509) *s)
15541{
15542 WOLFSSL_ENTER("wolfSSL_sk_X509_num");
15543
15544 if (s == NULL)
15545 return WOLFSSL_FATAL_ERROR;
15546 return (int)s->num;
15547}
15548
15549#endif /* OPENSSL_EXTRA */
15550
15551#ifdef HAVE_EX_DATA_CRYPTO
15552int wolfSSL_X509_get_ex_new_index(int idx, void *arg,
15553 WOLFSSL_CRYPTO_EX_new* new_func,
15554 WOLFSSL_CRYPTO_EX_dup* dup_func,
15555 WOLFSSL_CRYPTO_EX_free* free_func)
15556{
15557 WOLFSSL_ENTER("wolfSSL_X509_get_ex_new_index");
15558
15559 return wolfssl_local_get_ex_new_index(WOLF_CRYPTO_EX_INDEX_X509, idx, arg,
15560 new_func, dup_func, free_func);
15561}
15562#endif
15563
15564#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
15565void *wolfSSL_X509_get_ex_data(WOLFSSL_X509 *x509, int idx)
15566{
15567 WOLFSSL_ENTER("wolfSSL_X509_get_ex_data");
15568#ifdef HAVE_EX_DATA
15569 if (x509 != NULL) {
15570 return wolfSSL_CRYPTO_get_ex_data(&x509->ex_data, idx);
15571 }
15572#else
15573 (void)x509;
15574 (void)idx;
15575#endif
15576 return NULL;
15577}
15578
15579int wolfSSL_X509_set_ex_data(WOLFSSL_X509 *x509, int idx, void *data)
15580{
15581 WOLFSSL_ENTER("wolfSSL_X509_set_ex_data");
15582#ifdef HAVE_EX_DATA
15583 if (x509 != NULL) {
15584 return wolfSSL_CRYPTO_set_ex_data(&x509->ex_data, idx, data);
15585 }
15586#else
15587 (void)x509;
15588 (void)idx;
15589 (void)data;
15590#endif
15591 return WOLFSSL_FAILURE;
15592}
15593
15594#ifdef HAVE_EX_DATA_CLEANUP_HOOKS
15595int wolfSSL_X509_set_ex_data_with_cleanup(
15596 WOLFSSL_X509 *x509,
15597 int idx,
15598 void *data,
15599 wolfSSL_ex_data_cleanup_routine_t cleanup_routine)
15600{
15601 WOLFSSL_ENTER("wolfSSL_X509_set_ex_data_with_cleanup");
15602 if (x509 != NULL)
15603 {
15604 return wolfSSL_CRYPTO_set_ex_data_with_cleanup(&x509->ex_data, idx,
15605 data, cleanup_routine);
15606 }
15607 return WOLFSSL_FAILURE;
15608}
15609#endif /* HAVE_EX_DATA_CLEANUP_HOOKS */
15610#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
15611
15612
15613#ifndef NO_ASN
15614int wolfSSL_X509_check_host(WOLFSSL_X509 *x, const char *chk, size_t chklen,
15615 unsigned int flags, char **peername)
15616{
15617 int ret;
15618 size_t i;
15619 WC_DECLARE_VAR(dCert, DecodedCert, 1, 0);
15620
15621 WOLFSSL_ENTER("wolfSSL_X509_check_host");
15622
15623 /* flags and peername not needed for Nginx. */
15624 (void)peername;
15625
15626 if ((x == NULL) || (chk == NULL)) {
15627 WOLFSSL_MSG("Invalid parameter");
15628 return WOLFSSL_FAILURE;
15629 }
15630
15631 if (flags & WOLFSSL_NO_WILDCARDS) {
15632 WOLFSSL_MSG("X509_CHECK_FLAG_NO_WILDCARDS not yet implemented");
15633 return WOLFSSL_FAILURE;
15634 }
15635 if (flags & WOLFSSL_NO_PARTIAL_WILDCARDS) {
15636 WOLFSSL_MSG("X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS not yet implemented");
15637 return WOLFSSL_FAILURE;
15638 }
15639 if (flags & WOLFSSL_MULTI_LABEL_WILDCARDS) {
15640 WOLFSSL_MSG("X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS not yet implemented");
15641 return WOLFSSL_FAILURE;
15642 }
15643
15644#ifdef WOLFSSL_SMALL_STACK
15645 dCert = (DecodedCert *)XMALLOC(sizeof(*dCert), x->heap,
15646 DYNAMIC_TYPE_DCERT);
15647 if (dCert == NULL) {
15648 WOLFSSL_MSG("\tout of memory");
15649 return WOLFSSL_FATAL_ERROR;
15650 }
15651#endif
15652
15653 InitDecodedCert(dCert, x->derCert->buffer, x->derCert->length, NULL);
15654 ret = ParseCertRelative(dCert, CERT_TYPE, 0, NULL, NULL);
15655 if (ret != 0) {
15656 goto out;
15657 }
15658
15659 /* Replicate openssl behavior for checklen */
15660 if (chklen == 0) {
15661 chklen = (size_t)(XSTRLEN(chk));
15662 }
15663 else {
15664 for (i = 0; i < (chklen > 1 ? chklen - 1 : chklen); i++) {
15665 if (chk[i] == '\0') {
15666 ret = WOLFSSL_FATAL_ERROR;
15667 goto out;
15668 }
15669 }
15670 }
15671 if (chklen > 1 && (chk[chklen - 1] == '\0')) {
15672 chklen--;
15673 }
15674
15675#ifdef WOLFSSL_IP_ALT_NAME
15676 ret = CheckIPAddr(dCert, (char *)chk);
15677 if (ret == 0) {
15678 goto out;
15679 }
15680#endif /* WOLFSSL_IP_ALT_NAME */
15681
15682 ret = CheckHostName(dCert, (char *)chk, chklen, flags, 0);
15683
15684out:
15685
15686 FreeDecodedCert(dCert);
15687 WC_FREE_VAR_EX(dCert, x->heap, DYNAMIC_TYPE_DCERT);
15688
15689 if (ret != 0)
15690 return WOLFSSL_FAILURE;
15691 return WOLFSSL_SUCCESS;
15692}
15693
15694
15695int wolfSSL_X509_check_ip_asc(WOLFSSL_X509 *x, const char *ipasc,
15696 unsigned int flags)
15697{
15698 int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
15699 WC_DECLARE_VAR(dCert, DecodedCert, 1, 0);
15700
15701 WOLFSSL_ENTER("wolfSSL_X509_check_ip_asc");
15702
15703 /* flags not yet implemented */
15704 (void)flags;
15705
15706 if ((x == NULL) || (x->derCert == NULL) || (ipasc == NULL)) {
15707 WOLFSSL_MSG("Invalid parameter");
15708 }
15709 else {
15710 ret = WOLFSSL_SUCCESS;
15711 }
15712
15713#ifdef WOLFSSL_SMALL_STACK
15714 if (ret == WOLFSSL_SUCCESS) {
15715 dCert = (DecodedCert *)XMALLOC(sizeof(*dCert), x->heap,
15716 DYNAMIC_TYPE_DCERT);
15717 if (dCert == NULL) {
15718 WOLFSSL_MSG("\tout of memory");
15719 ret = WOLFSSL_FAILURE;
15720 }
15721 }
15722#endif
15723
15724 if (ret == WOLFSSL_SUCCESS) {
15725 InitDecodedCert(dCert, x->derCert->buffer, x->derCert->length, NULL);
15726 ret = ParseCertRelative(dCert, CERT_TYPE, 0, NULL, NULL);
15727 if (ret != 0) {
15728 ret = WOLFSSL_FAILURE;
15729 }
15730 else {
15731 ret = CheckIPAddr(dCert, ipasc);
15732 if (ret != 0) {
15733 ret = WOLFSSL_FAILURE;
15734 }
15735 else {
15736 ret = WOLFSSL_SUCCESS;
15737 }
15738 }
15739 FreeDecodedCert(dCert);
15740 }
15741
15742#ifdef WOLFSSL_SMALL_STACK
15743 if (x != NULL) {
15744 XFREE(dCert, x->heap, DYNAMIC_TYPE_DCERT);
15745 }
15746#endif
15747
15748 return ret;
15749}
15750#endif
15751
15752#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_CERT_GEN)
15753int wolfSSL_X509_check_email(WOLFSSL_X509 *x, const char *chk, size_t chkLen,
15754 unsigned int flags)
15755{
15756 WOLFSSL_X509_NAME *subjName;
15757 int emailLen;
15758 char *emailBuf;
15759
15760 (void)flags;
15761
15762 WOLFSSL_ENTER("wolfSSL_X509_check_email");
15763
15764 if ((x == NULL) || (chk == NULL)) {
15765 WOLFSSL_MSG("Invalid parameter");
15766 return WOLFSSL_FAILURE;
15767 }
15768
15769 subjName = wolfSSL_X509_get_subject_name(x);
15770 if (subjName == NULL)
15771 return WOLFSSL_FAILURE;
15772
15773 /* Call with NULL buffer to get required length. */
15774 emailLen = wolfSSL_X509_NAME_get_text_by_NID(subjName, WC_NID_emailAddress,
15775 NULL, 0);
15776 if (emailLen < 0)
15777 return WOLFSSL_FAILURE;
15778
15779 ++emailLen; /* Add 1 for the NUL. */
15780
15781 emailBuf = (char*)XMALLOC(emailLen, x->heap, DYNAMIC_TYPE_OPENSSL);
15782 if (emailBuf == NULL)
15783 return WOLFSSL_FAILURE;
15784
15785 emailLen = wolfSSL_X509_NAME_get_text_by_NID(subjName, WC_NID_emailAddress,
15786 emailBuf, emailLen);
15787 if (emailLen < 0) {
15788 XFREE(emailBuf, x->heap, DYNAMIC_TYPE_OPENSSL);
15789 return WOLFSSL_FAILURE;
15790 }
15791
15792 if (chkLen == 0)
15793 chkLen = XSTRLEN(chk);
15794
15795 if (chkLen != (size_t)emailLen
15796 || XSTRNCMP(chk, emailBuf, chkLen)) {
15797 XFREE(emailBuf, x->heap, DYNAMIC_TYPE_OPENSSL);
15798 return WOLFSSL_FAILURE;
15799 }
15800
15801 XFREE(emailBuf, x->heap, DYNAMIC_TYPE_OPENSSL);
15802 return WOLFSSL_SUCCESS;
15803}
15804#endif /* OPENSSL_EXTRA && WOLFSSL_CERT_GEN */
15805
15806#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) \
15807 || defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY)
15808
15809int wolfSSL_X509_NAME_digest(const WOLFSSL_X509_NAME *name,
15810 const WOLFSSL_EVP_MD *type, unsigned char *md, unsigned int *len)
15811{
15812 WOLFSSL_ENTER("wolfSSL_X509_NAME_digest");
15813
15814 if (name == NULL || type == NULL)
15815 return WOLFSSL_FAILURE;
15816
15817#if !defined(NO_FILESYSTEM) && !defined(NO_PWDBASED)
15818 return wolfSSL_EVP_Digest((unsigned char*)name->name,
15819 name->sz, md, len, type, NULL);
15820#else
15821 (void)md;
15822 (void)len;
15823 return NOT_COMPILED_IN;
15824#endif
15825}
15826
15827#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY ||
15828 OPENSSL_EXTRA || HAVE_LIGHTY */
15829
15830#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \
15831 defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
15832
15833void wolfSSL_X509_email_free(WOLF_STACK_OF(WOLFSSL_STRING) *sk)
15834{
15835 wolfSSL_sk_pop_free(sk, NULL);
15836}
15837
15838static int x509_aia_append_string(WOLFSSL_STACK* list, const byte* uri,
15839 word32 uriSz)
15840{
15841 WOLFSSL_STRING url = (WOLFSSL_STRING)XMALLOC(uriSz + 1, NULL,
15842 DYNAMIC_TYPE_OPENSSL);
15843 if (url == NULL)
15844 return -1;
15845 XMEMCPY(url, uri, uriSz);
15846 url[uriSz] = '\0';
15847
15848 if (wolfSSL_sk_push(list, url) <= 0) {
15849 XFREE(url, NULL, DYNAMIC_TYPE_OPENSSL);
15850 return -1;
15851 }
15852
15853 return 0;
15854}
15855
15856static WOLFSSL_STACK* x509_get1_aia_by_method(WOLFSSL_X509* x, word32 method,
15857 const byte* fallback, int fallbackSz)
15858{
15859 WOLFSSL_STACK* ret = NULL;
15860 int i;
15861
15862 if (x == NULL)
15863 return NULL;
15864
15865 ret = wolfSSL_sk_WOLFSSL_STRING_new();
15866 if (ret == NULL)
15867 return NULL;
15868
15869 /* Build from multi-entry list when available; otherwise fall back to the
15870 * legacy single-entry fields to preserve previous behavior. */
15871 if (x->authInfoListSz > 0) {
15872 for (i = 0; i < x->authInfoListSz; i++) {
15873 if (x->authInfoList[i].method != method ||
15874 x->authInfoList[i].uri == NULL ||
15875 x->authInfoList[i].uriSz == 0) {
15876 continue;
15877 }
15878
15879 if (x509_aia_append_string(ret, x->authInfoList[i].uri,
15880 x->authInfoList[i].uriSz) != 0) {
15881 wolfSSL_X509_email_free(ret);
15882 return NULL;
15883 }
15884 }
15885 }
15886 /* Only use fallback when nothing was found in the list */
15887 if (wolfSSL_sk_num(ret) == 0 && fallback != NULL && fallbackSz > 0) {
15888 if (x509_aia_append_string(ret, fallback, (word32)fallbackSz) != 0) {
15889 wolfSSL_X509_email_free(ret);
15890 return NULL;
15891 }
15892 }
15893
15894 /* Return NULL when empty */
15895 if (wolfSSL_sk_num(ret) == 0) {
15896 wolfSSL_X509_email_free(ret);
15897 ret = NULL;
15898 }
15899
15900 return ret;
15901}
15902
15903WOLF_STACK_OF(WOLFSSL_STRING) *wolfSSL_X509_get1_ocsp(WOLFSSL_X509 *x)
15904{
15905 if (x == NULL)
15906 return NULL;
15907 return x509_get1_aia_by_method(x, AIA_OCSP_OID, x->authInfo, x->authInfoSz);
15908}
15909
15910int wolfSSL_X509_get_aia_overflow(WOLFSSL_X509 *x)
15911{
15912 int overflow = 0;
15913
15914 WOLFSSL_ENTER("wolfSSL_X509_get_aia_overflow");
15915
15916 if (x != NULL) {
15917 overflow = x->authInfoListOverflow;
15918 }
15919
15920 WOLFSSL_LEAVE("wolfSSL_X509_get_aia_overflow", overflow);
15921
15922 return overflow;
15923}
15924
15925#ifdef WOLFSSL_ASN_CA_ISSUER
15926WOLF_STACK_OF(WOLFSSL_STRING) *wolfSSL_X509_get1_ca_issuers(WOLFSSL_X509 *x)
15927{
15928 if (x == NULL)
15929 return NULL;
15930 return x509_get1_aia_by_method(x, AIA_CA_ISSUER_OID, x->authInfoCaIssuer,
15931 x->authInfoCaIssuerSz);
15932}
15933#endif /* WOLFSSL_ASN_CA_ISSUER */
15934
15935int wolfSSL_X509_check_issued(WOLFSSL_X509 *issuer, WOLFSSL_X509 *subject)
15936{
15937 WOLFSSL_X509_NAME *issuerName = wolfSSL_X509_get_issuer_name(subject);
15938 WOLFSSL_X509_NAME *subjectName = wolfSSL_X509_get_subject_name(issuer);
15939
15940 if (issuerName == NULL || subjectName == NULL)
15941 return WOLFSSL_X509_V_ERR_SUBJECT_ISSUER_MISMATCH;
15942
15943 /* Literal matching of encoded names and key ids. */
15944 if (issuerName->sz != subjectName->sz ||
15945 XMEMCMP(issuerName->name, subjectName->name, subjectName->sz) != 0) {
15946 return WOLFSSL_X509_V_ERR_SUBJECT_ISSUER_MISMATCH;
15947 }
15948
15949 if (subject->authKeyId != NULL && issuer->subjKeyId != NULL) {
15950 if (subject->authKeyIdSz != issuer->subjKeyIdSz ||
15951 XMEMCMP(subject->authKeyId, issuer->subjKeyId,
15952 issuer->subjKeyIdSz) != 0) {
15953 return WOLFSSL_X509_V_ERR_SUBJECT_ISSUER_MISMATCH;
15954 }
15955 }
15956
15957 return WOLFSSL_X509_V_OK;
15958}
15959
15960#endif /* WOLFSSL_NGINX || WOLFSSL_HAPROXY || OPENSSL_EXTRA || OPENSSL_ALL */
15961
15962#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \
15963 defined(KEEP_PEER_CERT) || defined(SESSION_CERTS)
15964WOLFSSL_X509* wolfSSL_X509_dup(WOLFSSL_X509 *x)
15965{
15966 WOLFSSL_ENTER("wolfSSL_X509_dup");
15967
15968 if (x == NULL) {
15969 WOLFSSL_MSG("Error: NULL input");
15970 return NULL;
15971 }
15972
15973 if (x->derCert == NULL) {
15974 WOLFSSL_MSG("Error: NULL derCert parameter");
15975 return NULL;
15976 }
15977
15978 return wolfSSL_X509_d2i_ex(NULL, x->derCert->buffer, x->derCert->length,
15979 x->heap);
15980}
15981#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL || KEEP_PEER_CERT || \
15982 SESSION_CERTS */
15983
15984#if defined(OPENSSL_EXTRA)
15985int wolfSSL_X509_check_ca(WOLFSSL_X509 *x509)
15986{
15987 WOLFSSL_ENTER("wolfSSL_X509_check_ca");
15988
15989 if (x509 == NULL)
15990 return WOLFSSL_FAILURE;
15991 if (x509->isCa)
15992 return 1;
15993 if (x509->extKeyUsageCrit)
15994 return 4;
15995
15996 return 0;
15997}
15998#endif /* OPENSSL_EXTRA */
15999
16000#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
16001long wolfSSL_X509_get_version(const WOLFSSL_X509 *x509)
16002{
16003 int version = 0;
16004
16005 WOLFSSL_ENTER("wolfSSL_X509_get_version");
16006
16007 if (x509 == NULL) {
16008 WOLFSSL_MSG("invalid parameter");
16009 return 0L;
16010 }
16011 version = x509->version;
16012 if (version != 0)
16013 return (long)version - 1L;
16014
16015 return 0L;
16016}
16017#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
16018
16019#if defined(OPENSSL_EXTRA)
16020int wolfSSL_X509_get_signature_nid(const WOLFSSL_X509 *x)
16021{
16022 if (x == NULL)
16023 return 0;
16024
16025 return oid2nid((word32)x->sigOID, oidSigType);
16026}
16027#endif /* OPENSSL_EXTRA */
16028
16029#if defined(OPENSSL_EXTRA)
16030WOLFSSL_STACK* wolfSSL_sk_X509_new(WOLF_SK_COMPARE_CB(WOLFSSL_X509, cb))
16031{
16032 (void)cb;
16033 return wolfSSL_sk_X509_new_null();
16034}
16035
16036WOLFSSL_STACK* wolfSSL_sk_X509_new_null(void)
16037{
16038 WOLFSSL_STACK* s = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
16039 DYNAMIC_TYPE_OPENSSL);
16040 if (s != NULL) {
16041 XMEMSET(s, 0, sizeof(*s));
16042 s->type = STACK_TYPE_X509;
16043 }
16044
16045 return s;
16046}
16047#endif /* OPENSSL_EXTRA */
16048
16049#ifdef OPENSSL_ALL
16050
16051WOLFSSL_STACK* wolfSSL_sk_X509_OBJECT_new(void)
16052{
16053 WOLFSSL_STACK* s = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
16054 DYNAMIC_TYPE_OPENSSL);
16055 WOLFSSL_ENTER("wolfSSL_sk_X509_OBJECT_new");
16056 if (s != NULL) {
16057 XMEMSET(s, 0, sizeof(*s));
16058 s->type = STACK_TYPE_X509_OBJ;
16059 }
16060 return s;
16061}
16062
16063void wolfSSL_sk_X509_OBJECT_free(WOLFSSL_STACK* s)
16064{
16065 WOLFSSL_ENTER("wolfSSL_sk_X509_OBJECT_free");
16066 wolfSSL_sk_free(s);
16067}
16068
16069void wolfSSL_sk_X509_OBJECT_pop_free(WOLFSSL_STACK* s,
16070 void (*f) (WOLFSSL_X509_OBJECT*))
16071{
16072 WOLFSSL_ENTER("wolfSSL_sk_X509_OBJECT_pop_free");
16073 wolfSSL_sk_pop_free(s, (wolfSSL_sk_freefunc)f);
16074}
16075
16076int wolfSSL_sk_X509_OBJECT_push(WOLFSSL_STACK* sk, WOLFSSL_X509_OBJECT* obj)
16077{
16078 WOLFSSL_ENTER("wolfSSL_sk_X509_OBJECT_push");
16079
16080 if (sk == NULL || obj == NULL) {
16081 return WOLFSSL_FAILURE;
16082 }
16083
16084 return wolfSSL_sk_push(sk, obj);
16085}
16086
16087#endif /* OPENSSL_ALL */
16088
16089#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
16090/* unlike wolfSSL_X509_NAME_dup this does not malloc a duplicate, only deep
16091 * copy. "to" is expected to be a fresh blank name, if not pointers could be
16092 * lost */
16093int wolfSSL_X509_NAME_copy(const WOLFSSL_X509_NAME* from, WOLFSSL_X509_NAME* to)
16094{
16095 int i;
16096
16097 WOLFSSL_ENTER("wolfSSL_X509_NAME_copy");
16098
16099 if (from == NULL || to == NULL) {
16100 WOLFSSL_MSG("NULL parameter");
16101 return BAD_FUNC_ARG;
16102 }
16103
16104#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY)
16105 if (from->rawLen > 0) {
16106 if (from->rawLen > ASN_NAME_MAX) {
16107 WOLFSSL_MSG("Bad raw size");
16108 return BAD_FUNC_ARG;
16109 }
16110 XMEMCPY(to->raw, from->raw, from->rawLen);
16111 to->rawLen = from->rawLen;
16112 }
16113#endif
16114
16115 if (from->dynamicName) {
16116 to->name = (char*)XMALLOC(from->sz, to->heap, DYNAMIC_TYPE_SUBJECT_CN);
16117 if (to->name == NULL)
16118 return WOLFSSL_FAILURE;
16119 to->dynamicName = 1;
16120 }
16121 XMEMCPY(to->name, from->name, from->sz);
16122 to->sz = from->sz;
16123
16124 for (i = 0; i < MAX_NAME_ENTRIES; i++) {
16125 WOLFSSL_X509_NAME_ENTRY* ne = wolfSSL_X509_NAME_get_entry(from, i);
16126 if (ne != NULL) {
16127 if (wolfSSL_X509_NAME_add_entry(to, ne, i, 1) != WOLFSSL_SUCCESS) {
16128 return WOLFSSL_FAILURE;
16129 }
16130 }
16131 }
16132 to->entrySz = from->entrySz;
16133 return WOLFSSL_SUCCESS;
16134}
16135
16136
16137/* copies over information from "name" to the "cert" subject name
16138 * returns WOLFSSL_SUCCESS on success */
16139int wolfSSL_X509_set_subject_name(WOLFSSL_X509 *cert, WOLFSSL_X509_NAME *name)
16140{
16141 WOLFSSL_ENTER("wolfSSL_X509_set_subject_name");
16142 if (cert == NULL || name == NULL)
16143 return WOLFSSL_FAILURE;
16144
16145 FreeX509Name(&cert->subject);
16146 InitX509Name(&cert->subject, 0, cert->heap);
16147
16148 if (wolfSSL_X509_NAME_copy(name, &cert->subject) != WOLFSSL_SUCCESS) {
16149 FreeX509Name(&cert->subject);
16150 return WOLFSSL_FAILURE;
16151 }
16152
16153 cert->subject.x509 = cert;
16154 return WOLFSSL_SUCCESS;
16155}
16156
16157
16158/* copies over information from "name" to the "cert" issuer name
16159 * returns WOLFSSL_SUCCESS on success */
16160int wolfSSL_X509_set_issuer_name(WOLFSSL_X509 *cert, WOLFSSL_X509_NAME *name)
16161{
16162 WOLFSSL_ENTER("wolfSSL_X509_set_issuer_name");
16163 if (cert == NULL || name == NULL)
16164 return WOLFSSL_FAILURE;
16165
16166 FreeX509Name(&cert->issuer);
16167 InitX509Name(&cert->issuer, 0, cert->heap);
16168
16169 if (wolfSSL_X509_NAME_copy(name, &cert->issuer) != WOLFSSL_SUCCESS) {
16170 FreeX509Name(&cert->issuer);
16171 return WOLFSSL_FAILURE;
16172 }
16173
16174 cert->issuer.x509 = cert;
16175 cert->issuerSet = 1;
16176
16177 return WOLFSSL_SUCCESS;
16178}
16179
16180
16181int wolfSSL_X509_set_notAfter(WOLFSSL_X509* x509, const WOLFSSL_ASN1_TIME* t)
16182{
16183 if (x509 == NULL || t == NULL) {
16184 return WOLFSSL_FAILURE;
16185 }
16186
16187 if (t->length < 0 || t->length > CTC_DATE_SIZE - 2) {
16188 return WOLFSSL_FAILURE;
16189 }
16190
16191 x509->notAfter.type = t->type;
16192 x509->notAfter.length = t->length;
16193
16194 XMEMCPY(x509->notAfter.data, t->data, CTC_DATE_SIZE);
16195
16196 return WOLFSSL_SUCCESS;
16197}
16198
16199int wolfSSL_X509_set_notBefore(WOLFSSL_X509* x509, const WOLFSSL_ASN1_TIME* t)
16200{
16201 if (x509 == NULL || t == NULL) {
16202 return WOLFSSL_FAILURE;
16203 }
16204
16205 if (t->length < 0 || t->length > CTC_DATE_SIZE - 2) {
16206 return WOLFSSL_FAILURE;
16207 }
16208
16209 x509->notBefore.type = t->type;
16210 x509->notBefore.length = t->length;
16211
16212 XMEMCPY(x509->notBefore.data, t->data, CTC_DATE_SIZE);
16213
16214 return WOLFSSL_SUCCESS;
16215}
16216
16217int wolfSSL_X509_set1_notAfter(WOLFSSL_X509* x509, const WOLFSSL_ASN1_TIME *t)
16218{
16219 return wolfSSL_X509_set_notAfter(x509, t);
16220}
16221
16222int wolfSSL_X509_set1_notBefore(WOLFSSL_X509* x509, const WOLFSSL_ASN1_TIME *t)
16223{
16224 return wolfSSL_X509_set_notBefore(x509, t);
16225}
16226
16227int wolfSSL_X509_set_serialNumber(WOLFSSL_X509* x509, WOLFSSL_ASN1_INTEGER* s)
16228{
16229 WOLFSSL_ENTER("wolfSSL_X509_set_serialNumber");
16230 if (x509 == NULL || s == NULL || s->data == NULL ||
16231 s->length >= EXTERNAL_SERIAL_SIZE)
16232 return WOLFSSL_FAILURE;
16233
16234 /* WOLFSSL_ASN1_INTEGER has type | size | data
16235 * Sanity check that the data is actually in ASN format */
16236 if (s->length < 3 || s->data[0] != ASN_INTEGER ||
16237 s->data[1] != s->length - 2) {
16238 return WOLFSSL_FAILURE;
16239 }
16240 XMEMCPY(x509->serial, s->data + 2, s->length - 2);
16241 x509->serialSz = s->length - 2;
16242 x509->serial[x509->serialSz] = 0;
16243
16244 return WOLFSSL_SUCCESS;
16245}
16246
16247
16248int wolfSSL_X509_set_pubkey(WOLFSSL_X509 *cert, WOLFSSL_EVP_PKEY *pkey)
16249{
16250 byte* p = NULL;
16251 int derSz = 0;
16252 WOLFSSL_ENTER("wolfSSL_X509_set_pubkey");
16253
16254 if (cert == NULL || pkey == NULL)
16255 return WOLFSSL_FAILURE;
16256
16257 /* Regenerate since pkey->pkey.ptr may contain private key */
16258 switch (pkey->type) {
16259#if (defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA)) && !defined(NO_RSA)
16260 case WC_EVP_PKEY_RSA:
16261 {
16262 RsaKey* rsa;
16263
16264 if (pkey->rsa == NULL || pkey->rsa->internal == NULL)
16265 return WOLFSSL_FAILURE;
16266
16267 rsa = (RsaKey*)pkey->rsa->internal;
16268 derSz = wc_RsaPublicKeyDerSize(rsa, 1);
16269 if (derSz <= 0)
16270 return WOLFSSL_FAILURE;
16271
16272 p = (byte*)XMALLOC(derSz, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY);
16273 if (p == NULL)
16274 return WOLFSSL_FAILURE;
16275
16276 if ((derSz = wc_RsaKeyToPublicDer(rsa, p, (word32)derSz)) <= 0) {
16277 XFREE(p, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY);
16278 return WOLFSSL_FAILURE;
16279 }
16280 cert->pubKeyOID = RSAk;
16281 }
16282 break;
16283#endif /* (WOLFSSL_KEY_GEN || OPENSSL_EXTRA) && !NO_RSA */
16284#if !defined(HAVE_SELFTEST) && (defined(WOLFSSL_KEY_GEN) || \
16285 defined(WOLFSSL_CERT_GEN)) && !defined(NO_DSA)
16286 case WC_EVP_PKEY_DSA:
16287 {
16288 DsaKey* dsa;
16289
16290 if (pkey->dsa == NULL || pkey->dsa->internal == NULL)
16291 return WOLFSSL_FAILURE;
16292
16293 dsa = (DsaKey*)pkey->dsa->internal;
16294 /* size of pub, priv, p, q, g + ASN.1 additional information */
16295 derSz = 5 * mp_unsigned_bin_size(&dsa->g) + MAX_ALGO_SZ;
16296 p = (byte*)XMALLOC(derSz, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY);
16297 if (p == NULL)
16298 return WOLFSSL_FAILURE;
16299
16300 if ((derSz = wc_DsaKeyToPublicDer(dsa, p, (word32)derSz)) <= 0) {
16301 XFREE(p, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY);
16302 return WOLFSSL_FAILURE;
16303 }
16304 cert->pubKeyOID = DSAk;
16305 }
16306 break;
16307#endif /* !HAVE_SELFTEST && (WOLFSSL_KEY_GEN || WOLFSSL_CERT_GEN) && !NO_DSA */
16308#ifdef HAVE_ECC
16309 case WC_EVP_PKEY_EC:
16310 {
16311 ecc_key* ecc;
16312
16313 if (pkey->ecc == NULL || pkey->ecc->internal == NULL)
16314 return WOLFSSL_FAILURE;
16315
16316 ecc = (ecc_key*)pkey->ecc->internal;
16317 derSz = wc_EccPublicKeyDerSize(ecc, 1);
16318 if (derSz <= 0)
16319 return WOLFSSL_FAILURE;
16320
16321 p = (byte*)XMALLOC(derSz, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY);
16322 if (p == NULL)
16323 return WOLFSSL_FAILURE;
16324
16325 if ((derSz = wc_EccPublicKeyToDer(ecc, p, (word32)derSz, 1)) <= 0) {
16326 XFREE(p, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY);
16327 return WOLFSSL_FAILURE;
16328 }
16329 cert->pubKeyOID = ECDSAk;
16330 }
16331 break;
16332#endif
16333 default:
16334 return WOLFSSL_FAILURE;
16335 }
16336 XFREE(cert->pubKey.buffer, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY);
16337 cert->pubKey.buffer = p;
16338 cert->pubKey.length = (unsigned int)derSz;
16339
16340 return WOLFSSL_SUCCESS;
16341}
16342
16343int wolfSSL_X509_set_version(WOLFSSL_X509* x509, long v)
16344{
16345 WOLFSSL_ENTER("wolfSSL_X509_set_version");
16346 if ((x509 == NULL) || (v < 0) || (v >= INT_MAX)) {
16347 return WOLFSSL_FAILURE;
16348 }
16349 x509->version = (int) v + 1;
16350
16351 return WOLFSSL_SUCCESS;
16352}
16353
16354#ifdef WOLFSSL_CERT_EXT
16355/* Set Subject Key Identifier from raw bytes.
16356 *
16357 * x509 - Certificate to modify
16358 * skid - Raw SKID bytes
16359 * skidSz - Size of SKID in bytes
16360 *
16361 * Returns WOLFSSL_SUCCESS or WOLFSSL_FAILURE
16362 */
16363int wolfSSL_X509_set_subject_key_id(WOLFSSL_X509* x509,
16364 const unsigned char* skid, int skidSz)
16365{
16366 WOLFSSL_ENTER("wolfSSL_X509_set_subject_key_id");
16367
16368 if (x509 == NULL || skid == NULL || skidSz <= 0) {
16369 return WOLFSSL_FAILURE;
16370 }
16371
16372 /* Allocate/reallocate memory for subjKeyId */
16373 if (x509->subjKeyId == NULL || (int)x509->subjKeyIdSz < skidSz) {
16374 if (x509->subjKeyId != NULL) {
16375 XFREE(x509->subjKeyId, x509->heap, DYNAMIC_TYPE_X509_EXT);
16376 }
16377 x509->subjKeyId = (byte*)XMALLOC((word32)skidSz, x509->heap,
16378 DYNAMIC_TYPE_X509_EXT);
16379 if (x509->subjKeyId == NULL) {
16380 return WOLFSSL_FAILURE;
16381 }
16382 }
16383
16384 XMEMCPY(x509->subjKeyId, skid, (word32)skidSz);
16385 x509->subjKeyIdSz = (word32)skidSz;
16386 x509->subjKeyIdSet = 1;
16387
16388 return WOLFSSL_SUCCESS;
16389}
16390
16391#ifndef NO_SHA
16392/* Set Subject Key Identifier by computing SHA-1 hash of the public key.
16393 *
16394 * x509 - Certificate to modify (must have public key set)
16395 *
16396 * Returns WOLFSSL_SUCCESS or WOLFSSL_FAILURE
16397 */
16398int wolfSSL_X509_set_subject_key_id_ex(WOLFSSL_X509* x509)
16399{
16400 byte hash[WC_SHA_DIGEST_SIZE];
16401 int ret;
16402
16403 WOLFSSL_ENTER("wolfSSL_X509_set_subject_key_id_ex");
16404
16405 if (x509 == NULL) {
16406 return WOLFSSL_FAILURE;
16407 }
16408
16409 /* Check if public key has been set */
16410 if (x509->pubKey.buffer == NULL || x509->pubKey.length == 0) {
16411 WOLFSSL_MSG("Public key not set");
16412 return WOLFSSL_FAILURE;
16413 }
16414
16415 /* Compute SHA-1 hash of the public key */
16416 ret = wc_ShaHash(x509->pubKey.buffer, x509->pubKey.length, hash);
16417 if (ret != 0) {
16418 WOLFSSL_MSG("wc_ShaHash failed");
16419 return WOLFSSL_FAILURE;
16420 }
16421
16422 return wolfSSL_X509_set_subject_key_id(x509, hash, WC_SHA_DIGEST_SIZE);
16423}
16424#endif /* !NO_SHA */
16425
16426/* Set Authority Key Identifier from raw bytes.
16427 * The bytes passed in are the keyIdentifier OCTET STRING contents only,
16428 * they must not be a pre-encoded AuthorityKeyIdentifier SEQUENCE.
16429 * The cert encoder wraps them in SEQUENCE { [0] keyIdentifier } at sign time.
16430 *
16431 * x509 - Certificate to modify
16432 * akid - Raw AKID bytes
16433 * akidSz - Size of AKID in bytes
16434 *
16435 * Returns WOLFSSL_SUCCESS or WOLFSSL_FAILURE
16436 */
16437int wolfSSL_X509_set_authority_key_id(WOLFSSL_X509* x509,
16438 const unsigned char* akid, int akidSz)
16439{
16440 byte* newAkid = NULL;
16441
16442 WOLFSSL_ENTER("wolfSSL_X509_set_authority_key_id");
16443
16444 if (x509 == NULL || akid == NULL || akidSz <= 0) {
16445 return WOLFSSL_FAILURE;
16446 }
16447
16448 /* Allocate new buffer up front so failure leaves prior state intact */
16449 newAkid = (byte*)XMALLOC((word32)akidSz, x509->heap, DYNAMIC_TYPE_X509_EXT);
16450 if (newAkid == NULL) {
16451 return WOLFSSL_FAILURE;
16452 }
16453 XMEMCPY(newAkid, akid, (word32)akidSz);
16454
16455 /* Free any prior storage. authKeyIdSrc may be populated from a prior
16456 * parse cert operation. authKeyId aliases inside that buffer, so
16457 * authKeyIdSrc must be freed first to avoid a dangling authKeyId. */
16458 if (x509->authKeyIdSrc != NULL) {
16459 XFREE(x509->authKeyIdSrc, x509->heap, DYNAMIC_TYPE_X509_EXT);
16460 x509->authKeyIdSrc = NULL;
16461 x509->authKeyIdSrcSz = 0;
16462 }
16463 else if (x509->authKeyId != NULL) {
16464 XFREE(x509->authKeyId, x509->heap, DYNAMIC_TYPE_X509_EXT);
16465 }
16466
16467 /* Store newAkid as authKeyId only, do not populate authKeyIdSrc.
16468 * When authKeyIdSrc is non-NULL, the encoder writes those bytes without
16469 * SEQUENCE/[0] wrapper. authKeyIdSrc must be NULL here so encoder does
16470 * wrap them. */
16471 x509->authKeyId = newAkid;
16472 x509->authKeyIdSz = (word32)akidSz;
16473 x509->authKeyIdSet = 1;
16474
16475 return WOLFSSL_SUCCESS;
16476}
16477
16478#ifndef NO_SHA
16479/* Set Authority Key Identifier from issuer certificate.
16480 * Extracts SKID from issuer (or computes from issuer's public key).
16481 *
16482 * x509 - Certificate to modify
16483 * issuer - Issuer certificate
16484 *
16485 * Returns WOLFSSL_SUCCESS or WOLFSSL_FAILURE
16486 */
16487int wolfSSL_X509_set_authority_key_id_ex(WOLFSSL_X509* x509,
16488 WOLFSSL_X509* issuer)
16489{
16490 byte hash[WC_SHA_DIGEST_SIZE];
16491 int ret;
16492
16493 WOLFSSL_ENTER("wolfSSL_X509_set_authority_key_id_ex");
16494
16495 if (x509 == NULL || issuer == NULL) {
16496 return WOLFSSL_FAILURE;
16497 }
16498
16499 /* First try to use issuer's SKID if it's set */
16500 if (issuer->subjKeyIdSet && issuer->subjKeyId != NULL &&
16501 issuer->subjKeyIdSz > 0) {
16502 return wolfSSL_X509_set_authority_key_id(x509, issuer->subjKeyId,
16503 (int)issuer->subjKeyIdSz);
16504 }
16505
16506 /* Otherwise compute from issuer's public key */
16507 if (issuer->pubKey.buffer == NULL || issuer->pubKey.length == 0) {
16508 WOLFSSL_MSG("Issuer public key not available");
16509 return WOLFSSL_FAILURE;
16510 }
16511
16512 ret = wc_ShaHash(issuer->pubKey.buffer, issuer->pubKey.length, hash);
16513 if (ret != 0) {
16514 WOLFSSL_MSG("wc_ShaHash failed");
16515 return WOLFSSL_FAILURE;
16516 }
16517
16518 return wolfSSL_X509_set_authority_key_id(x509, hash, WC_SHA_DIGEST_SIZE);
16519}
16520#endif /* !NO_SHA */
16521#endif /* WOLFSSL_CERT_EXT */
16522
16523#ifndef IGNORE_NETSCAPE_CERT_TYPE
16524/* Set Netscape Certificate Type extension.
16525 *
16526 * x509 - Certificate to modify
16527 * nsCertType - Bitwise OR of NS_SSL_CLIENT, NS_SSL_SERVER, etc.
16528 *
16529 * Returns WOLFSSL_SUCCESS or WOLFSSL_FAILURE
16530 */
16531int wolfSSL_X509_set_ns_cert_type(WOLFSSL_X509* x509, int nsCertType)
16532{
16533 WOLFSSL_ENTER("wolfSSL_X509_set_ns_cert_type");
16534
16535 if (x509 == NULL) {
16536 return WOLFSSL_FAILURE;
16537 }
16538
16539 x509->nsCertType = (byte)nsCertType;
16540
16541 return WOLFSSL_SUCCESS;
16542}
16543#endif /* !IGNORE_NETSCAPE_CERT_TYPE */
16544
16545#endif /* (OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL) && WOLFSSL_CERT_GEN */
16546
16547#if (defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)) && \
16548 defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ)
16549
16550void wolfSSL_X509V3_set_ctx(WOLFSSL_X509V3_CTX* ctx, WOLFSSL_X509* issuer,
16551 WOLFSSL_X509* subject, WOLFSSL_X509* req, WOLFSSL_X509_CRL* crl,
16552 int flag)
16553{
16554 int ret = WOLFSSL_SUCCESS;
16555 WOLFSSL_ENTER("wolfSSL_X509V3_set_ctx");
16556 if (!ctx) {
16557 ret = WOLFSSL_FAILURE;
16558 WOLFSSL_MSG("wolfSSL_X509V3_set_ctx() called with null ctx.");
16559 }
16560
16561 if (ret == WOLFSSL_SUCCESS && (ctx->x509 != NULL)) {
16562 ret = WOLFSSL_FAILURE;
16563 WOLFSSL_MSG("wolfSSL_X509V3_set_ctx() called "
16564 "with ctx->x509 already allocated.");
16565 }
16566
16567 if (ret == WOLFSSL_SUCCESS) {
16568 ctx->x509 = wolfSSL_X509_new_ex(
16569 (issuer && issuer->heap) ? issuer->heap :
16570 (subject && subject->heap) ? subject->heap :
16571 (req && req->heap) ? req->heap :
16572 NULL);
16573 if (!ctx->x509) {
16574 ret = WOLFSSL_FAILURE;
16575 WOLFSSL_MSG("wolfSSL_X509_new_ex() failed "
16576 "in wolfSSL_X509V3_set_ctx().");
16577 }
16578 }
16579
16580 /* Set parameters in ctx as long as ret == WOLFSSL_SUCCESS */
16581 if (ret == WOLFSSL_SUCCESS && issuer)
16582 ret = wolfSSL_X509_set_issuer_name(ctx->x509, &issuer->issuer);
16583
16584 if (ret == WOLFSSL_SUCCESS && subject)
16585 ret = wolfSSL_X509_set_subject_name(ctx->x509, &subject->subject);
16586
16587 if (ret == WOLFSSL_SUCCESS && req) {
16588 WOLFSSL_MSG("req not implemented.");
16589 }
16590
16591 if (ret == WOLFSSL_SUCCESS && crl) {
16592 WOLFSSL_MSG("crl not implemented.");
16593 }
16594
16595 if (ret == WOLFSSL_SUCCESS && flag) {
16596 WOLFSSL_MSG("flag not implemented.");
16597 }
16598
16599 if (ret != WOLFSSL_SUCCESS) {
16600 WOLFSSL_MSG("Error setting WOLFSSL_X509V3_CTX parameters.");
16601 }
16602}
16603
16604#ifndef NO_BIO
16605int wolfSSL_i2d_X509_REQ(WOLFSSL_X509* req, unsigned char** out)
16606{
16607 int derSz = 0;
16608 int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
16609 WOLFSSL_BIO* bio = NULL;
16610 WOLFSSL_ENTER("wolfSSL_i2d_X509_REQ");
16611
16612 if (req == NULL || out == NULL) {
16613 return BAD_FUNC_ARG;
16614 }
16615
16616 if (!(bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem()))) {
16617 return WOLFSSL_FAILURE;
16618 }
16619
16620 if (wolfSSL_i2d_X509_REQ_bio(bio, req) != WOLFSSL_SUCCESS) {
16621 WOLFSSL_MSG("wolfSSL_i2d_X509_REQ_bio error");
16622 goto cleanup;
16623 }
16624
16625 derSz = wolfSSL_BIO_get_len(bio);
16626
16627 if (*out == NULL) {
16628 *out = (unsigned char*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_OPENSSL);
16629 if (!*out) {
16630 WOLFSSL_MSG("malloc error");
16631 ret = MEMORY_E;
16632 goto cleanup;
16633 }
16634 }
16635
16636 if (wolfSSL_BIO_read(bio, *out, derSz) != derSz) {
16637 WOLFSSL_MSG("wolfSSL_BIO_read error");
16638 goto cleanup;
16639 }
16640
16641 ret = derSz;
16642cleanup:
16643 wolfSSL_BIO_free(bio);
16644
16645 return ret;
16646}
16647#endif /* !NO_BIO */
16648
16649WOLFSSL_X509* wolfSSL_X509_REQ_new(void)
16650{
16651 return wolfSSL_X509_new();
16652}
16653
16654void wolfSSL_X509_REQ_free(WOLFSSL_X509* req)
16655{
16656 wolfSSL_X509_free(req);
16657}
16658
16659int wolfSSL_X509_REQ_set_version(WOLFSSL_X509 *x, long version)
16660{
16661 WOLFSSL_ENTER("wolfSSL_X509_REQ_set_version");
16662 if ((x == NULL) || (version < 0) || (version >= INT_MAX)) {
16663 return WOLFSSL_FAILURE;
16664 }
16665 x->version = (int)version;
16666 return WOLFSSL_SUCCESS;
16667}
16668
16669long wolfSSL_X509_REQ_get_version(const WOLFSSL_X509 *req)
16670{
16671 WOLFSSL_ENTER("wolfSSL_X509_REQ_get_version");
16672 if (req == NULL) {
16673 return 0; /* invalid arg */
16674 }
16675 return (long)req->version;
16676}
16677
16678int wolfSSL_X509_REQ_sign(WOLFSSL_X509 *req, WOLFSSL_EVP_PKEY *pkey,
16679 const WOLFSSL_EVP_MD *md)
16680{
16681 int ret;
16682 WC_DECLARE_VAR(der, byte, 2048, 0);
16683 int derSz = 2048;
16684
16685 if (req == NULL || pkey == NULL || md == NULL) {
16686 WOLFSSL_LEAVE("wolfSSL_X509_REQ_sign", BAD_FUNC_ARG);
16687 return WOLFSSL_FAILURE;
16688 }
16689
16690 WC_ALLOC_VAR_EX(der, byte, derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER,
16691 return WOLFSSL_FAILURE);
16692
16693 /* Create a Cert that has the certificate request fields. */
16694 req->sigOID = wolfSSL_sigTypeFromPKEY((WOLFSSL_EVP_MD*)md, pkey);
16695 ret = wolfssl_x509_make_der(req, 1, der, &derSz, 0);
16696 if (ret != WOLFSSL_SUCCESS) {
16697 WC_FREE_VAR_EX(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
16698 WOLFSSL_MSG("Unable to make DER for X509");
16699 WOLFSSL_LEAVE("wolfSSL_X509_REQ_sign", ret);
16700 return WOLFSSL_FAILURE;
16701 }
16702
16703 if (wolfSSL_X509_resign_cert(req, 1, der, 2048, derSz,
16704 (WOLFSSL_EVP_MD*)md, pkey) <= 0) {
16705 WC_FREE_VAR_EX(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
16706 return WOLFSSL_FAILURE;
16707 }
16708 WC_FREE_VAR_EX(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
16709 return WOLFSSL_SUCCESS;
16710}
16711
16712int wolfSSL_X509_REQ_sign_ctx(WOLFSSL_X509 *req,
16713 WOLFSSL_EVP_MD_CTX* md_ctx)
16714{
16715 if (md_ctx && md_ctx->pctx)
16716 return wolfSSL_X509_REQ_sign(req, md_ctx->pctx->pkey,
16717 wolfSSL_EVP_MD_CTX_md(md_ctx));
16718 else
16719 return WOLFSSL_FAILURE;
16720}
16721
16722static int regenX509REQDerBuffer(WOLFSSL_X509* x509)
16723{
16724 int derSz = X509_BUFFER_SZ;
16725 int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
16726#ifndef WOLFSSL_SMALL_STACK
16727 byte der[X509_BUFFER_SZ];
16728#else
16729 byte* der;
16730
16731 der = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
16732 if (!der) {
16733 WOLFSSL_MSG("malloc failed");
16734 return WOLFSSL_FAILURE;
16735 }
16736#endif
16737
16738 if (wolfssl_x509_make_der(x509, 1, der, &derSz, 0) == WOLFSSL_SUCCESS) {
16739 FreeDer(&x509->derCert);
16740 if (AllocDer(&x509->derCert, (word32)derSz, CERT_TYPE,
16741 x509->heap) == 0) {
16742 XMEMCPY(x509->derCert->buffer, der, derSz);
16743 ret = WOLFSSL_SUCCESS;
16744 }
16745 else {
16746 WOLFSSL_MSG("Failed to allocate DER buffer for X509");
16747 }
16748 }
16749 else {
16750 WOLFSSL_MSG("Unable to make DER for X509 REQ");
16751 }
16752 WC_FREE_VAR_EX(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
16753 return ret;
16754}
16755
16756int wolfSSL_X509_REQ_add_extensions(WOLFSSL_X509* req,
16757 WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* ext_sk)
16758{
16759 WOLFSSL_X509_EXTENSION* ext = NULL;
16760
16761 if (!req || !ext_sk) {
16762 WOLFSSL_MSG("Bad parameter");
16763 return WOLFSSL_FAILURE;
16764 }
16765
16766 /* It is not an error if the stack is empty. */
16767 ext = ext_sk->data.ext;
16768 if (ext == NULL) {
16769 return WOLFSSL_SUCCESS;
16770 }
16771
16772 while (ext_sk) {
16773 ext = ext_sk->data.ext;
16774
16775 if (wolfSSL_X509_add_ext(req, ext, -1) != WOLFSSL_SUCCESS) {
16776 WOLFSSL_MSG("wolfSSL_X509_add_ext error");
16777 return WOLFSSL_FAILURE;
16778 }
16779
16780 ext_sk = ext_sk->next;
16781 }
16782
16783 return regenX509REQDerBuffer(req);
16784}
16785
16786int wolfSSL_X509_REQ_add1_attr_by_txt(WOLFSSL_X509 *req,
16787 const char *attrname, int type,
16788 const unsigned char *bytes, int len)
16789{
16790 WOLFSSL_ENTER("wolfSSL_X509_REQ_add1_attr_by_txt");
16791
16792#ifdef HAVE_LIBEST
16793 if (!req || !attrname || !bytes || type != MBSTRING_ASC) {
16794 WOLFSSL_MSG("Bad parameter");
16795 return WOLFSSL_FAILURE;
16796 }
16797
16798 if (len < 0) {
16799 len = (int)XSTRLEN((char*)bytes);
16800 }
16801
16802 /* For now just pretend that we support this for libest testing */
16803 if (len == XSTR_SIZEOF("1.3.6.1.1.1.1.22") &&
16804 XMEMCMP("1.3.6.1.1.1.1.22", bytes, len) == 0) {
16805 /* MAC Address */
16806 }
16807 else if (len == XSTR_SIZEOF("1.2.840.10045.2.1") &&
16808 XMEMCMP("1.2.840.10045.2.1", bytes, len) == 0) {
16809 /* ecPublicKey */
16810 }
16811 else if (len == XSTR_SIZEOF("1.2.840.10045.4.3.3") &&
16812 XMEMCMP("1.2.840.10045.4.3.3", bytes, len) == 0) {
16813 /* ecdsa-with-SHA384 */
16814 }
16815 else {
16816 return WOLFSSL_FAILURE;
16817 }
16818
16819 /* return error if not built for libest */
16820 return WOLFSSL_SUCCESS;
16821#else
16822 (void)req;
16823 (void)attrname;
16824 (void)type;
16825 (void)bytes;
16826 (void)len;
16827 return WOLFSSL_FAILURE;
16828#endif
16829}
16830
16831
16832static int wolfSSL_X509_ATTRIBUTE_set(WOLFSSL_X509_ATTRIBUTE* attr,
16833 const char* data, int dataSz, int type, int nid)
16834{
16835 if (attr) {
16836 attr->value->value.asn1_string = wolfSSL_ASN1_STRING_new();
16837 if (wolfSSL_ASN1_STRING_set(attr->value->value.asn1_string,
16838 data, dataSz) != WOLFSSL_SUCCESS) {
16839 wolfSSL_ASN1_STRING_free(attr->value->value.asn1_string);
16840 WOLFSSL_MSG("wolfSSL_ASN1_STRING_set error");
16841 return WOLFSSL_FAILURE;
16842 }
16843 attr->value->type = type;
16844 attr->object->nid = nid;
16845 }
16846 else {
16847 WOLFSSL_MSG("wolfSSL_X509_ATTRIBUTE_new error");
16848 return WOLFSSL_FAILURE;
16849 }
16850
16851 return WOLFSSL_SUCCESS;
16852}
16853
16854
16855int wolfSSL_X509_REQ_add1_attr_by_NID(WOLFSSL_X509 *req,
16856 int nid, int type,
16857 const unsigned char *bytes,
16858 int len)
16859{
16860 int ret;
16861 WOLFSSL_X509_ATTRIBUTE* attr;
16862
16863 WOLFSSL_ENTER("wolfSSL_X509_REQ_add1_attr_by_NID");
16864
16865 if (!req || !bytes || type != WOLFSSL_MBSTRING_ASC) {
16866 WOLFSSL_MSG("Bad parameter");
16867 return WOLFSSL_FAILURE;
16868 }
16869
16870 switch (nid) {
16871 case WC_NID_pkcs9_challengePassword:
16872 if (len < 0)
16873 len = (int)XSTRLEN((char*)bytes);
16874 if (len < CTC_NAME_SIZE) {
16875 XMEMCPY(req->challengePw, bytes, len);
16876 req->challengePw[len] = '\0';
16877 }
16878 else {
16879 WOLFSSL_MSG("Challenge password too long");
16880 WOLFSSL_ERROR_VERBOSE(BUFFER_E);
16881 return WOLFSSL_FAILURE;
16882 }
16883 break;
16884 case WC_NID_serialNumber:
16885 if (len < 0)
16886 len = (int)XSTRLEN((char*)bytes);
16887 if (len + 1 > EXTERNAL_SERIAL_SIZE) {
16888 WOLFSSL_MSG("SerialNumber too long");
16889 WOLFSSL_ERROR_VERBOSE(BUFFER_E);
16890 return WOLFSSL_FAILURE;
16891 }
16892 XMEMCPY(req->serial, bytes, len);
16893 req->serialSz = len;
16894 break;
16895
16896 case WC_NID_pkcs9_unstructuredName:
16897 case WC_NID_pkcs9_contentType:
16898 case WC_NID_surname:
16899 case WC_NID_initials:
16900 case WC_NID_givenName:
16901 case WC_NID_dnQualifier:
16902 break;
16903
16904 default:
16905 WOLFSSL_MSG("Unsupported attribute");
16906 return WOLFSSL_FAILURE;
16907 }
16908
16909 attr = wolfSSL_X509_ATTRIBUTE_new();
16910 ret = wolfSSL_X509_ATTRIBUTE_set(attr, (const char*)bytes, len,
16911 WOLFSSL_V_ASN1_PRINTABLESTRING, nid);
16912 if (ret != WOLFSSL_SUCCESS) {
16913 wolfSSL_X509_ATTRIBUTE_free(attr);
16914 }
16915 else {
16916 if (req->reqAttributes == NULL) {
16917 req->reqAttributes = wolfSSL_sk_new_node(req->heap);
16918 if (req->reqAttributes != NULL) {
16919 req->reqAttributes->type = STACK_TYPE_X509_REQ_ATTR;
16920 }
16921 }
16922 if ((req->reqAttributes != NULL) &&
16923 (req->reqAttributes->type == STACK_TYPE_X509_REQ_ATTR)) {
16924 /* Using wolfSSL_sk_insert to maintain backwards compatibility with
16925 * earlier versions of _push API that pushed items to the start of
16926 * the list instead of the end. */
16927 ret = wolfSSL_sk_insert(req->reqAttributes, attr, 0) > 0
16928 ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
16929 }
16930 else {
16931 ret = WOLFSSL_FAILURE;
16932 }
16933 if (ret != WOLFSSL_SUCCESS)
16934 wolfSSL_X509_ATTRIBUTE_free(attr);
16935 }
16936
16937 return ret;
16938}
16939
16940WOLFSSL_X509 *wolfSSL_X509_to_X509_REQ(WOLFSSL_X509 *x,
16941 WOLFSSL_EVP_PKEY *pkey, const WOLFSSL_EVP_MD *md)
16942{
16943 WOLFSSL_ENTER("wolfSSL_X509_to_X509_REQ");
16944 (void)pkey;
16945 (void)md;
16946 return wolfSSL_X509_dup(x);
16947}
16948
16949int wolfSSL_X509_REQ_set_subject_name(WOLFSSL_X509 *req,
16950 WOLFSSL_X509_NAME *name)
16951{
16952 return wolfSSL_X509_set_subject_name(req, name);
16953}
16954
16955int wolfSSL_X509_REQ_set_pubkey(WOLFSSL_X509 *req, WOLFSSL_EVP_PKEY *pkey)
16956{
16957 return wolfSSL_X509_set_pubkey(req, pkey);
16958}
16959#endif /* OPENSSL_ALL && WOLFSSL_CERT_GEN && WOLFSSL_CERT_REQ */
16960
16961#if (defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)) && \
16962 (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_CERT_REQ))
16963
16964WOLFSSL_ASN1_TYPE *wolfSSL_X509_ATTRIBUTE_get0_type(
16965 WOLFSSL_X509_ATTRIBUTE *attr, int idx)
16966{
16967 WOLFSSL_ENTER("wolfSSL_X509_ATTRIBUTE_get0_type");
16968
16969 if (!attr || idx != 0) {
16970 WOLFSSL_MSG("Bad parameter");
16971 return NULL;
16972 }
16973
16974 return attr->value;
16975}
16976
16977
16978/**
16979 * @param req X509_REQ containing attribute
16980 * @return the number of attributes
16981 */
16982int wolfSSL_X509_REQ_get_attr_count(const WOLFSSL_X509 *req)
16983{
16984 if (req == NULL || req->reqAttributes == NULL)
16985 return 0;
16986
16987 return wolfSSL_sk_num(req->reqAttributes);
16988}
16989
16990
16991/**
16992 * @param req X509_REQ containing attribute
16993 * @param loc NID of the attribute to return
16994 */
16995WOLFSSL_X509_ATTRIBUTE *wolfSSL_X509_REQ_get_attr(
16996 const WOLFSSL_X509 *req, int loc)
16997{
16998 WOLFSSL_ENTER("wolfSSL_X509_REQ_get_attr");
16999
17000 if (!req || req->reqAttributes == NULL) {
17001 WOLFSSL_MSG("Bad parameter");
17002 return NULL;
17003 }
17004
17005 return (WOLFSSL_X509_ATTRIBUTE*)wolfSSL_sk_value(req->reqAttributes, loc);
17006}
17007
17008/* Return NID as the attr index */
17009int wolfSSL_X509_REQ_get_attr_by_NID(const WOLFSSL_X509 *req,
17010 int nid, int lastpos)
17011{
17012 int idx;
17013
17014 WOLFSSL_ENTER("wolfSSL_X509_REQ_get_attr_by_NID");
17015
17016 if (!req) {
17017 WOLFSSL_MSG("Bad parameter");
17018 return WOLFSSL_FATAL_ERROR;
17019 }
17020
17021 /* search through stack for first matching nid */
17022 for (idx = lastpos + 1; idx < wolfSSL_sk_num(req->reqAttributes); idx++) {
17023 WOLFSSL_X509_ATTRIBUTE* attr =
17024 (WOLFSSL_X509_ATTRIBUTE*)wolfSSL_sk_value(req->reqAttributes, idx);
17025 if (attr != NULL && attr->object != NULL && attr->object->nid == nid)
17026 return idx;
17027 }
17028
17029 return WOLFSSL_FATAL_ERROR;
17030}
17031
17032WOLFSSL_X509_ATTRIBUTE* wolfSSL_X509_ATTRIBUTE_new(void)
17033{
17034 WOLFSSL_X509_ATTRIBUTE* ret;
17035 WOLFSSL_ENTER("wolfSSL_X509_ATTRIBUTE_new");
17036 ret = (WOLFSSL_X509_ATTRIBUTE*)XMALLOC(sizeof(WOLFSSL_X509_ATTRIBUTE),
17037 NULL, DYNAMIC_TYPE_OPENSSL);
17038 if (!ret) {
17039 WOLFSSL_MSG("malloc error");
17040 return NULL;
17041 }
17042 XMEMSET(ret, 0, sizeof(WOLFSSL_X509_ATTRIBUTE));
17043 ret->object = wolfSSL_ASN1_OBJECT_new();
17044 ret->value = wolfSSL_ASN1_TYPE_new();
17045 /* Don't allocate ret->set since WOLFSSL_ASN1_TYPE
17046 * is not supported as a stack type */
17047 if (!ret->object || !ret->value) {
17048 WOLFSSL_MSG("wolfSSL_ASN1_OBJECT_new or wolfSSL_ASN1_TYPE_new error");
17049 wolfSSL_X509_ATTRIBUTE_free(ret);
17050 return NULL;
17051 }
17052 return ret;
17053}
17054
17055void wolfSSL_X509_ATTRIBUTE_free(WOLFSSL_X509_ATTRIBUTE* attr)
17056{
17057 WOLFSSL_ENTER("wolfSSL_X509_ATTRIBUTE_free");
17058 if (attr) {
17059 if (attr->object) {
17060 wolfSSL_ASN1_OBJECT_free(attr->object);
17061 }
17062 if (attr->value) {
17063 wolfSSL_ASN1_TYPE_free(attr->value);
17064 }
17065 if (attr->set) {
17066 wolfSSL_sk_pop_free(attr->set, NULL);
17067 }
17068 XFREE(attr, NULL, DYNAMIC_TYPE_OPENSSL);
17069 }
17070}
17071#endif /* (OPENSSL_ALL || OPENSSL_EXTRA) &&
17072 (WOLFSSL_CERT_GEN || WOLFSSL_CERT_REQ) */
17073
17074#if defined(WOLFSSL_ACERT) && \
17075 (defined(OPENSSL_EXTRA_X509_SMALL) || defined(OPENSSL_EXTRA))
17076
17077/* Allocate and return a new WOLFSSL_X509_ACERT struct pointer.
17078 *
17079 * @param [in] heap heap hint
17080 *
17081 * @return pointer on success
17082 * @return NULL on error
17083 * */
17084WOLFSSL_X509_ACERT * wolfSSL_X509_ACERT_new_ex(void* heap)
17085{
17086 WOLFSSL_X509_ACERT * x509 = NULL;
17087
17088 WOLFSSL_ENTER("wolfSSL_X509_ACERT_new");
17089
17090 x509 = (WOLFSSL_X509_ACERT*) XMALLOC(sizeof(WOLFSSL_X509_ACERT), heap,
17091 DYNAMIC_TYPE_X509_ACERT);
17092
17093 if (x509 != NULL) {
17094 wolfSSL_X509_ACERT_init(x509, 1, heap);
17095 }
17096
17097 return x509;
17098}
17099
17100WOLFSSL_X509_ACERT * wolfSSL_X509_ACERT_new(void)
17101{
17102 return wolfSSL_X509_ACERT_new_ex(NULL);
17103}
17104
17105/* Initialize a WOLFSSL_X509_ACERT struct.
17106 *
17107 * If dynamic == 1, then the x509 pointer will be freed
17108 * in wolfSSL_X509_ACERT_free.
17109 *
17110 * @param [in] x509 x509 acert pointer
17111 * @param [in] dynamic dynamic mem flag
17112 * @param [in] heap heap hint
17113 *
17114 * @return void
17115 * */
17116void wolfSSL_X509_ACERT_init(WOLFSSL_X509_ACERT * x509, int dynamic, void* heap)
17117{
17118 WOLFSSL_ENTER("wolfSSL_X509_ACERT_init");
17119
17120 if (x509 == NULL) {
17121 WOLFSSL_MSG("error: InitX509Acert: null parameter");
17122 return;
17123 }
17124
17125 XMEMSET(x509, 0, sizeof(*x509));
17126
17127 x509->heap = heap;
17128 x509->dynamic = dynamic;
17129}
17130
17131/* Free a WOLFSSL_X509_ACERT struct and its sub-fields.
17132 *
17133 * If this ACERT was initialized with dynamic == 1, then
17134 * the x509 pointer itself will be freed as well.
17135 *
17136 * @param [in] x509 x509 acert pointer
17137 *
17138 * @return void
17139 * */
17140void wolfSSL_X509_ACERT_free(WOLFSSL_X509_ACERT * x509)
17141{
17142 int dynamic = 0;
17143 void * heap = NULL;
17144
17145 WOLFSSL_ENTER("wolfSSL_X509_ACERT_free");
17146
17147 if (x509 == NULL) {
17148 WOLFSSL_MSG("error: wolfSSL_X509_ACERT_free: null parameter");
17149 return;
17150 }
17151
17152 dynamic = x509->dynamic;
17153 heap = x509->heap;
17154
17155 /* Free holder and att cert issuer structures. */
17156 if (x509->holderIssuerName) {
17157 FreeAltNames(x509->holderIssuerName, heap);
17158 x509->holderIssuerName = NULL;
17159 }
17160
17161 if (x509->holderEntityName) {
17162 FreeAltNames(x509->holderEntityName, heap);
17163 x509->holderEntityName = NULL;
17164 }
17165
17166 if (x509->AttCertIssuerName) {
17167 FreeAltNames(x509->AttCertIssuerName, heap);
17168 x509->AttCertIssuerName = NULL;
17169 }
17170
17171 if (x509->rawAttr != NULL) {
17172 XFREE(x509->rawAttr, heap, DYNAMIC_TYPE_X509_EXT);
17173 x509->rawAttr = NULL;
17174 x509->rawAttrLen = 0;
17175 }
17176
17177 /* Free derCert source and signature buffer. */
17178 FreeDer(&x509->derCert);
17179
17180 if (x509->sig.buffer != NULL) {
17181 XFREE(x509->sig.buffer, heap, DYNAMIC_TYPE_SIGNATURE);
17182 x509->sig.buffer = NULL;
17183 }
17184
17185 /* Finally memset and free x509 acert structure. */
17186 XMEMSET(x509, 0, sizeof(*x509));
17187
17188 if (dynamic == 1) {
17189 XFREE(x509, heap, DYNAMIC_TYPE_X509_ACERT);
17190 }
17191
17192 return;
17193}
17194
17195#if defined(OPENSSL_EXTRA)
17196long wolfSSL_X509_ACERT_get_version(const WOLFSSL_X509_ACERT* x509)
17197{
17198 int version = 0;
17199
17200 if (x509 == NULL) {
17201 return 0L;
17202 }
17203
17204 version = x509->version;
17205
17206 return version != 0 ? (long)version - 1L : 0L;
17207}
17208#endif /* OPENSSL_EXTRA */
17209
17210int wolfSSL_X509_ACERT_version(WOLFSSL_X509_ACERT* x509)
17211{
17212 if (x509 == NULL) {
17213 return 0;
17214 }
17215
17216 return x509->version;
17217}
17218
17219/* Retrieve the serial number from an ACERT.
17220 *
17221 * @param [in] x509 the x509 attribute certificate
17222 * @param [in, out] buf the serial number buffer pointer
17223 * @param [in, out] bufSz the serial number buffer size pointer
17224 *
17225 * buf may be null, but bufSz is required. On success, sets
17226 * bufSz pointer to signature length, and copies signature
17227 * to buf if provided.
17228 *
17229 * Returns WWOLFSSL_FATAL_ERROR if bufSz is null or too small.
17230 * Returns WOLFSSL_SUCCESS on success.
17231 */
17232int wolfSSL_X509_ACERT_get_serial_number(WOLFSSL_X509_ACERT* x509,
17233 byte* buf, int* bufSz)
17234{
17235 WOLFSSL_ENTER("wolfSSL_X509_ACERT_get_serial_number");
17236
17237 if (x509 == NULL || bufSz == NULL) {
17238 WOLFSSL_MSG("error: null argument passed in");
17239 return BAD_FUNC_ARG;
17240 }
17241
17242 if (buf != NULL) {
17243 if (*bufSz < x509->serialSz) {
17244 WOLFSSL_MSG("error: serial buffer too small");
17245 return BUFFER_E;
17246 }
17247
17248 XMEMCPY(buf, x509->serial, x509->serialSz);
17249 }
17250
17251 *bufSz = x509->serialSz;
17252
17253 return WOLFSSL_SUCCESS;
17254}
17255
17256/* Sets buf pointer and len to raw Attribute buffer and buffer len
17257 * in X509 struct.
17258 *
17259 * Returns WOLFSSL_SUCCESS on success.
17260 * Returns BAD_FUNC_ARG if input pointers are null.
17261 * */
17262int wolfSSL_X509_ACERT_get_attr_buf(const WOLFSSL_X509_ACERT* x509,
17263 const byte ** rawAttr,
17264 word32 * rawAttrLen)
17265{
17266 if (x509 == NULL || rawAttr == NULL || rawAttrLen == NULL) {
17267 return BAD_FUNC_ARG;
17268 }
17269
17270 *rawAttr = x509->rawAttr;
17271 *rawAttrLen = x509->rawAttrLen;
17272
17273 return WOLFSSL_SUCCESS;
17274}
17275
17276#ifndef NO_WOLFSSL_STUB
17277int wolfSSL_X509_ACERT_sign(WOLFSSL_X509_ACERT * x509,
17278 WOLFSSL_EVP_PKEY * pkey,
17279 const WOLFSSL_EVP_MD * md)
17280{
17281 WOLFSSL_STUB("X509_ACERT_sign");
17282 (void) x509;
17283 (void) pkey;
17284 (void) md;
17285 return WOLFSSL_NOT_IMPLEMENTED;
17286}
17287#endif /* NO_WOLFSSL_STUB */
17288
17289/* Helper function for ACERT_verify.
17290 *
17291 * @param [in] x509 the x509 attribute certificate
17292 * @param [in, out] outSz the x509 der length
17293 *
17294 * @return der buffer on success
17295 * @return NULL on error
17296 * */
17297static const byte* acert_get_der(WOLFSSL_X509_ACERT * x509, int* outSz)
17298{
17299 if (x509 == NULL || x509->derCert == NULL || outSz == NULL) {
17300 return NULL;
17301 }
17302
17303 *outSz = (int)x509->derCert->length;
17304 return x509->derCert->buffer;
17305}
17306
17307/* Given an X509_ACERT and EVP_PKEY, verify the acert's signature.
17308 *
17309 * @param [in] x509 the x509 attribute certificate
17310 * @param [in] pkey the evp_pkey
17311 *
17312 * @return WOLFSSL_SUCCESS on verify success
17313 * @return < 0 on error
17314 * */
17315int wolfSSL_X509_ACERT_verify(WOLFSSL_X509_ACERT* x509, WOLFSSL_EVP_PKEY* pkey)
17316{
17317 int ret = 0;
17318 const byte * der = NULL;
17319 int derSz = 0;
17320 int pkey_type;
17321
17322 if (x509 == NULL || pkey == NULL) {
17323 WOLFSSL_MSG("error: wolfSSL_X509_ACERT_verify: bad arg");
17324 return WOLFSSL_FATAL_ERROR;
17325 }
17326
17327 WOLFSSL_ENTER("wolfSSL_X509_ACERT_verify");
17328
17329 der = acert_get_der(x509, &derSz);
17330
17331 if (der == NULL || derSz <= 0) {
17332 WOLFSSL_MSG("error: wolfSSL_X509_ACERT_verify: get der failed");
17333 return WOLFSSL_FATAL_ERROR;
17334 }
17335
17336 switch (pkey->type) {
17337 case WC_EVP_PKEY_RSA:
17338 pkey_type = RSAk;
17339 break;
17340
17341 case WC_EVP_PKEY_EC:
17342 pkey_type = ECDSAk;
17343 break;
17344
17345 case WC_EVP_PKEY_DSA:
17346 pkey_type = DSAk;
17347 break;
17348
17349 default:
17350 WOLFSSL_MSG("error: wolfSSL_X509_ACERT_verify: unknown pkey type");
17351 return WOLFSSL_FATAL_ERROR;
17352 }
17353
17354
17355 ret = VerifyX509Acert(der, (word32)derSz,
17356 (const byte *)pkey->pkey.ptr, pkey->pkey_sz,
17357 pkey_type, x509->heap);
17358
17359 return ret == 0 ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
17360}
17361
17362/* Loads an x509 attribute certificate from buffer, and returns
17363 * pointer to new WOLFSSL_X509_ACERT struct on success.
17364 *
17365 * @param [in] buf The acert buffer to load.
17366 * @param [in] sz The size of the buffer.
17367 * @param [in] format The format of the buffer data.
17368 * @param [in] heap Dynamic memory allocation hint.
17369 *
17370 * @return pointer to WOLFSSL_X509_ACERT on success.
17371 * @return NULL on error.
17372 * */
17373WOLFSSL_X509_ACERT * wolfSSL_X509_ACERT_load_certificate_buffer_ex(
17374 const unsigned char* buf, int sz, int format, void * heap)
17375{
17376 int ret = 0;
17377 WOLFSSL_X509_ACERT * x509 = NULL;
17378 DerBuffer * der = NULL;
17379 WC_DECLARE_VAR(acert, DecodedAcert, 1, 0);
17380
17381 WOLFSSL_ENTER("wolfSSL_X509_ACERT_load_certificate_buffer");
17382
17383 if (format == WOLFSSL_FILETYPE_PEM) {
17384 #ifdef WOLFSSL_PEM_TO_DER
17385 ret = PemToDer(buf, sz, ACERT_TYPE, &der, heap, NULL, NULL);
17386
17387 if (ret != 0 || der == NULL || der->buffer == NULL) {
17388 WOLFSSL_ERROR(ret);
17389
17390 if (der != NULL) {
17391 FreeDer(&der);
17392 }
17393
17394 return NULL;
17395 }
17396 #else
17397 WOLFSSL_ERROR(NOT_COMPILED_IN);
17398 return NULL;
17399 #endif
17400 }
17401 else {
17402 ret = AllocDer(&der, (word32)sz, ACERT_TYPE, heap);
17403
17404 if (ret != 0 || der == NULL || der->buffer == NULL) {
17405 WOLFSSL_ERROR(ret);
17406 return NULL;
17407 }
17408
17409 XMEMCPY(der->buffer, buf, sz);
17410 }
17411
17412 #ifdef WOLFSSL_SMALL_STACK
17413 acert = (DecodedAcert*)XMALLOC(sizeof(DecodedAcert), heap,
17414 DYNAMIC_TYPE_DCERT);
17415 if (acert == NULL) {
17416 WOLFSSL_ERROR(MEMORY_ERROR);
17417 FreeDer(&der);
17418 return NULL;
17419 }
17420 #endif
17421
17422 InitDecodedAcert(acert, der->buffer, der->length, heap);
17423
17424 ret = ParseX509Acert(acert, VERIFY_SKIP_DATE);
17425
17426 if (ret == 0) {
17427 x509 = wolfSSL_X509_ACERT_new_ex(heap);
17428
17429 if (x509 != NULL) {
17430 ret = CopyDecodedAcertToX509(x509, acert);
17431
17432 if (ret != 0) {
17433 wolfSSL_X509_ACERT_free(x509);
17434 x509 = NULL;
17435 }
17436 }
17437 else {
17438 ret = MEMORY_ERROR;
17439 }
17440 }
17441
17442 FreeDecodedAcert(acert);
17443
17444 WC_FREE_VAR_EX(acert, heap, DYNAMIC_TYPE_DCERT);
17445
17446 FreeDer(&der);
17447
17448 if (ret != 0) {
17449 WOLFSSL_ERROR(ret);
17450 }
17451
17452 return x509;
17453}
17454
17455WOLFSSL_X509_ACERT * wolfSSL_X509_ACERT_load_certificate_buffer(
17456 const unsigned char* buf, int sz, int format)
17457{
17458 return wolfSSL_X509_ACERT_load_certificate_buffer_ex(buf, sz, format, NULL);
17459}
17460
17461/* Retrieve the signature from an ACERT.
17462 *
17463 * @param [in] x509 the x509 attribute certificate
17464 * @param [in, out] buf the signature buffer pointer
17465 * @param [in, out] bufSz the signature buffer size pointer
17466 *
17467 * buf may be null, but bufSz is required. On success, sets
17468 * bufSz pointer to signature length, and copies signature
17469 * to buf if provided.
17470 *
17471 * Returns WWOLFSSL_FATAL_ERROR if bufSz is null or too small.
17472 * Returns WOLFSSL_SUCCESS on success.
17473 */
17474int wolfSSL_X509_ACERT_get_signature(WOLFSSL_X509_ACERT* x509,
17475 unsigned char* buf, int* bufSz)
17476{
17477 WOLFSSL_ENTER("wolfSSL_X509_ACERT_get_signature");
17478
17479 if (x509 == NULL || bufSz == NULL) {
17480 return WOLFSSL_FATAL_ERROR;
17481 }
17482
17483 /* If buf array is provided, it must be long enough. */
17484 if (buf != NULL && *bufSz < (int)x509->sig.length) {
17485 return WOLFSSL_FATAL_ERROR;
17486 }
17487
17488 if (buf != NULL) {
17489 /* Copy in buffer if provided. */
17490 XMEMCPY(buf, x509->sig.buffer, x509->sig.length);
17491 }
17492
17493 *bufSz = (int)x509->sig.length;
17494
17495 return WOLFSSL_SUCCESS;
17496}
17497#endif /* WOLFSSL_ACERT && (OPENSSL_EXTRA_X509_SMALL || OPENSSL_EXTRA) */
17498
17499#endif /* !NO_CERTS */
17500
17501#endif /* !WOLFCRYPT_ONLY */
17502
17503#endif /* WOLFSSL_X509_INCLUDED */