cjson
.github
workflows CI.yml ci-fuzz.yml
CONTRIBUTING.md
fuzzing
inputs test1 test10 test11 test2 test3 test3.bu test3.uf test3.uu test4 test5 test6 test7 test8 test9
.gitignore CMakeLists.txt afl-prepare-linux.sh afl.c afl.sh cjson_read_fuzzer.c fuzz_main.c json.dict ossfuzz.sh
library_config cJSONConfig.cmake.in cJSONConfigVersion.cmake.in libcjson.pc.in libcjson_utils.pc.in uninstall.cmake
tests
inputs test1 test1.expected test10 test10.expected test11 test11.expected test2 test2.expected test3 test3.expected test4 test4.expected test5 test5.expected test6 test7 test7.expected test8 test8.expected test9 test9.expected
json-patch-tests .editorconfig .gitignore .npmignore README.md cjson-utils-tests.json package.json spec_tests.json tests.json
unity
auto colour_prompt.rb colour_reporter.rb generate_config.yml generate_module.rb generate_test_runner.rb parse_output.rb stylize_as_junit.rb test_file_filter.rb type_sanitizer.rb unity_test_summary.py unity_test_summary.rb unity_to_junit.py
docs ThrowTheSwitchCodingStandard.md UnityAssertionsCheatSheetSuitableforPrintingandPossiblyFraming.pdf UnityAssertionsReference.md UnityConfigurationGuide.md UnityGettingStartedGuide.md UnityHelperScriptsGuide.md license.txt
examples
example_1
src ProductionCode.c ProductionCode.h ProductionCode2.c ProductionCode2.h
makefile readme.txt
example_2
src ProductionCode.c ProductionCode.h ProductionCode2.c ProductionCode2.h
makefile readme.txt
example_3
helper UnityHelper.c UnityHelper.h
src ProductionCode.c ProductionCode.h ProductionCode2.c ProductionCode2.h
rakefile.rb rakefile_helper.rb readme.txt target_gcc_32.yml
unity_config.h
extras
eclipse error_parsers.txt
fixture
src unity_fixture.c unity_fixture.h unity_fixture_internals.h unity_fixture_malloc_overrides.h
rakefile.rb rakefile_helper.rb readme.txt
release build.info version.info
src unity.c unity.h unity_internals.h
.gitattributes .gitignore .travis.yml README.md
CMakeLists.txt cjson_add.c common.h compare_tests.c json_patch_tests.c minify_tests.c misc_tests.c misc_utils_tests.c old_utils_tests.c parse_array.c parse_examples.c parse_hex4.c parse_number.c parse_object.c parse_string.c parse_value.c parse_with_opts.c print_array.c print_number.c print_object.c print_string.c print_value.c readme_examples.c unity_setup.c
.editorconfig .gitattributes .gitignore .travis.yml CHANGELOG.md CMakeLists.txt CONTRIBUTORS.md LICENSE Makefile README.md SECURITY.md appveyor.yml cJSON.c cJSON.h cJSON_Utils.c cJSON_Utils.h test.c valgrind.supp
curl
.circleci config.yml
.github
ISSUE_TEMPLATE bug_report.yml config.yml docs.yml
scripts cleancmd.pl cmp-config.pl cmp-pkg-config.sh codespell-ignore.words codespell.sh distfiles.sh pyspelling.words pyspelling.yaml randcurl.pl requirements-docs.txt requirements-proselint.txt requirements.txt shellcheck-ci.sh shellcheck.sh spellcheck.curl trimmarkdownheader.pl typos.sh typos.toml verify-examples.pl verify-synopsis.pl yamlcheck.sh yamlcheck.yaml
workflows appveyor-status.yml checkdocs.yml checksrc.yml checkurls.yml codeql.yml configure-vs-cmake.yml curl-for-win.yml distcheck.yml fuzz.yml http3-linux.yml label.yml linux-old.yml linux.yml macos.yml non-native.yml windows.yml
CODEOWNERS CONTRIBUTING.md FUNDING.yml dependabot.yml labeler.yml lock.yml stale.yml
CMake CurlSymbolHiding.cmake CurlTests.c FindBrotli.cmake FindCares.cmake FindGSS.cmake FindGnuTLS.cmake FindLDAP.cmake FindLibbacktrace.cmake FindLibgsasl.cmake FindLibidn2.cmake FindLibpsl.cmake FindLibssh.cmake FindLibssh2.cmake FindLibuv.cmake FindMbedTLS.cmake FindNGHTTP2.cmake FindNGHTTP3.cmake FindNGTCP2.cmake FindNettle.cmake FindQuiche.cmake FindRustls.cmake FindWolfSSL.cmake FindZstd.cmake Macros.cmake OtherTests.cmake PickyWarnings.cmake Utilities.cmake cmake_uninstall.in.cmake curl-config.in.cmake unix-cache.cmake win32-cache.cmake
LICENSES BSD-4-Clause-UC.txt ISC.txt curl.txt
docs
cmdline-opts .gitignore CMakeLists.txt MANPAGE.md Makefile.am Makefile.inc _AUTHORS.md _BUGS.md _DESCRIPTION.md _ENVIRONMENT.md _EXITCODES.md _FILES.md _GLOBBING.md _NAME.md _OPTIONS.md _OUTPUT.md _PROGRESS.md _PROTOCOLS.md _PROXYPREFIX.md _SEEALSO.md _SYNOPSIS.md _URL.md _VARIABLES.md _VERSION.md _WWW.md abstract-unix-socket.md alt-svc.md anyauth.md append.md aws-sigv4.md basic.md ca-native.md cacert.md capath.md cert-status.md cert-type.md cert.md ciphers.md compressed-ssh.md compressed.md config.md connect-timeout.md connect-to.md continue-at.md cookie-jar.md cookie.md create-dirs.md create-file-mode.md crlf.md crlfile.md curves.md data-ascii.md data-binary.md data-raw.md data-urlencode.md data.md delegation.md digest.md disable-eprt.md disable-epsv.md disable.md disallow-username-in-url.md dns-interface.md dns-ipv4-addr.md dns-ipv6-addr.md dns-servers.md doh-cert-status.md doh-insecure.md doh-url.md dump-ca-embed.md dump-header.md ech.md egd-file.md engine.md etag-compare.md etag-save.md expect100-timeout.md fail-early.md fail-with-body.md fail.md false-start.md follow.md form-escape.md form-string.md form.md ftp-account.md ftp-alternative-to-user.md ftp-create-dirs.md ftp-method.md ftp-pasv.md ftp-port.md ftp-pret.md ftp-skip-pasv-ip.md ftp-ssl-ccc-mode.md ftp-ssl-ccc.md ftp-ssl-control.md get.md globoff.md happy-eyeballs-timeout-ms.md haproxy-clientip.md haproxy-protocol.md head.md header.md help.md hostpubmd5.md hostpubsha256.md hsts.md http0.9.md http1.0.md http1.1.md http2-prior-knowledge.md http2.md http3-only.md http3.md ignore-content-length.md insecure.md interface.md ip-tos.md ipfs-gateway.md ipv4.md ipv6.md json.md junk-session-cookies.md keepalive-cnt.md keepalive-time.md key-type.md key.md knownhosts.md krb.md libcurl.md limit-rate.md list-only.md local-port.md location-trusted.md location.md login-options.md mail-auth.md mail-from.md mail-rcpt-allowfails.md mail-rcpt.md mainpage.idx manual.md max-filesize.md max-redirs.md max-time.md metalink.md mptcp.md negotiate.md netrc-file.md netrc-optional.md netrc.md next.md no-alpn.md no-buffer.md no-clobber.md no-keepalive.md no-npn.md no-progress-meter.md no-sessionid.md noproxy.md ntlm-wb.md ntlm.md oauth2-bearer.md out-null.md output-dir.md output.md parallel-immediate.md parallel-max-host.md parallel-max.md parallel.md pass.md path-as-is.md pinnedpubkey.md post301.md post302.md post303.md preproxy.md progress-bar.md proto-default.md proto-redir.md proto.md proxy-anyauth.md proxy-basic.md proxy-ca-native.md proxy-cacert.md proxy-capath.md proxy-cert-type.md proxy-cert.md proxy-ciphers.md proxy-crlfile.md proxy-digest.md proxy-header.md proxy-http2.md proxy-insecure.md proxy-key-type.md proxy-key.md proxy-negotiate.md proxy-ntlm.md proxy-pass.md proxy-pinnedpubkey.md proxy-service-name.md proxy-ssl-allow-beast.md proxy-ssl-auto-client-cert.md proxy-tls13-ciphers.md proxy-tlsauthtype.md proxy-tlspassword.md proxy-tlsuser.md proxy-tlsv1.md proxy-user.md proxy.md proxy1.0.md proxytunnel.md pubkey.md quote.md random-file.md range.md rate.md raw.md referer.md remote-header-name.md remote-name-all.md remote-name.md remote-time.md remove-on-error.md request-target.md request.md resolve.md retry-all-errors.md retry-connrefused.md retry-delay.md retry-max-time.md retry.md sasl-authzid.md sasl-ir.md service-name.md show-error.md show-headers.md sigalgs.md silent.md skip-existing.md socks4.md socks4a.md socks5-basic.md socks5-gssapi-nec.md socks5-gssapi-service.md socks5-gssapi.md socks5-hostname.md socks5.md speed-limit.md speed-time.md ssl-allow-beast.md ssl-auto-client-cert.md ssl-no-revoke.md ssl-reqd.md ssl-revoke-best-effort.md ssl-sessions.md ssl.md sslv2.md sslv3.md stderr.md styled-output.md suppress-connect-headers.md tcp-fastopen.md tcp-nodelay.md telnet-option.md tftp-blksize.md tftp-no-options.md time-cond.md tls-earlydata.md tls-max.md tls13-ciphers.md tlsauthtype.md tlspassword.md tlsuser.md tlsv1.0.md tlsv1.1.md tlsv1.2.md tlsv1.3.md tlsv1.md tr-encoding.md trace-ascii.md trace-config.md trace-ids.md trace-time.md trace.md unix-socket.md upload-file.md upload-flags.md url-query.md url.md use-ascii.md user-agent.md user.md variable.md verbose.md version.md vlan-priority.md write-out.md xattr.md
examples .checksrc .gitignore 10-at-a-time.c CMakeLists.txt Makefile.am Makefile.example Makefile.inc README.md adddocsref.pl address-scope.c altsvc.c anyauthput.c block_ip.c cacertinmem.c certinfo.c chkspeed.c connect-to.c cookie_interface.c crawler.c debug.c default-scheme.c ephiperfifo.c evhiperfifo.c externalsocket.c fileupload.c ftp-delete.c ftp-wildcard.c ftpget.c ftpgetinfo.c ftpgetresp.c ftpsget.c ftpupload.c ftpuploadfrommem.c ftpuploadresume.c getinfo.c getinmemory.c getredirect.c getreferrer.c ghiper.c headerapi.c hiperfifo.c hsts-preload.c htmltidy.c htmltitle.cpp http-options.c http-post.c http2-download.c http2-pushinmemory.c http2-serverpush.c http2-upload.c http3-present.c http3.c httpcustomheader.c httpput-postfields.c httpput.c https.c imap-append.c imap-authzid.c imap-copy.c imap-create.c imap-delete.c imap-examine.c imap-fetch.c imap-list.c imap-lsub.c imap-multi.c imap-noop.c imap-search.c imap-ssl.c imap-store.c imap-tls.c interface.c ipv6.c keepalive.c localport.c log_failed_transfers.c maxconnects.c multi-app.c multi-debugcallback.c multi-double.c multi-event.c multi-formadd.c multi-legacy.c multi-post.c multi-single.c multi-uv.c netrc.c parseurl.c persistent.c pop3-authzid.c pop3-dele.c pop3-list.c pop3-multi.c pop3-noop.c pop3-retr.c pop3-ssl.c pop3-stat.c pop3-tls.c pop3-top.c pop3-uidl.c post-callback.c postinmemory.c postit2-formadd.c postit2.c progressfunc.c protofeats.c range.c resolve.c rtsp-options.c sendrecv.c sepheaders.c sessioninfo.c sftpget.c sftpuploadresume.c shared-connection-cache.c simple.c simplepost.c simplessl.c smooth-gtk-thread.c smtp-authzid.c smtp-expn.c smtp-mail.c smtp-mime.c smtp-multi.c smtp-ssl.c smtp-tls.c smtp-vrfy.c sslbackend.c synctime.c threaded.c unixsocket.c url2file.c urlapi.c usercertinmem.c version-check.pl websocket-cb.c websocket-updown.c websocket.c xmlstream.c
internals BUFQ.md BUFREF.md CHECKSRC.md CLIENT-READERS.md CLIENT-WRITERS.md CODE_STYLE.md CONNECTION-FILTERS.md CREDENTIALS.md CURLX.md DYNBUF.md HASH.md LLIST.md MID.md MQTT.md MULTI-EV.md NEW-PROTOCOL.md PEERS.md PORTING.md RATELIMITS.md README.md SCORECARD.md SPLAY.md STRPARSE.md THRDPOOL-AND-QUEUE.md TIME-KEEPING.md TLS-SESSIONS.md UINT_SETS.md WEBSOCKET.md
libcurl
opts CMakeLists.txt CURLINFO_ACTIVESOCKET.md CURLINFO_APPCONNECT_TIME.md CURLINFO_APPCONNECT_TIME_T.md CURLINFO_CAINFO.md CURLINFO_CAPATH.md CURLINFO_CERTINFO.md CURLINFO_CONDITION_UNMET.md CURLINFO_CONNECT_TIME.md CURLINFO_CONNECT_TIME_T.md CURLINFO_CONN_ID.md CURLINFO_CONTENT_LENGTH_DOWNLOAD.md CURLINFO_CONTENT_LENGTH_DOWNLOAD_T.md CURLINFO_CONTENT_LENGTH_UPLOAD.md CURLINFO_CONTENT_LENGTH_UPLOAD_T.md CURLINFO_CONTENT_TYPE.md CURLINFO_COOKIELIST.md CURLINFO_EARLYDATA_SENT_T.md CURLINFO_EFFECTIVE_METHOD.md CURLINFO_EFFECTIVE_URL.md CURLINFO_FILETIME.md CURLINFO_FILETIME_T.md CURLINFO_FTP_ENTRY_PATH.md CURLINFO_HEADER_SIZE.md CURLINFO_HTTPAUTH_AVAIL.md CURLINFO_HTTPAUTH_USED.md CURLINFO_HTTP_CONNECTCODE.md CURLINFO_HTTP_VERSION.md CURLINFO_LASTSOCKET.md CURLINFO_LOCAL_IP.md CURLINFO_LOCAL_PORT.md CURLINFO_NAMELOOKUP_TIME.md CURLINFO_NAMELOOKUP_TIME_T.md CURLINFO_NUM_CONNECTS.md CURLINFO_OS_ERRNO.md CURLINFO_POSTTRANSFER_TIME_T.md CURLINFO_PRETRANSFER_TIME.md CURLINFO_PRETRANSFER_TIME_T.md CURLINFO_PRIMARY_IP.md CURLINFO_PRIMARY_PORT.md CURLINFO_PRIVATE.md CURLINFO_PROTOCOL.md CURLINFO_PROXYAUTH_AVAIL.md CURLINFO_PROXYAUTH_USED.md CURLINFO_PROXY_ERROR.md CURLINFO_PROXY_SSL_VERIFYRESULT.md CURLINFO_QUEUE_TIME_T.md CURLINFO_REDIRECT_COUNT.md CURLINFO_REDIRECT_TIME.md CURLINFO_REDIRECT_TIME_T.md CURLINFO_REDIRECT_URL.md CURLINFO_REFERER.md CURLINFO_REQUEST_SIZE.md CURLINFO_RESPONSE_CODE.md CURLINFO_RETRY_AFTER.md CURLINFO_RTSP_CLIENT_CSEQ.md CURLINFO_RTSP_CSEQ_RECV.md CURLINFO_RTSP_SERVER_CSEQ.md CURLINFO_RTSP_SESSION_ID.md CURLINFO_SCHEME.md CURLINFO_SIZE_DELIVERED.md CURLINFO_SIZE_DOWNLOAD.md CURLINFO_SIZE_DOWNLOAD_T.md CURLINFO_SIZE_UPLOAD.md CURLINFO_SIZE_UPLOAD_T.md CURLINFO_SPEED_DOWNLOAD.md CURLINFO_SPEED_DOWNLOAD_T.md CURLINFO_SPEED_UPLOAD.md CURLINFO_SPEED_UPLOAD_T.md CURLINFO_SSL_ENGINES.md CURLINFO_SSL_VERIFYRESULT.md CURLINFO_STARTTRANSFER_TIME.md CURLINFO_STARTTRANSFER_TIME_T.md CURLINFO_TLS_SESSION.md CURLINFO_TLS_SSL_PTR.md CURLINFO_TOTAL_TIME.md CURLINFO_TOTAL_TIME_T.md CURLINFO_USED_PROXY.md CURLINFO_XFER_ID.md CURLMINFO_XFERS_ADDED.md CURLMINFO_XFERS_CURRENT.md CURLMINFO_XFERS_DONE.md CURLMINFO_XFERS_PENDING.md CURLMINFO_XFERS_RUNNING.md CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE.md CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE.md CURLMOPT_MAXCONNECTS.md CURLMOPT_MAX_CONCURRENT_STREAMS.md CURLMOPT_MAX_HOST_CONNECTIONS.md CURLMOPT_MAX_PIPELINE_LENGTH.md CURLMOPT_MAX_TOTAL_CONNECTIONS.md CURLMOPT_NETWORK_CHANGED.md CURLMOPT_NOTIFYDATA.md CURLMOPT_NOTIFYFUNCTION.md CURLMOPT_PIPELINING.md CURLMOPT_PIPELINING_SERVER_BL.md CURLMOPT_PIPELINING_SITE_BL.md CURLMOPT_PUSHDATA.md CURLMOPT_PUSHFUNCTION.md CURLMOPT_QUICK_EXIT.md CURLMOPT_RESOLVE_THREADS_MAX.md CURLMOPT_SOCKETDATA.md CURLMOPT_SOCKETFUNCTION.md CURLMOPT_TIMERDATA.md CURLMOPT_TIMERFUNCTION.md CURLOPT_ABSTRACT_UNIX_SOCKET.md CURLOPT_ACCEPTTIMEOUT_MS.md CURLOPT_ACCEPT_ENCODING.md CURLOPT_ADDRESS_SCOPE.md CURLOPT_ALTSVC.md CURLOPT_ALTSVC_CTRL.md CURLOPT_APPEND.md CURLOPT_AUTOREFERER.md CURLOPT_AWS_SIGV4.md CURLOPT_BUFFERSIZE.md CURLOPT_CAINFO.md CURLOPT_CAINFO_BLOB.md CURLOPT_CAPATH.md CURLOPT_CA_CACHE_TIMEOUT.md CURLOPT_CERTINFO.md CURLOPT_CHUNK_BGN_FUNCTION.md CURLOPT_CHUNK_DATA.md CURLOPT_CHUNK_END_FUNCTION.md CURLOPT_CLOSESOCKETDATA.md CURLOPT_CLOSESOCKETFUNCTION.md CURLOPT_CONNECTTIMEOUT.md CURLOPT_CONNECTTIMEOUT_MS.md CURLOPT_CONNECT_ONLY.md CURLOPT_CONNECT_TO.md CURLOPT_CONV_FROM_NETWORK_FUNCTION.md CURLOPT_CONV_FROM_UTF8_FUNCTION.md CURLOPT_CONV_TO_NETWORK_FUNCTION.md CURLOPT_COOKIE.md CURLOPT_COOKIEFILE.md CURLOPT_COOKIEJAR.md CURLOPT_COOKIELIST.md CURLOPT_COOKIESESSION.md CURLOPT_COPYPOSTFIELDS.md CURLOPT_CRLF.md CURLOPT_CRLFILE.md CURLOPT_CURLU.md CURLOPT_CUSTOMREQUEST.md CURLOPT_DEBUGDATA.md CURLOPT_DEBUGFUNCTION.md CURLOPT_DEFAULT_PROTOCOL.md CURLOPT_DIRLISTONLY.md CURLOPT_DISALLOW_USERNAME_IN_URL.md CURLOPT_DNS_CACHE_TIMEOUT.md CURLOPT_DNS_INTERFACE.md CURLOPT_DNS_LOCAL_IP4.md CURLOPT_DNS_LOCAL_IP6.md CURLOPT_DNS_SERVERS.md CURLOPT_DNS_SHUFFLE_ADDRESSES.md CURLOPT_DNS_USE_GLOBAL_CACHE.md CURLOPT_DOH_SSL_VERIFYHOST.md CURLOPT_DOH_SSL_VERIFYPEER.md CURLOPT_DOH_SSL_VERIFYSTATUS.md CURLOPT_DOH_URL.md CURLOPT_ECH.md CURLOPT_EGDSOCKET.md CURLOPT_ERRORBUFFER.md CURLOPT_EXPECT_100_TIMEOUT_MS.md CURLOPT_FAILONERROR.md CURLOPT_FILETIME.md CURLOPT_FNMATCH_DATA.md CURLOPT_FNMATCH_FUNCTION.md CURLOPT_FOLLOWLOCATION.md CURLOPT_FORBID_REUSE.md CURLOPT_FRESH_CONNECT.md CURLOPT_FTPPORT.md CURLOPT_FTPSSLAUTH.md CURLOPT_FTP_ACCOUNT.md CURLOPT_FTP_ALTERNATIVE_TO_USER.md CURLOPT_FTP_CREATE_MISSING_DIRS.md CURLOPT_FTP_FILEMETHOD.md CURLOPT_FTP_SKIP_PASV_IP.md CURLOPT_FTP_SSL_CCC.md CURLOPT_FTP_USE_EPRT.md CURLOPT_FTP_USE_EPSV.md CURLOPT_FTP_USE_PRET.md CURLOPT_GSSAPI_DELEGATION.md CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.md CURLOPT_HAPROXYPROTOCOL.md CURLOPT_HAPROXY_CLIENT_IP.md CURLOPT_HEADER.md CURLOPT_HEADERDATA.md CURLOPT_HEADERFUNCTION.md CURLOPT_HEADEROPT.md CURLOPT_HSTS.md CURLOPT_HSTSREADDATA.md CURLOPT_HSTSREADFUNCTION.md CURLOPT_HSTSWRITEDATA.md CURLOPT_HSTSWRITEFUNCTION.md CURLOPT_HSTS_CTRL.md CURLOPT_HTTP09_ALLOWED.md CURLOPT_HTTP200ALIASES.md CURLOPT_HTTPAUTH.md CURLOPT_HTTPGET.md CURLOPT_HTTPHEADER.md CURLOPT_HTTPPOST.md CURLOPT_HTTPPROXYTUNNEL.md CURLOPT_HTTP_CONTENT_DECODING.md CURLOPT_HTTP_TRANSFER_DECODING.md CURLOPT_HTTP_VERSION.md CURLOPT_IGNORE_CONTENT_LENGTH.md CURLOPT_INFILESIZE.md CURLOPT_INFILESIZE_LARGE.md CURLOPT_INTERFACE.md CURLOPT_INTERLEAVEDATA.md CURLOPT_INTERLEAVEFUNCTION.md CURLOPT_IOCTLDATA.md CURLOPT_IOCTLFUNCTION.md CURLOPT_IPRESOLVE.md CURLOPT_ISSUERCERT.md CURLOPT_ISSUERCERT_BLOB.md CURLOPT_KEEP_SENDING_ON_ERROR.md CURLOPT_KEYPASSWD.md CURLOPT_KRBLEVEL.md CURLOPT_LOCALPORT.md CURLOPT_LOCALPORTRANGE.md CURLOPT_LOGIN_OPTIONS.md CURLOPT_LOW_SPEED_LIMIT.md CURLOPT_LOW_SPEED_TIME.md CURLOPT_MAIL_AUTH.md CURLOPT_MAIL_FROM.md CURLOPT_MAIL_RCPT.md CURLOPT_MAIL_RCPT_ALLOWFAILS.md CURLOPT_MAXAGE_CONN.md CURLOPT_MAXCONNECTS.md CURLOPT_MAXFILESIZE.md CURLOPT_MAXFILESIZE_LARGE.md CURLOPT_MAXLIFETIME_CONN.md CURLOPT_MAXREDIRS.md CURLOPT_MAX_RECV_SPEED_LARGE.md CURLOPT_MAX_SEND_SPEED_LARGE.md CURLOPT_MIMEPOST.md CURLOPT_MIME_OPTIONS.md CURLOPT_NETRC.md CURLOPT_NETRC_FILE.md CURLOPT_NEW_DIRECTORY_PERMS.md CURLOPT_NEW_FILE_PERMS.md CURLOPT_NOBODY.md CURLOPT_NOPROGRESS.md CURLOPT_NOPROXY.md CURLOPT_NOSIGNAL.md CURLOPT_OPENSOCKETDATA.md CURLOPT_OPENSOCKETFUNCTION.md CURLOPT_PASSWORD.md CURLOPT_PATH_AS_IS.md CURLOPT_PINNEDPUBLICKEY.md CURLOPT_PIPEWAIT.md CURLOPT_PORT.md CURLOPT_POST.md CURLOPT_POSTFIELDS.md CURLOPT_POSTFIELDSIZE.md CURLOPT_POSTFIELDSIZE_LARGE.md CURLOPT_POSTQUOTE.md CURLOPT_POSTREDIR.md CURLOPT_PREQUOTE.md CURLOPT_PREREQDATA.md CURLOPT_PREREQFUNCTION.md CURLOPT_PRE_PROXY.md CURLOPT_PRIVATE.md CURLOPT_PROGRESSDATA.md CURLOPT_PROGRESSFUNCTION.md CURLOPT_PROTOCOLS.md CURLOPT_PROTOCOLS_STR.md CURLOPT_PROXY.md CURLOPT_PROXYAUTH.md CURLOPT_PROXYHEADER.md CURLOPT_PROXYPASSWORD.md CURLOPT_PROXYPORT.md CURLOPT_PROXYTYPE.md CURLOPT_PROXYUSERNAME.md CURLOPT_PROXYUSERPWD.md CURLOPT_PROXY_CAINFO.md CURLOPT_PROXY_CAINFO_BLOB.md CURLOPT_PROXY_CAPATH.md CURLOPT_PROXY_CRLFILE.md CURLOPT_PROXY_ISSUERCERT.md CURLOPT_PROXY_ISSUERCERT_BLOB.md CURLOPT_PROXY_KEYPASSWD.md CURLOPT_PROXY_PINNEDPUBLICKEY.md CURLOPT_PROXY_SERVICE_NAME.md CURLOPT_PROXY_SSLCERT.md CURLOPT_PROXY_SSLCERTTYPE.md CURLOPT_PROXY_SSLCERT_BLOB.md CURLOPT_PROXY_SSLKEY.md CURLOPT_PROXY_SSLKEYTYPE.md CURLOPT_PROXY_SSLKEY_BLOB.md CURLOPT_PROXY_SSLVERSION.md CURLOPT_PROXY_SSL_CIPHER_LIST.md CURLOPT_PROXY_SSL_OPTIONS.md CURLOPT_PROXY_SSL_VERIFYHOST.md CURLOPT_PROXY_SSL_VERIFYPEER.md CURLOPT_PROXY_TLS13_CIPHERS.md CURLOPT_PROXY_TLSAUTH_PASSWORD.md CURLOPT_PROXY_TLSAUTH_TYPE.md CURLOPT_PROXY_TLSAUTH_USERNAME.md CURLOPT_PROXY_TRANSFER_MODE.md CURLOPT_PUT.md CURLOPT_QUICK_EXIT.md CURLOPT_QUOTE.md CURLOPT_RANDOM_FILE.md CURLOPT_RANGE.md CURLOPT_READDATA.md CURLOPT_READFUNCTION.md CURLOPT_REDIR_PROTOCOLS.md CURLOPT_REDIR_PROTOCOLS_STR.md CURLOPT_REFERER.md CURLOPT_REQUEST_TARGET.md CURLOPT_RESOLVE.md CURLOPT_RESOLVER_START_DATA.md CURLOPT_RESOLVER_START_FUNCTION.md CURLOPT_RESUME_FROM.md CURLOPT_RESUME_FROM_LARGE.md CURLOPT_RTSP_CLIENT_CSEQ.md CURLOPT_RTSP_REQUEST.md CURLOPT_RTSP_SERVER_CSEQ.md CURLOPT_RTSP_SESSION_ID.md CURLOPT_RTSP_STREAM_URI.md CURLOPT_RTSP_TRANSPORT.md CURLOPT_SASL_AUTHZID.md CURLOPT_SASL_IR.md CURLOPT_SEEKDATA.md CURLOPT_SEEKFUNCTION.md CURLOPT_SERVER_RESPONSE_TIMEOUT.md CURLOPT_SERVER_RESPONSE_TIMEOUT_MS.md CURLOPT_SERVICE_NAME.md CURLOPT_SHARE.md CURLOPT_SOCKOPTDATA.md CURLOPT_SOCKOPTFUNCTION.md CURLOPT_SOCKS5_AUTH.md CURLOPT_SOCKS5_GSSAPI_NEC.md CURLOPT_SOCKS5_GSSAPI_SERVICE.md CURLOPT_SSH_AUTH_TYPES.md CURLOPT_SSH_COMPRESSION.md CURLOPT_SSH_HOSTKEYDATA.md CURLOPT_SSH_HOSTKEYFUNCTION.md CURLOPT_SSH_HOST_PUBLIC_KEY_MD5.md CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256.md CURLOPT_SSH_KEYDATA.md CURLOPT_SSH_KEYFUNCTION.md CURLOPT_SSH_KNOWNHOSTS.md CURLOPT_SSH_PRIVATE_KEYFILE.md CURLOPT_SSH_PUBLIC_KEYFILE.md CURLOPT_SSLCERT.md CURLOPT_SSLCERTTYPE.md CURLOPT_SSLCERT_BLOB.md CURLOPT_SSLENGINE.md CURLOPT_SSLENGINE_DEFAULT.md CURLOPT_SSLKEY.md CURLOPT_SSLKEYTYPE.md CURLOPT_SSLKEY_BLOB.md CURLOPT_SSLVERSION.md CURLOPT_SSL_CIPHER_LIST.md CURLOPT_SSL_CTX_DATA.md CURLOPT_SSL_CTX_FUNCTION.md CURLOPT_SSL_EC_CURVES.md CURLOPT_SSL_ENABLE_ALPN.md CURLOPT_SSL_ENABLE_NPN.md CURLOPT_SSL_FALSESTART.md CURLOPT_SSL_OPTIONS.md CURLOPT_SSL_SESSIONID_CACHE.md CURLOPT_SSL_SIGNATURE_ALGORITHMS.md CURLOPT_SSL_VERIFYHOST.md CURLOPT_SSL_VERIFYPEER.md CURLOPT_SSL_VERIFYSTATUS.md CURLOPT_STDERR.md CURLOPT_STREAM_DEPENDS.md CURLOPT_STREAM_DEPENDS_E.md CURLOPT_STREAM_WEIGHT.md CURLOPT_SUPPRESS_CONNECT_HEADERS.md CURLOPT_TCP_FASTOPEN.md CURLOPT_TCP_KEEPALIVE.md CURLOPT_TCP_KEEPCNT.md CURLOPT_TCP_KEEPIDLE.md CURLOPT_TCP_KEEPINTVL.md CURLOPT_TCP_NODELAY.md CURLOPT_TELNETOPTIONS.md CURLOPT_TFTP_BLKSIZE.md CURLOPT_TFTP_NO_OPTIONS.md CURLOPT_TIMECONDITION.md CURLOPT_TIMEOUT.md CURLOPT_TIMEOUT_MS.md CURLOPT_TIMEVALUE.md CURLOPT_TIMEVALUE_LARGE.md CURLOPT_TLS13_CIPHERS.md CURLOPT_TLSAUTH_PASSWORD.md CURLOPT_TLSAUTH_TYPE.md CURLOPT_TLSAUTH_USERNAME.md CURLOPT_TRAILERDATA.md CURLOPT_TRAILERFUNCTION.md CURLOPT_TRANSFERTEXT.md CURLOPT_TRANSFER_ENCODING.md CURLOPT_UNIX_SOCKET_PATH.md CURLOPT_UNRESTRICTED_AUTH.md CURLOPT_UPKEEP_INTERVAL_MS.md CURLOPT_UPLOAD.md CURLOPT_UPLOAD_BUFFERSIZE.md CURLOPT_UPLOAD_FLAGS.md CURLOPT_URL.md CURLOPT_USERAGENT.md CURLOPT_USERNAME.md CURLOPT_USERPWD.md CURLOPT_USE_SSL.md CURLOPT_VERBOSE.md CURLOPT_WILDCARDMATCH.md CURLOPT_WRITEDATA.md CURLOPT_WRITEFUNCTION.md CURLOPT_WS_OPTIONS.md CURLOPT_XFERINFODATA.md CURLOPT_XFERINFOFUNCTION.md CURLOPT_XOAUTH2_BEARER.md CURLSHOPT_LOCKFUNC.md CURLSHOPT_SHARE.md CURLSHOPT_UNLOCKFUNC.md CURLSHOPT_UNSHARE.md CURLSHOPT_USERDATA.md Makefile.am Makefile.inc
.gitignore ABI.md CMakeLists.txt Makefile.am Makefile.inc curl_easy_cleanup.md curl_easy_duphandle.md curl_easy_escape.md curl_easy_getinfo.md curl_easy_header.md curl_easy_init.md curl_easy_nextheader.md curl_easy_option_by_id.md curl_easy_option_by_name.md curl_easy_option_next.md curl_easy_pause.md curl_easy_perform.md curl_easy_recv.md curl_easy_reset.md curl_easy_send.md curl_easy_setopt.md curl_easy_ssls_export.md curl_easy_ssls_import.md curl_easy_strerror.md curl_easy_unescape.md curl_easy_upkeep.md curl_escape.md curl_formadd.md curl_formfree.md curl_formget.md curl_free.md curl_getdate.md curl_getenv.md curl_global_cleanup.md curl_global_init.md curl_global_init_mem.md curl_global_sslset.md curl_global_trace.md curl_mime_addpart.md curl_mime_data.md curl_mime_data_cb.md curl_mime_encoder.md curl_mime_filedata.md curl_mime_filename.md curl_mime_free.md curl_mime_headers.md curl_mime_init.md curl_mime_name.md curl_mime_subparts.md curl_mime_type.md curl_mprintf.md curl_multi_add_handle.md curl_multi_assign.md curl_multi_cleanup.md curl_multi_fdset.md curl_multi_get_handles.md curl_multi_get_offt.md curl_multi_info_read.md curl_multi_init.md curl_multi_notify_disable.md curl_multi_notify_enable.md curl_multi_perform.md curl_multi_poll.md curl_multi_remove_handle.md curl_multi_setopt.md curl_multi_socket.md curl_multi_socket_action.md curl_multi_socket_all.md curl_multi_strerror.md curl_multi_timeout.md curl_multi_wait.md curl_multi_waitfds.md curl_multi_wakeup.md curl_pushheader_byname.md curl_pushheader_bynum.md curl_share_cleanup.md curl_share_init.md curl_share_setopt.md curl_share_strerror.md curl_slist_append.md curl_slist_free_all.md curl_strequal.md curl_strnequal.md curl_unescape.md curl_url.md curl_url_cleanup.md curl_url_dup.md curl_url_get.md curl_url_set.md curl_url_strerror.md curl_version.md curl_version_info.md curl_ws_meta.md curl_ws_recv.md curl_ws_send.md curl_ws_start_frame.md libcurl-easy.md libcurl-env-dbg.md libcurl-env.md libcurl-errors.md libcurl-multi.md libcurl-security.md libcurl-share.md libcurl-thread.md libcurl-tutorial.md libcurl-url.md libcurl-ws.md libcurl.m4 libcurl.md mksymbolsmanpage.pl symbols-in-versions symbols.pl
tests CI.md FILEFORMAT.md HTTP.md TEST-SUITE.md
.gitignore ALTSVC.md BINDINGS.md BUG-BOUNTY.md BUGS.md CIPHERS-TLS12.md CIPHERS.md CMakeLists.txt CODE_OF_CONDUCT.md CODE_REVIEW.md CONTRIBUTE.md CURL-DISABLE.md CURLDOWN.md DEPRECATE.md DISTROS.md EARLY-RELEASE.md ECH.md EXPERIMENTAL.md FAQ.md FEATURES.md GOVERNANCE.md HELP-US.md HISTORY.md HSTS.md HTTP-COOKIES.md HTTP3.md HTTPSRR.md INFRASTRUCTURE.md INSTALL-CMAKE.md INSTALL.md INTERNALS.md IPFS.md KNOWN_BUGS.md KNOWN_RISKS.md MAIL-ETIQUETTE.md MANUAL.md Makefile.am README.md RELEASE-PROCEDURE.md ROADMAP.md RUSTLS.md SECURITY-ADVISORY.md SPONSORS.md SSL-PROBLEMS.md SSLCERTS.md THANKS THANKS-filter TODO.md TheArtOfHttpScripting.md URL-SYNTAX.md VERIFY.md VERSIONS.md VULN-DISCLOSURE-POLICY.md curl-config.md mk-ca-bundle.md options-in-versions runtests.md testcurl.md wcurl.md
include
curl Makefile.am curl.h curlver.h easy.h header.h mprintf.h multi.h options.h stdcheaders.h system.h typecheck-gcc.h urlapi.h websockets.h
Makefile.am README.md
lib
curlx base64.c base64.h basename.c basename.h dynbuf.c dynbuf.h fopen.c fopen.h inet_ntop.c inet_ntop.h inet_pton.c inet_pton.h multibyte.c multibyte.h nonblock.c nonblock.h snprintf.c snprintf.h strcopy.c strcopy.h strdup.c strdup.h strerr.c strerr.h strparse.c strparse.h timediff.c timediff.h timeval.c timeval.h version_win32.c version_win32.h wait.c wait.h warnless.c warnless.h winapi.c winapi.h
vauth cleartext.c cram.c digest.c digest.h digest_sspi.c gsasl.c krb5_gssapi.c krb5_sspi.c ntlm.c ntlm_sspi.c oauth2.c spnego_gssapi.c spnego_sspi.c vauth.c vauth.h
vquic curl_ngtcp2.c curl_ngtcp2.h curl_quiche.c curl_quiche.h vquic-tls.c vquic-tls.h vquic.c vquic.h vquic_int.h
vssh libssh.c libssh2.c ssh.h vssh.c vssh.h
vtls apple.c apple.h cipher_suite.c cipher_suite.h gtls.c gtls.h hostcheck.c hostcheck.h keylog.c keylog.h mbedtls.c mbedtls.h openssl.c openssl.h rustls.c rustls.h schannel.c schannel.h schannel_int.h schannel_verify.c vtls.c vtls.h vtls_int.h vtls_scache.c vtls_scache.h vtls_spack.c vtls_spack.h wolfssl.c wolfssl.h x509asn1.c x509asn1.h
.gitignore CMakeLists.txt Makefile.am Makefile.inc Makefile.soname altsvc.c altsvc.h amigaos.c amigaos.h arpa_telnet.h asyn-ares.c asyn-base.c asyn-thrdd.c asyn.h bufq.c bufq.h bufref.c bufref.h cf-dns.c cf-dns.h cf-h1-proxy.c cf-h1-proxy.h cf-h2-proxy.c cf-h2-proxy.h cf-haproxy.c cf-haproxy.h cf-https-connect.c cf-https-connect.h cf-ip-happy.c cf-ip-happy.h cf-socket.c cf-socket.h cfilters.c cfilters.h config-mac.h config-os400.h config-riscos.h config-win32.h conncache.c conncache.h connect.c connect.h content_encoding.c content_encoding.h cookie.c cookie.h creds.c creds.h cshutdn.c cshutdn.h curl_addrinfo.c curl_addrinfo.h curl_config-cmake.h.in curl_ctype.h curl_endian.c curl_endian.h curl_fnmatch.c curl_fnmatch.h curl_fopen.c curl_fopen.h curl_get_line.c curl_get_line.h curl_gethostname.c curl_gethostname.h curl_gssapi.c curl_gssapi.h curl_hmac.h curl_ldap.h curl_md4.h curl_md5.h curl_memrchr.c curl_memrchr.h curl_ntlm_core.c curl_ntlm_core.h curl_printf.h curl_range.c curl_range.h curl_sasl.c curl_sasl.h curl_setup.h curl_sha256.h curl_sha512_256.c curl_sha512_256.h curl_share.c curl_share.h curl_sspi.c curl_sspi.h curl_threads.c curl_threads.h curl_trc.c curl_trc.h cw-out.c cw-out.h cw-pause.c cw-pause.h dict.c dict.h dllmain.c dnscache.c dnscache.h doh.c doh.h dynhds.c dynhds.h easy.c easy_lock.h easygetopt.c easyif.h easyoptions.c easyoptions.h escape.c escape.h fake_addrinfo.c fake_addrinfo.h file.c file.h fileinfo.c fileinfo.h formdata.c formdata.h ftp-int.h ftp.c ftp.h ftplistparser.c ftplistparser.h functypes.h getenv.c getinfo.c getinfo.h gopher.c gopher.h hash.c hash.h headers.c headers.h hmac.c hostip.c hostip.h hostip4.c hostip6.c hsts.c hsts.h http.c http.h http1.c http1.h http2.c http2.h http_aws_sigv4.c http_aws_sigv4.h http_chunks.c http_chunks.h http_digest.c http_digest.h http_negotiate.c http_negotiate.h http_ntlm.c http_ntlm.h http_proxy.c http_proxy.h httpsrr.c httpsrr.h idn.c idn.h if2ip.c if2ip.h imap.c imap.h ldap.c libcurl.def libcurl.rc libcurl.vers.in llist.c llist.h macos.c macos.h md4.c md5.c memdebug.c mime.c mime.h mprintf.c mqtt.c mqtt.h multi.c multi_ev.c multi_ev.h multi_ntfy.c multi_ntfy.h multihandle.h multiif.h netrc.c netrc.h noproxy.c noproxy.h openldap.c optiontable.pl parsedate.c parsedate.h peer.c peer.h pingpong.c pingpong.h pop3.c pop3.h progress.c progress.h protocol.c protocol.h psl.c psl.h rand.c rand.h ratelimit.c ratelimit.h request.c request.h rtsp.c rtsp.h select.c select.h sendf.c sendf.h setopt.c setopt.h setup-os400.h setup-vms.h setup-win32.h sha256.c sigpipe.h slist.c slist.h smb.c smb.h smtp.c smtp.h sockaddr.h socketpair.c socketpair.h socks.c socks.h socks_gssapi.c socks_sspi.c splay.c splay.h strcase.c strcase.h strequal.c strerror.c strerror.h system_win32.c system_win32.h telnet.c telnet.h tftp.c tftp.h thrdpool.c thrdpool.h thrdqueue.c thrdqueue.h transfer.c transfer.h uint-bset.c uint-bset.h uint-hash.c uint-hash.h uint-spbset.c uint-spbset.h uint-table.c uint-table.h url.c url.h urlapi-int.h urlapi.c urldata.h version.c ws.c ws.h
m4 .gitignore curl-amissl.m4 curl-apple-sectrust.m4 curl-compilers.m4 curl-confopts.m4 curl-functions.m4 curl-gnutls.m4 curl-mbedtls.m4 curl-openssl.m4 curl-override.m4 curl-reentrant.m4 curl-rustls.m4 curl-schannel.m4 curl-sysconfig.m4 curl-wolfssl.m4 xc-am-iface.m4 xc-cc-check.m4 xc-lt-iface.m4 xc-val-flgs.m4 zz40-xc-ovr.m4 zz50-xc-ovr.m4
projects
OS400
rpg-examples HEADERAPI HTTPPOST INMEMORY SIMPLE1 SIMPLE2 SMTPSRCMBR
.checksrc README.OS400 ccsidcurl.c ccsidcurl.h config400.default curl.cmd curl.inc.in curlcl.c curlmain.c initscript.sh make-docs.sh make-include.sh make-lib.sh make-src.sh make-tests.sh makefile.sh os400sys.c os400sys.h
Windows
tmpl .gitattributes README.txt curl-all.sln curl.sln curl.vcxproj curl.vcxproj.filters libcurl.sln libcurl.vcxproj libcurl.vcxproj.filters
.gitignore README.md generate.bat
vms Makefile.am backup_gnv_curl_src.com build_curl-config_script.com build_gnv_curl.com build_gnv_curl_pcsi_desc.com build_gnv_curl_pcsi_text.com build_gnv_curl_release_notes.com build_libcurl_pc.com build_vms.com clean_gnv_curl.com compare_curl_source.com config_h.com curl_crtl_init.c curl_gnv_build_steps.txt curl_release_note_start.txt curl_startup.com curlmsg.h curlmsg.msg curlmsg.sdl curlmsg_vms.h generate_config_vms_h_curl.com generate_vax_transfer.com gnv_conftest.c_first gnv_curl_configure.sh gnv_libcurl_symbols.opt gnv_link_curl.com macro32_exactcase.patch make_gnv_curl_install.sh make_pcsi_curl_kit_name.com pcsi_gnv_curl_file_list.txt pcsi_product_gnv_curl.com readme report_openssl_version.c setup_gnv_curl_build.com stage_curl_install.com vms_eco_level.h
Makefile.am README.md
scripts .checksrc CMakeLists.txt Makefile.am badwords badwords-all badwords.txt cd2cd cd2nroff cdall checksrc-all.pl checksrc.pl cmakelint.sh completion.pl contributors.sh contrithanks.sh coverage.sh delta dmaketgz extract-unit-protos firefox-db2pem.sh installcheck.sh maketgz managen mdlinkcheck mk-ca-bundle.pl mk-unity.pl nroff2cd perlcheck.sh pythonlint.sh randdisable release-notes.pl release-tools.sh schemetable.c singleuse.pl spacecheck.pl top-complexity top-length verify-release wcurl
src
toolx tool_time.c tool_time.h
.checksrc .gitignore CMakeLists.txt Makefile.am Makefile.inc config2setopts.c config2setopts.h curl.rc curlinfo.c mk-file-embed.pl mkhelp.pl slist_wc.c slist_wc.h terminal.c terminal.h tool_cb_dbg.c tool_cb_dbg.h tool_cb_hdr.c tool_cb_hdr.h tool_cb_prg.c tool_cb_prg.h tool_cb_rea.c tool_cb_rea.h tool_cb_see.c tool_cb_see.h tool_cb_soc.c tool_cb_soc.h tool_cb_wrt.c tool_cb_wrt.h tool_cfgable.c tool_cfgable.h tool_dirhie.c tool_dirhie.h tool_doswin.c tool_doswin.h tool_easysrc.c tool_easysrc.h tool_filetime.c tool_filetime.h tool_findfile.c tool_findfile.h tool_formparse.c tool_formparse.h tool_getparam.c tool_getparam.h tool_getpass.c tool_getpass.h tool_help.c tool_help.h tool_helpers.c tool_helpers.h tool_hugehelp.h tool_ipfs.c tool_ipfs.h tool_libinfo.c tool_libinfo.h tool_listhelp.c tool_main.c tool_main.h tool_msgs.c tool_msgs.h tool_operate.c tool_operate.h tool_operhlp.c tool_operhlp.h tool_paramhlp.c tool_paramhlp.h tool_parsecfg.c tool_parsecfg.h tool_progress.c tool_progress.h tool_sdecls.h tool_setopt.c tool_setopt.h tool_setup.h tool_ssls.c tool_ssls.h tool_stderr.c tool_stderr.h tool_urlglob.c tool_urlglob.h tool_util.c tool_util.h tool_version.h tool_vms.c tool_vms.h tool_writeout.c tool_writeout.h tool_writeout_json.c tool_writeout_json.h tool_xattr.c tool_xattr.h var.c var.h
tests
certs .gitignore CMakeLists.txt Makefile.am Makefile.inc genserv.pl srp-verifier-conf srp-verifier-db test-ca.cnf test-ca.prm test-client-cert.prm test-client-eku-only.prm test-localhost-san-first.prm test-localhost-san-last.prm test-localhost.nn.prm test-localhost.prm test-localhost0h.prm
cmake CMakeLists.txt test.c test.cpp test.sh
data .gitignore DISABLED Makefile.am data-xml1 data1400.c data1401.c data1402.c data1403.c data1404.c data1405.c data1406.c data1407.c data1420.c data1461.txt data1463.txt data1465.c data1481.c data1705-1.md data1705-2.md data1705-3.md data1705-4.md data1705-stdout.1 data1706-1.md data1706-2.md data1706-3.md data1706-4.md data1706-stdout.txt data320.html test1 test10 test100 test1000 test1001 test1002 test1003 test1004 test1005 test1006 test1007 test1008 test1009 test101 test1010 test1011 test1012 test1013 test1014 test1015 test1016 test1017 test1018 test1019 test102 test1020 test1021 test1022 test1023 test1024 test1025 test1026 test1027 test1028 test1029 test103 test1030 test1031 test1032 test1033 test1034 test1035 test1036 test1037 test1038 test1039 test104 test1040 test1041 test1042 test1043 test1044 test1045 test1046 test1047 test1048 test1049 test105 test1050 test1051 test1052 test1053 test1054 test1055 test1056 test1057 test1058 test1059 test106 test1060 test1061 test1062 test1063 test1064 test1065 test1066 test1067 test1068 test1069 test107 test1070 test1071 test1072 test1073 test1074 test1075 test1076 test1077 test1078 test1079 test108 test1080 test1081 test1082 test1083 test1084 test1085 test1086 test1087 test1088 test1089 test109 test1090 test1091 test1092 test1093 test1094 test1095 test1096 test1097 test1098 test1099 test11 test110 test1100 test1101 test1102 test1103 test1104 test1105 test1106 test1107 test1108 test1109 test111 test1110 test1111 test1112 test1113 test1114 test1115 test1116 test1117 test1118 test1119 test112 test1120 test1121 test1122 test1123 test1124 test1125 test1126 test1127 test1128 test1129 test113 test1130 test1131 test1132 test1133 test1134 test1135 test1136 test1137 test1138 test1139 test114 test1140 test1141 test1142 test1143 test1144 test1145 test1146 test1147 test1148 test1149 test115 test1150 test1151 test1152 test1153 test1154 test1155 test1156 test1157 test1158 test1159 test116 test1160 test1161 test1162 test1163 test1164 test1165 test1166 test1167 test1168 test1169 test117 test1170 test1171 test1172 test1173 test1174 test1175 test1176 test1177 test1178 test1179 test118 test1180 test1181 test1182 test1183 test1184 test1185 test1186 test1187 test1188 test1189 test119 test1190 test1191 test1192 test1193 test1194 test1195 test1196 test1197 test1198 test1199 test12 test120 test1200 test1201 test1202 test1203 test1204 test1205 test1206 test1207 test1208 test1209 test121 test1210 test1211 test1212 test1213 test1214 test1215 test1216 test1217 test1218 test1219 test122 test1220 test1221 test1222 test1223 test1224 test1225 test1226 test1227 test1228 test1229 test123 test1230 test1231 test1232 test1233 test1234 test1235 test1236 test1237 test1238 test1239 test124 test1240 test1241 test1242 test1243 test1244 test1245 test1246 test1247 test1248 test1249 test125 test1250 test1251 test1252 test1253 test1254 test1255 test1256 test1257 test1258 test1259 test126 test1260 test1261 test1262 test1263 test1264 test1265 test1266 test1267 test1268 test1269 test127 test1270 test1271 test1272 test1273 test1274 test1275 test1276 test1277 test1278 test1279 test128 test1280 test1281 test1282 test1283 test1284 test1285 test1286 test1287 test1288 test1289 test129 test1290 test1291 test1292 test1293 test1294 test1295 test1296 test1297 test1298 test1299 test13 test130 test1300 test1301 test1302 test1303 test1304 test1305 test1306 test1307 test1308 test1309 test131 test1310 test1311 test1312 test1313 test1314 test1315 test1316 test1317 test1318 test1319 test132 test1320 test1321 test1322 test1323 test1324 test1325 test1326 test1327 test1328 test1329 test133 test1330 test1331 test1332 test1333 test1334 test1335 test1336 test1337 test1338 test1339 test134 test1340 test1341 test1342 test1343 test1344 test1345 test1346 test1347 test1348 test1349 test135 test1350 test1351 test1352 test1353 test1354 test1355 test1356 test1357 test1358 test1359 test136 test1360 test1361 test1362 test1363 test1364 test1365 test1366 test1367 test1368 test1369 test137 test1370 test1371 test1372 test1373 test1374 test1375 test1376 test1377 test1378 test1379 test138 test1380 test1381 test1382 test1383 test1384 test1385 test1386 test1387 test1388 test1389 test139 test1390 test1391 test1392 test1393 test1394 test1395 test1396 test1397 test1398 test1399 test14 test140 test1400 test1401 test1402 test1403 test1404 test1405 test1406 test1407 test1408 test1409 test141 test1410 test1411 test1412 test1413 test1414 test1415 test1416 test1417 test1418 test1419 test142 test1420 test1421 test1422 test1423 test1424 test1425 test1426 test1427 test1428 test1429 test143 test1430 test1431 test1432 test1433 test1434 test1435 test1436 test1437 test1438 test1439 test144 test1440 test1441 test1442 test1443 test1444 test1445 test1446 test1447 test1448 test1449 test145 test1450 test1451 test1452 test1453 test1454 test1455 test1456 test1457 test1458 test1459 test146 test1460 test1461 test1462 test1463 test1464 test1465 test1466 test1467 test1468 test1469 test147 test1470 test1471 test1472 test1473 test1474 test1475 test1476 test1477 test1478 test1479 test148 test1480 test1481 test1482 test1483 test1484 test1485 test1486 test1487 test1488 test1489 test149 test1490 test1491 test1492 test1493 test1494 test1495 test1496 test1497 test1498 test1499 test15 test150 test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 test1508 test1509 test151 test1510 test1511 test1512 test1513 test1514 test1515 test1516 test1517 test1518 test1519 test152 test1520 test1521 test1522 test1523 test1524 test1525 test1526 test1527 test1528 test1529 test153 test1530 test1531 test1532 test1533 test1534 test1535 test1536 test1537 test1538 test1539 test154 test1540 test1541 test1542 test1543 test1544 test1545 test1546 test1547 test1548 test1549 test155 test1550 test1551 test1552 test1553 test1554 test1555 test1556 test1557 test1558 test1559 test156 test1560 test1561 test1562 test1563 test1564 test1565 test1566 test1567 test1568 test1569 test157 test1570 test1571 test1572 test1573 test1574 test1575 test1576 test1577 test1578 test1579 test158 test1580 test1581 test1582 test1583 test1584 test1585 test1586 test1587 test1588 test1589 test159 test1590 test1591 test1592 test1593 test1594 test1595 test1596 test1597 test1598 test1599 test16 test160 test1600 test1601 test1602 test1603 test1604 test1605 test1606 test1607 test1608 test1609 test161 test1610 test1611 test1612 test1613 test1614 test1615 test1616 test1617 test1618 test1619 test162 test1620 test1621 test1622 test1623 test1624 test1625 test1626 test1627 test1628 test1629 test163 test1630 test1631 test1632 test1633 test1634 test1635 test1636 test1637 test1638 test1639 test164 test1640 test1641 test1642 test1643 test1644 test1645 test165 test1650 test1651 test1652 test1653 test1654 test1655 test1656 test1657 test1658 test1659 test166 test1660 test1661 test1662 test1663 test1664 test1665 test1666 test1667 test1668 test1669 test167 test1670 test1671 test1672 test1673 test1674 test1675 test1676 test168 test1680 test1681 test1682 test1683 test1684 test1685 test169 test17 test170 test1700 test1701 test1702 test1703 test1704 test1705 test1706 test1707 test1708 test1709 test171 test1710 test1711 test1712 test1713 test1714 test1715 test172 test1720 test1721 test173 test174 test175 test176 test177 test178 test179 test18 test180 test1800 test1801 test1802 test181 test182 test183 test184 test1847 test1848 test1849 test185 test1850 test1851 test186 test187 test188 test189 test19 test190 test1900 test1901 test1902 test1903 test1904 test1905 test1906 test1907 test1908 test1909 test191 test1910 test1911 test1912 test1913 test1914 test1915 test1916 test1917 test1918 test1919 test192 test1920 test1921 test193 test1933 test1934 test1935 test1936 test1937 test1938 test1939 test194 test1940 test1941 test1942 test1943 test1944 test1945 test1946 test1947 test1948 test195 test1955 test1956 test1957 test1958 test1959 test196 test1960 test1964 test1965 test1966 test197 test1970 test1971 test1972 test1973 test1974 test1975 test1976 test1977 test1978 test1979 test198 test1980 test1981 test1982 test1983 test1984 test199 test2 test20 test200 test2000 test2001 test2002 test2003 test2004 test2005 test2006 test2007 test2008 test2009 test201 test2010 test2011 test2012 test2013 test2014 test202 test2023 test2024 test2025 test2026 test2027 test2028 test2029 test203 test2030 test2031 test2032 test2033 test2034 test2035 test2037 test2038 test2039 test204 test2040 test2041 test2042 test2043 test2044 test2045 test2046 test2047 test2048 test2049 test205 test2050 test2051 test2052 test2053 test2054 test2055 test2056 test2057 test2058 test2059 test206 test2060 test2061 test2062 test2063 test2064 test2065 test2066 test2067 test2068 test2069 test207 test2070 test2071 test2072 test2073 test2074 test2075 test2076 test2077 test2078 test2079 test208 test2080 test2081 test2082 test2083 test2084 test2085 test2086 test2087 test2088 test2089 test209 test2090 test2091 test2092 test21 test210 test2100 test2101 test2102 test2103 test2104 test211 test212 test213 test214 test215 test216 test217 test218 test219 test22 test220 test2200 test2201 test2202 test2203 test2204 test2205 test2206 test2207 test221 test222 test223 test224 test225 test226 test227 test228 test229 test23 test230 test2300 test2301 test2302 test2303 test2304 test2306 test2307 test2308 test2309 test231 test232 test233 test234 test235 test236 test237 test238 test239 test24 test240 test2400 test2401 test2402 test2403 test2404 test2405 test2406 test2407 test2408 test2409 test241 test2410 test2411 test242 test243 test244 test245 test246 test247 test248 test249 test25 test250 test2500 test2501 test2502 test2503 test2504 test2505 test2506 test251 test252 test253 test254 test255 test256 test257 test258 test259 test26 test260 test2600 test2601 test2602 test2603 test2604 test2605 test261 test262 test263 test264 test265 test266 test267 test268 test269 test27 test270 test2700 test2701 test2702 test2703 test2704 test2705 test2706 test2707 test2708 test2709 test271 test2710 test2711 test2712 test2713 test2714 test2715 test2716 test2717 test2718 test2719 test272 test2720 test2721 test2722 test2723 test273 test274 test275 test276 test277 test278 test279 test28 test280 test281 test282 test283 test284 test285 test286 test287 test288 test289 test29 test290 test291 test292 test293 test294 test295 test296 test297 test298 test299 test3 test30 test300 test3000 test3001 test3002 test3003 test3004 test3005 test3006 test3007 test3008 test3009 test301 test3010 test3011 test3012 test3013 test3014 test3015 test3016 test3017 test3018 test3019 test302 test3020 test3021 test3022 test3023 test3024 test3025 test3026 test3027 test3028 test3029 test303 test3030 test3031 test3032 test3033 test3034 test3035 test3036 test304 test305 test306 test307 test308 test309 test31 test310 test3100 test3101 test3102 test3103 test3104 test3105 test3106 test311 test312 test313 test314 test315 test316 test317 test318 test319 test32 test320 test3200 test3201 test3202 test3203 test3204 test3205 test3206 test3207 test3208 test3209 test321 test3210 test3211 test3212 test3213 test3214 test3215 test3216 test3217 test3218 test3219 test322 test3220 test323 test324 test325 test326 test327 test328 test329 test33 test330 test3300 test3301 test3302 test331 test332 test333 test334 test335 test336 test337 test338 test339 test34 test340 test341 test342 test343 test344 test345 test346 test347 test348 test349 test35 test350 test351 test352 test353 test354 test355 test356 test357 test358 test359 test36 test360 test361 test362 test363 test364 test365 test366 test367 test368 test369 test37 test370 test371 test372 test373 test374 test375 test376 test378 test379 test38 test380 test381 test383 test384 test385 test386 test387 test388 test389 test39 test390 test391 test392 test393 test394 test395 test396 test397 test398 test399 test4 test40 test400 test4000 test4001 test401 test402 test403 test404 test405 test406 test407 test408 test409 test41 test410 test411 test412 test413 test414 test415 test416 test417 test418 test419 test42 test420 test421 test422 test423 test424 test425 test426 test427 test428 test429 test43 test430 test431 test432 test433 test434 test435 test436 test437 test438 test439 test44 test440 test441 test442 test443 test444 test445 test446 test447 test448 test449 test45 test450 test451 test452 test453 test454 test455 test456 test457 test458 test459 test46 test460 test461 test462 test463 test467 test468 test469 test47 test470 test471 test472 test473 test474 test475 test476 test477 test478 test479 test48 test480 test481 test482 test483 test484 test485 test486 test487 test488 test489 test49 test490 test491 test492 test493 test494 test495 test496 test497 test498 test499 test5 test50 test500 test501 test502 test503 test504 test505 test506 test507 test508 test509 test51 test510 test511 test512 test513 test514 test515 test516 test517 test518 test519 test52 test520 test521 test522 test523 test524 test525 test526 test527 test528 test529 test53 test530 test531 test532 test533 test534 test535 test536 test537 test538 test539 test54 test540 test541 test542 test543 test544 test545 test546 test547 test548 test549 test55 test550 test551 test552 test553 test554 test555 test556 test557 test558 test559 test56 test560 test561 test562 test563 test564 test565 test566 test567 test568 test569 test57 test570 test571 test572 test573 test574 test575 test576 test577 test578 test579 test58 test580 test581 test582 test583 test584 test585 test586 test587 test588 test589 test59 test590 test591 test592 test593 test594 test595 test596 test597 test598 test599 test6 test60 test600 test601 test602 test603 test604 test605 test606 test607 test608 test609 test61 test610 test611 test612 test613 test614 test615 test616 test617 test618 test619 test62 test620 test621 test622 test623 test624 test625 test626 test627 test628 test629 test63 test630 test631 test632 test633 test634 test635 test636 test637 test638 test639 test64 test640 test641 test642 test643 test644 test645 test646 test647 test648 test649 test65 test650 test651 test652 test653 test654 test655 test656 test658 test659 test66 test660 test661 test662 test663 test664 test665 test666 test667 test668 test669 test67 test670 test671 test672 test673 test674 test675 test676 test677 test678 test679 test68 test680 test681 test682 test683 test684 test685 test686 test687 test688 test689 test69 test690 test691 test692 test693 test694 test695 test696 test697 test698 test699 test7 test70 test700 test701 test702 test703 test704 test705 test706 test707 test708 test709 test71 test710 test711 test712 test713 test714 test715 test716 test717 test718 test719 test72 test720 test721 test722 test723 test724 test725 test726 test727 test728 test729 test73 test730 test731 test732 test733 test734 test735 test736 test737 test738 test739 test74 test740 test741 test742 test743 test744 test745 test746 test747 test748 test749 test75 test750 test751 test752 test753 test754 test755 test756 test757 test758 test759 test76 test760 test761 test762 test763 test764 test765 test766 test767 test768 test769 test77 test770 test771 test772 test773 test774 test775 test776 test777 test778 test779 test78 test780 test781 test782 test783 test784 test785 test786 test787 test788 test789 test79 test790 test791 test792 test793 test794 test795 test796 test797 test798 test799 test8 test80 test800 test801 test802 test803 test804 test805 test806 test807 test808 test809 test81 test810 test811 test812 test813 test814 test815 test816 test817 test818 test819 test82 test820 test821 test822 test823 test824 test825 test826 test827 test828 test829 test83 test830 test831 test832 test833 test834 test835 test836 test837 test838 test839 test84 test840 test841 test842 test843 test844 test845 test846 test847 test848 test849 test85 test850 test851 test852 test853 test854 test855 test856 test857 test858 test859 test86 test860 test861 test862 test863 test864 test865 test866 test867 test868 test869 test87 test870 test871 test872 test873 test874 test875 test876 test877 test878 test879 test88 test880 test881 test882 test883 test884 test885 test886 test887 test888 test889 test89 test890 test891 test892 test893 test894 test895 test896 test897 test898 test899 test9 test90 test900 test901 test902 test903 test904 test905 test906 test907 test908 test909 test91 test910 test911 test912 test913 test914 test915 test916 test917 test918 test919 test92 test920 test921 test922 test923 test924 test925 test926 test927 test928 test929 test93 test930 test931 test932 test933 test934 test935 test936 test937 test938 test939 test94 test940 test941 test942 test943 test944 test945 test946 test947 test948 test949 test95 test950 test951 test952 test953 test954 test955 test956 test957 test958 test959 test96 test960 test961 test962 test963 test964 test965 test966 test967 test968 test969 test97 test970 test971 test972 test973 test974 test975 test976 test977 test978 test979 test98 test980 test981 test982 test983 test984 test985 test986 test987 test988 test989 test99 test990 test991 test992 test993 test994 test995 test996 test997 test998 test999
http
testenv
mod_curltest .gitignore mod_curltest.c
__init__.py caddy.py certs.py client.py curl.py dante.py dnsd.py env.py httpd.py nghttpx.py ports.py sshd.py vsftpd.py ws_echo_server.py
.gitignore CMakeLists.txt Makefile.am config.ini.in conftest.py requirements.txt scorecard.py test_01_basic.py test_02_download.py test_03_goaway.py test_04_stuttered.py test_05_errors.py test_06_eyeballs.py test_07_upload.py test_08_caddy.py test_09_push.py test_10_proxy.py test_11_unix.py test_12_reuse.py test_13_proxy_auth.py test_14_auth.py test_15_tracing.py test_16_info.py test_17_ssl_use.py test_18_methods.py test_19_shutdown.py test_20_websockets.py test_21_resolve.py test_22_httpsrr.py test_30_vsftpd.py test_31_vsftpds.py test_32_ftps_vsftpd.py test_40_socks.py test_50_scp.py test_51_sftp.py
libtest .gitignore CMakeLists.txt Makefile.am Makefile.inc cli_ftp_upload.c cli_h2_pausing.c cli_h2_serverpush.c cli_h2_upgrade_extreme.c cli_hx_download.c cli_hx_upload.c cli_tls_session_reuse.c cli_upload_pausing.c cli_ws_data.c cli_ws_pingpong.c first.c first.h lib1156.c lib1301.c lib1308.c lib1485.c lib1500.c lib1501.c lib1502.c lib1506.c lib1507.c lib1508.c lib1509.c lib1510.c lib1511.c lib1512.c lib1513.c lib1514.c lib1515.c lib1517.c lib1518.c lib1520.c lib1522.c lib1523.c lib1525.c lib1526.c lib1527.c lib1528.c lib1529.c lib1530.c lib1531.c lib1532.c lib1533.c lib1534.c lib1535.c lib1536.c lib1537.c lib1538.c lib1540.c lib1541.c lib1542.c lib1545.c lib1549.c lib1550.c lib1551.c lib1552.c lib1553.c lib1554.c lib1555.c lib1556.c lib1557.c lib1558.c lib1559.c lib1560.c lib1564.c lib1565.c lib1567.c lib1568.c lib1569.c lib1571.c lib1576.c lib1582.c lib1587.c lib1588.c lib1589.c lib1591.c lib1592.c lib1593.c lib1594.c lib1597.c lib1598.c lib1599.c lib1662.c lib1900.c lib1901.c lib1902.c lib1903.c lib1905.c lib1906.c lib1907.c lib1908.c lib1910.c lib1911.c lib1912.c lib1913.c lib1915.c lib1916.c lib1918.c lib1919.c lib1920.c lib1921.c lib1933.c lib1934.c lib1935.c lib1936.c lib1937.c lib1938.c lib1939.c lib1940.c lib1945.c lib1947.c lib1948.c lib1955.c lib1956.c lib1957.c lib1958.c lib1959.c lib1960.c lib1964.c lib1965.c lib1970.c lib1971.c lib1972.c lib1973.c lib1974.c lib1975.c lib1977.c lib1978.c lib2023.c lib2032.c lib2082.c lib2301.c lib2302.c lib2304.c lib2306.c lib2308.c lib2309.c lib2402.c lib2404.c lib2405.c lib2502.c lib2504.c lib2505.c lib2506.c lib2700.c lib3010.c lib3025.c lib3026.c lib3027.c lib3033.c lib3034.c lib3100.c lib3101.c lib3102.c lib3103.c lib3104.c lib3105.c lib3207.c lib3208.c lib500.c lib501.c lib502.c lib503.c lib504.c lib505.c lib506.c lib507.c lib508.c lib509.c lib510.c lib511.c lib512.c lib513.c lib514.c lib515.c lib516.c lib517.c lib518.c lib519.c lib520.c lib521.c lib523.c lib524.c lib525.c lib526.c lib530.c lib533.c lib536.c lib537.c lib539.c lib540.c lib541.c lib542.c lib543.c lib544.c lib547.c lib549.c lib552.c lib553.c lib554.c lib555.c lib556.c lib557.c lib558.c lib559.c lib560.c lib562.c lib564.c lib566.c lib567.c lib568.c lib569.c lib570.c lib571.c lib572.c lib573.c lib574.c lib575.c lib576.c lib578.c lib579.c lib582.c lib583.c lib586.c lib589.c lib590.c lib591.c lib597.c lib598.c lib599.c lib643.c lib650.c lib651.c lib652.c lib653.c lib654.c lib655.c lib658.c lib659.c lib661.c lib666.c lib667.c lib668.c lib670.c lib674.c lib676.c lib677.c lib678.c lib694.c lib695.c lib751.c lib753.c lib757.c lib758.c lib766.c memptr.c mk-lib1521.pl test1013.pl test1022.pl test307.pl test610.pl test613.pl testtrace.c testtrace.h testutil.c testutil.h unitcheck.h
server .checksrc .gitignore CMakeLists.txt Makefile.am Makefile.inc dnsd.c first.c first.h getpart.c mqttd.c resolve.c rtspd.c sockfilt.c socksd.c sws.c tftpd.c util.c
tunit .gitignore CMakeLists.txt Makefile.am Makefile.inc README.md tool1394.c tool1604.c tool1621.c tool1622.c tool1623.c tool1720.c
unit .gitignore CMakeLists.txt Makefile.am Makefile.inc README.md unit1300.c unit1302.c unit1303.c unit1304.c unit1305.c unit1307.c unit1309.c unit1323.c unit1330.c unit1395.c unit1396.c unit1397.c unit1398.c unit1399.c unit1600.c unit1601.c unit1602.c unit1603.c unit1605.c unit1606.c unit1607.c unit1608.c unit1609.c unit1610.c unit1611.c unit1612.c unit1614.c unit1615.c unit1616.c unit1620.c unit1625.c unit1626.c unit1627.c unit1636.c unit1650.c unit1651.c unit1652.c unit1653.c unit1654.c unit1655.c unit1656.c unit1657.c unit1658.c unit1660.c unit1661.c unit1663.c unit1664.c unit1666.c unit1667.c unit1668.c unit1669.c unit1674.c unit1675.c unit1676.c unit1979.c unit1980.c unit2600.c unit2601.c unit2602.c unit2603.c unit2604.c unit2605.c unit3200.c unit3205.c unit3211.c unit3212.c unit3213.c unit3214.c unit3216.c unit3219.c unit3300.c unit3301.c unit3302.c
.gitignore CMakeLists.txt Makefile.am allversions.pm appveyor.pm azure.pm config.in configurehelp.pm.in devtest.pl dictserver.py directories.pm ech_combos.py ech_tests.sh ftpserver.pl getpart.pm globalconfig.pm http-server.pl http2-server.pl http3-server.pl memanalyze.pl memanalyzer.pm negtelnetserver.py nghttpx.conf pathhelp.pm processhelp.pm requirements.txt rtspserver.pl runner.pm runtests.pl secureserver.pl serverhelp.pm servers.pm smbserver.py sshhelp.pm sshserver.pl test1119.pl test1135.pl test1139.pl test1140.pl test1165.pl test1167.pl test1173.pl test1175.pl test1177.pl test1222.pl test1275.pl test1276.pl test1477.pl test1486.pl test1488.pl test1544.pl test1707.pl test745.pl test971.pl testcurl.pl testutil.pm tftpserver.pl util.py valgrind.pm valgrind.supp
.clang-tidy.yml .dir-locals.el .editorconfig .git-blame-ignore-revs .gitattributes .gitignore .mailmap CHANGES.md CMakeLists.txt COPYING Dockerfile GIT-INFO.md Makefile.am README README.md RELEASE-NOTES REUSE.toml SECURITY.md acinclude.m4 appveyor.sh appveyor.yml configure.ac curl-config.in libcurl.pc.in renovate.json
examples .env config.ini crypto_test.lua env_test.lua fs_example.lua http_server.lua https_test.lua ini_example.lua json.lua log.lua path_fs_example.lua process_example.lua request_download.lua request_test.lua run_all.lua sqlite_example.lua sqlite_http_template.lua stash_test.lua template_test.lua timer.lua websocket.lua
iniparser
.github
ISSUE_TEMPLATE config.yml
workflows disable-pull-requests.yml trigger-gitlab-ci.yml
cmake JoinPaths.cmake config.cmake.in pc.in
example iniexample.c iniwrite.c parse.c twisted-errors.ini twisted-genhuge.py twisted-ofkey.ini twisted-ofval.ini twisted.ini
src dictionary.c dictionary.h iniparser.c iniparser.h
test
ressources
bad_ini ends_well.ini twisted-errors.ini twisted-ofkey.ini twisted-ofval.ini
good_ini empty.ini spaced.ini spaced2.ini twisted.ini
gruezi.ini old.ini quotes.ini utf8.ini
CMakeLists.txt test_dictionary.c test_iniparser.c unity-config.yml unity_config.h
.cmake-format.py .gitignore .gitlab-ci.yml .gitmessage .travis.yml AUTHORS CMakeLists.txt FAQ-en.md FAQ-zhcn.md INSTALL LICENSE README.md compile_commands.json
jinjac
example CMakeLists.txt example.c
jinjac_test_app CMakeLists.txt jinjac_test_app.c
libjinjac
include jinjac.h
src CMakeLists.txt ast.c ast.h block_statement.c block_statement.h buffer.c buffer.h buildin.c buildin.h common.h convert.c convert.h flex_decl.h jfunction.c jfunction.h jinja_expression.l jinja_expression.y jinjac_parse.c jinjac_parse.h jinjac_stream.c jinjac_stream.h jlist.c jlist.h jobject.c jobject.h parameter.c parameter.h str_obj.c str_obj.h trace.c trace.h
CMakeLists.txt
test .gitignore CMakeLists.txt autotest.rb test_01.expected test_01.jinja test_01b.expected test_01b.jinja test_01c.expected test_01c.jinja test_01d.expected test_01d.jinja test_02.expected test_02.jinja test_03.expected test_03.jinja test_04.expected test_04.jinja test_05.expected test_05.jinja test_06.expected test_06.jinja test_07.expected test_07.jinja test_08.expected test_08.jinja test_08b.expected test_08b.jinja test_09.expected test_09.jinja test_10.expected test_10.jinja test_11.expected test_11.jinja test_12.expected test_12.jinja test_13.expected test_13.jinja test_14.expected test_14.jinja test_15.expected test_15.jinja test_16.expected test_16.jinja test_17.expected test_17.jinja test_18.expected test_18.jinja test_18b.expected test_18b.jinja test_18c.expected test_18c.jinja test_19.expected test_19.jinja test_19b.expected test_19b.jinja test_19c.expected test_19c.jinja test_19d.expected test_19d.jinja test_19e.expected test_19e.jinja test_19f.expected test_19f.jinja test_20.expected test_20.jinja test_21.expected test_21.jinja test_22.expected test_22.jinja test_22a.expected test_22a.jinja test_22b.expected test_22b.jinja test_23.expected test_23.jinja test_24.expected test_24.jinja
.gitignore CMakeLists.txt LICENSE.txt README.md build_coverage.sh build_debug.sh build_release.sh cppcheck_analysis.sh
libev Changes LICENSE Makefile Makefile.am Makefile.in README Symbols.ev Symbols.event aclocal.m4 autogen.sh compile config.guess config.h config.h.in config.status config.sub configure configure.ac depcomp ev++.h ev.3 ev.c ev.h ev.pod ev_epoll.c ev_kqueue.c ev_poll.c ev_port.c ev_select.c ev_vars.h ev_win32.c ev_wrap.h event.c event.h install-sh libev.m4 libtool ltmain.sh missing mkinstalldirs stamp-h1
luajit
doc
img contact.png
bluequad-print.css bluequad.css contact.html ext_buffer.html ext_c_api.html ext_ffi.html ext_ffi_api.html ext_ffi_semantics.html ext_ffi_tutorial.html ext_jit.html ext_profiler.html extensions.html install.html luajit.html running.html
dynasm dasm_arm.h dasm_arm.lua dasm_arm64.h dasm_arm64.lua dasm_mips.h dasm_mips.lua dasm_mips64.lua dasm_ppc.h dasm_ppc.lua dasm_proto.h dasm_x64.lua dasm_x86.h dasm_x86.lua dynasm.lua
etc luajit.1 luajit.pc
src
host .gitignore README buildvm.c buildvm.h buildvm_asm.c buildvm_fold.c buildvm_lib.c buildvm_libbc.h buildvm_peobj.c genlibbc.lua genminilua.lua genversion.lua minilua.c
jit .gitignore bc.lua bcsave.lua dis_arm.lua dis_arm64.lua dis_arm64be.lua dis_mips.lua dis_mips64.lua dis_mips64el.lua dis_mips64r6.lua dis_mips64r6el.lua dis_mipsel.lua dis_ppc.lua dis_x64.lua dis_x86.lua dump.lua p.lua v.lua zone.lua
.gitignore Makefile Makefile.dep lauxlib.h lib_aux.c lib_base.c lib_bit.c lib_buffer.c lib_debug.c lib_ffi.c lib_init.c lib_io.c lib_jit.c lib_math.c lib_os.c lib_package.c lib_string.c lib_table.c lj_alloc.c lj_alloc.h lj_api.c lj_arch.h lj_asm.c lj_asm.h lj_asm_arm.h lj_asm_arm64.h lj_asm_mips.h lj_asm_ppc.h lj_asm_x86.h lj_assert.c lj_bc.c lj_bc.h lj_bcdump.h lj_bcread.c lj_bcwrite.c lj_buf.c lj_buf.h lj_carith.c lj_carith.h lj_ccall.c lj_ccall.h lj_ccallback.c lj_ccallback.h lj_cconv.c lj_cconv.h lj_cdata.c lj_cdata.h lj_char.c lj_char.h lj_clib.c lj_clib.h lj_cparse.c lj_cparse.h lj_crecord.c lj_crecord.h lj_ctype.c lj_ctype.h lj_debug.c lj_debug.h lj_def.h lj_dispatch.c lj_dispatch.h lj_emit_arm.h lj_emit_arm64.h lj_emit_mips.h lj_emit_ppc.h lj_emit_x86.h lj_err.c lj_err.h lj_errmsg.h lj_ff.h lj_ffrecord.c lj_ffrecord.h lj_frame.h lj_func.c lj_func.h lj_gc.c lj_gc.h lj_gdbjit.c lj_gdbjit.h lj_ir.c lj_ir.h lj_ircall.h lj_iropt.h lj_jit.h lj_lex.c lj_lex.h lj_lib.c lj_lib.h lj_load.c lj_mcode.c lj_mcode.h lj_meta.c lj_meta.h lj_obj.c lj_obj.h lj_opt_dce.c lj_opt_fold.c lj_opt_loop.c lj_opt_mem.c lj_opt_narrow.c lj_opt_sink.c lj_opt_split.c lj_parse.c lj_parse.h lj_prng.c lj_prng.h lj_profile.c lj_profile.h lj_record.c lj_record.h lj_serialize.c lj_serialize.h lj_snap.c lj_snap.h lj_state.c lj_state.h lj_str.c lj_str.h lj_strfmt.c lj_strfmt.h lj_strfmt_num.c lj_strscan.c lj_strscan.h lj_tab.c lj_tab.h lj_target.h lj_target_arm.h lj_target_arm64.h lj_target_mips.h lj_target_ppc.h lj_target_x86.h lj_trace.c lj_trace.h lj_traceerr.h lj_udata.c lj_udata.h lj_vm.h lj_vmevent.c lj_vmevent.h lj_vmmath.c ljamalg.c lua.h lua.hpp luaconf.h luajit.c luajit_rolling.h lualib.h msvcbuild.bat nxbuild.bat ps4build.bat ps5build.bat psvitabuild.bat vm_arm.dasc vm_arm64.dasc vm_mips.dasc vm_mips64.dasc vm_ppc.dasc vm_x64.dasc vm_x86.dasc xb1build.bat xedkbuild.bat
.gitattributes .gitignore .relver COPYRIGHT Makefile README
sqlite shell.c sqlite3.c sqlite3.h sqlite3ext.h
wolfssl
.github
ISSUE_TEMPLATE bug_report.yaml other.yaml
actions
install-apt-deps action.yml
scripts
zephyr-4.x external_libc.conf zephyr-test.sh
openssl-ech.sh tls-anvil-test.sh
workflows
disabled haproxy.yml hitch.yml hostap.yml
hostap-files
configs
07c9f183ea744ac04585fb6dd10220c75a5e2e74 hostapd.config tests wpa_supplicant.config
b607d2723e927a3446d89aed813f1aa6068186bb hostapd.config tests wpa_supplicant.config
hostap_2_10 extra.patch hostapd.config tests wpa_supplicant.config
Makefile README dbus-wpa_supplicant.conf
ada.yml arduino.yml async-examples.yml async.yml atecc608-sim.yml bind.yml cmake-autoconf.yml cmake.yml codespell.yml coverity-scan-fixes.yml cryptocb-only.yml curl.yml cyrus-sasl.yml disable-pk-algs.yml docker-Espressif.yml docker-OpenWrt.yml emnet-nonblock.yml fil-c.yml freertos-mem-track.yml gencertbuf.yml grpc.yml haproxy.yml hostap-vm.yml intelasm-c-fallback.yml ipmitool.yml jwt-cpp.yml krb5.yml libspdm.yml libssh2.yml libvncserver.yml linuxkm.yml macos-apple-native-cert-validation.yml mbedtls.sh mbedtls.yml membrowse-comment.yml membrowse-onboard.yml membrowse-report.yml memcached.sh memcached.yml mono.yml mosquitto.yml msmtp.yml msys2.yml multi-arch.yml multi-compiler.yml net-snmp.yml nginx.yml no-malloc.yml no-tls.yml nss.sh nss.yml ntp.yml ocsp.yml openldap.yml openssh.yml openssl-ech.yml opensslcoexist.yml openvpn.yml os-check.yml packaging.yml pam-ipmi.yml pq-all.yml pr-commit-check.yml psk.yml puf.yml python.yml rng-tools.yml rust-wrapper.yml se050-sim.yml smallStackSize.yml socat.yml softhsm.yml sssd.yml stm32-sim.yml stsafe-a120-sim.yml stunnel.yml symbol-prefixes.yml threadx.yml tls-anvil.yml trackmemory.yml watcomc.yml win-csharp-test.yml wolfCrypt-Wconversion.yml wolfboot-integration.yml wolfsm.yml xcode.yml zephyr-4.x.yml zephyr.yml
PULL_REQUEST_TEMPLATE.md SECURITY.md membrowse-targets.json
Docker
OpenWrt Dockerfile README.md runTests.sh
packaging
debian Dockerfile
fedora Dockerfile
wolfCLU Dockerfile README.md
yocto Dockerfile buildAndPush.sh
Dockerfile Dockerfile.cross-compiler README.md buildAndPush.sh include.am run.sh
IDE
ARDUINO
sketches
wolfssl_client README.md
wolfssl_server README.md
wolfssl_version README.md
README.md
Arduino_README_prepend.md README.md include.am keywords.txt library.properties.template wolfssl-arduino.cpp wolfssl-arduino.sh wolfssl.h
AURIX Cpu0_Main.c README.md include.am user_settings.h wolf_main.c
Android Android.bp README.md include.am user_settings.h
CRYPTOCELL README.md include.am main.c user_settings.h
CSBENCH include.am user_settings.h
ECLIPSE
DEOS
deos_wolfssl .options
README.md deos_malloc.c include.am tls_wolfssl.c tls_wolfssl.h user_settings.h
MICRIUM README.md client_wolfssl.c client_wolfssl.h include.am server_wolfssl.c server_wolfssl.h user_settings.h wolfsslRunTests.c
RTTHREAD README.md include.am user_settings.h wolfssl_test.c
SIFIVE README.md include.am
Espressif
ESP-IDF
examples
template
VisualGDB wolfssl_template_IDF_v5.1_ESP32.vgdbproj
components
wolfssl
include user_settings.h
CMakeLists.txt Kconfig README.md component.mk
main
include main.h
CMakeLists.txt Kconfig.projbuild component.mk main.c
CMakeLists.txt Makefile README.md partitions_singleapp_large.csv sdkconfig.defaults sdkconfig.defaults.esp8266
wolfssl_benchmark
VisualGDB wolfssl_benchmark_IDF_v4.4_ESP32.sln wolfssl_benchmark_IDF_v4.4_ESP32.vgdbproj wolfssl_benchmark_IDF_v5_ESP32.sln wolfssl_benchmark_IDF_v5_ESP32.vgdbproj wolfssl_benchmark_IDF_v5_ESP32C3.sln wolfssl_benchmark_IDF_v5_ESP32C3.vgdbproj wolfssl_benchmark_IDF_v5_ESP32S3.sln wolfssl_benchmark_IDF_v5_ESP32S3.vgdbproj
components
wolfssl
include user_settings.h
CMakeLists.txt Kconfig README.md component.mk
main
include main.h
CMakeLists.txt Kconfig.projbuild component.mk main.c
CMakeLists.txt Makefile README.md partitions_singleapp_large.csv sdkconfig.defaults sdkconfig.defaults.esp8266
wolfssl_client
VisualGDB README.md wolfssl_client_IDF_v5_ESP32.sln wolfssl_client_IDF_v5_ESP32.vgdbproj
components
wolfssl
include user_settings.h
CMakeLists.txt Kconfig README.md component.mk
main
include client-tls.h main.h time_helper.h wifi_connect.h
CMakeLists.txt Kconfig.projbuild client-tls.c component.mk main.c time_helper.c wifi_connect.c
CMakeLists.txt Makefile README.md README_server_sm.md partitions_singleapp_large.csv sdkconfig.defaults sdkconfig.defaults.esp32c2 sdkconfig.defaults.esp8266 wolfssl_client_ESP8266.vgdbproj
wolfssl_server
VisualGDB README.md wolfssl_server_IDF_v5_ESP32.sln wolfssl_server_IDF_v5_ESP32.vgdbproj
components
wolfssl
include user_settings.h
CMakeLists.txt Kconfig README.md component.mk
main
include main.h server-tls.h time_helper.h wifi_connect.h
CMakeLists.txt Kconfig.projbuild component.mk main.c server-tls.c time_helper.c wifi_connect.c
CMakeLists.txt Makefile README.md README_server_sm.md partitions_singleapp_large.csv sdkconfig.defaults sdkconfig.defaults.esp32c2 sdkconfig.defaults.esp8266 wolfssl_server_ESP8266.vgdbproj
wolfssl_test
VisualGDB wolfssl_test-IDF_v5_ESP32.sln wolfssl_test-IDF_v5_ESP32.vgdbproj wolfssl_test-IDF_v5_ESP32C3.sln wolfssl_test-IDF_v5_ESP32C3.vgdbproj wolfssl_test-IDF_v5_ESP32C6.sln wolfssl_test-IDF_v5_ESP32C6.vgdbproj wolfssl_test_IDF_v5_ESP32S3.sln wolfssl_test_IDF_v5_ESP32S3.vgdbproj
components
wolfssl
include user_settings.h
CMakeLists.txt Kconfig README.md component.mk
main
include main.h
CMakeLists.txt Kconfig.projbuild component.mk main.c
CMakeLists.txt Makefile README.md partitions_singleapp_large.csv sdkconfig.defaults sdkconfig.defaults.esp32 sdkconfig.defaults.esp32c3 sdkconfig.defaults.esp32c6 sdkconfig.defaults.esp32h2 sdkconfig.defaults.esp32s2 sdkconfig.defaults.esp32s3 sdkconfig.defaults.esp8266 testAll.sh testMonitor.sh wolfssl_test_ESP8266.sln wolfssl_test_ESP8266.vgdbproj
wolfssl_test_idf
VisualGDB VisualGDB_wolfssl_test_idf.sln VisualGDB_wolfssl_test_idf.vgdbproj
main CMakeLists.txt Kconfig.projbuild component.mk main.c main_wip.c.ex time_helper.c time_helper.h
CMakeLists.txt Kconfig.projbuild README.md component.mk sdkconfig.defaults
README.md
libs CMakeLists.txt README.md component.mk tigard.cfg
test CMakeLists.txt README.md component.mk test_wolfssl.c
README.md README_32se.md UPDATE.md compileAllExamples.sh dummy_config_h dummy_test_paths.h setup.sh setup_win.bat user_settings.h
README.md include.am
GCC-ARM
Header user_settings.h
Source armtarget.c benchmark_main.c test_main.c tls_client.c tls_server.c wolf_main.c
Makefile Makefile.bench Makefile.client Makefile.common Makefile.server Makefile.static Makefile.test README.md include.am linker.ld linker_fips.ld
Gaisler-BCC README.md include.am
HEXAGON
DSP Makefile wolfssl_dsp.idl
Makefile README.md build.sh ecc-verify-benchmark.c ecc-verify.c include.am user_settings.h
HEXIWEAR
wolfSSL_HW .cwGeneratedFileSetLog user_settings.h
IAR-EWARM
Projects
benchmark benchmark-main.c current_time.c wolfCrypt-benchmark.ewd wolfCrypt-benchmark.ewp
common minimum-startup.c wolfssl.icf
lib wolfSSL-Lib.ewd wolfSSL-Lib.ewp
test test-main.c wolfCrypt-test.ewd wolfCrypt-test.ewp
user_settings.h wolfssl.eww
embOS
SAMV71_XULT
embOS_SAMV71_XULT_Linker_Script samv71q21_wolfssl.icf
embOS_SAMV71_XULT_user_settings user_settings.h user_settings_simple_example.h user_settings_verbose_example.h
embOS_wolfcrypt_benchmark_SAMV71_XULT
Application runBenchmarks.c
README_wolfcrypt_benchmark wolfcrypt_benchmark.ewd wolfcrypt_benchmark.ewp
embOS_wolfcrypt_lib_SAMV71_XULT README_wolfcrypt_lib wolfcrypt_lib.ewd wolfcrypt_lib.ewp
embOS_wolfcrypt_test_SAMV71_XULT
Application runWolfcryptTests.c
README_wolfcrypt_test wolfcrypt_test.ewd wolfcrypt_test.ewp
README_SAMV71
custom_port
custom_port_Linker_Script samv71q21_wolfssl.icf
custom_port_user_settings user_settings.h
wolfcrypt_benchmark_custom_port
Application runBenchmarks.c
wolfcrypt_test_custom_port
Application runWolfcryptTests.c
README_custom_port
extract_trial_here README_extract_trial_here
README
.gitignore README
IAR-MSP430 Makefile README.md include.am main.c user_settings.h
INTIME-RTOS Makefile README.md include.am libwolfssl.c libwolfssl.vcxproj user_settings.h wolfExamples.c wolfExamples.h wolfExamples.sln wolfExamples.vcxproj wolfssl-lib.sln wolfssl-lib.vcxproj
Infineon README.md include.am user_settings.h
KDS
config user_settings.h
include.am
LINUX-SGX README.md build.sh clean.sh include.am sgx_t_static.mk
LPCXPRESSO
lib_wolfssl lpc_18xx_port.c user_settings.h
wolf_example
src lpc_18xx_startup.c wolfssl_example.c
readme.txt
README.md
M68K
benchmark Makefile main.cpp
testwolfcrypt Makefile main.cpp
Makefile README.md include.am user_settings.h
MCUEXPRESSO
RT1170 fsl_caam_c.patch fsl_caam_h.patch user_settings.h
benchmark
source run_benchmark.c
wolfssl liblinks.xml
README.md include.am user_settings.h wolfcrypt_test.c
MDK-ARM
LPC43xx time-LCP43xx.c
MDK-ARM
wolfSSL Retarget.c cert_data.c cert_data.h config-BARE-METAL.h config-FS.h config-RTX-TCP-FS.h config-WOLFLIB.h main.c shell.c time-CortexM3-4.c time-dummy.c wolfssl_MDK_ARM.c wolfssl_MDK_ARM.h
STM32F2xx_StdPeriph_Lib time-STM32F2xx.c
MDK5-ARM
Conf user_settings.h
Inc wolfssl_MDK_ARM.h
Projects
CryptBenchmark Abstract.txt CryptBenchmark.sct CryptBenchmark.uvoptx CryptBenchmark.uvprojx main.c
CryptTest Abstract.txt CryptTest.sct CryptTest.uvoptx CryptTest.uvprojx main.c
EchoClient Abstract.txt EchoClient.uvoptx EchoClient.uvprojx main.c wolfssl-link.sct
EchoServer Abstract.txt EchoServer.uvoptx EchoServer.uvprojx main.c wolfssl-link.sct
SimpleClient Abstract.txt SimpleClient.uvoptx SimpleClient.uvprojx main.c wolfssl-link.sct
SimpleServer Abstract.txt SimpleServer.uvoptx SimpleServer.uvprojx main.c wolfssl-link.sct
wolfSSL-Full Abstract.txt main.c shell.c time-CortexM3-4.c wolfsslFull.uvoptx wolfsslFull.uvprojx
wolfSSL-Lib Abstract.txt wolfSSL-Lib.uvoptx wolfSSL-Lib.uvprojx
Src ssl-dummy.c
README.md include.am
MPLABX16
wolfcrypt_test.X
nbproject
private configurations.xml private.xml
configurations.xml include.am project.xml
Makefile
wolfssl.X
nbproject configurations.xml include.am project.xml
Makefile
README.md include.am main.c user_settings.h
MQX Makefile README-jp.md README.md client-tls.c include.am server-tls.c user_config.h user_settings.h
MSVS-2019-AZSPHERE
client client.c client.h
server server.c server.h
shared util.h
wolfssl_new_azsphere
HardwareDefinitions
avnet_mt3620_sk
inc
hw template_appliance.h
template_appliance.json
mt3620_rdb
inc
hw template_appliance.h
template_appliance.json
seeed_mt3620_mdb
inc
hw template_appliance.h
template_appliance.json
.gitignore CMakeLists.txt CMakeSettings.json app_manifest.json applibs_versions.h launch.vs.json main.c
README.md include.am user_settings.h
MYSQL CMakeLists_wolfCrypt.txt CMakeLists_wolfSSL.txt do.sh
NDS README.md
NETOS Makefile.wolfcrypt.inc README.md include.am user_settings.h user_settings.h-cert2425 user_settings.h-cert3389 wolfssl_netos_custom.c
OPENSTM32 README.md
PlatformIO
examples
wolfssl_benchmark
include README main.h
lib README
src CMakeLists.txt main.c
test README
CMakeLists.txt README.md platformio.ini sdkconfig.defaults wolfssl_benchmark.code-workspace
wolfssl_test
include README main.h
lib README
src CMakeLists.txt main.c
test README
CMakeLists.txt README.md platformio.ini sdkconfig.defaults wolfssl_test.code-workspace
README.md wolfssl_platformio.code-workspace
README.md include.am
QNX
CAAM-DRIVER Makefile
example-client Makefile client-tls.c
example-cmac Makefile cmac-test.c
example-server Makefile server-tls.c
testwolfcrypt Makefile
wolfssl Makefile user_settings.h
README.md include.am
RISCV
SIFIVE-HIFIVE1 Makefile README.md include.am main.c user_settings.h
SIFIVE-UNLEASHED README.md include.am
include.am
ROWLEY-CROSSWORKS-ARM Kinetis_FlashPlacement.xml README.md arm_startup.c benchmark_main.c hw.h include.am kinetis_hw.c retarget.c test_main.c user_settings.h wolfssl.hzp wolfssl_ltc.hzp
Renesas
cs+
Projects
common strings.h unistd.h user_settings.h wolfssl_dummy.c
t4_demo README_en.txt README_jp.txt t4_demo.mtpj wolf_client.c wolf_demo.h wolf_main.c wolf_server.c
test test.mtpj test_main.c
wolfssl_lib wolfssl_lib.mtpj
README include.am
e2studio
DK-S7G2
benchmark-template
src app_entry.c
example_server-template
src app_entry.c
wolfcrypttest-template
src app_entry.c
wolfssl-template-project configuration.xml
README.md include.am user_settings.h
Projects
common strings.h unistd.h user_settings.h wolfssl_dummy.c
test
src key_data.c key_data.h test_main.c wolf_client.c wolf_server.c wolfssl_demo.h
tools generate_rsa_keypair.sh genhexbuf.pl rsa_pss_sign.sh
wolfssl
src .gitkeep
wolfcrypt
src .gitkeep
README include.am
RA6M3
benchmark-wolfcrypt
common .gitkeep
script .gitkeep
src wolfssl_thread_entry.c
client-wolfssl
common
src .gitkeep
script .gitkeep
src wolfssl_thread_entry.c
wolfssl_thread_entry.h
common
ra6m3g README.md
src freertos_tcp_port.c
user_settings.h util.h
server-wolfssl
common
src .gitkeep
script .gitkeep
src wolfssl_thread_entry.c
wolfssl_thread_entry.h
test-wolfcrypt
common .gitkeep
script .gitkeep
src wolfssl_thread_entry.c
wolfssl
src .gitkeep
wolfcrypt .gitkeep
README.md README_APRA6M_en.md README_APRA6M_jp.md include.am
RA6M3G README.md
RA6M4
common user_settings.h wolfssl_demo.h
test
key_data key_data.h key_data_sce.c
src
SEGGER_RTT myprint.c
common .gitignore
test_main.c wolf_client.c wolfssl_sce_unit_test.c
test_RA6M4Debug.launch
tools
example_keys generate_SignedCA.sh rsa_private.pem rsa_public.pem
README.md
README.md include.am
RX65N
GR-ROSE
common strings.h unistd.h user_settings.h wolfssl_dummy.c
smc smc.scfg
test
src key_data.c key_data.h test_main.c wolf_client.c wolf_server.c wolfssl_demo.h
test.rcpc test_HardwareDebug.launch
tools
example_keys generate_SignedCA.sh rsa_private.pem rsa_public.pem
README.md
wolfssl wolfssl.rcpc
README_EN.md README_JP.md include.am
RSK
resource section.esi
wolfssl wolfssl.rcpc
wolfssl_demo key_data.c key_data.h user_settings.h wolfssl_demo.c wolfssl_demo.h
InstructionManualForExample_RSK+RX65N-2MB_EN.pdf InstructionManualForExample_RSK+RX65N-2MB_JP.pdf README_EN.md README_JP.md include.am
RX72N
EnvisionKit
Simple
common sectioninfo.esi wolfssl_dummy.c
test
src
client simple_tcp_client.c simple_tls_tsip_client.c
server simple_tcp_server.c simple_tls_server.c
test_main.c wolfssl_simple_demo.h
test.rcpc test.scfg test_HardwareDebug.launch
wolfssl wolfssl.rcpc
README_EN.md README_JP.md
resource section.esi
tools
example_keys generate_SignedCA.sh rsa_private.pem rsa_public.pem
README.md
wolfssl wolfssl.rcpc
wolfssl_demo key_data.c key_data.h user_settings.h wolfssl_demo.c wolfssl_demo.h wolfssl_tsip_unit_test.c
InstructionManualForExample_RX72N_EnvisonKit_EN.pdf InstructionManualForExample_RX72N_EnvisonKit_JP.pdf README_EN.md README_JP.md include.am
RZN2L
common user_settings.h wolfssl_demo.h
test
src
serial_io app_print.c
test wolf_client.c wolf_server.c wolfssl_rsip_unit_test.c
wolfCrypt .gitignore
wolfSSL .gitignore
local_system_init.c rzn2l_tst_thread_entry.c wolfssl_dummy.c
README.md include.am
SK-S7G2
common user_settings.h
wolfssl_lib configuration.xml
.gitignore README.md include.am
STARCORE README.txt include.am starcore_test.c user_settings.h
STM32Cube README.md STM32_Benchmarks.md default_conf.ftl include.am main.c wolfssl_example.c wolfssl_example.h
SimplicityStudio README.md include.am test_wolf.c user_settings.h
TRUESTUDIO
wolfssl user_settings.h
README include.am
VS-ARM README.md include.am user_settings.h wolfssl.sln wolfssl.vcxproj
VS-AZURE-SPHERE
client app_manifest.json client.c client.h client.vcxproj
server app_manifest.json server.c server.h server.vcxproj
shared util.h
wolfcrypt_test app_manifest.json wolfcrypt_test.vcxproj
README.md include.am user_settings.h wolfssl.sln wolfssl.vcxproj
VisualDSP include.am user_settings.h wolf_tasks.c
WICED-STUDIO README include.am user_settings.h
WIN README.txt include.am test.vcxproj user_settings.h user_settings_dtls.h wolfssl-fips.sln wolfssl-fips.vcxproj
WIN-SGX ReadMe.txt include.am wolfSSL_SGX.edl wolfSSL_SGX.sln wolfSSL_SGX.vcxproj
WIN-SRTP-KDF-140-3 README.txt include.am resource.h test.vcxproj user_settings.h wolfssl-fips.rc wolfssl-fips.sln wolfssl-fips.vcxproj
WIN10 README.txt include.am resource.h test.vcxproj user_settings.h wolfssl-fips.rc wolfssl-fips.sln wolfssl-fips.vcxproj
WINCE README.md include.am user_settings.h user_settings.h.140-2-deprecated
WORKBENCH README.md include.am
XCODE
Benchmark
wolfBench
Assets.xcassets
AppIcon.appiconset Contents.json
Base.lproj LaunchScreen.storyboard Main.storyboard
AppDelegate.h AppDelegate.m Info.plist ViewController.h ViewController.m main.m
wolfBench.xcodeproj project.pbxproj
include.am
wolfssl-FIPS.xcodeproj project.pbxproj
wolfssl.xcodeproj project.pbxproj
wolfssl_testsuite.xcodeproj project.pbxproj
README.md build-for-i386.sh include.am user_settings.h
XCODE-FIPSv2
macOS-C++
Intel user_settings.h
M1 user_settings.h
include.am user_settings.h
XCODE-FIPSv5 README include.am user_settings.h
XCODE-FIPSv6 README include.am user_settings.h
XilinxSDK
2018_2 lscript.ld
2019_2
wolfCrypt_example
src lscript.ld
wolfCrypt_example_system wolfCrypt_example_system.sprj
2022_1
wolfCrypt_FreeRTOS_example wolfCrypt_FreeRTOS_example.prj
wolfCrypt_FreeRTOS_example_system wolfCrypt_FreeRTOS_example_system.sprj
wolfCrypt_example wolfCrypt_example.prj
wolfCrypt_example_system wolfCrypt_example_system.sprj
.gitignore
README.md bench.sh combine.sh eclipse_formatter_profile.xml graph.sh include.am user_settings.h wolfssl_example.c
apple-universal
wolfssl-multiplatform
wolfssl-multiplatform
Assets.xcassets
AccentColor.colorset Contents.json
AppIcon.appiconset Contents.json
Contents.json
ContentView.swift simple_client_example.c simple_client_example.h wolfssl-multiplatform-Bridging-Header.h wolfssl_multiplatform.entitlements wolfssl_multiplatformApp.swift wolfssl_test_driver.c wolfssl_test_driver.h
wolfssl-multiplatform.xcodeproj project.pbxproj
.gitignore README.md build-wolfssl-framework.sh include.am
iotsafe Makefile README.md ca-cert.c devices.c devices.h include.am main.c memory-tls.c startup.c target.ld user_settings.h
iotsafe-raspberrypi Makefile README.md client-tls13.c include.am main.c
mynewt README.md apps.wolfcrypttest.pkg.yml crypto.wolfssl.pkg.yml crypto.wolfssl.syscfg.yml include.am setup.sh
zephyr README.md include.am
include.am
RTOS
nuttx
wolfssl .gitignore Kconfig Make.defs Makefile README.md setup-wolfssl.sh user_settings.h
include.am
bsdkm Makefile README.md bsdkm_wc_port.h include.am wolfkmod.c wolfkmod_aes.c x86_vecreg.c
certs
1024 ca-cert.der ca-cert.pem ca-key.der ca-key.pem client-cert.der client-cert.pem client-key.der client-key.pem client-keyPub.der dh1024.der dh1024.pem dsa-pub-1024.pem dsa1024.der dsa1024.pem include.am rsa1024.der server-cert.der server-cert.pem server-key.der server-key.pem
3072 client-cert.der client-cert.pem client-key.der client-key.pem client-keyPub.der include.am
4096 client-cert.der client-cert.pem client-key.der client-key.pem client-keyPub.der include.am
acert
rsa_pss acert.pem acert_ietf.pem acert_ietf_pubkey.pem acert_pubkey.pem
acert.pem acert_ietf.pem acert_ietf_pubkey.pem acert_pubkey.pem include.am
aia ca-issuers-cert.pem multi-aia-cert.pem overflow-aia-cert.pem
crl
extra-crls ca-int-cert-revoked.pem claim-root.pem crl_critical_entry.pem crlnum_57oct.pem crlnum_64oct.pem general-server-crl.pem large_crlnum.pem large_crlnum2.pem
hash_der 0fdb2da4.r0
hash_pem 0fdb2da4.r0
bad_time_fmt.pem ca-int-ecc.pem ca-int.pem ca-int2-ecc.pem ca-int2.pem caEcc384Crl.pem caEccCrl.der caEccCrl.pem cliCrl.pem client-int-ecc.pem client-int.pem crl.der crl.pem crl.revoked crl2.der crl2.pem crl_reason.pem crl_rsapss.pem eccCliCRL.pem eccSrvCRL.pem gencrls.sh include.am server-goodaltCrl.pem server-goodaltwildCrl.pem server-goodcnCrl.pem server-goodcnwildCrl.pem server-int-ecc.pem server-int.pem wolfssl.cnf
dilithium bench_dilithium_level2_key.der bench_dilithium_level3_key.der bench_dilithium_level5_key.der include.am
ecc bp256r1-key.der bp256r1-key.pem ca-secp256k1-cert.pem ca-secp256k1-key.pem client-bp256r1-cert.der client-bp256r1-cert.pem client-secp256k1-cert.der client-secp256k1-cert.pem genecc.sh include.am secp256k1-key.der secp256k1-key.pem secp256k1-param.pem secp256k1-privkey.der secp256k1-privkey.pem server-bp256r1-cert.der server-bp256r1-cert.pem server-secp256k1-cert.der server-secp256k1-cert.pem server2-secp256k1-cert.der server2-secp256k1-cert.pem wolfssl.cnf wolfssl_384.cnf
ed25519 ca-ed25519-key.der ca-ed25519-key.pem ca-ed25519-priv.der ca-ed25519-priv.pem ca-ed25519.der ca-ed25519.pem client-ed25519-key.der client-ed25519-key.pem client-ed25519-priv.der client-ed25519-priv.pem client-ed25519.der client-ed25519.pem eddsa-ed25519.der eddsa-ed25519.pem gen-ed25519-certs.sh gen-ed25519-keys.sh gen-ed25519.sh include.am root-ed25519-key.der root-ed25519-key.pem root-ed25519-priv.der root-ed25519-priv.pem root-ed25519.der root-ed25519.pem server-ed25519-cert.pem server-ed25519-key.der server-ed25519-key.pem server-ed25519-priv.der server-ed25519-priv.pem server-ed25519.der server-ed25519.pem
ed448 ca-ed448-key.der ca-ed448-key.pem ca-ed448-priv.der ca-ed448-priv.pem ca-ed448.der ca-ed448.pem client-ed448-key.der client-ed448-key.pem client-ed448-priv.der client-ed448-priv.pem client-ed448.der client-ed448.pem gen-ed448-certs.sh gen-ed448-keys.sh include.am root-ed448-key.der root-ed448-key.pem root-ed448-priv.der root-ed448-priv.pem root-ed448.der root-ed448.pem server-ed448-cert.pem server-ed448-key.der server-ed448-key.pem server-ed448-priv.der server-ed448-priv.pem server-ed448.der server-ed448.pem
external DigiCertGlobalRootCA.pem README.txt ca-digicert-ev.pem ca-globalsign-root.pem ca-google-root.pem ca_collection.pem include.am
falcon bench_falcon_level1_key.der bench_falcon_level5_key.der include.am
intermediate
ca_false_intermediate gentestcert.sh int_ca.key server.key test_ca.key test_ca.pem test_int_not_cacert.pem test_sign_bynoca_srv.pem wolfssl_base.conf wolfssl_srv.conf
ca-ecc-bad-aki.der ca-ecc-bad-aki.pem ca-int-cert.der ca-int-cert.pem ca-int-ecc-cert.der ca-int-ecc-cert.pem ca-int-ecc-key.der ca-int-ecc-key.pem ca-int-key.der ca-int-key.pem ca-int2-cert.der ca-int2-cert.pem ca-int2-ecc-cert.der ca-int2-ecc-cert.pem ca-int2-ecc-key.der ca-int2-ecc-key.pem ca-int2-key.der ca-int2-key.pem client-chain-alt-ecc.pem client-chain-alt.pem client-chain-ecc.der client-chain-ecc.pem client-chain.der client-chain.pem client-int-cert.der client-int-cert.pem client-int-ecc-cert.der client-int-ecc-cert.pem genintcerts.sh include.am server-chain-alt-ecc.pem server-chain-alt.pem server-chain-ecc.der server-chain-ecc.pem server-chain-short.pem server-chain.der server-chain.pem server-int-cert.der server-int-cert.pem server-int-ecc-cert.der server-int-ecc-cert.pem
lms bc_hss_L2_H5_W8_root.der bc_hss_L3_H5_W4_root.der bc_lms_chain_ca.der bc_lms_chain_leaf.der bc_lms_native_bc_root.der bc_lms_sha256_h10_w8_root.der bc_lms_sha256_h5_w4_root.der include.am
mldsa README.txt include.am mldsa44-cert.der mldsa44-cert.pem mldsa44-key.pem mldsa44_bare-priv.der mldsa44_bare-seed.der mldsa44_oqskeypair.der mldsa44_priv-only.der mldsa44_pub-spki.der mldsa44_seed-only.der mldsa44_seed-priv.der mldsa65-cert.der mldsa65-cert.pem mldsa65-key.pem mldsa65_bare-priv.der mldsa65_bare-seed.der mldsa65_oqskeypair.der mldsa65_priv-only.der mldsa65_pub-spki.der mldsa65_seed-only.der mldsa65_seed-priv.der mldsa87-cert.der mldsa87-cert.pem mldsa87-key.pem mldsa87_bare-priv.der mldsa87_bare-seed.der mldsa87_oqskeypair.der mldsa87_priv-only.der mldsa87_pub-spki.der mldsa87_seed-only.der mldsa87_seed-priv.der
ocsp imposter-root-ca-cert.der imposter-root-ca-cert.pem imposter-root-ca-key.der imposter-root-ca-key.pem include.am index-ca-and-intermediate-cas.txt index-ca-and-intermediate-cas.txt.attr index-intermediate1-ca-issued-certs.txt index-intermediate1-ca-issued-certs.txt.attr index-intermediate2-ca-issued-certs.txt index-intermediate2-ca-issued-certs.txt.attr index-intermediate3-ca-issued-certs.txt index-intermediate3-ca-issued-certs.txt.attr intermediate1-ca-cert.der intermediate1-ca-cert.pem intermediate1-ca-key.der intermediate1-ca-key.pem intermediate2-ca-cert.der intermediate2-ca-cert.pem intermediate2-ca-key.der intermediate2-ca-key.pem intermediate3-ca-cert.der intermediate3-ca-cert.pem intermediate3-ca-key.der intermediate3-ca-key.pem ocsp-responder-cert.der ocsp-responder-cert.pem ocsp-responder-key.der ocsp-responder-key.pem openssl.cnf renewcerts-for-test.sh renewcerts.sh root-ca-cert.der root-ca-cert.pem root-ca-crl.pem root-ca-key.der root-ca-key.pem server1-cert.der server1-cert.pem server1-chain-noroot.pem server1-key.der server1-key.pem server2-cert.der server2-cert.pem server2-key.der server2-key.pem server3-cert.der server3-cert.pem server3-key.der server3-key.pem server4-cert.der server4-cert.pem server4-key.der server4-key.pem server5-cert.der server5-cert.pem server5-key.der server5-key.pem test-leaf-response.der test-multi-response.der test-response-nointern.der test-response-rsapss.der test-response.der
p521 ca-p521-key.der ca-p521-key.pem ca-p521-priv.der ca-p521-priv.pem ca-p521.der ca-p521.pem client-p521-key.der client-p521-key.pem client-p521-priv.der client-p521-priv.pem client-p521.der client-p521.pem gen-p521-certs.sh gen-p521-keys.sh include.am root-p521-key.der root-p521-key.pem root-p521-priv.der root-p521-priv.pem root-p521.der root-p521.pem server-p521-cert.pem server-p521-key.der server-p521-key.pem server-p521-priv.der server-p521-priv.pem server-p521.der server-p521.pem
renewcerts wolfssl.cnf
rpk client-cert-rpk.der client-ecc-cert-rpk.der include.am server-cert-rpk.der server-ecc-cert-rpk.der
rsapss ca-3072-rsapss-key.der ca-3072-rsapss-key.pem ca-3072-rsapss-priv.der ca-3072-rsapss-priv.pem ca-3072-rsapss.der ca-3072-rsapss.pem ca-rsapss-key.der ca-rsapss-key.pem ca-rsapss-priv.der ca-rsapss-priv.pem ca-rsapss.der ca-rsapss.pem client-3072-rsapss-key.der client-3072-rsapss-key.pem client-3072-rsapss-priv.der client-3072-rsapss-priv.pem client-3072-rsapss.der client-3072-rsapss.pem client-rsapss-key.der client-rsapss-key.pem client-rsapss-priv.der client-rsapss-priv.pem client-rsapss.der client-rsapss.pem gen-rsapss-keys.sh include.am renew-rsapss-certs.sh root-3072-rsapss-key.der root-3072-rsapss-key.pem root-3072-rsapss-priv.der root-3072-rsapss-priv.pem root-3072-rsapss.der root-3072-rsapss.pem root-rsapss-key.der root-rsapss-key.pem root-rsapss-priv.der root-rsapss-priv.pem root-rsapss.der root-rsapss.pem server-3072-rsapss-cert.pem server-3072-rsapss-key.der server-3072-rsapss-key.pem server-3072-rsapss-priv.der server-3072-rsapss-priv.pem server-3072-rsapss.der server-3072-rsapss.pem server-mix-rsapss-cert.pem server-rsapss-cert.pem server-rsapss-key.der server-rsapss-key.pem server-rsapss-priv.der server-rsapss-priv.pem server-rsapss.der server-rsapss.pem
sia timestamping-sia-cert.pem
slhdsa bench_slhdsa_sha2_128f_key.der bench_slhdsa_sha2_128s_key.der bench_slhdsa_sha2_192f_key.der bench_slhdsa_sha2_192s_key.der bench_slhdsa_sha2_256f_key.der bench_slhdsa_sha2_256s_key.der bench_slhdsa_shake128f_key.der bench_slhdsa_shake128s_key.der bench_slhdsa_shake192f_key.der bench_slhdsa_shake192s_key.der bench_slhdsa_shake256f_key.der bench_slhdsa_shake256s_key.der client-mldsa44-priv.pem client-mldsa44-sha2.der client-mldsa44-sha2.pem client-mldsa44-shake.der client-mldsa44-shake.pem gen-slhdsa-mldsa-certs.sh include.am root-slhdsa-sha2-128s-priv.der root-slhdsa-sha2-128s-priv.pem root-slhdsa-sha2-128s.der root-slhdsa-sha2-128s.pem root-slhdsa-shake-128s-priv.der root-slhdsa-shake-128s-priv.pem root-slhdsa-shake-128s.der root-slhdsa-shake-128s.pem server-mldsa44-priv.pem server-mldsa44-sha2.der server-mldsa44-sha2.pem server-mldsa44-shake.der server-mldsa44-shake.pem
sm2 ca-sm2-key.der ca-sm2-key.pem ca-sm2-priv.der ca-sm2-priv.pem ca-sm2.der ca-sm2.pem client-sm2-key.der client-sm2-key.pem client-sm2-priv.der client-sm2-priv.pem client-sm2.der client-sm2.pem fix_sm2_spki.py gen-sm2-certs.sh gen-sm2-keys.sh include.am root-sm2-key.der root-sm2-key.pem root-sm2-priv.der root-sm2-priv.pem root-sm2.der root-sm2.pem self-sm2-cert.pem self-sm2-key.pem self-sm2-priv.pem server-sm2-cert.der server-sm2-cert.pem server-sm2-key.der server-sm2-key.pem server-sm2-priv.der server-sm2-priv.pem server-sm2.der server-sm2.pem
statickeys dh-ffdhe2048-params.pem dh-ffdhe2048-pub.der dh-ffdhe2048-pub.pem dh-ffdhe2048.der dh-ffdhe2048.pem ecc-secp256r1.der ecc-secp256r1.pem gen-static.sh include.am x25519-pub.der x25519-pub.pem x25519.der x25519.pem
test
expired expired-ca.der expired-ca.pem expired-cert.der expired-cert.pem
catalog.txt cert-bad-neg-int.der cert-bad-oid.der cert-bad-utf8.der cert-ext-ia.cfg cert-ext-ia.der cert-ext-ia.pem cert-ext-joi.cfg cert-ext-joi.der cert-ext-joi.pem cert-ext-mnc.der cert-ext-multiple.cfg cert-ext-multiple.der cert-ext-multiple.pem cert-ext-nc-combined.der cert-ext-nc-combined.pem cert-ext-nc.cfg cert-ext-nc.der cert-ext-nc.pem cert-ext-ncdns.der cert-ext-ncdns.pem cert-ext-ncip.der cert-ext-ncip.pem cert-ext-ncmixed.der cert-ext-ncmulti.der cert-ext-ncmulti.pem cert-ext-ncrid.der cert-ext-ncrid.pem cert-ext-nct.cfg cert-ext-nct.der cert-ext-nct.pem cert-ext-ndir-exc.cfg cert-ext-ndir-exc.der cert-ext-ndir-exc.pem cert-ext-ndir.cfg cert-ext-ndir.der cert-ext-ndir.pem cert-ext-ns.der cert-over-max-altnames.cfg cert-over-max-altnames.der cert-over-max-altnames.pem cert-over-max-nc.cfg cert-over-max-nc.der cert-over-max-nc.pem client-ecc-cert-ski.hex cn-ip-literal.der cn-ip-wildcard.der crit-cert.pem crit-key.pem dh1024.der dh1024.pem dh512.der dh512.pem digsigku.pem encrypteddata.msg gen-badsig.sh gen-ext-certs.sh gen-testcerts.sh include.am kari-keyid-cms.msg ktri-keyid-cms.msg ossl-trusted-cert.pem server-badaltname.der server-badaltname.pem server-badaltnull.der server-badaltnull.pem server-badcn.der server-badcn.pem server-badcnnull.der server-badcnnull.pem server-cert-ecc-badsig.der server-cert-ecc-badsig.pem server-cert-rsa-badsig.der server-cert-rsa-badsig.pem server-duplicate-policy.pem server-garbage.der server-garbage.pem server-goodalt.der server-goodalt.pem server-goodaltwild.der server-goodaltwild.pem server-goodcn.der server-goodcn.pem server-goodcnwild.der server-goodcnwild.pem server-localhost.der server-localhost.pem smime-test-canon.p7s smime-test-multipart-badsig.p7s smime-test-multipart.p7s smime-test.p7s
test-pathlen assemble-chains.sh chainA-ICA1-key.pem chainA-ICA1-pathlen0.pem chainA-assembled.pem chainA-entity-key.pem chainA-entity.pem chainB-ICA1-key.pem chainB-ICA1-pathlen0.pem chainB-ICA2-key.pem chainB-ICA2-pathlen1.pem chainB-assembled.pem chainB-entity-key.pem chainB-entity.pem chainC-ICA1-key.pem chainC-ICA1-pathlen1.pem chainC-assembled.pem chainC-entity-key.pem chainC-entity.pem chainD-ICA1-key.pem chainD-ICA1-pathlen127.pem chainD-assembled.pem chainD-entity-key.pem chainD-entity.pem chainE-ICA1-key.pem chainE-ICA1-pathlen128.pem chainE-assembled.pem chainE-entity-key.pem chainE-entity.pem chainF-ICA1-key.pem chainF-ICA1-pathlen1.pem chainF-ICA2-key.pem chainF-ICA2-pathlen0.pem chainF-assembled.pem chainF-entity-key.pem chainF-entity.pem chainG-ICA1-key.pem chainG-ICA1-pathlen0.pem chainG-ICA2-key.pem chainG-ICA2-pathlen1.pem chainG-ICA3-key.pem chainG-ICA3-pathlen99.pem chainG-ICA4-key.pem chainG-ICA4-pathlen5.pem chainG-ICA5-key.pem chainG-ICA5-pathlen20.pem chainG-ICA6-key.pem chainG-ICA6-pathlen10.pem chainG-ICA7-key.pem chainG-ICA7-pathlen100.pem chainG-assembled.pem chainG-entity-key.pem chainG-entity.pem chainH-ICA1-key.pem chainH-ICA1-pathlen0.pem chainH-ICA2-key.pem chainH-ICA2-pathlen2.pem chainH-ICA3-key.pem chainH-ICA3-pathlen2.pem chainH-ICA4-key.pem chainH-ICA4-pathlen2.pem chainH-assembled.pem chainH-entity-key.pem chainH-entity.pem chainI-ICA1-key.pem chainI-ICA1-no_pathlen.pem chainI-ICA2-key.pem chainI-ICA2-no_pathlen.pem chainI-ICA3-key.pem chainI-ICA3-pathlen2.pem chainI-assembled.pem chainI-entity-key.pem chainI-entity.pem chainJ-ICA1-key.pem chainJ-ICA1-no_pathlen.pem chainJ-ICA2-key.pem chainJ-ICA2-no_pathlen.pem chainJ-ICA3-key.pem chainJ-ICA3-no_pathlen.pem chainJ-ICA4-key.pem chainJ-ICA4-pathlen2.pem chainJ-assembled.pem chainJ-entity-key.pem chainJ-entity.pem include.am refreshkeys.sh
test-serial0 ee_normal.pem ee_serial0.pem generate_certs.sh include.am intermediate_serial0.pem root_serial0.pem root_serial0_key.pem selfsigned_nonca_serial0.pem
xmss bc_xmss_chain_ca.der bc_xmss_chain_leaf.der bc_xmss_sha2_10_256_root.der bc_xmss_sha2_16_256_root.der bc_xmssmt_sha2_20_2_256_root.der bc_xmssmt_sha2_20_4_256_root.der bc_xmssmt_sha2_40_8_256_root.der include.am
ca-cert-chain.der ca-cert.der ca-cert.pem ca-ecc-cert.der ca-ecc-cert.pem ca-ecc-key.der ca-ecc-key.pem ca-ecc384-cert.der ca-ecc384-cert.pem ca-ecc384-key.der ca-ecc384-key.pem ca-key-pkcs8-attribute.der ca-key.der ca-key.pem check_dates.sh client-absolute-urn.pem client-ca-cert.der client-ca-cert.pem client-ca.pem client-cert-ext.der client-cert-ext.pem client-cert.der client-cert.pem client-crl-dist.der client-crl-dist.pem client-ecc-ca-cert.der client-ecc-ca-cert.pem client-ecc-cert.der client-ecc-cert.pem client-ecc384-cert.der client-ecc384-cert.pem client-ecc384-key.der client-ecc384-key.pem client-key.der client-key.pem client-keyEnc.pem client-keyPub.der client-keyPub.pem client-relative-uri.pem client-uri-cert.pem csr.attr.der csr.dsa.der csr.dsa.pem csr.ext.der csr.signed.der dh-priv-2048.der dh-priv-2048.pem dh-pub-2048.der dh-pub-2048.pem dh-pubkey-2048.der dh2048.der dh2048.pem dh3072.der dh3072.pem dh4096.der dh4096.pem dsa-pubkey-2048.der dsa2048.der dsa2048.pem dsa3072.der dsaparams.der dsaparams.pem ecc-client-key.der ecc-client-key.pem ecc-client-keyPub.der ecc-client-keyPub.pem ecc-key-comp.pem ecc-keyPkcs8.der ecc-keyPkcs8.pem ecc-keyPkcs8Enc.der ecc-keyPkcs8Enc.pem ecc-keyPub.der ecc-keyPub.pem ecc-params.der ecc-params.pem ecc-privOnlyCert.pem ecc-privOnlyKey.pem ecc-privkey.der ecc-privkey.pem ecc-privkeyPkcs8.der ecc-privkeyPkcs8.pem ecc-rsa-server.p12 empty-issuer-cert.pem entity-no-ca-bool-cert.pem entity-no-ca-bool-key.pem fpki-cert.der fpki-certpol-cert.der gen_revoked.sh include.am renewcerts.sh rid-cert.der rsa-pub-2048.pem rsa2048.der rsa3072.der server-cert-chain.der server-cert.der server-cert.pem server-ecc-comp.der server-ecc-comp.pem server-ecc-rsa.der server-ecc-rsa.pem server-ecc-self.der server-ecc-self.pem server-ecc.der server-ecc.pem server-ecc384-cert.der server-ecc384-cert.pem server-ecc384-key.der server-ecc384-key.pem server-key.der server-key.pem server-keyEnc.pem server-keyPkcs8.der server-keyPkcs8.pem server-keyPkcs8Enc.der server-keyPkcs8Enc.pem server-keyPkcs8Enc12.pem server-keyPkcs8Enc2.pem server-keyPub.der server-keyPub.pem server-revoked-cert.pem server-revoked-key.pem taoCert.txt test-ber-exp02-05-2022.p7b test-degenerate.p7b test-multiple-recipients.p7b test-servercert-rc2.p12 test-servercert.p12 test-stream-dec.p7b test-stream-sign.p7b wolfssl-website-ca.pem x942dh2048.der x942dh2048.pem
cmake
consumer CMakeLists.txt README.md main.c
modules FindARIA.cmake FindOQS.cmake
Config.cmake.in README.md config.in functions.cmake include.am options.h.in wolfssl-config-version.cmake.in wolfssl-targets.cmake.in
debian
source format
changelog.in control.in copyright include.am libwolfssl-dev.install libwolfssl.install rules.in
doc
dox_comments
header_files aes.h arc4.h ascon.h asn.h asn_public.h blake2.h bn.h camellia.h chacha.h chacha20_poly1305.h cmac.h coding.h compress.h cryptocb.h curve25519.h curve448.h des3.h dh.h doxygen_groups.h doxygen_pages.h dsa.h ecc.h eccsi.h ed25519.h ed448.h error-crypt.h evp.h hash.h hmac.h iotsafe.h kdf.h logging.h md2.h md4.h md5.h memory.h ocsp.h pem.h pkcs11.h pkcs7.h poly1305.h psa.h puf.h pwdbased.h quic.h random.h ripemd.h rsa.h sakke.h sha.h sha256.h sha3.h sha512.h signature.h siphash.h srp.h ssl.h tfm.h types.h wc_encrypt.h wc_port.h wc_she.h wc_slhdsa.h wolfio.h
header_files-ja aes.h arc4.h ascon.h asn.h asn_public.h blake2.h bn.h camellia.h chacha.h chacha20_poly1305.h cmac.h coding.h compress.h cryptocb.h curve25519.h curve448.h des3.h dh.h doxygen_groups.h doxygen_pages.h dsa.h ecc.h eccsi.h ed25519.h ed448.h error-crypt.h evp.h hash.h hmac.h iotsafe.h kdf.h logging.h md2.h md4.h md5.h memory.h ocsp.h pem.h pkcs11.h pkcs7.h poly1305.h psa.h pwdbased.h quic.h random.h ripemd.h rsa.h sakke.h sha.h sha256.h sha3.h sha512.h signature.h siphash.h srp.h ssl.h tfm.h types.h wc_encrypt.h wc_port.h wolfio.h
formats
html
html_changes
search search.css search.js
customdoxygen.css doxygen.css menu.js menudata.js tabs.css
Doxyfile footer.html header.html mainpage.dox
pdf Doxyfile header.tex
images wolfssl_logo.png
QUIC.md README.txt README_DOXYGEN check_api.sh generate_documentation.sh include.am
examples
asn1 asn1.c dumpasn1.cfg gen_oid_names.rb include.am oid_names.h
async Makefile README.md async_client.c async_server.c async_tls.c async_tls.h include.am user_settings.h
benchmark include.am tls_bench.c tls_bench.h
client client.c client.h client.sln client.vcproj client.vcxproj include.am
configs README.md include.am user_settings_EBSnet.h user_settings_all.h user_settings_arduino.h user_settings_baremetal.h user_settings_ca.h user_settings_curve25519nonblock.h user_settings_dtls13.h user_settings_eccnonblock.h user_settings_espressif.h user_settings_fipsv2.h user_settings_fipsv5.h user_settings_min_ecc.h user_settings_openssl_compat.h user_settings_pkcs7.h user_settings_platformio.h user_settings_pq.h user_settings_rsa_only.h user_settings_stm32.h user_settings_template.h user_settings_tls12.h user_settings_tls13.h user_settings_wolfboot_keytools.h user_settings_wolfssh.h user_settings_wolftpm.h
crypto_policies
default wolfssl.txt
future wolfssl.txt
legacy wolfssl.txt
echoclient echoclient.c echoclient.h echoclient.sln echoclient.vcproj echoclient.vcxproj include.am quit
echoserver echoserver.c echoserver.h echoserver.sln echoserver.vcproj echoserver.vcxproj include.am
ocsp_responder include.am ocsp_responder.c ocsp_responder.h
pem include.am pem.c
sctp include.am sctp-client-dtls.c sctp-client.c sctp-server-dtls.c sctp-server.c
server include.am server.c server.h server.sln server.vcproj server.vcxproj
README.md include.am
linuxkm
patches
5.10.17 WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-5v10v17.patch
5.10.236 WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-5v10v236.patch
5.14.0-570.58.1.el9_6 WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-5v14-570v58v1-el9_6.patch
5.15 WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-5v15.patch
5.17 WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-5v17.patch
5.17-ubuntu-jammy-tegra WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-5v17-ubuntu-jammy-tegra.patch
6.1.73 WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-6v1v73.patch
6.12 WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-6v12.patch
6.15 WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-6v15.patch
7.0 WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-7v0.patch
regen-patches.sh
Kbuild Makefile README.md get_thread_size.c include.am linuxkm-fips-hash-wrapper.sh linuxkm-fips-hash.c linuxkm_memory.c linuxkm_memory.h linuxkm_wc_port.h lkcapi_aes_glue.c lkcapi_dh_glue.c lkcapi_ecdh_glue.c lkcapi_ecdsa_glue.c lkcapi_glue.c lkcapi_rsa_glue.c lkcapi_sha_glue.c module_exports.c.template module_hooks.c pie_redirect_table.c wolfcrypt.lds x86_vector_register_glue.c
m4 ax_add_am_macro.m4 ax_am_jobserver.m4 ax_am_macros.m4 ax_append_compile_flags.m4 ax_append_flag.m4 ax_append_link_flags.m4 ax_append_to_file.m4 ax_atomic.m4 ax_bsdkm.m4 ax_check_compile_flag.m4 ax_check_link_flag.m4 ax_compiler_version.m4 ax_count_cpus.m4 ax_create_generic_config.m4 ax_debug.m4 ax_file_escapes.m4 ax_harden_compiler_flags.m4 ax_linuxkm.m4 ax_print_to_file.m4 ax_pthread.m4 ax_require_defined.m4 ax_tls.m4 ax_vcs_checkout.m4 hexversion.m4 lib_socket_nsl.m4 visibility.m4
mcapi
wolfcrypt_mcapi.X
nbproject configurations.xml include.am project.xml
Makefile
wolfcrypt_test.X
nbproject configurations.xml include.am project.xml
Makefile
wolfssl.X
nbproject configurations.xml include.am project.xml
Makefile
zlib.X
nbproject configurations.xml include.am project.xml
Makefile
PIC32MZ-serial.h README crypto.c crypto.h include.am mcapi_test.c user_settings.h
mplabx
wolfcrypt_benchmark.X
nbproject configurations.xml include.am project.xml
Makefile
wolfcrypt_test.X
nbproject configurations.xml include.am project.xml
Makefile
wolfssl.X
nbproject configurations.xml include.am project.xml
Makefile
PIC32MZ-serial.h README benchmark_main.c include.am test_main.c user_settings.h
mqx
util_lib
Sources include.am util.c util.h
wolfcrypt_benchmark
Debugger K70FN1M0.mem init_kinetis.tcl mass_erase_kinetis.tcl
Sources include.am main.c main.h
ReferencedRSESystems.xml wolfcrypt_benchmark_twrk70f120m_Int_Flash_DDRData_Debug_PnE_U-MultiLink.launch wolfcrypt_benchmark_twrk70f120m_Int_Flash_DDRData_Release_PnE_U-MultiLink.launch wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Debug_JTrace.jlink wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Debug_JTrace.launch wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Debug_PnE_U-MultiLink.launch wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Release_PnE_U-MultiLink.launch
wolfcrypt_test
Debugger K70FN1M0.mem init_kinetis.tcl mass_erase_kinetis.tcl
Sources include.am main.c main.h
ReferencedRSESystems.xml wolfcrypt_test_twrk70f120m_Int_Flash_DDRData_Debug_PnE_U-MultiLink.launch wolfcrypt_test_twrk70f120m_Int_Flash_DDRData_Release_PnE_U-MultiLink.launch wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Debug_JTrace.jlink wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Debug_JTrace.launch wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Debug_PnE_U-MultiLink.launch wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Release_PnE_U-MultiLink.launch
wolfssl include.am
wolfssl_client
Debugger K70FN1M0.mem init_kinetis.tcl mass_erase_kinetis.tcl
Sources include.am main.c main.h
ReferencedRSESystems.xml wolfssl_client_twrk70f120m_Int_Flash_DDRData_Debug_PnE_U-MultiLink.launch wolfssl_client_twrk70f120m_Int_Flash_DDRData_Release_PnE_U-MultiLink.launch wolfssl_client_twrk70f120m_Int_Flash_SramData_Debug_JTrace.jlink wolfssl_client_twrk70f120m_Int_Flash_SramData_Debug_JTrace.launch wolfssl_client_twrk70f120m_Int_Flash_SramData_Debug_PnE_U-MultiLink.launch wolfssl_client_twrk70f120m_Int_Flash_SramData_Release_PnE_U-MultiLink.launch
README
rpm include.am spec.in
scripts
bench bench_functions.sh
aria-cmake-build-test.sh asn1_oid_sum.pl benchmark.test benchmark_compare.sh cleanup_testfiles.sh crl-gen-openssl.test crl-revoked.test dertoc.pl dtls.test dtlscid.test external.test google.test include.am makedistsmall.sh memtest.sh ocsp-responder-openssl-interop.test ocsp-stapling-with-ca-as-responder.test ocsp-stapling-with-wolfssl-responder.test ocsp-stapling.test ocsp-stapling2.test ocsp-stapling_tls13multi.test ocsp.test openssl.test openssl_srtp.test pem.test ping.test pkcallbacks.test psk.test resume.test rsapss.test sniffer-gen.sh sniffer-ipv6.pcap sniffer-static-rsa.pcap sniffer-testsuite.test sniffer-tls12-keylog.out sniffer-tls12-keylog.pcap sniffer-tls12-keylog.sslkeylog sniffer-tls13-dh-resume.pcap sniffer-tls13-dh.pcap sniffer-tls13-ecc-resume.pcap sniffer-tls13-ecc.pcap sniffer-tls13-hrr.pcap sniffer-tls13-keylog.out sniffer-tls13-keylog.pcap sniffer-tls13-keylog.sslkeylog sniffer-tls13-x25519-resume.pcap sniffer-tls13-x25519.pcap stm32l4-v4_0_1_build.sh tls13.test trusted_peer.test unit.test.in user_settings_asm.sh
src bio.c conf.c crl.c dtls.c dtls13.c include.am internal.c keys.c ocsp.c pk.c pk_ec.c pk_rsa.c quic.c sniffer.c ssl.c ssl_api_cert.c ssl_api_crl_ocsp.c ssl_api_pk.c ssl_asn1.c ssl_bn.c ssl_certman.c ssl_crypto.c ssl_ech.c ssl_load.c ssl_misc.c ssl_p7p12.c ssl_sess.c ssl_sk.c tls.c tls13.c wolfio.c x509.c x509_str.c
sslSniffer
sslSnifferTest README_WIN.md include.am snifftest.c sslSniffTest.vcproj sslSniffTest.vcxproj
README.md sslSniffer.vcproj sslSniffer.vcxproj
support gen-debug-trace-error-codes.sh include.am wolfssl.pc.in
tests
api api.h api_decl.h create_ocsp_test_blobs.py include.am test_aes.c test_aes.h test_arc4.c test_arc4.h test_ascon.c test_ascon.h test_ascon_kats.h test_asn.c test_asn.h test_blake2.c test_blake2.h test_camellia.c test_camellia.h test_certman.c test_certman.h test_chacha.c test_chacha.h test_chacha20_poly1305.c test_chacha20_poly1305.h test_cmac.c test_cmac.h test_curve25519.c test_curve25519.h test_curve448.c test_curve448.h test_des3.c test_des3.h test_dh.c test_dh.h test_digest.h test_dsa.c test_dsa.h test_dtls.c test_dtls.h test_ecc.c test_ecc.h test_ed25519.c test_ed25519.h test_ed448.c test_ed448.h test_evp.c test_evp.h test_evp_cipher.c test_evp_cipher.h test_evp_digest.c test_evp_digest.h test_evp_pkey.c test_evp_pkey.h test_hash.c test_hash.h test_hmac.c test_hmac.h test_md2.c test_md2.h test_md4.c test_md4.h test_md5.c test_md5.h test_mldsa.c test_mldsa.h test_mlkem.c test_mlkem.h test_ocsp.c test_ocsp.h test_ocsp_test_blobs.h test_ossl_asn1.c test_ossl_asn1.h test_ossl_bio.c test_ossl_bio.h test_ossl_bn.c test_ossl_bn.h test_ossl_cipher.c test_ossl_cipher.h test_ossl_dgst.c test_ossl_dgst.h test_ossl_dh.c test_ossl_dh.h test_ossl_dsa.c test_ossl_dsa.h test_ossl_ec.c test_ossl_ec.h test_ossl_ecx.c test_ossl_ecx.h test_ossl_mac.c test_ossl_mac.h test_ossl_obj.c test_ossl_obj.h test_ossl_p7p12.c test_ossl_p7p12.h test_ossl_pem.c test_ossl_pem.h test_ossl_rand.c test_ossl_rand.h test_ossl_rsa.c test_ossl_rsa.h test_ossl_sk.c test_ossl_sk.h test_ossl_x509.c test_ossl_x509.h test_ossl_x509_acert.c test_ossl_x509_acert.h test_ossl_x509_crypto.c test_ossl_x509_crypto.h test_ossl_x509_ext.c test_ossl_x509_ext.h test_ossl_x509_info.c test_ossl_x509_info.h test_ossl_x509_io.c test_ossl_x509_io.h test_ossl_x509_lu.c test_ossl_x509_lu.h test_ossl_x509_name.c test_ossl_x509_name.h test_ossl_x509_pk.c test_ossl_x509_pk.h test_ossl_x509_str.c test_ossl_x509_str.h test_ossl_x509_vp.c test_ossl_x509_vp.h test_pkcs12.c test_pkcs12.h test_pkcs7.c test_pkcs7.h test_poly1305.c test_poly1305.h test_random.c test_random.h test_rc2.c test_rc2.h test_ripemd.c test_ripemd.h test_rsa.c test_rsa.h test_sha.c test_sha.h test_sha256.c test_sha256.h test_sha3.c test_sha3.h test_sha512.c test_sha512.h test_she.c test_she.h test_signature.c test_signature.h test_slhdsa.c test_slhdsa.h test_sm2.c test_sm2.h test_sm3.c test_sm3.h test_sm4.c test_sm4.h test_tls.c test_tls.h test_tls13.c test_tls13.h test_tls_ext.c test_tls_ext.h test_wc_encrypt.c test_wc_encrypt.h test_wolfmath.c test_wolfmath.h test_x509.c test_x509.h
emnet
IP IP.h
Makefile emnet_nonblock_test.c emnet_shim.c
freertos-mem-track-repro FreeRTOS.h repro.c run.sh semphr.h task.h user_settings.h
swdev .gitignore Makefile README.md swdev.c swdev.h swdev_loader.c swdev_loader.h user_settings.h
CONF_FILES_README.md NCONF_test.cnf README TXT_DB.txt api.c include.am quic.c srp.c suites.c test-altchains.conf test-chains.conf test-dhprime.conf test-dtls-downgrade.conf test-dtls-fails-cipher.conf test-dtls-fails.conf test-dtls-group.conf test-dtls-mtu.conf test-dtls-reneg-client.conf test-dtls-reneg-server.conf test-dtls-resume.conf test-dtls-sha2.conf test-dtls-srtp-fails.conf test-dtls-srtp.conf test-dtls.conf test-dtls13-cid.conf test-dtls13-downgrade-fails.conf test-dtls13-downgrade.conf test-dtls13-pq-hybrid-extra-frag.conf test-dtls13-pq-hybrid-extra.conf test-dtls13-pq-hybrid-frag.conf test-dtls13-pq-standalone-frag.conf test-dtls13-pq-standalone.conf test-dtls13-psk.conf test-dtls13.conf test-ecc-cust-curves.conf test-ed25519.conf test-ed448.conf test-enckeys.conf test-fails.conf test-maxfrag-dtls.conf test-maxfrag.conf test-p521.conf test-psk-no-id-sha2.conf test-psk-no-id.conf test-psk.conf test-rsapss.conf test-sctp-sha2.conf test-sctp.conf test-sha2.conf test-sig.conf test-sm2.conf test-tls-downgrade.conf test-tls13-down.conf test-tls13-ecc.conf test-tls13-pq-hybrid-extra.conf test-tls13-pq-hybrid.conf test-tls13-pq-standalone.conf test-tls13-psk-certs.conf test-tls13-psk.conf test-tls13-slhdsa-fail.conf test-tls13-slhdsa-sha2.conf test-tls13-slhdsa-shake.conf test-tls13.conf test-trustpeer.conf test.conf unit.c unit.h utils.c utils.h w64wrapper.c
testsuite include.am testsuite.c testsuite.sln testsuite.vcproj testsuite.vcxproj utils.c utils.h
tirtos
packages
ti
net
wolfssl
tests
EK_TM4C1294XL
wolfcrypt
benchmark TM4C1294NC.icf benchmark.cfg main.c package.bld.hide package.xdc
test TM4C1294NC.icf main.c package.bld.hide package.xdc test.cfg
package.bld package.xdc package.xs
.gitignore README include.am products.mak wolfssl.bld wolfssl.mak
wolfcrypt
benchmark README.md benchmark-VS2022.sln benchmark-VS2022.vcxproj benchmark-VS2022.vcxproj.user benchmark.c benchmark.h benchmark.sln benchmark.vcproj benchmark.vcxproj include.am
src
port
Espressif
esp_crt_bundle README.md cacrt_all.pem cacrt_deprecated.pem cacrt_local.pem esp_crt_bundle.c gen_crt_bundle.py pio_install_cryptography.py
README.md esp32_aes.c esp32_mp.c esp32_sha.c esp32_util.c esp_sdk_mem_lib.c esp_sdk_time_lib.c esp_sdk_wifi_lib.c
Renesas README.md renesas_common.c renesas_fspsm_aes.c renesas_fspsm_rsa.c renesas_fspsm_sha.c renesas_fspsm_util.c renesas_rx64_hw_sha.c renesas_rx64_hw_util.c renesas_tsip_aes.c renesas_tsip_rsa.c renesas_tsip_sha.c renesas_tsip_util.c
af_alg afalg_aes.c afalg_hash.c wc_afalg.c
aria aria-crypt.c aria-cryptocb.c
arm armv8-32-aes-asm.S armv8-32-aes-asm_c.c armv8-32-chacha-asm.S armv8-32-chacha-asm_c.c armv8-32-curve25519.S armv8-32-curve25519_c.c armv8-32-mlkem-asm.S armv8-32-mlkem-asm_c.c armv8-32-poly1305-asm.S armv8-32-poly1305-asm_c.c armv8-32-sha256-asm.S armv8-32-sha256-asm_c.c armv8-32-sha3-asm.S armv8-32-sha3-asm_c.c armv8-32-sha512-asm.S armv8-32-sha512-asm_c.c armv8-aes-asm.S armv8-aes-asm_c.c armv8-aes.c armv8-chacha-asm.S armv8-chacha-asm_c.c armv8-curve25519.S armv8-curve25519_c.c armv8-mlkem-asm.S armv8-mlkem-asm_c.c armv8-poly1305-asm.S armv8-poly1305-asm_c.c armv8-sha256-asm.S armv8-sha256-asm_c.c armv8-sha256.c armv8-sha3-asm.S armv8-sha3-asm_c.c armv8-sha512-asm.S armv8-sha512-asm_c.c armv8-sha512.c cryptoCell.c cryptoCellHash.c thumb2-aes-asm.S thumb2-aes-asm_c.c thumb2-chacha-asm.S thumb2-chacha-asm_c.c thumb2-curve25519.S thumb2-curve25519_c.c thumb2-mlkem-asm.S thumb2-mlkem-asm_c.c thumb2-poly1305-asm.S thumb2-poly1305-asm_c.c thumb2-sha256-asm.S thumb2-sha256-asm_c.c thumb2-sha3-asm.S thumb2-sha3-asm_c.c thumb2-sha512-asm.S thumb2-sha512-asm_c.c
atmel README.md atmel.c
autosar README.md cryif.c crypto.c csm.c include.am test.c
caam README.md caam_aes.c caam_doc.pdf caam_driver.c caam_error.c caam_integrity.c caam_qnx.c caam_sha.c wolfcaam_aes.c wolfcaam_cmac.c wolfcaam_ecdsa.c wolfcaam_fsl_nxp.c wolfcaam_hash.c wolfcaam_hmac.c wolfcaam_init.c wolfcaam_qnx.c wolfcaam_rsa.c wolfcaam_seco.c wolfcaam_x25519.c
cavium README.md README_Octeon.md cavium_nitrox.c cavium_octeon_sync.c
cuda README.md aes-cuda.cu
cypress README.md psoc6_crypto.c
devcrypto README.md devcrypto_aes.c devcrypto_ecdsa.c devcrypto_hash.c devcrypto_hmac.c devcrypto_rsa.c devcrypto_x25519.c wc_devcrypto.c
intel README.md quickassist.c quickassist_mem.c quickassist_sync.c
iotsafe iotsafe.c
kcapi README.md kcapi_aes.c kcapi_dh.c kcapi_ecc.c kcapi_hash.c kcapi_hmac.c kcapi_rsa.c
liboqs liboqs.c
maxim README.md max3266x.c maxq10xx.c
mynewt mynewt_port.c
nxp README.md README_SE050.md casper_port.c dcp_port.c hashcrypt_port.c ksdk_port.c se050_port.c
pic32 pic32mz-crypt.c
ppc32 ppc32-sha256-asm.S ppc32-sha256-asm_c.c ppc32-sha256-asm_cr.c
psa README.md psa.c psa_aes.c psa_hash.c psa_pkcbs.c
riscv riscv-64-aes.c riscv-64-chacha.c riscv-64-poly1305.c riscv-64-sha256.c riscv-64-sha3.c riscv-64-sha512.c
rpi_pico README.md pico.c
silabs README.md silabs_aes.c silabs_ecc.c silabs_hash.c silabs_random.c
st README.md STM32MP13.md STM32MP25.md stm32.c stsafe.c
ti ti-aes.c ti-ccm.c ti-des3.c ti-hash.c
tropicsquare README.md tropic01.c
xilinx xil-aesgcm.c xil-sha3.c xil-versal-glue.c xil-versal-trng.c
nrf51.c
ASN_TEMPLATE.md aes.c aes_asm.S aes_asm.asm aes_gcm_asm.S aes_gcm_asm.asm aes_gcm_x86_asm.S aes_xts_asm.S aes_xts_asm.asm arc4.c ascon.c asm.c asn.c asn_orig.c async.c blake2b.c blake2s.c camellia.c chacha.c chacha20_poly1305.c chacha_asm.S chacha_asm.asm cmac.c coding.c compress.c cpuid.c cryptocb.c curve25519.c curve448.c des3.c dh.c dilithium.c dsa.c ecc.c ecc_fp.c eccsi.c ed25519.c ed448.c error.c evp.c evp_pk.c falcon.c fe_448.c fe_low_mem.c fe_operations.c fe_x25519_128.h fe_x25519_asm.S fp_mont_small.i fp_mul_comba_12.i fp_mul_comba_17.i fp_mul_comba_20.i fp_mul_comba_24.i fp_mul_comba_28.i fp_mul_comba_3.i fp_mul_comba_32.i fp_mul_comba_4.i fp_mul_comba_48.i fp_mul_comba_6.i fp_mul_comba_64.i fp_mul_comba_7.i fp_mul_comba_8.i fp_mul_comba_9.i fp_mul_comba_small_set.i fp_sqr_comba_12.i fp_sqr_comba_17.i fp_sqr_comba_20.i fp_sqr_comba_24.i fp_sqr_comba_28.i fp_sqr_comba_3.i fp_sqr_comba_32.i fp_sqr_comba_4.i fp_sqr_comba_48.i fp_sqr_comba_6.i fp_sqr_comba_64.i fp_sqr_comba_7.i fp_sqr_comba_8.i fp_sqr_comba_9.i fp_sqr_comba_small_set.i ge_448.c ge_low_mem.c ge_operations.c hash.c hmac.c hpke.c include.am integer.c kdf.c logging.c md2.c md4.c md5.c memory.c misc.c pkcs12.c pkcs7.c poly1305.c poly1305_asm.S poly1305_asm.asm puf.c pwdbased.c random.c rc2.c ripemd.c rng_bank.c rsa.c sakke.c sha.c sha256.c sha256_asm.S sha3.c sha3_asm.S sha512.c sha512_asm.S signature.c siphash.c sm2.c sm3.c sm3_asm.S sm4.c sp_arm32.c sp_arm64.c sp_armthumb.c sp_c32.c sp_c64.c sp_cortexm.c sp_dsp32.c sp_int.c sp_sm2_arm32.c sp_sm2_arm64.c sp_sm2_armthumb.c sp_sm2_c32.c sp_sm2_c64.c sp_sm2_cortexm.c sp_sm2_x86_64.c sp_sm2_x86_64_asm.S sp_x86_64.c sp_x86_64_asm.S sp_x86_64_asm.asm srp.c tfm.c wc_dsp.c wc_encrypt.c wc_lms.c wc_lms_impl.c wc_mldsa_asm.S wc_mlkem.c wc_mlkem_asm.S wc_mlkem_poly.c wc_pkcs11.c wc_port.c wc_she.c wc_slhdsa.c wc_xmss.c wc_xmss_impl.c wolfentropy.c wolfevent.c wolfmath.c
test README.md include.am test-VS2022.sln test-VS2022.vcxproj test-VS2022.vcxproj.user test.c test.h test.sln test.vcproj test_paths.h.in
wolfssl
openssl aes.h asn1.h asn1t.h bio.h bn.h buffer.h camellia.h cmac.h cms.h compat_types.h conf.h crypto.h des.h dh.h dsa.h ec.h ec25519.h ec448.h ecdh.h ecdsa.h ed25519.h ed448.h engine.h err.h evp.h fips_rand.h hmac.h include.am kdf.h lhash.h md4.h md5.h modes.h obj_mac.h objects.h ocsp.h opensslconf.h opensslv.h ossl_typ.h pem.h pkcs12.h pkcs7.h rand.h rc4.h ripemd.h rsa.h safestack.h sha.h sha3.h srp.h ssl.h ssl23.h stack.h tls1.h txt_db.h ui.h x509.h x509_vfy.h x509v3.h
wolfcrypt
port
Espressif esp-sdk-lib.h esp32-crypt.h esp_crt_bundle.h
Renesas renesas-fspsm-crypt.h renesas-fspsm-types.h renesas-rx64-hw-crypt.h renesas-tsip-crypt.h renesas_cmn.h renesas_fspsm_internal.h renesas_sync.h renesas_tsip_internal.h renesas_tsip_types.h
af_alg afalg_hash.h wc_afalg.h
aria aria-crypt.h aria-cryptocb.h
arm cryptoCell.h
atmel atmel.h
autosar CryIf.h Crypto.h Csm.h StandardTypes.h
caam caam_driver.h caam_error.h caam_qnx.h wolfcaam.h wolfcaam_aes.h wolfcaam_cmac.h wolfcaam_ecdsa.h wolfcaam_fsl_nxp.h wolfcaam_hash.h wolfcaam_qnx.h wolfcaam_rsa.h wolfcaam_seco.h wolfcaam_sha.h wolfcaam_x25519.h
cavium cavium_nitrox.h cavium_octeon_sync.h
cypress psoc6_crypto.h
devcrypto wc_devcrypto.h
intel quickassist.h quickassist_mem.h quickassist_sync.h
iotsafe iotsafe.h
kcapi kcapi_dh.h kcapi_ecc.h kcapi_hash.h kcapi_hmac.h kcapi_rsa.h wc_kcapi.h
liboqs liboqs.h
maxim max3266x-cryptocb.h max3266x.h maxq10xx.h
nxp casper_port.h dcp_port.h hashcrypt_port.h ksdk_port.h se050_port.h
pic32 pic32mz-crypt.h
psa psa.h
riscv riscv-64-asm.h
rpi_pico pico.h
silabs silabs_aes.h silabs_ecc.h silabs_hash.h silabs_random.h
st stm32.h stsafe.h
ti ti-ccm.h ti-hash.h
tropicsquare tropic01.h
xilinx xil-sha3.h xil-versal-glue.h xil-versal-trng.h
nrf51.h
aes.h arc4.h ascon.h asn.h asn_public.h async.h blake2-impl.h blake2-int.h blake2.h camellia.h chacha.h chacha20_poly1305.h cmac.h coding.h compress.h cpuid.h cryptocb.h curve25519.h curve448.h des3.h dh.h dilithium.h dsa.h ecc.h eccsi.h ed25519.h ed448.h error-crypt.h falcon.h fe_448.h fe_operations.h fips_test.h ge_448.h ge_operations.h hash.h hmac.h hpke.h include.am integer.h kdf.h libwolfssl_sources.h libwolfssl_sources_asm.h logging.h md2.h md4.h md5.h mem_track.h memory.h misc.h mpi_class.h mpi_superclass.h oid_sum.h pkcs11.h pkcs12.h pkcs7.h poly1305.h puf.h pwdbased.h random.h rc2.h ripemd.h rng_bank.h rsa.h sakke.h selftest.h settings.h sha.h sha256.h sha3.h sha512.h signature.h siphash.h sm2.h sm3.h sm4.h sp.h sp_int.h srp.h tfm.h types.h visibility.h wc_encrypt.h wc_lms.h wc_mlkem.h wc_pkcs11.h wc_port.h wc_she.h wc_slhdsa.h wc_xmss.h wolfentropy.h wolfevent.h wolfmath.h
callbacks.h certs_test.h certs_test_sm.h crl.h error-ssl.h include.am internal.h ocsp.h options.h.in quic.h sniffer.h sniffer_error.h sniffer_error.rc ssl.h test.h version.h version.h.in wolfio.h
wrapper
Ada
examples
src aes_verify_main.adb rsa_verify_main.adb sha256_main.adb spark_sockets.adb spark_sockets.ads spark_terminal.adb spark_terminal.ads tls_client.adb tls_client.ads tls_client_main.adb tls_server.adb tls_server.ads tls_server_main.adb
.gitignore alire.toml examples.gpr
tests
src
support test_support.adb test_support.ads tests_root_suite.adb tests_root_suite.ads
aes_bindings_tests.adb aes_bindings_tests.ads rsa_verify_bindings_tests.adb rsa_verify_bindings_tests.ads sha256_bindings_tests.adb sha256_bindings_tests.ads tests.adb
.gitignore README.md alire.toml tests.gpr valgrind.supp
.gitignore README.md ada_binding.c alire.toml default.gpr include.am restricted.adc user_settings.h wolfssl-full_runtime.adb wolfssl-full_runtime.ads wolfssl.adb wolfssl.ads wolfssl.gpr
CSharp
wolfCrypt-Test
Properties AssemblyInfo.cs
App.config wolfCrypt-Test.cs wolfCrypt-Test.csproj
wolfSSL-DTLS-PSK-Server
Properties AssemblyInfo.cs
App.config wolfSSL-DTLS-PSK-Server.cs wolfSSL-DTLS-PSK-Server.csproj
wolfSSL-DTLS-Server
Properties AssemblyInfo.cs
App.config wolfSSL-DTLS-Server.cs wolfSSL-DTLS-Server.csproj
wolfSSL-Example-IOCallbacks
Properties AssemblyInfo.cs
App.config wolfSSL-Example-IOCallbacks.cs wolfSSL-Example-IOCallbacks.csproj
wolfSSL-TLS-Client
Properties AssemblyInfo.cs
App.config wolfSSL-TLS-Client.cs wolfSSL-TLS-Client.csproj
wolfSSL-TLS-PSK-Client
Properties AssemblyInfo.cs
App.config wolfSSL-TLS-PSK-Client.cs wolfSSL-TLS-PSK-Client.csproj
wolfSSL-TLS-PSK-Server
Properties AssemblyInfo.cs
App.config wolfSSL-TLS-PSK-Server.cs wolfSSL-TLS-PSK-Server.csproj
wolfSSL-TLS-Server
Properties AssemblyInfo.cs
App.config wolfSSL-TLS-Server.cs wolfSSL-TLS-Server.csproj
wolfSSL-TLS-ServerThreaded
Properties AssemblyInfo.cs
App.config wolfSSL-TLS-ServerThreaded.cs wolfSSL-TLS-ServerThreaded.csproj
wolfSSL_CSharp
Properties AssemblyInfo.cs Resources.Designer.cs Resources.resx
X509.cs wolfCrypt.cs wolfSSL.cs wolfSSL_CSharp.csproj
README.md include.am user_settings.h wolfSSL_CSharp.sln wolfssl.vcxproj
python README.md
rust
wolfssl-wolfcrypt
src aes.rs blake2.rs chacha20_poly1305.rs cmac.rs cmac_mac.rs curve25519.rs dh.rs dilithium.rs ecc.rs ecdsa.rs ed25519.rs ed448.rs fips.rs hkdf.rs hmac.rs hmac_mac.rs kdf.rs lib.rs lms.rs mlkem.rs mlkem_kem.rs pbkdf2_password_hash.rs prf.rs random.rs rsa.rs rsa_pkcs1v15.rs sha.rs sha_digest.rs sys.rs
tests
common mod.rs
test_aes.rs test_blake2.rs test_chacha20_poly1305.rs test_cmac.rs test_cmac_mac.rs test_curve25519.rs test_dh.rs test_dilithium.rs test_ecc.rs test_ecdsa.rs test_ed25519.rs test_ed448.rs test_hkdf.rs test_hmac.rs test_hmac_mac.rs test_kdf.rs test_lms.rs test_mlkem.rs test_mlkem_kem.rs test_pbkdf2_password_hash.rs test_prf.rs test_random.rs test_rsa.rs test_rsa_pkcs1v15.rs test_sha.rs test_sha_digest.rs test_wolfcrypt.rs
CHANGELOG.md Cargo.lock Cargo.toml Makefile README.md build.rs headers.h
Makefile README.md include.am
include.am
zephyr
samples
wolfssl_benchmark
boards native_sim.conf nrf5340dk_nrf5340_cpuapp.conf nrf5340dk_nrf5340_cpuapp_ns.conf
CMakeLists.txt README install_test.sh prj.conf sample.yaml zephyr_legacy.conf zephyr_v4.1.conf
wolfssl_test
boards native_sim.conf nrf5340dk_nrf5340_cpuapp.conf nrf5340dk_nrf5340_cpuapp_ns.conf
CMakeLists.txt README install_test.sh prj-no-malloc.conf prj.conf sample.yaml zephyr_legacy.conf zephyr_v4.1.conf
wolfssl_tls_sock
boards native_sim.conf
src tls_sock.c
CMakeLists.txt README install_sample.sh prj-no-malloc.conf prj.conf sample.yaml zephyr_legacy.conf zephyr_v4.1.conf
wolfssl_tls_thread
boards native_sim.conf nrf5340dk_nrf5340_cpuapp.conf nrf5340dk_nrf5340_cpuapp_ns.conf
src tls_threaded.c
CMakeLists.txt README install_sample.sh prj.conf sample.yaml zephyr_legacy.conf zephyr_v4.1.conf
wolfssl options.h
CMakeLists.txt Kconfig Kconfig.tls-generic README.md include.am module.yml user_settings-no-malloc.h user_settings.h zephyr_init.c
.codespellexcludelines .cyignore .editorconfig .gitignore .wolfssl_known_macro_extras AUTHORS CMakeLists.txt CMakePresets.json CMakeSettings.json COPYING ChangeLog.md INSTALL LICENSING LPCExpresso.cproject LPCExpresso.project Makefile.am README README-async.md README.md SCRIPTS-LIST SECURITY-POLICY.md SECURITY-REPORT-TEMPLATE.md Vagrantfile autogen.sh commit-tests.sh configure.ac fips-check.sh fips-hash.sh gencertbuf.pl input pull_to_vagrant.sh quit resource.h stamp-h.in valgrind-bash.supp valgrind-error.sh wnr-example.conf wolfssl-VS2022.vcxproj wolfssl.rc wolfssl.vcproj wolfssl.vcxproj wolfssl64.sln
.clangd .gitignore DOCS.md Makefile README.md assert.c core.c crypto.c env.c fs.c http.c ini.c json.c log.c luna.h main.c makext.mk path.c process.c request.c sqlite.c stash.c template.c util.c
wolfssl/wolfcrypt/src/pkcs7.c raw
    1/* pkcs7.c
    2 *
    3 * Copyright (C) 2006-2026 wolfSSL Inc.
    4 *
    5 * This file is part of wolfSSL.
    6 *
    7 * wolfSSL is free software; you can redistribute it and/or modify
    8 * it under the terms of the GNU General Public License as published by
    9 * the Free Software Foundation; either version 3 of the License, or
   10 * (at your option) any later version.
   11 *
   12 * wolfSSL is distributed in the hope that it will be useful,
   13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
   14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   15 * GNU General Public License for more details.
   16 *
   17 * You should have received a copy of the GNU General Public License
   18 * along with this program; if not, write to the Free Software
   19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
   20 */
   21
   22/*
   23 * PKCS#7 Build Options:
   24 *
   25 * Core:
   26 * HAVE_PKCS7:               Enable PKCS#7 support                 default: off
   27 * NO_PKCS7_STREAM:          Disable PKCS#7 streaming mode         default: off
   28 * NO_PKCS7_ENCRYPTED_DATA:  Disable PKCS#7 EncryptedData type    default: off
   29 * NO_PKCS7_COMPRESSED_DATA: Disable PKCS#7 CompressedData type   default: off
   30 * WC_PKCS7_STREAM_DEBUG:    Enable PKCS#7 stream debug output    default: off
   31 * WOLFSSL_PKCS7_MAX_DECOMPRESSION: Max decompression size        default: off
   32 *
   33 * Callbacks:
   34 * HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK: Custom RSA raw sign callback default: off
   35 * HAVE_PKCS7_ECC_RAW_SIGN_CALLBACK: Custom ECC raw sign callback default: off
   36 *
   37 * Key Derivation:
   38 * HAVE_X963_KDF:            Enable ANSI X9.63 KDF                 default: off
   39 */
   40
   41#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
   42
   43#ifdef HAVE_PKCS7
   44
   45#include <wolfssl/wolfcrypt/pkcs7.h>
   46#include <wolfssl/wolfcrypt/hash.h>
   47#ifndef NO_HMAC
   48    #include <wolfssl/wolfcrypt/hmac.h>
   49#endif
   50#ifndef NO_RSA
   51    #include <wolfssl/wolfcrypt/rsa.h>
   52#endif
   53#ifndef RSA_PSS_SALT_LEN_DEFAULT
   54    #define RSA_PSS_SALT_LEN_DEFAULT (-1)
   55#endif
   56#if defined(WC_RSA_PSS) && !defined(NO_RSA)
   57    #if (defined(HAVE_FIPS) && \
   58            (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))) || \
   59        (defined(HAVE_SELFTEST) && \
   60            (!defined(HAVE_SELFTEST_VERSION) || (HAVE_SELFTEST_VERSION < 2)))
   61        #ifndef WC_MGF1NONE
   62            #define WC_MGF1NONE       0
   63            #define WC_MGF1SHA1       26
   64            #define WC_MGF1SHA224     4
   65            #define WC_MGF1SHA256     1
   66            #define WC_MGF1SHA384     2
   67            #define WC_MGF1SHA512     3
   68            #define WC_MGF1SHA512_224 5
   69            #define WC_MGF1SHA512_256 6
   70        #endif
   71    #endif
   72#endif
   73#ifdef HAVE_ECC
   74    #include <wolfssl/wolfcrypt/ecc.h>
   75#endif
   76#ifdef HAVE_LIBZ
   77    #include <wolfssl/wolfcrypt/compress.h>
   78#endif
   79#ifndef NO_PWDBASED
   80    #include <wolfssl/wolfcrypt/pwdbased.h>
   81#endif
   82#ifdef NO_INLINE
   83    #include <wolfssl/wolfcrypt/misc.h>
   84#else
   85    #define WOLFSSL_MISC_INCLUDED
   86    #include <wolfcrypt/src/misc.c>
   87#endif
   88
   89/* direction for processing, encoding or decoding */
   90typedef enum {
   91    WC_PKCS7_ENCODE,
   92    WC_PKCS7_DECODE
   93} pkcs7Direction;
   94
   95#define NO_USER_CHECK 0
   96
   97/* holds information about the signers */
   98struct PKCS7SignerInfo {
   99    int version;
  100    int sidType;    /* CMS_ISSUER_AND_SERIAL_NUMBER or CMS_SKID */
  101    byte  *sid;
  102    word32 sidSz;
  103};
  104
  105
  106#ifndef WOLFSSL_PKCS7_MAX_DECOMPRESSION
  107    /* 1031 comes from "Maximum Compression Factor" in the zlib tech document,
  108     * typical compression is from 2:1 to 5:1 but there is rare cases where
  109     * 1030.3:1 could happen (like a file with all 0's)
  110     */
  111    #define WOLFSSL_PKCS7_MAX_DECOMPRESSION 1031
  112#endif
  113
  114#ifndef NO_PKCS7_STREAM
  115
  116/* Hard upper bound on a single PKCS7 streaming buffer allocation. Guards
  117 * wc_PKCS7_GrowStream against attacker-controlled ASN.1 lengths that were
  118 * parsed with NO_USER_CHECK and would otherwise drive allocations up to
  119 * around 2GB (e.g. via a forged RecipientInfo SET length). 16 MB is well above
  120 * any legitimate RecipientInfo / encoded-attribute size but small enough
  121 * that a forged length fails allocation on constrained targets and is
  122 * rejected on larger ones. */
  123#ifndef WOLFSSL_PKCS7_MAX_STREAM_ALLOC
  124    #define WOLFSSL_PKCS7_MAX_STREAM_ALLOC (16 * 1024 * 1024)
  125#endif
  126
  127#define MAX_PKCS7_STREAM_BUFFER 256
  128struct PKCS7State {
  129    byte* tmpCert;
  130    byte* bufferPt;
  131    byte* key;
  132    byte* nonce;    /* stored nonce */
  133    byte* aad;      /* additional data for AEAD algos */
  134    byte* tag;      /* tag data for AEAD algos */
  135    byte* content;
  136    byte* buffer;   /* main internal read buffer */
  137
  138    wc_HashAlg  hashAlg;
  139    enum wc_HashType hashType;
  140    int   cntIdfCnt; /* count of in-definite length in content info */
  141
  142    /* stack variables to store for when returning */
  143    word32 varOne;
  144    int    varTwo;
  145    int    varThree;
  146
  147    word32 vers;
  148    word32 idx;      /* index read into current input buffer */
  149    word32 maxLen;   /* sanity cap on maximum amount of data to allow
  150                      * needed for GetSequence and other calls */
  151    word32 length;   /* amount of data stored */
  152    word32 bufferSz; /* size of internal buffer */
  153    word32 expected; /* next amount of data expected, if needed */
  154    word32 totalRd;  /* total amount of bytes read */
  155    word32 nonceSz;  /* size of nonce stored */
  156    word32 aadSz;    /* size of additional AEAD data */
  157    word32 tagSz;    /* size of tag for AEAD */
  158    word32 icvSz;    /* expected ICV/MAC size from AlgoID parameter */
  159    word32 contentSz;
  160    word32 currContIdx;   /* index of current content */
  161    word32 currContSz;    /* size of current content */
  162    word32 currContRmnSz; /* remaining size of current content */
  163    word32 accumContSz;   /* size of accumulated content size */
  164    int recipientSz; /* size of recipient set */
  165    byte tmpIv[MAX_CONTENT_IV_SIZE]; /* store IV if needed */
  166#ifdef WC_PKCS7_STREAM_DEBUG
  167    word32 peakUsed; /* most bytes used for struct at any one time */
  168    word32 peakRead; /* most bytes used by read buffer */
  169#endif
  170    WC_BITFIELD multi:1;  /* flag for if content is in multiple parts */
  171    WC_BITFIELD flagOne:1;
  172    WC_BITFIELD detached:1; /* flag to indicate detached signature is present */
  173    WC_BITFIELD noContent:1;/* indicates content isn't included in bundle */
  174    WC_BITFIELD degenerate:1;
  175    WC_BITFIELD indefLen:1; /* flag to indicate indef-length encoding used */
  176};
  177
  178
  179/* creates a PKCS7State structure and returns 0 on success */
  180static int wc_PKCS7_CreateStream(wc_PKCS7* pkcs7)
  181{
  182    WOLFSSL_MSG("creating PKCS7 stream structure");
  183    pkcs7->stream = (PKCS7State*)XMALLOC(sizeof(PKCS7State), pkcs7->heap,
  184        DYNAMIC_TYPE_PKCS7);
  185    if (pkcs7->stream == NULL) {
  186        return MEMORY_E;
  187    }
  188    XMEMSET(pkcs7->stream, 0, sizeof(PKCS7State));
  189#ifdef WC_PKCS7_STREAM_DEBUG
  190    printf("\nCreating new PKCS#7 stream %p\n", pkcs7->stream);
  191#endif
  192    return 0;
  193}
  194
  195
  196static void wc_PKCS7_ResetStream(wc_PKCS7* pkcs7)
  197{
  198    if (pkcs7 != NULL && pkcs7->stream != NULL) {
  199#ifdef WC_PKCS7_STREAM_DEBUG
  200        /* collect final data point in case more was read right before reset */
  201        if (pkcs7->stream->length > pkcs7->stream->peakRead) {
  202            pkcs7->stream->peakRead = pkcs7->stream->length;
  203        }
  204        if (pkcs7->stream->bufferSz + pkcs7->stream->aadSz +
  205                pkcs7->stream->nonceSz + pkcs7->stream->tagSz >
  206                pkcs7->stream->peakUsed) {
  207            pkcs7->stream->peakUsed = pkcs7->stream->bufferSz +
  208                pkcs7->stream->aadSz + pkcs7->stream->nonceSz +
  209                pkcs7->stream->tagSz;
  210        }
  211
  212        /* print out debugging statistics */
  213        if (pkcs7->stream->peakUsed > 0 || pkcs7->stream->peakRead > 0) {
  214            printf("PKCS#7 STREAM:\n\tPeak heap used by struct = %d"
  215                                 "\n\tPeak read buffer bytes   = %d"
  216                                 "\n\tTotal bytes read         = %d"
  217                                 "\n",
  218                   pkcs7->stream->peakUsed, pkcs7->stream->peakRead,
  219                   pkcs7->stream->totalRd);
  220        }
  221        printf("PKCS#7 stream reset : Address [%p]\n", pkcs7->stream);
  222    #endif
  223
  224        /* free any buffers that may be allocated */
  225        if (pkcs7->stream->aad != NULL && pkcs7->stream->aadSz > 0)
  226            ForceZero(pkcs7->stream->aad, pkcs7->stream->aadSz);
  227        XFREE(pkcs7->stream->aad, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
  228        XFREE(pkcs7->stream->tag, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
  229        XFREE(pkcs7->stream->nonce, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
  230        XFREE(pkcs7->stream->buffer, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
  231        /* stream->key is always allocated with MAX_ENCRYPTED_KEY_SZ */
  232        if (pkcs7->stream->key != NULL)
  233            ForceZero(pkcs7->stream->key, MAX_ENCRYPTED_KEY_SZ);
  234        XFREE(pkcs7->stream->key, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
  235        pkcs7->stream->aad    = NULL;
  236        pkcs7->stream->tag    = NULL;
  237        pkcs7->stream->nonce  = NULL;
  238        pkcs7->stream->buffer = NULL;
  239        pkcs7->stream->key    = NULL;
  240
  241        /* reset values, note that content and tmpCert are saved */
  242        pkcs7->stream->maxLen   = 0;
  243        pkcs7->stream->length   = 0;
  244        pkcs7->stream->idx      = 0;
  245        pkcs7->stream->expected = 0;
  246        pkcs7->stream->totalRd  = 0;
  247        pkcs7->stream->bufferSz = 0;
  248
  249        pkcs7->stream->multi    = 0;
  250        pkcs7->stream->flagOne  = 0;
  251        pkcs7->stream->detached = 0;
  252        pkcs7->stream->varOne   = 0;
  253        pkcs7->stream->varTwo   = 0;
  254        pkcs7->stream->varThree = 0;
  255        pkcs7->stream->noContent    = 0;
  256        pkcs7->stream->indefLen     = 0;
  257        pkcs7->stream->cntIdfCnt    = 0;
  258        pkcs7->stream->currContIdx  = 0;
  259        pkcs7->stream->currContSz   = 0;
  260        pkcs7->stream->currContRmnSz= 0;
  261        pkcs7->stream->accumContSz  = 0;
  262        pkcs7->stream->contentSz    = 0;
  263        pkcs7->stream->hashType     = WC_HASH_TYPE_NONE;
  264    }
  265}
  266
  267
  268static void wc_PKCS7_FreeStream(wc_PKCS7* pkcs7)
  269{
  270    if (pkcs7 != NULL && pkcs7->stream != NULL) {
  271        wc_PKCS7_ResetStream(pkcs7);
  272
  273        XFREE(pkcs7->stream->content, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
  274        XFREE(pkcs7->stream->tmpCert, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
  275        pkcs7->stream->content = NULL;
  276        pkcs7->stream->tmpCert = NULL;
  277        XFREE(pkcs7->stream, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
  278        pkcs7->stream = NULL;
  279    }
  280}
  281
  282
  283/* used to increase the max size for internal buffer
  284 * returns 0 on success  */
  285static int wc_PKCS7_GrowStream(wc_PKCS7* pkcs7, word32 newSz)
  286{
  287    byte* pt;
  288
  289    /* Guard against attacker-controlled ASN.1 lengths reaching this
  290     * allocation. Several callers parse lengths with NO_USER_CHECK and
  291     * pass them here unvalidated (e.g. wc_PKCS7_ParseToRecipientInfoSet
  292     * on a forged RecipientInfo SET header). */
  293    if (newSz > WOLFSSL_PKCS7_MAX_STREAM_ALLOC) {
  294        WOLFSSL_MSG("PKCS7 streaming allocation exceeds maximum");
  295        return BUFFER_E;
  296    }
  297
  298    pt = (byte*)XMALLOC(newSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
  299    if (pt == NULL) {
  300        return MEMORY_E;
  301    }
  302
  303    if (pkcs7->stream->buffer != NULL && pkcs7->stream->bufferSz > 0) {
  304        XMEMCPY(pt, pkcs7->stream->buffer, pkcs7->stream->bufferSz);
  305    }
  306
  307#ifdef WC_PKCS7_STREAM_DEBUG
  308    printf("PKCS7 increasing internal stream buffer %d -> %d\n",
  309            pkcs7->stream->bufferSz, newSz);
  310#endif
  311    pkcs7->stream->bufferSz = newSz;
  312    XFREE(pkcs7->stream->buffer, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
  313    pkcs7->stream->buffer = pt;
  314    return 0;
  315}
  316
  317
  318/* pt gets set to the buffer that is holding data in the case that stream struct
  319 *    is used.
  320 *
  321 * Sets idx to be the current offset into "pt" buffer
  322 * returns 0 on success
  323 */
  324static int wc_PKCS7_AddDataToStream(wc_PKCS7* pkcs7, byte* in, word32 inSz,
  325        word32 expected, byte** pt, word32* idx)
  326{
  327    word32 rdSz = pkcs7->stream->idx;
  328
  329    /* If the input size minus current index into input buffer is greater than
  330     * the expected size then use the input buffer. If data is already stored
  331     * in stream buffer or if there is not enough input data available then use
  332     * the stream buffer. */
  333    if (inSz - rdSz >= expected && pkcs7->stream->length == 0) {
  334        /* storing input buffer is not needed */
  335        *pt  = in; /* reset in case previously used internal buffer */
  336        *idx = rdSz;
  337        return 0;
  338    }
  339
  340    /* is there enough stored in buffer already? */
  341    if (pkcs7->stream->length >= expected) {
  342        *idx = 0; /* start reading from beginning of stream buffer */
  343        *pt  = pkcs7->stream->buffer;
  344        return 0;
  345    }
  346
  347    /* check if all data has been read from input */
  348    if (rdSz >= inSz) {
  349        /* no more input to read, reset input index and request more data */
  350        pkcs7->stream->idx = 0;
  351        return WC_NO_ERR_TRACE(WC_PKCS7_WANT_READ_E);
  352    }
  353
  354    /* try to store input data into stream buffer */
  355    if (inSz - rdSz > 0 && pkcs7->stream->length < expected) {
  356        word32 len = min(inSz - rdSz, expected - pkcs7->stream->length);
  357
  358        /* sanity check that the input buffer is not internal buffer */
  359        if (in == pkcs7->stream->buffer) {
  360            return WC_PKCS7_WANT_READ_E;
  361        }
  362
  363        /* check if internal buffer size needs to be increased */
  364        if ((len + pkcs7->stream->length > pkcs7->stream->bufferSz) ||
  365            (pkcs7->stream->buffer == NULL))
  366        {
  367            int ret = wc_PKCS7_GrowStream(pkcs7, expected);
  368            if (ret < 0) {
  369                return ret;
  370            }
  371        }
  372        XMEMCPY(pkcs7->stream->buffer + pkcs7->stream->length, in + rdSz, len);
  373        pkcs7->stream->length  += len;
  374        pkcs7->stream->idx     += len;
  375        pkcs7->stream->totalRd += len;
  376    }
  377
  378#ifdef WC_PKCS7_STREAM_DEBUG
  379    /* collects memory usage for debugging */
  380    if (pkcs7->stream->length > pkcs7->stream->peakRead) {
  381        pkcs7->stream->peakRead = pkcs7->stream->length;
  382    }
  383    if (pkcs7->stream->bufferSz + pkcs7->stream->aadSz + pkcs7->stream->nonceSz +
  384        pkcs7->stream->tagSz > pkcs7->stream->peakUsed) {
  385        pkcs7->stream->peakUsed = pkcs7->stream->bufferSz +
  386           pkcs7->stream->aadSz + pkcs7->stream->nonceSz + pkcs7->stream->tagSz;
  387    }
  388#endif
  389
  390    /* if not enough data was read in then request more */
  391    if (pkcs7->stream->length < expected) {
  392        pkcs7->stream->idx = 0;
  393        return WC_NO_ERR_TRACE(WC_PKCS7_WANT_READ_E);
  394    }
  395
  396    /* adjust pointer to read from stored buffer */
  397    *idx = 0;
  398    *pt  = pkcs7->stream->buffer;
  399    return 0;
  400}
  401
  402
  403/* setter function for stored variables */
  404static void wc_PKCS7_StreamStoreVar(wc_PKCS7* pkcs7, word32 var1, int var2,
  405        int var3)
  406{
  407    if (pkcs7 != NULL && pkcs7->stream != NULL) {
  408        pkcs7->stream->varOne   = var1;
  409        pkcs7->stream->varTwo   = var2;
  410        pkcs7->stream->varThree = var3;
  411    }
  412}
  413
  414/* Tries to peek at the SEQ and get the length
  415 * returns 0 on success
  416 */
  417static int wc_PKCS7_SetMaxStream(wc_PKCS7* pkcs7, byte* in, word32 defSz)
  418{
  419    /* check there is a buffer to read from */
  420    if (pkcs7) {
  421        int     length = 0, ret;
  422        word32  idx = 0, maxIdx;
  423        byte*   pt;
  424
  425        if (pkcs7->stream->length > 0) {
  426            length = (int)pkcs7->stream->length;
  427            pt     = pkcs7->stream->buffer;
  428        }
  429        else {
  430            length = (int)defSz;
  431            pt     = in;
  432        }
  433        maxIdx = (word32)length;
  434
  435        if (length < MAX_SEQ_SZ) {
  436            WOLFSSL_MSG("PKCS7 Error not enough data for SEQ peek");
  437            return 0;
  438        }
  439
  440        if ((ret = GetSequence_ex(pt, &idx, &length, maxIdx, NO_USER_CHECK))
  441                < 0) {
  442            return ret;
  443        }
  444
  445        if (length == 0 && ret == 0) {
  446            idx = 0;
  447            WOLFSSL_MSG("PKCS7 found indef SEQ with peek");
  448        }
  449
  450        pkcs7->stream->maxLen = (word32)length + idx;
  451
  452        if (pkcs7->stream->maxLen == 0) {
  453            pkcs7->stream->maxLen = defSz;
  454        }
  455    }
  456
  457    return 0;
  458}
  459
  460
  461/* getter function for stored variables */
  462static void wc_PKCS7_StreamGetVar(wc_PKCS7* pkcs7, word32* var1, int* var2,
  463        int* var3)
  464{
  465    if (pkcs7 != NULL && pkcs7->stream != NULL) {
  466        if (var1 != NULL) *var1 = pkcs7->stream->varOne;
  467        if (var2 != NULL) *var2 = pkcs7->stream->varTwo;
  468        if (var3 != NULL) *var3 = pkcs7->stream->varThree;
  469    }
  470}
  471
  472
  473/* common update of index and total read after section complete
  474 * returns 0 on success */
  475static int wc_PKCS7_StreamEndCase(wc_PKCS7* pkcs7, word32* tmpIdx, word32* idx)
  476{
  477    int ret = 0;
  478
  479    if (pkcs7->stream->length > 0) {
  480        if (pkcs7->stream->length < *idx) {
  481            WOLFSSL_MSG("PKCS7 read too much data from internal buffer");
  482            ret = BUFFER_E;
  483        }
  484        else {
  485            XMEMMOVE(pkcs7->stream->buffer, pkcs7->stream->buffer + *idx,
  486                 pkcs7->stream->length - *idx);
  487            pkcs7->stream->length -= *idx;
  488        }
  489    }
  490    else {
  491        pkcs7->stream->totalRd += *idx - *tmpIdx;
  492        pkcs7->stream->idx = *idx; /* adjust index into input buffer */
  493        *tmpIdx = *idx;
  494    }
  495
  496    return ret;
  497}
  498#endif /* NO_PKCS7_STREAM */
  499
  500#ifdef WC_PKCS7_STREAM_DEBUG
  501/* used to print out human readable state for debugging */
  502static const char* wc_PKCS7_GetStateName(int in)
  503{
  504    switch (in) {
  505        case WC_PKCS7_START: return "WC_PKCS7_START";
  506
  507        case WC_PKCS7_STAGE2: return "WC_PKCS7_STAGE2";
  508        case WC_PKCS7_STAGE3: return "WC_PKCS7_STAGE3";
  509        case WC_PKCS7_STAGE4: return "WC_PKCS7_STAGE4";
  510        case WC_PKCS7_STAGE5: return "WC_PKCS7_STAGE5";
  511        case WC_PKCS7_STAGE6: return "WC_PKCS7_STAGE6";
  512
  513        /* parse info set */
  514        case WC_PKCS7_INFOSET_START:  return "WC_PKCS7_INFOSET_START";
  515        case WC_PKCS7_INFOSET_BER:    return "WC_PKCS7_INFOSET_BER";
  516        case WC_PKCS7_INFOSET_STAGE1: return "WC_PKCS7_INFOSET_STAGE1";
  517        case WC_PKCS7_INFOSET_STAGE2: return "WC_PKCS7_INFOSET_STAGE2";
  518        case WC_PKCS7_INFOSET_END:    return "WC_PKCS7_INFOSET_END";
  519
  520        /* decode enveloped data */
  521        case WC_PKCS7_ENV_2: return "WC_PKCS7_ENV_2";
  522        case WC_PKCS7_ENV_3: return "WC_PKCS7_ENV_3";
  523        case WC_PKCS7_ENV_4: return "WC_PKCS7_ENV_4";
  524        case WC_PKCS7_ENV_5: return "WC_PKCS7_ENV_5";
  525
  526        /* decode auth enveloped */
  527        case WC_PKCS7_AUTHENV_2: return "WC_PKCS7_AUTHENV_2";
  528        case WC_PKCS7_AUTHENV_3: return "WC_PKCS7_AUTHENV_3";
  529        case WC_PKCS7_AUTHENV_4: return "WC_PKCS7_AUTHENV_4";
  530        case WC_PKCS7_AUTHENV_5: return "WC_PKCS7_AUTHENV_5";
  531        case WC_PKCS7_AUTHENV_6: return "WC_PKCS7_AUTHENV_6";
  532        case WC_PKCS7_AUTHENV_ATRB: return "WC_PKCS7_AUTHENV_ATRB";
  533        case WC_PKCS7_AUTHENV_ATRBEND: return "WC_PKCS7_AUTHENV_ATRBEND";
  534        case WC_PKCS7_AUTHENV_7: return "WC_PKCS7_AUTHENV_7";
  535
  536        /* decryption state types */
  537        case WC_PKCS7_DECRYPT_KTRI:   return "WC_PKCS7_DECRYPT_KTRI";
  538        case WC_PKCS7_DECRYPT_KTRI_2: return "WC_PKCS7_DECRYPT_KTRI_2";
  539        case WC_PKCS7_DECRYPT_KTRI_3: return "WC_PKCS7_DECRYPT_KTRI_3";
  540
  541        case WC_PKCS7_DECRYPT_KARI:  return "WC_PKCS7_DECRYPT_KARI";
  542        case WC_PKCS7_DECRYPT_KEKRI: return "WC_PKCS7_DECRYPT_KEKRI";
  543        case WC_PKCS7_DECRYPT_PWRI:  return "WC_PKCS7_DECRYPT_PWRI";
  544        case WC_PKCS7_DECRYPT_ORI:   return "WC_PKCS7_DECRYPT_ORI";
  545        case WC_PKCS7_DECRYPT_DONE:  return "WC_PKCS7_DECRYPT_DONE";
  546
  547        case WC_PKCS7_VERIFY_STAGE2: return "WC_PKCS7_VERIFY_STAGE2";
  548        case WC_PKCS7_VERIFY_STAGE3: return "WC_PKCS7_VERIFY_STAGE3";
  549        case WC_PKCS7_VERIFY_STAGE4: return "WC_PKCS7_VERIFY_STAGE4";
  550        case WC_PKCS7_VERIFY_STAGE5: return "WC_PKCS7_VERIFY_STAGE5";
  551        case WC_PKCS7_VERIFY_STAGE6: return "WC_PKCS7_VERIFY_STAGE6";
  552        case WC_PKCS7_VERIFY_STAGE7: return "WC_PKCS7_VERIFY_STAGE7";
  553
  554        default:
  555            return "Unknown state";
  556    }
  557}
  558#endif
  559
  560/* Used to change the PKCS7 state. Having state change as a function allows
  561 * for easier debugging */
  562static void wc_PKCS7_ChangeState(wc_PKCS7* pkcs7, int newState)
  563{
  564#ifdef WC_PKCS7_STREAM_DEBUG
  565    printf("\tChanging from state [%02d] %s to [%02d] %s\n",
  566            pkcs7->state, wc_PKCS7_GetStateName(pkcs7->state),
  567            newState, wc_PKCS7_GetStateName(newState));
  568#endif
  569    pkcs7->state = (word32)newState;
  570}
  571
  572#define MAX_PKCS7_DIGEST_SZ (MAX_SEQ_SZ + MAX_ALGO_SZ + \
  573                             MAX_OCTET_STR_SZ + WC_MAX_DIGEST_SIZE)
  574
  575
  576/* placed ASN.1 contentType OID into *output, return idx on success,
  577 * 0 upon failure */
  578static int wc_SetContentType(int pkcs7TypeOID, byte* output, word32 outputSz)
  579{
  580    /* PKCS#7 content types, RFC 2315, section 14 */
  581    static const byte pkcs7[]              =
  582        { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07 };
  583    static const byte data[]               =
  584        { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01 };
  585    static const byte signedData[]         =
  586        { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02};
  587    static const byte envelopedData[]      =
  588        { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x03 };
  589    static const byte authEnvelopedData[]  =
  590        { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x10, 0x01, 0x17};
  591    static const byte signedAndEnveloped[] =
  592        { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x04 };
  593    static const byte digestedData[]       =
  594        { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x05 };
  595#ifndef NO_PKCS7_ENCRYPTED_DATA
  596    static const byte encryptedData[]      =
  597        { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x06 };
  598#endif
  599    /* FirmwarePkgData (1.2.840.113549.1.9.16.1.16), RFC 4108 */
  600    static const byte firmwarePkgData[]    =
  601        { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x10, 0x01, 0x10 };
  602#if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA)
  603    /* id-ct-compressedData (1.2.840.113549.1.9.16.1.9), RFC 3274 */
  604    static const byte compressedData[]     =
  605       { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x10, 0x01, 0x09 };
  606#endif
  607
  608#if !defined(NO_PWDBASED) && !defined(NO_SHA)
  609    static const byte pwriKek[]            =
  610       { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x10, 0x03, 0x09 };
  611    static const byte pbkdf2[]             =
  612       { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x05, 0x0C };
  613#endif
  614
  615    word32 idSz, idx = 0;
  616    word32 typeSz = 0;
  617    const byte* typeName = 0;
  618    byte ID_Length[MAX_LENGTH_SZ];
  619
  620    switch (pkcs7TypeOID) {
  621        case PKCS7_MSG:
  622            typeSz = sizeof(pkcs7);
  623            typeName = pkcs7;
  624            break;
  625
  626        case DATA:
  627            typeSz = sizeof(data);
  628            typeName = data;
  629            break;
  630
  631        case SIGNED_DATA:
  632            typeSz = sizeof(signedData);
  633            typeName = signedData;
  634            break;
  635
  636        case ENVELOPED_DATA:
  637            typeSz = sizeof(envelopedData);
  638            typeName = envelopedData;
  639            break;
  640
  641        case AUTH_ENVELOPED_DATA:
  642            typeSz = sizeof(authEnvelopedData);
  643            typeName = authEnvelopedData;
  644            break;
  645
  646        case SIGNED_AND_ENVELOPED_DATA:
  647            typeSz = sizeof(signedAndEnveloped);
  648            typeName = signedAndEnveloped;
  649            break;
  650
  651        case DIGESTED_DATA:
  652            typeSz = sizeof(digestedData);
  653            typeName = digestedData;
  654            break;
  655
  656#ifndef NO_PKCS7_ENCRYPTED_DATA
  657        case ENCRYPTED_DATA:
  658            typeSz = sizeof(encryptedData);
  659            typeName = encryptedData;
  660            break;
  661#endif
  662#if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA)
  663        case COMPRESSED_DATA:
  664            typeSz = sizeof(compressedData);
  665            typeName = compressedData;
  666            break;
  667#endif
  668        case FIRMWARE_PKG_DATA:
  669            typeSz = sizeof(firmwarePkgData);
  670            typeName = firmwarePkgData;
  671            break;
  672
  673#if !defined(NO_PWDBASED) && !defined(NO_SHA)
  674        case PWRI_KEK_WRAP:
  675            typeSz = sizeof(pwriKek);
  676            typeName = pwriKek;
  677            break;
  678
  679        case PBKDF2_OID:
  680            typeSz = sizeof(pbkdf2);
  681            typeName = pbkdf2;
  682            break;
  683#endif
  684
  685        default:
  686            WOLFSSL_MSG("Unknown PKCS#7 Type");
  687            return 0;
  688    };
  689
  690    if (outputSz < (MAX_LENGTH_SZ + 1 + typeSz)) {
  691        WOLFSSL_MSG("CMS content type buffer too small");
  692        return BAD_FUNC_ARG;
  693    }
  694
  695    idSz  = SetLength(typeSz, ID_Length);
  696    output[idx++] = ASN_OBJECT_ID;
  697    XMEMCPY(output + idx, ID_Length, idSz);
  698    idx += idSz;
  699    XMEMCPY(output + idx, typeName, typeSz);
  700    idx += typeSz;
  701
  702    return (int)idx;
  703}
  704
  705
  706/* get ASN.1 contentType OID sum, return 0 on success, <0 on failure */
  707static int wc_GetContentType(const byte* input, word32* inOutIdx, word32* oid,
  708                             word32 maxIdx)
  709{
  710    WOLFSSL_ENTER("wc_GetContentType");
  711    if (GetObjectId(input, inOutIdx, oid, oidIgnoreType, maxIdx) < 0) {
  712        WOLFSSL_LEAVE("wc_GetContentType", ASN_PARSE_E);
  713        return ASN_PARSE_E;
  714    }
  715
  716    return 0;
  717}
  718
  719
  720/* return block size for algorithm represented by oid, or <0 on error */
  721static int wc_PKCS7_GetOIDBlockSize(int oid)
  722{
  723    int blockSz;
  724
  725    switch (oid) {
  726#ifndef NO_AES
  727    #ifdef WOLFSSL_AES_128
  728        #ifdef HAVE_AES_CBC
  729        case AES128CBCb:
  730        #endif
  731        #ifdef HAVE_AESGCM
  732        case AES128GCMb:
  733        #endif
  734        #ifdef HAVE_AESCCM
  735        case AES128CCMb:
  736        #endif
  737    #endif
  738    #ifdef WOLFSSL_AES_192
  739        #ifdef HAVE_AES_CBC
  740        case AES192CBCb:
  741        #endif
  742        #ifdef HAVE_AESGCM
  743        case AES192GCMb:
  744        #endif
  745        #ifdef HAVE_AESCCM
  746        case AES192CCMb:
  747        #endif
  748    #endif
  749    #ifdef WOLFSSL_AES_256
  750        #ifdef HAVE_AES_CBC
  751        case AES256CBCb:
  752        #endif
  753        #ifdef HAVE_AESGCM
  754        case AES256GCMb:
  755        #endif
  756        #ifdef HAVE_AESCCM
  757        case AES256CCMb:
  758        #endif
  759    #endif
  760            blockSz = WC_AES_BLOCK_SIZE;
  761            break;
  762#endif /* !NO_AES */
  763
  764#ifndef NO_DES3
  765        case DESb:
  766        case DES3b:
  767            blockSz = DES_BLOCK_SIZE;
  768            break;
  769#endif
  770        default:
  771            WOLFSSL_MSG("Unsupported content cipher type");
  772            return ALGO_ID_E;
  773    };
  774
  775    return blockSz;
  776}
  777
  778
  779/* get key size for algorithm represented by oid, or <0 on error */
  780static int wc_PKCS7_GetOIDKeySize(int oid)
  781{
  782    int blockKeySz;
  783
  784    switch (oid) {
  785#ifndef NO_AES
  786    #ifdef WOLFSSL_AES_128
  787        #ifdef HAVE_AES_CBC
  788        case AES128CBCb:
  789        #endif
  790        #ifdef HAVE_AESGCM
  791        case AES128GCMb:
  792        #endif
  793        #ifdef HAVE_AESCCM
  794        case AES128CCMb:
  795        #endif
  796        case AES128_WRAP:
  797            blockKeySz = 16;
  798            break;
  799    #endif
  800    #ifdef WOLFSSL_AES_192
  801        #ifdef HAVE_AES_CBC
  802        case AES192CBCb:
  803        #endif
  804        #ifdef HAVE_AESGCM
  805        case AES192GCMb:
  806        #endif
  807        #ifdef HAVE_AESCCM
  808        case AES192CCMb:
  809        #endif
  810        case AES192_WRAP:
  811            blockKeySz = 24;
  812            break;
  813    #endif
  814    #ifdef WOLFSSL_AES_256
  815        #ifdef HAVE_AES_CBC
  816        case AES256CBCb:
  817        #endif
  818        #ifdef HAVE_AESGCM
  819        case AES256GCMb:
  820        #endif
  821        #ifdef HAVE_AESCCM
  822        case AES256CCMb:
  823        #endif
  824        case AES256_WRAP:
  825            blockKeySz = 32;
  826            break;
  827    #endif
  828#endif /* !NO_AES */
  829
  830#ifndef NO_DES3
  831        case DESb:
  832            blockKeySz = DES_KEYLEN;
  833            break;
  834        case DES3b:
  835            blockKeySz = DES3_KEYLEN;
  836            break;
  837#endif
  838        default:
  839            WOLFSSL_MSG("Unsupported content cipher type");
  840            return ALGO_ID_E;
  841    };
  842
  843    return blockKeySz;
  844}
  845
  846
  847wc_PKCS7* wc_PKCS7_New(void* heap, int devId)
  848{
  849    wc_PKCS7* pkcs7 = (wc_PKCS7*)XMALLOC(sizeof(wc_PKCS7), heap, DYNAMIC_TYPE_PKCS7);
  850    if (pkcs7) {
  851        XMEMSET(pkcs7, 0, sizeof(wc_PKCS7));
  852        if (wc_PKCS7_Init(pkcs7, heap, devId) == 0) {
  853            pkcs7->isDynamic = 1;
  854        }
  855        else {
  856            XFREE(pkcs7, heap, DYNAMIC_TYPE_PKCS7);
  857            pkcs7 = NULL;
  858        }
  859    }
  860    return pkcs7;
  861}
  862
  863/* This is to initialize a PKCS7 structure. It sets all values to 0 and can be
  864 * used to set the heap hint.
  865 *
  866 * pkcs7 PKCS7 structure to initialize
  867 * heap  memory heap hint for PKCS7 structure to use
  868 * devId currently not used but a place holder for async operations
  869 *
  870 * returns 0 on success or a negative value for failure
  871 */
  872int wc_PKCS7_Init(wc_PKCS7* pkcs7, void* heap, int devId)
  873{
  874    word16 isDynamic;
  875
  876    WOLFSSL_ENTER("wc_PKCS7_Init");
  877
  878    if (pkcs7 == NULL) {
  879        return BAD_FUNC_ARG;
  880    }
  881
  882    isDynamic = pkcs7->isDynamic;
  883    XMEMSET(pkcs7, 0, sizeof(wc_PKCS7));
  884    pkcs7->isDynamic = (isDynamic != 0);
  885#ifdef WOLFSSL_HEAP_TEST
  886    pkcs7->heap = (void*)WOLFSSL_HEAP_TEST;
  887#else
  888    pkcs7->heap = heap;
  889#endif
  890    pkcs7->devId = devId;
  891
  892    return 0;
  893}
  894
  895#ifdef WC_ASN_UNKNOWN_EXT_CB
  896void wc_PKCS7_SetUnknownExtCallback(wc_PKCS7* pkcs7, wc_UnknownExtCallback cb)
  897{
  898    if (pkcs7 != NULL) {
  899        pkcs7->unknownExtCallback = cb;
  900    }
  901}
  902#endif
  903
  904/* Certificate structure holding der pointer, size, and pointer to next
  905 * Pkcs7Cert struct. Used when creating SignedData types with multiple
  906 * certificates. */
  907struct Pkcs7Cert {
  908    byte*  der;
  909    word32 derSz;
  910    Pkcs7Cert* next;
  911};
  912
  913
  914/* Linked list of ASN.1 encoded RecipientInfos */
  915struct Pkcs7EncodedRecip {
  916    byte recip[MAX_RECIP_SZ];
  917    word32 recipSz;
  918    int recipType;
  919    int recipVersion;
  920    Pkcs7EncodedRecip* next;
  921};
  922
  923
  924/* free all members of Pkcs7Cert linked list */
  925static void wc_PKCS7_FreeCertSet(wc_PKCS7* pkcs7)
  926{
  927    Pkcs7Cert* curr = NULL;
  928    Pkcs7Cert* next = NULL;
  929
  930    if (pkcs7 == NULL)
  931        return;
  932
  933    curr = pkcs7->certList;
  934    pkcs7->certList = NULL;
  935
  936    while (curr != NULL) {
  937        next = curr->next;
  938        curr->next = NULL;
  939        XFREE(curr, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
  940        curr = next;
  941    }
  942
  943    return;
  944}
  945
  946
  947/* Get total size of all recipients in recipient list.
  948 *
  949 * Returns total size of recipients, or negative upon error */
  950static int wc_PKCS7_GetRecipientListSize(wc_PKCS7* pkcs7)
  951{
  952    word32 totalSz = 0;
  953    Pkcs7EncodedRecip* tmp = NULL;
  954
  955    if (pkcs7 == NULL)
  956        return BAD_FUNC_ARG;
  957
  958    tmp = pkcs7->recipList;
  959
  960    while (tmp != NULL) {
  961        totalSz += tmp->recipSz;
  962        tmp = tmp->next;
  963    }
  964
  965    return (int)totalSz;
  966}
  967
  968
  969/* free all members of Pkcs7EncodedRecip linked list */
  970static void wc_PKCS7_FreeEncodedRecipientSet(wc_PKCS7* pkcs7)
  971{
  972    Pkcs7EncodedRecip* curr = NULL;
  973    Pkcs7EncodedRecip* next = NULL;
  974
  975    if (pkcs7 == NULL)
  976        return;
  977
  978    curr = pkcs7->recipList;
  979    pkcs7->recipList = NULL;
  980
  981    while (curr != NULL) {
  982        next = curr->next;
  983        curr->next = NULL;
  984        XFREE(curr, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
  985        curr = next;
  986    }
  987
  988    return;
  989}
  990
  991
  992/* search through RecipientInfo list for specific type.
  993 * return 1 if ANY recipient of type specified is present, otherwise
  994 * return 0 */
  995static int wc_PKCS7_RecipientListIncludesType(wc_PKCS7* pkcs7, int type)
  996{
  997    Pkcs7EncodedRecip* tmp = NULL;
  998
  999    if (pkcs7 == NULL)
 1000        return BAD_FUNC_ARG;
 1001
 1002    tmp = pkcs7->recipList;
 1003
 1004    while (tmp != NULL) {
 1005        if (tmp->recipType == type)
 1006            return 1;
 1007
 1008        tmp = tmp->next;
 1009    }
 1010
 1011    return 0;
 1012}
 1013
 1014
 1015/* searches through RecipientInfo list, returns 1 if all structure
 1016 * versions are set to 0, otherwise returns 0 */
 1017static int wc_PKCS7_RecipientListVersionsAllZero(wc_PKCS7* pkcs7)
 1018{
 1019    Pkcs7EncodedRecip* tmp = NULL;
 1020
 1021    if (pkcs7 == NULL)
 1022        return BAD_FUNC_ARG;
 1023
 1024    tmp = pkcs7->recipList;
 1025
 1026    while (tmp != NULL) {
 1027        if (tmp->recipVersion != 0)
 1028            return 0;
 1029
 1030        tmp = tmp->next;
 1031    }
 1032
 1033    return 1;
 1034}
 1035
 1036/* Verify RSA/ECC key is correctly formatted, used as sanity check after
 1037 * import of key/cert.
 1038 *
 1039 * keyOID - key OID (ex: RSAk, ECDSAk)
 1040 * key    - key in DER
 1041 * keySz  - size of key, octets
 1042 *
 1043 * Returns 0 on success, negative on error */
 1044static int wc_PKCS7_CheckPublicKeyDer(wc_PKCS7* pkcs7, int keyOID,
 1045                                      const byte* key, word32 keySz)
 1046{
 1047    int ret = 0;
 1048    word32 scratch = 0;
 1049#ifdef WOLFSSL_SMALL_STACK
 1050    #ifndef NO_RSA
 1051        RsaKey* rsa;
 1052    #endif
 1053    #ifdef HAVE_ECC
 1054        ecc_key* ecc;
 1055    #endif
 1056#else
 1057    #ifndef NO_RSA
 1058        RsaKey rsa[1];
 1059    #endif
 1060    #ifdef HAVE_ECC
 1061        ecc_key ecc[1];
 1062    #endif
 1063#endif
 1064
 1065    if (pkcs7 == NULL || key == NULL || keySz == 0) {
 1066        return BAD_FUNC_ARG;
 1067    }
 1068
 1069#ifdef WOLFSSL_SMALL_STACK
 1070    #ifndef NO_RSA
 1071        rsa = (RsaKey*)XMALLOC(sizeof(RsaKey), pkcs7->heap,
 1072                               DYNAMIC_TYPE_TMP_BUFFER);
 1073        if (rsa == NULL) {
 1074            return MEMORY_E;
 1075        }
 1076    #endif
 1077
 1078    #ifdef HAVE_ECC
 1079        ecc = (ecc_key*)XMALLOC(sizeof(ecc_key), pkcs7->heap,
 1080                                DYNAMIC_TYPE_TMP_BUFFER);
 1081        if (ecc == NULL) {
 1082            #ifndef NO_RSA
 1083                XFREE(rsa, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 1084            #endif
 1085            return MEMORY_E;
 1086        }
 1087    #endif
 1088#endif
 1089
 1090    switch (keyOID) {
 1091#ifndef NO_RSA
 1092    #ifdef WC_RSA_PSS
 1093        case RSAPSSk:
 1094            /* RSA-PSS cert: public key is same RSA format as RSAk */
 1095            FALL_THROUGH;
 1096    #endif
 1097        case RSAk:
 1098            ret = wc_InitRsaKey_ex(rsa, pkcs7->heap, pkcs7->devId);
 1099            if (ret != 0) {
 1100                break;
 1101            }
 1102
 1103            /* Try to decode public key as sanity check. wc_CheckRsaKey()
 1104               only checks private key not public. */
 1105            ret = wc_RsaPublicKeyDecode(key, &scratch, rsa, keySz);
 1106            wc_FreeRsaKey(rsa);
 1107
 1108            break;
 1109#endif
 1110#ifdef HAVE_ECC
 1111        case ECDSAk:
 1112            ret = wc_ecc_init_ex(ecc, pkcs7->heap, pkcs7->devId);
 1113            if (ret != 0) {
 1114                break;
 1115            }
 1116
 1117            /* Try to decode public key and check with wc_ecc_check_key() */
 1118            ret = wc_EccPublicKeyDecode(key, &scratch, ecc, keySz);
 1119        #if defined(WOLFSSL_VALIDATE_ECC_IMPORT)
 1120            if (ret == 0) {
 1121                ret = wc_ecc_check_key(ecc);
 1122            }
 1123        #endif
 1124            wc_ecc_free(ecc);
 1125
 1126            break;
 1127#endif
 1128    }
 1129
 1130#ifdef WOLFSSL_SMALL_STACK
 1131    #ifndef NO_RSA
 1132        XFREE(rsa, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 1133    #endif
 1134    #ifdef HAVE_ECC
 1135        XFREE(ecc, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 1136    #endif
 1137#endif
 1138
 1139    return ret;
 1140}
 1141
 1142
 1143/* Init PKCS7 struct with recipient cert, decode into DecodedCert
 1144 * NOTE: keeps previously set pkcs7 heap hint, devId and isDynamic */
 1145int wc_PKCS7_InitWithCert(wc_PKCS7* pkcs7, byte* derCert, word32 derCertSz)
 1146{
 1147    int ret = 0;
 1148    void* heap;
 1149    int devId;
 1150    Pkcs7Cert* cert;
 1151    Pkcs7Cert* lastCert;
 1152#ifdef WC_ASN_UNKNOWN_EXT_CB
 1153    wc_UnknownExtCallback cb;
 1154#endif
 1155
 1156    if (pkcs7 == NULL || (derCert == NULL && derCertSz != 0)) {
 1157        return BAD_FUNC_ARG;
 1158    }
 1159
 1160    heap = pkcs7->heap;
 1161    devId = pkcs7->devId;
 1162    cert = pkcs7->certList;
 1163#ifdef WC_ASN_UNKNOWN_EXT_CB
 1164    cb = pkcs7->unknownExtCallback; /* save / restore callback */
 1165#endif
 1166    ret = wc_PKCS7_Init(pkcs7, heap, devId);
 1167    if (ret != 0)
 1168        return ret;
 1169
 1170#ifdef WC_ASN_UNKNOWN_EXT_CB
 1171    pkcs7->unknownExtCallback = cb;
 1172#endif
 1173    pkcs7->certList = cert;
 1174
 1175    if (derCert != NULL && derCertSz > 0) {
 1176#ifdef WOLFSSL_SMALL_STACK
 1177        DecodedCert* dCert;
 1178
 1179        dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), pkcs7->heap,
 1180                                                       DYNAMIC_TYPE_DCERT);
 1181        if (dCert == NULL)
 1182            return MEMORY_E;
 1183#else
 1184        DecodedCert dCert[1];
 1185#endif
 1186
 1187        pkcs7->singleCert = derCert;
 1188        pkcs7->singleCertSz = derCertSz;
 1189        pkcs7->cert[0] = derCert;
 1190        pkcs7->certSz[0] = derCertSz;
 1191
 1192        /* create new Pkcs7Cert for recipient, freed during cleanup */
 1193        cert = (Pkcs7Cert*)XMALLOC(sizeof(Pkcs7Cert), pkcs7->heap,
 1194                                   DYNAMIC_TYPE_PKCS7);
 1195        if (cert == NULL) {
 1196            WC_FREE_VAR_EX(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT);
 1197            return MEMORY_E;
 1198        }
 1199        XMEMSET(cert, 0, sizeof(Pkcs7Cert));
 1200        cert->der = derCert;
 1201        cert->derSz = derCertSz;
 1202        cert->next = NULL;
 1203
 1204        /* free existing cert list if existing */
 1205        wc_PKCS7_FreeCertSet(pkcs7);
 1206
 1207        /* add cert to list */
 1208        if (pkcs7->certList == NULL) {
 1209            pkcs7->certList = cert;
 1210        } else {
 1211           lastCert = pkcs7->certList;
 1212           while (lastCert->next != NULL) {
 1213               lastCert = lastCert->next;
 1214           }
 1215           lastCert->next = cert;
 1216        }
 1217
 1218        InitDecodedCert(dCert, derCert, derCertSz, pkcs7->heap);
 1219#ifdef WC_ASN_UNKNOWN_EXT_CB
 1220        if (pkcs7->unknownExtCallback != NULL)
 1221            wc_SetUnknownExtCallback(dCert, pkcs7->unknownExtCallback);
 1222#endif
 1223        ret = ParseCert(dCert, CA_TYPE, NO_VERIFY, 0);
 1224        if (ret < 0) {
 1225            FreeDecodedCert(dCert);
 1226            WC_FREE_VAR_EX(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT);
 1227            return ret;
 1228        }
 1229
 1230        /* verify extracted public key is valid before storing */
 1231        ret = wc_PKCS7_CheckPublicKeyDer(pkcs7, (int)dCert->keyOID,
 1232                                         dCert->publicKey, dCert->pubKeySize);
 1233        if (ret != 0) {
 1234            WOLFSSL_MSG("Invalid public key, check pkcs7->cert");
 1235            FreeDecodedCert(dCert);
 1236            WC_FREE_VAR_EX(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT);
 1237            return ret;
 1238        }
 1239
 1240        if (dCert->pubKeySize > (MAX_RSA_INT_SZ + MAX_RSA_E_SZ) ||
 1241            dCert->serialSz > MAX_SN_SZ) {
 1242            WOLFSSL_MSG("Invalid size in certificate");
 1243            FreeDecodedCert(dCert);
 1244            WC_FREE_VAR_EX(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT);
 1245            return ASN_PARSE_E;
 1246        }
 1247
 1248        XMEMCPY(pkcs7->publicKey, dCert->publicKey, dCert->pubKeySize);
 1249        pkcs7->publicKeySz = dCert->pubKeySize;
 1250        pkcs7->publicKeyOID = dCert->keyOID;
 1251        /* Do not derive publicKeyOID from cert signatureOID: the cert's
 1252         * signature is how the cert was signed by its issuer; the signer
 1253         * chooses digestEncryptionAlgorithm (e.g. RSASSA-PSS vs PKCS#1 v1.5)
 1254         * via API / pkcs7->publicKeyOID set by the application. */
 1255        XMEMCPY(pkcs7->issuerHash, dCert->issuerHash, KEYID_SIZE);
 1256        pkcs7->issuer = dCert->issuerRaw;
 1257        pkcs7->issuerSz = (word32)dCert->issuerRawLen;
 1258        XMEMCPY(pkcs7->issuerSn, dCert->serial, (word32)dCert->serialSz);
 1259        pkcs7->issuerSnSz = (word32)dCert->serialSz;
 1260        XMEMCPY(pkcs7->issuerSubjKeyId, dCert->extSubjKeyId, KEYID_SIZE);
 1261
 1262        /* default to IssuerAndSerialNumber for SignerIdentifier */
 1263        pkcs7->sidType = CMS_ISSUER_AND_SERIAL_NUMBER;
 1264
 1265        /* free existing recipient list if existing */
 1266        wc_PKCS7_FreeEncodedRecipientSet(pkcs7);
 1267
 1268        FreeDecodedCert(dCert);
 1269
 1270        WC_FREE_VAR_EX(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT);
 1271    }
 1272
 1273    return ret;
 1274}
 1275
 1276
 1277/* Adds one DER-formatted certificate to the internal PKCS7/CMS certificate
 1278 * list, to be added as part of the certificates CertificateSet. Currently
 1279 * used in SignedData content type.
 1280 *
 1281 * Must be called after wc_PKCS7_Init() or wc_PKCS7_InitWithCert().
 1282 *
 1283 * Does not represent the recipient/signer certificate, only certificates that
 1284 * are part of the certificate chain used to build and verify signer
 1285 * certificates.
 1286 *
 1287 * This API does not currently validate certificates.
 1288 *
 1289 * Returns 0 on success, negative upon error */
 1290int wc_PKCS7_AddCertificate(wc_PKCS7* pkcs7, byte* derCert, word32 derCertSz)
 1291{
 1292    Pkcs7Cert* cert;
 1293
 1294    if (pkcs7 == NULL || derCert == NULL || derCertSz == 0)
 1295        return BAD_FUNC_ARG;
 1296
 1297    cert = (Pkcs7Cert*)XMALLOC(sizeof(Pkcs7Cert), pkcs7->heap,
 1298                               DYNAMIC_TYPE_PKCS7);
 1299    if (cert == NULL)
 1300        return MEMORY_E;
 1301    XMEMSET(cert, 0, sizeof(Pkcs7Cert));
 1302
 1303    cert->der = derCert;
 1304    cert->derSz = derCertSz;
 1305
 1306    if (pkcs7->certList == NULL) {
 1307        pkcs7->certList = cert;
 1308    } else {
 1309        cert->next = pkcs7->certList;
 1310        pkcs7->certList = cert;
 1311    }
 1312
 1313    return 0;
 1314}
 1315
 1316
 1317/* free linked list of PKCS7DecodedAttrib structs */
 1318static void wc_PKCS7_FreeDecodedAttrib(PKCS7DecodedAttrib* attrib, void* heap)
 1319{
 1320    PKCS7DecodedAttrib* current;
 1321
 1322    if (attrib == NULL) {
 1323        return;
 1324    }
 1325
 1326    current = attrib;
 1327    while (current != NULL) {
 1328        PKCS7DecodedAttrib* next = current->next;
 1329        XFREE(current->oid, heap, DYNAMIC_TYPE_PKCS7);
 1330        XFREE(current->value, heap, DYNAMIC_TYPE_PKCS7);
 1331        XFREE(current, heap, DYNAMIC_TYPE_PKCS7);
 1332        current = next;
 1333    }
 1334
 1335    (void)heap;
 1336}
 1337
 1338
 1339/* return 0 on success */
 1340static int wc_PKCS7_SignerInfoNew(wc_PKCS7* pkcs7)
 1341{
 1342    XFREE(pkcs7->signerInfo, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 1343    pkcs7->signerInfo = NULL;
 1344
 1345    pkcs7->signerInfo = (PKCS7SignerInfo*)XMALLOC(sizeof(PKCS7SignerInfo),
 1346            pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 1347    if (pkcs7->signerInfo == NULL) {
 1348        WOLFSSL_MSG("Unable to malloc memory for signer info");
 1349        return MEMORY_E;
 1350    }
 1351    XMEMSET(pkcs7->signerInfo, 0, sizeof(PKCS7SignerInfo));
 1352    return 0;
 1353}
 1354
 1355
 1356static void wc_PKCS7_SignerInfoFree(wc_PKCS7* pkcs7)
 1357{
 1358    if (pkcs7->signerInfo != NULL) {
 1359        XFREE(pkcs7->signerInfo->sid, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 1360        pkcs7->signerInfo->sid = NULL;
 1361        XFREE(pkcs7->signerInfo, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 1362        pkcs7->signerInfo = NULL;
 1363    }
 1364}
 1365
 1366
 1367/* free's any current SID and sets it to "in"
 1368 * returns 0 on success
 1369 */
 1370static int wc_PKCS7_SignerInfoSetSID(wc_PKCS7* pkcs7, byte* in, int inSz)
 1371{
 1372    if (pkcs7 == NULL || in == NULL || inSz < 0) {
 1373        return BAD_FUNC_ARG;
 1374    }
 1375
 1376    XFREE(pkcs7->signerInfo->sid, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 1377    pkcs7->signerInfo->sid = NULL;
 1378    pkcs7->signerInfo->sid = (byte*)XMALLOC((word32)inSz, pkcs7->heap,
 1379            DYNAMIC_TYPE_PKCS7);
 1380    if (pkcs7->signerInfo->sid == NULL) {
 1381        return MEMORY_E;
 1382    }
 1383    XMEMCPY(pkcs7->signerInfo->sid, in, (word32)inSz);
 1384    pkcs7->signerInfo->sidSz = (word32)inSz;
 1385    return 0;
 1386}
 1387
 1388
 1389/* releases any memory allocated by a PKCS7 initializer */
 1390void wc_PKCS7_Free(wc_PKCS7* pkcs7)
 1391{
 1392    if (pkcs7 == NULL)
 1393        return;
 1394
 1395#ifndef NO_PKCS7_STREAM
 1396    wc_PKCS7_FreeStream(pkcs7);
 1397#endif
 1398
 1399    wc_PKCS7_SignerInfoFree(pkcs7);
 1400    wc_PKCS7_FreeDecodedAttrib(pkcs7->decodedAttrib, pkcs7->heap);
 1401    pkcs7->decodedAttrib = NULL;
 1402    wc_PKCS7_FreeCertSet(pkcs7);
 1403
 1404#ifdef ASN_BER_TO_DER
 1405    XFREE(pkcs7->der, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 1406    pkcs7->der = NULL;
 1407#endif
 1408    XFREE(pkcs7->contentDynamic, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 1409    pkcs7->contentDynamic = NULL;
 1410
 1411    if (pkcs7->cek != NULL) {
 1412        ForceZero(pkcs7->cek, pkcs7->cekSz);
 1413        XFREE(pkcs7->cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 1414        pkcs7->cek = NULL;
 1415    }
 1416
 1417    pkcs7->contentTypeSz = 0;
 1418
 1419    if (pkcs7->signature) {
 1420        XFREE(pkcs7->signature, pkcs7->heap, DYNAMIC_TYPE_SIGNATURE);
 1421        pkcs7->signature = NULL;
 1422        pkcs7->signatureSz = 0;
 1423    }
 1424    if (pkcs7->plainDigest) {
 1425        XFREE(pkcs7->plainDigest, pkcs7->heap, DYNAMIC_TYPE_DIGEST);
 1426        pkcs7->plainDigest = NULL;
 1427        pkcs7->plainDigestSz = 0;
 1428    }
 1429    if (pkcs7->pkcs7Digest) {
 1430        XFREE(pkcs7->pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_DIGEST);
 1431        pkcs7->pkcs7Digest = NULL;
 1432        pkcs7->pkcs7DigestSz = 0;
 1433    }
 1434    if (pkcs7->cachedEncryptedContent != NULL) {
 1435        XFREE(pkcs7->cachedEncryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 1436        pkcs7->cachedEncryptedContent = NULL;
 1437        pkcs7->cachedEncryptedContentSz = 0;
 1438    }
 1439
 1440    if (pkcs7->customSKID) {
 1441        XFREE(pkcs7->customSKID, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 1442        pkcs7->customSKID = NULL;
 1443        pkcs7->customSKIDSz = 0;
 1444    }
 1445
 1446    if (pkcs7->isDynamic) {
 1447        pkcs7->isDynamic = 0;
 1448        XFREE(pkcs7, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 1449    }
 1450}
 1451
 1452
 1453/* helper function for parsing through attributes and finding a specific one.
 1454 * returns PKCS7DecodedAttrib pointer on success */
 1455static PKCS7DecodedAttrib* findAttrib(wc_PKCS7* pkcs7, const byte* oid, word32 oidSz)
 1456{
 1457    PKCS7DecodedAttrib* list;
 1458
 1459    if (pkcs7 == NULL || oid == NULL) {
 1460        return NULL;
 1461    }
 1462
 1463    /* search attributes for pkiStatus */
 1464    list = pkcs7->decodedAttrib;
 1465    while (list != NULL) {
 1466        word32 sz  = oidSz;
 1467        word32 idx = 0;
 1468        int    length = 0;
 1469        byte   tag;
 1470
 1471        if (GetASNTag(list->oid, &idx, &tag, list->oidSz) < 0) {
 1472            return NULL;
 1473        }
 1474        if (tag != ASN_OBJECT_ID) {
 1475            WOLFSSL_MSG("Bad attribute ASN1 syntax");
 1476            return NULL;
 1477        }
 1478
 1479        if (GetLength(list->oid, &idx, &length, list->oidSz) < 0) {
 1480            WOLFSSL_MSG("Bad attribute length");
 1481            return NULL;
 1482        }
 1483
 1484        sz = (sz < (word32)length)? sz : (word32)length;
 1485        if (XMEMCMP(oid, list->oid + idx, sz) == 0) {
 1486            return list;
 1487        }
 1488        list = list->next;
 1489    }
 1490    return NULL;
 1491}
 1492
 1493
 1494/* Searches through decoded attributes and returns the value for the first one
 1495 * matching the oid passed in. Note that this value includes the leading ASN1
 1496 * syntax. So for a printable string of "3" this would be something like
 1497 *
 1498 * 0x13, 0x01, 0x33
 1499 *  ID   SIZE  "3"
 1500 *
 1501 * pkcs7  structure to get value from
 1502 * oid    OID value to search for with attributes
 1503 * oidSz  size of oid buffer
 1504 * out    buffer to hold result
 1505 * outSz  size of out buffer (if out is NULL this is set to needed size and
 1506          LENGTH_ONLY_E is returned)
 1507 *
 1508 * returns size of value on success
 1509 */
 1510int wc_PKCS7_GetAttributeValue(wc_PKCS7* pkcs7, const byte* oid, word32 oidSz,
 1511        byte* out, word32* outSz)
 1512{
 1513    PKCS7DecodedAttrib* attrib;
 1514
 1515    if (pkcs7 == NULL || oid == NULL || outSz == NULL) {
 1516        return BAD_FUNC_ARG;
 1517    }
 1518
 1519    attrib = findAttrib(pkcs7, oid, oidSz);
 1520    if (attrib == NULL) {
 1521        return ASN_PARSE_E;
 1522    }
 1523
 1524    if (out == NULL) {
 1525        *outSz = attrib->valueSz;
 1526        return WC_NO_ERR_TRACE(LENGTH_ONLY_E);
 1527    }
 1528
 1529    if (*outSz < attrib->valueSz) {
 1530        return BUFFER_E;
 1531    }
 1532
 1533    XMEMCPY(out, attrib->value, attrib->valueSz);
 1534    return (int)attrib->valueSz;
 1535}
 1536
 1537
 1538/* build PKCS#7 data content type */
 1539int wc_PKCS7_EncodeData(wc_PKCS7* pkcs7, byte* output, word32 outputSz)
 1540{
 1541    static const byte oid[] =
 1542        { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
 1543                         0x07, 0x01 };
 1544    byte seq[MAX_SEQ_SZ];
 1545    byte octetStr[MAX_OCTET_STR_SZ];
 1546    word32 seqSz;
 1547    word32 octetStrSz;
 1548    word32 oidSz = (word32)sizeof(oid);
 1549    word32 idx = 0;
 1550
 1551    if (pkcs7 == NULL || output == NULL) {
 1552        return BAD_FUNC_ARG;
 1553    }
 1554
 1555    octetStrSz = SetOctetString(pkcs7->contentSz, octetStr);
 1556    seqSz = SetSequence(pkcs7->contentSz + octetStrSz + oidSz, seq);
 1557
 1558    if (outputSz < pkcs7->contentSz + octetStrSz + oidSz + seqSz)
 1559        return BUFFER_E;
 1560
 1561    XMEMCPY(output, seq, seqSz);
 1562    idx += seqSz;
 1563    XMEMCPY(output + idx, oid, oidSz);
 1564    idx += oidSz;
 1565    XMEMCPY(output + idx, octetStr, octetStrSz);
 1566    idx += octetStrSz;
 1567    XMEMCPY(output + idx, pkcs7->content, pkcs7->contentSz);
 1568    idx += pkcs7->contentSz;
 1569
 1570    return (int)idx;
 1571}
 1572
 1573
 1574typedef struct EncodedAttrib {
 1575    byte valueSeq[MAX_SEQ_SZ];
 1576        const byte* oid;
 1577        byte valueSet[MAX_SET_SZ];
 1578        const byte* value;
 1579    word32 valueSeqSz, oidSz, idSz, valueSetSz, valueSz, totalSz;
 1580} EncodedAttrib;
 1581
 1582
 1583typedef struct ESD {
 1584    wc_HashAlg  hash;
 1585    enum wc_HashType hashType;
 1586    byte contentDigest[WC_MAX_DIGEST_SIZE + 2]; /* content only + ASN.1 heading */
 1587    WC_BITFIELD contentDigestSet:1;
 1588    byte contentAttribsDigest[WC_MAX_DIGEST_SIZE];
 1589    byte encContentDigest[MAX_ENCRYPTED_KEY_SZ];
 1590
 1591    byte outerSeq[MAX_SEQ_SZ];
 1592        byte outerContent[MAX_EXP_SZ];
 1593            byte innerSeq[MAX_SEQ_SZ];
 1594                byte version[MAX_VERSION_SZ];
 1595                byte digAlgoIdSet[MAX_SET_SZ];
 1596                    byte singleDigAlgoId[MAX_ALGO_SZ];
 1597
 1598                byte contentInfoSeq[MAX_SEQ_SZ];
 1599                    byte innerContSeq[MAX_EXP_SZ];
 1600                        byte innerOctets[MAX_OCTET_STR_SZ];
 1601
 1602                byte certsSet[MAX_SET_SZ];
 1603
 1604                byte signerInfoSet[MAX_SET_SZ];
 1605                    byte signerInfoSeq[MAX_SEQ_SZ];
 1606                        byte signerVersion[MAX_VERSION_SZ];
 1607                        /* issuerAndSerialNumber ...*/
 1608                        byte issuerSnSeq[MAX_SEQ_SZ];
 1609                            byte issuerName[MAX_SEQ_SZ];
 1610                            byte issuerSn[MAX_SN_SZ];
 1611                        /* OR subjectKeyIdentifier */
 1612                        byte issuerSKIDSeq[MAX_SEQ_SZ];
 1613                            byte issuerSKID[MAX_OCTET_STR_SZ];
 1614                        byte signerDigAlgoId[MAX_ALGO_SZ];
 1615#if defined(WC_RSA_PSS)
 1616                        byte digEncAlgoId[128]; /* RSASSA-PSS needs full params */
 1617#else
 1618                        byte digEncAlgoId[MAX_ALGO_SZ];
 1619#endif
 1620                        byte signedAttribSet[MAX_SET_SZ];
 1621                            EncodedAttrib signedAttribs[7];
 1622                        byte signerDigest[MAX_OCTET_STR_SZ];
 1623    word32 innerOctetsSz, innerContSeqSz, contentInfoSeqSz;
 1624    word32 outerSeqSz, outerContentSz, innerSeqSz, versionSz, digAlgoIdSetSz,
 1625           singleDigAlgoIdSz, certsSetSz;
 1626    word32 signerInfoSetSz, signerInfoSeqSz, signerVersionSz,
 1627           issuerSnSeqSz, issuerNameSz, issuerSnSz, issuerSKIDSz,
 1628           issuerSKIDSeqSz, signerDigAlgoIdSz, digEncAlgoIdSz, signerDigestSz;
 1629    word32 encContentDigestSz, signedAttribsSz, signedAttribsCount,
 1630           signedAttribSetSz;
 1631} ESD;
 1632
 1633
 1634static int EncodeAttributes(EncodedAttrib* ea, int eaSz,
 1635                                            PKCS7Attrib* attribs, int attribsSz)
 1636{
 1637    int i;
 1638    int maxSz = (int)min((word32)eaSz, (word32)attribsSz);
 1639    int allAttribsSz = 0;
 1640
 1641    for (i = 0; i < maxSz; i++)
 1642    {
 1643        word32 attribSz = 0;
 1644
 1645        ea[i].value = attribs[i].value;
 1646        ea[i].valueSz = attribs[i].valueSz;
 1647        attribSz += ea[i].valueSz;
 1648        ea[i].valueSetSz = SetSet(attribSz, ea[i].valueSet);
 1649        attribSz += ea[i].valueSetSz;
 1650        ea[i].oid = attribs[i].oid;
 1651        ea[i].oidSz = attribs[i].oidSz;
 1652        attribSz += ea[i].oidSz;
 1653        ea[i].valueSeqSz = SetSequence(attribSz, ea[i].valueSeq);
 1654        attribSz += ea[i].valueSeqSz;
 1655        ea[i].totalSz = attribSz;
 1656
 1657        allAttribsSz += (int)attribSz;
 1658    }
 1659    return allAttribsSz;
 1660}
 1661
 1662
 1663typedef struct FlatAttrib {
 1664    byte* data;
 1665    word32 dataSz;
 1666} FlatAttrib;
 1667
 1668/* Returns a pointer to FlatAttrib whose members are initialized to 0.
 1669*  Caller is expected to free.
 1670*/
 1671static FlatAttrib* NewAttrib(void* heap)
 1672{
 1673    FlatAttrib* fb = (FlatAttrib*) XMALLOC(sizeof(FlatAttrib), heap,
 1674                                                   DYNAMIC_TYPE_TMP_BUFFER);
 1675    if (fb != NULL) {
 1676        ForceZero(fb, sizeof(FlatAttrib));
 1677    }
 1678    (void)heap;
 1679    return fb;
 1680}
 1681
 1682/* Free FlatAttrib array and memory allocated to internal struct members */
 1683static void FreeAttribArray(wc_PKCS7* pkcs7, FlatAttrib** arr, int rows)
 1684{
 1685    int i;
 1686
 1687    if (arr) {
 1688        for (i = 0; i < rows; i++) {
 1689            if (arr[i]) {
 1690                if (arr[i]->data) {
 1691                    ForceZero(arr[i]->data, arr[i]->dataSz);
 1692                    XFREE(arr[i]->data, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 1693                }
 1694                ForceZero(arr[i], sizeof(FlatAttrib));
 1695                XFREE(arr[i], pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 1696            }
 1697        }
 1698        ForceZero(arr, (word32)rows);
 1699        XFREE(arr, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 1700    }
 1701    (void)pkcs7;
 1702}
 1703
 1704
 1705/* Sort FlatAttrib array in ascending order */
 1706static int SortAttribArray(FlatAttrib** arr, int rows)
 1707{
 1708    int i, j;
 1709    word32 minSz, minIdx;
 1710    FlatAttrib* a   = NULL;
 1711    FlatAttrib* b   = NULL;
 1712    FlatAttrib* tmp = NULL;
 1713
 1714    if (arr == NULL) {
 1715        return BAD_FUNC_ARG;
 1716    }
 1717
 1718    for (i = 0; i < rows; i++) {
 1719        a = arr[i];
 1720        minSz = a->dataSz;
 1721        minIdx = (word32)i;
 1722        for (j = i+1; j < rows; j++) {
 1723            b = arr[j];
 1724            if (b->dataSz < minSz) {
 1725                minSz = b->dataSz;
 1726                minIdx = (word32)j;
 1727            }
 1728        }
 1729        if (minSz < a->dataSz) {
 1730            /* swap array positions */
 1731            tmp = arr[i];
 1732            arr[i] = arr[minIdx];
 1733            arr[minIdx] = tmp;
 1734        }
 1735    }
 1736
 1737    return 0;
 1738}
 1739
 1740
 1741/* Build up array of FlatAttrib structs from EncodedAttrib ones. FlatAttrib
 1742 * holds flattened DER encoding of each attribute */
 1743static int FlattenEncodedAttribs(wc_PKCS7* pkcs7, FlatAttrib** derArr, int rows,
 1744                                 EncodedAttrib* ea, int eaSz)
 1745{
 1746    int i;
 1747    word32 idx, sz;
 1748    byte* output   = NULL;
 1749    FlatAttrib* fa = NULL;
 1750
 1751    if (pkcs7 == NULL || derArr == NULL || ea == NULL) {
 1752        WOLFSSL_MSG("Invalid arguments to FlattenEncodedAttribs");
 1753        return BAD_FUNC_ARG;
 1754    }
 1755
 1756    if (rows != eaSz) {
 1757        WOLFSSL_MSG("DER array not large enough to hold attribute count");
 1758        return BAD_FUNC_ARG;
 1759    }
 1760
 1761    for (i = 0; i < eaSz; i++) {
 1762        sz = ea[i].valueSeqSz + ea[i].oidSz + ea[i].valueSetSz + ea[i].valueSz;
 1763
 1764        output = (byte*)XMALLOC(sz, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 1765        if (output == NULL) {
 1766            return MEMORY_E;
 1767        }
 1768
 1769        idx = 0;
 1770        XMEMCPY(output + idx, ea[i].valueSeq, ea[i].valueSeqSz);
 1771        idx += ea[i].valueSeqSz;
 1772        XMEMCPY(output + idx, ea[i].oid, ea[i].oidSz);
 1773        idx += ea[i].oidSz;
 1774        XMEMCPY(output + idx, ea[i].valueSet, ea[i].valueSetSz);
 1775        idx += ea[i].valueSetSz;
 1776        XMEMCPY(output + idx, ea[i].value, ea[i].valueSz);
 1777
 1778        fa = derArr[i];
 1779        fa->data = output;
 1780        fa->dataSz = sz;
 1781    }
 1782
 1783    return 0;
 1784}
 1785
 1786
 1787/* Sort and Flatten EncodedAttrib attributes into output buffer */
 1788static int FlattenAttributes(wc_PKCS7* pkcs7, byte* output, EncodedAttrib* ea,
 1789                             int eaSz)
 1790{
 1791    int i, ret;
 1792    word32 idx;
 1793    FlatAttrib** derArr = NULL;
 1794    FlatAttrib*  fa     = NULL;
 1795
 1796    if (pkcs7 == NULL || output == NULL || ea == NULL) {
 1797        return BAD_FUNC_ARG;
 1798    }
 1799
 1800    /* create array of FlatAttrib struct pointers to hold DER attribs */
 1801    derArr = (FlatAttrib**) XMALLOC((unsigned long)eaSz * sizeof(FlatAttrib*),
 1802        pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 1803    if (derArr == NULL) {
 1804        return MEMORY_E;
 1805    }
 1806    XMEMSET(derArr, 0, (unsigned long)eaSz * sizeof(FlatAttrib*));
 1807
 1808    for (i = 0; i < eaSz; i++) {
 1809        derArr[i] = NewAttrib(pkcs7->heap);
 1810        if (derArr[i] == NULL) {
 1811            FreeAttribArray(pkcs7, derArr, eaSz);
 1812            return MEMORY_E;
 1813        }
 1814        ForceZero(derArr[i], sizeof(FlatAttrib));
 1815    }
 1816
 1817    /* flatten EncodedAttrib into DER byte arrays */
 1818    ret = FlattenEncodedAttribs(pkcs7, derArr, eaSz, ea, eaSz);
 1819    if (ret != 0) {
 1820        FreeAttribArray(pkcs7, derArr, eaSz);
 1821        return ret;
 1822    }
 1823
 1824    /* SET OF DER signed attributes must be sorted in ascending order */
 1825    ret = SortAttribArray(derArr, eaSz);
 1826    if (ret != 0) {
 1827        FreeAttribArray(pkcs7, derArr, eaSz);
 1828        return ret;
 1829    }
 1830
 1831    /* copy sorted DER attribute arrays into output buffer */
 1832    idx = 0;
 1833    for (i = 0; i < eaSz; i++) {
 1834        fa = derArr[i];
 1835        XMEMCPY(output + idx, fa->data, fa->dataSz);
 1836        idx += fa->dataSz;
 1837    }
 1838
 1839    FreeAttribArray(pkcs7, derArr, eaSz);
 1840
 1841    return 0;
 1842}
 1843
 1844
 1845#ifndef NO_RSA
 1846
 1847static int wc_PKCS7_ImportRSA(wc_PKCS7* pkcs7, RsaKey* privKey)
 1848{
 1849    int ret;
 1850    word32 idx;
 1851
 1852    ret = wc_InitRsaKey_ex(privKey, pkcs7->heap, pkcs7->devId);
 1853    if (ret == 0) {
 1854        if (pkcs7->privateKey != NULL && pkcs7->privateKeySz > 0) {
 1855            idx = 0;
 1856            ret = wc_RsaPrivateKeyDecode(pkcs7->privateKey, &idx, privKey,
 1857                                         pkcs7->privateKeySz);
 1858            /* If not using old FIPS or CAVP selftest, or not using FAST,
 1859             * or USER RSA, able to check RSA key. */
 1860            if (ret == 0) {
 1861        #ifdef WOLFSSL_RSA_KEY_CHECK
 1862                /* verify imported private key is a valid key before using it */
 1863                ret = wc_CheckRsaKey(privKey);
 1864                if (ret != 0) {
 1865                    WOLFSSL_MSG("Invalid RSA private key, check "
 1866                                "pkcs7->privateKey");
 1867                }
 1868        #endif
 1869            }
 1870        #ifdef WOLF_CRYPTO_CB
 1871            else if (ret == WC_NO_ERR_TRACE(ASN_PARSE_E) &&
 1872                     pkcs7->devId != INVALID_DEVID) {
 1873                /* if using crypto callbacks, try public key decode */
 1874                idx = 0;
 1875                ret = wc_RsaPublicKeyDecode(pkcs7->privateKey, &idx, privKey,
 1876                                            pkcs7->privateKeySz);
 1877            }
 1878        #endif
 1879        }
 1880    #ifdef HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK
 1881        else if (pkcs7->rsaSignRawDigestCb != NULL && pkcs7->publicKeySz > 0) {
 1882            /* When using raw sign callback (e.g., HSM/secure element), private
 1883             * key may not be available. Use public key from signer certificate
 1884             * for signature size calculation. */
 1885            idx = 0;
 1886            ret = wc_RsaPublicKeyDecode(pkcs7->publicKey, &idx, privKey,
 1887                                        pkcs7->publicKeySz);
 1888        }
 1889    #endif
 1890        else if (pkcs7->devId == INVALID_DEVID) {
 1891            ret = BAD_FUNC_ARG;
 1892        }
 1893    }
 1894
 1895    return ret;
 1896}
 1897
 1898
 1899/* returns size of signature put into out, negative on error */
 1900static int wc_PKCS7_RsaSign(wc_PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd)
 1901{
 1902    int ret;
 1903    WC_DECLARE_VAR(privKey, RsaKey, 1, 0);
 1904
 1905    if (pkcs7 == NULL || pkcs7->rng == NULL || in == NULL || esd == NULL) {
 1906        return BAD_FUNC_ARG;
 1907    }
 1908
 1909    WC_ALLOC_VAR_EX(privKey, RsaKey, 1, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER,
 1910        return MEMORY_E);
 1911
 1912    ret = wc_PKCS7_ImportRSA(pkcs7, privKey);
 1913    if (ret == 0) {
 1914    #ifdef WOLFSSL_ASYNC_CRYPT
 1915        do {
 1916            ret = wc_AsyncWait(ret, &privKey->asyncDev,
 1917                WC_ASYNC_FLAG_CALL_AGAIN);
 1918            if (ret >= 0)
 1919    #endif
 1920            {
 1921                ret = wc_RsaSSL_Sign(in, inSz, esd->encContentDigest,
 1922                                     sizeof(esd->encContentDigest),
 1923                                     privKey, pkcs7->rng);
 1924            }
 1925    #ifdef WOLFSSL_ASYNC_CRYPT
 1926        } while (ret == WC_NO_ERR_TRACE(WC_PENDING_E));
 1927    #endif
 1928    }
 1929
 1930    wc_FreeRsaKey(privKey);
 1931    WC_FREE_VAR_EX(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 1932
 1933    return ret;
 1934}
 1935
 1936#endif /* NO_RSA */
 1937
 1938
 1939#ifdef HAVE_ECC
 1940
 1941static int wc_PKCS7_ImportECC(wc_PKCS7* pkcs7, ecc_key* privKey)
 1942{
 1943    int ret;
 1944    word32 idx;
 1945
 1946    ret = wc_ecc_init_ex(privKey, pkcs7->heap, pkcs7->devId);
 1947    if (ret == 0) {
 1948        if (pkcs7->privateKey != NULL && pkcs7->privateKeySz > 0) {
 1949            idx = 0;
 1950            ret = wc_EccPrivateKeyDecode(pkcs7->privateKey, &idx, privKey,
 1951                                         pkcs7->privateKeySz);
 1952            /* verify imported private key is a valid key before using it */
 1953            if (ret == 0) {
 1954                ret = wc_ecc_check_key(privKey);
 1955                if (ret != 0) {
 1956                    WOLFSSL_MSG("Invalid ECC private key, check "
 1957                                "pkcs7->privateKey");
 1958                }
 1959            }
 1960        #ifdef WOLF_CRYPTO_CB
 1961            else if (ret == WC_NO_ERR_TRACE(ASN_PARSE_E) &&
 1962                     pkcs7->devId != INVALID_DEVID) {
 1963                /* if using crypto callbacks, try public key decode */
 1964                idx = 0;
 1965                ret = wc_EccPublicKeyDecode(pkcs7->privateKey, &idx, privKey,
 1966                                            pkcs7->privateKeySz);
 1967            }
 1968        #endif
 1969        }
 1970    #ifdef HAVE_PKCS7_ECC_RAW_SIGN_CALLBACK
 1971        else if (pkcs7->eccSignRawDigestCb != NULL && pkcs7->publicKeySz > 0) {
 1972            /* When using raw sign callback (e.g., HSM/secure element), private
 1973             * key may not be available. Use public key from signer certificate
 1974             * for signature size calculation. */
 1975            idx = 0;
 1976            ret = wc_EccPublicKeyDecode(pkcs7->publicKey, &idx, privKey,
 1977                                        pkcs7->publicKeySz);
 1978        }
 1979    #endif
 1980        else if (pkcs7->devId == INVALID_DEVID) {
 1981            ret = BAD_FUNC_ARG;
 1982        }
 1983    }
 1984
 1985    return ret;
 1986}
 1987
 1988
 1989/* returns size of signature put into out, negative on error */
 1990static int wc_PKCS7_EcdsaSign(wc_PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd)
 1991{
 1992    int ret;
 1993    word32 outSz;
 1994    WC_DECLARE_VAR(privKey, ecc_key, 1, 0);
 1995
 1996    if (pkcs7 == NULL || pkcs7->rng == NULL || in == NULL || esd == NULL) {
 1997        return BAD_FUNC_ARG;
 1998    }
 1999
 2000    WC_ALLOC_VAR_EX(privKey, ecc_key, 1, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER,
 2001        return MEMORY_E);
 2002
 2003    ret = wc_PKCS7_ImportECC(pkcs7, privKey);
 2004    if (ret == 0) {
 2005        outSz = sizeof(esd->encContentDigest);
 2006    #ifdef WOLFSSL_ASYNC_CRYPT
 2007        do {
 2008            ret = wc_AsyncWait(ret, &privKey->asyncDev,
 2009                WC_ASYNC_FLAG_CALL_AGAIN);
 2010            if (ret >= 0)
 2011    #endif
 2012            {
 2013                ret = wc_ecc_sign_hash(in, inSz, esd->encContentDigest,
 2014                                       &outSz, pkcs7->rng, privKey);
 2015            }
 2016    #ifdef WOLFSSL_ASYNC_CRYPT
 2017        } while (ret == WC_NO_ERR_TRACE(WC_PENDING_E));
 2018    #endif
 2019        if (ret == 0)
 2020            ret = (int)outSz;
 2021    }
 2022
 2023    wc_ecc_free(privKey);
 2024    WC_FREE_VAR_EX(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 2025
 2026    return ret;
 2027}
 2028
 2029#endif /* HAVE_ECC */
 2030
 2031#if defined(WC_RSA_PSS) && !defined(NO_RSA)
 2032/* Map hash type to MGF1 identifier; local copy so PKCS7 does not depend on
 2033 * rsa.c when RSA is in a separate FIPS module (e.g. CAVP build). */
 2034static int pkcs7_hash2mgf(enum wc_HashType hType)
 2035{
 2036    switch (hType) {
 2037    case WC_HASH_TYPE_NONE:
 2038        return WC_MGF1NONE;
 2039    case WC_HASH_TYPE_SHA:
 2040#ifndef NO_SHA
 2041        return WC_MGF1SHA1;
 2042#else
 2043        break;
 2044#endif
 2045    case WC_HASH_TYPE_SHA224:
 2046#ifdef WOLFSSL_SHA224
 2047        return WC_MGF1SHA224;
 2048#else
 2049        break;
 2050#endif
 2051    case WC_HASH_TYPE_SHA256:
 2052#ifndef NO_SHA256
 2053        return WC_MGF1SHA256;
 2054#else
 2055        break;
 2056#endif
 2057    case WC_HASH_TYPE_SHA384:
 2058#ifdef WOLFSSL_SHA384
 2059        return WC_MGF1SHA384;
 2060#else
 2061        break;
 2062#endif
 2063    case WC_HASH_TYPE_SHA512:
 2064#ifdef WOLFSSL_SHA512
 2065        return WC_MGF1SHA512;
 2066#else
 2067        break;
 2068#endif
 2069    /* MGF1 only supports SHA-1 and SHA-2; other hashes fall through to WC_MGF1NONE */
 2070    case WC_HASH_TYPE_MD2:
 2071    case WC_HASH_TYPE_MD4:
 2072    case WC_HASH_TYPE_MD5:
 2073    case WC_HASH_TYPE_MD5_SHA:
 2074    case WC_HASH_TYPE_SHA3_224:
 2075    case WC_HASH_TYPE_SHA3_256:
 2076    case WC_HASH_TYPE_SHA3_384:
 2077    case WC_HASH_TYPE_SHA3_512:
 2078    case WC_HASH_TYPE_BLAKE2B:
 2079    case WC_HASH_TYPE_BLAKE2S:
 2080    case WC_HASH_TYPE_SHA512_224:
 2081    case WC_HASH_TYPE_SHA512_256:
 2082    case WC_HASH_TYPE_SHAKE128:
 2083    case WC_HASH_TYPE_SHAKE256:
 2084    case WC_HASH_TYPE_SM3:
 2085    default:
 2086        break;
 2087    }
 2088    return WC_MGF1NONE;
 2089}
 2090
 2091/* returns size of signature put into esd->encContentDigest, negative on error.
 2092 * Signs the digest (contentAttribsDigest) with RSA-PSS padding, like ECDSA. */
 2093static int wc_PKCS7_RsaPssSign(wc_PKCS7* pkcs7, byte* digest, word32 digestSz,
 2094                               ESD* esd)
 2095{
 2096    int ret;
 2097    word32 outSz;
 2098    WC_DECLARE_VAR(privKey, RsaKey, 1, 0);
 2099
 2100    if (pkcs7 == NULL || pkcs7->rng == NULL || digest == NULL || esd == NULL) {
 2101        return BAD_FUNC_ARG;
 2102    }
 2103
 2104    WC_ALLOC_VAR_EX(privKey, RsaKey, 1, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER,
 2105        return MEMORY_E);
 2106
 2107    ret = wc_PKCS7_ImportRSA(pkcs7, privKey);
 2108    if (ret == 0) {
 2109        outSz = sizeof(esd->encContentDigest);
 2110#ifdef WOLFSSL_ASYNC_CRYPT
 2111        do {
 2112            ret = wc_AsyncWait(ret, &privKey->asyncDev,
 2113                WC_ASYNC_FLAG_CALL_AGAIN);
 2114            if (ret >= 0)
 2115#endif
 2116            {
 2117                /* Salt length policy: use hash digest length (RFC 4055 typical).
 2118                 * RFC 3447 allows arbitrary salt lengths, but hash-length is the
 2119                 * most interoperable choice and matches OpenSSL's default.
 2120                 * Must agree with the saltLen encoded in
 2121                 * SignerInfo.signatureAlgorithm params above. */
 2122                int saltLen = wc_HashGetDigestSize(wc_OidGetHash(pkcs7->hashOID));
 2123                if (saltLen < 0) {
 2124                    ret = saltLen;
 2125                }
 2126                else {
 2127                    ret = wc_RsaPSS_Sign_ex(digest, digestSz,
 2128                        esd->encContentDigest, outSz,
 2129                        esd->hashType, pkcs7_hash2mgf(esd->hashType),
 2130                        saltLen, privKey, pkcs7->rng);
 2131                }
 2132            }
 2133#ifdef WOLFSSL_ASYNC_CRYPT
 2134        } while (ret == WC_NO_ERR_TRACE(WC_PENDING_E));
 2135#endif
 2136        /* wc_RsaPSS_Sign_ex returns signature length on success */
 2137    }
 2138
 2139    wc_FreeRsaKey(privKey);
 2140    WC_FREE_VAR_EX(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 2141
 2142    return ret;
 2143}
 2144#endif /* WC_RSA_PSS && !NO_RSA */
 2145
 2146/* returns encContentDigestSz based on the signature set to be used */
 2147static int wc_PKCS7_GetSignSize(wc_PKCS7* pkcs7)
 2148{
 2149    int ret = 0;
 2150
 2151    switch (pkcs7->publicKeyOID) {
 2152
 2153    #ifndef NO_RSA
 2154        case RSAk:
 2155    #ifdef WC_RSA_PSS
 2156        case RSAPSSk:
 2157    #endif
 2158        {
 2159        #ifndef WOLFSSL_SMALL_STACK
 2160            RsaKey  privKey[1];
 2161        #else
 2162            RsaKey* privKey;
 2163            privKey = (RsaKey*)XMALLOC(sizeof(RsaKey), pkcs7->heap,
 2164                DYNAMIC_TYPE_TMP_BUFFER);
 2165            if (privKey == NULL)
 2166                return MEMORY_E;
 2167        #endif
 2168
 2169            ret = wc_PKCS7_ImportRSA(pkcs7, privKey);
 2170            if (ret == 0) {
 2171                ret = wc_RsaEncryptSize(privKey);
 2172            }
 2173            wc_FreeRsaKey(privKey);
 2174            WC_FREE_VAR_EX(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 2175        }
 2176        break;
 2177    #endif
 2178
 2179    #ifdef HAVE_ECC
 2180        case ECDSAk:
 2181        {
 2182        #ifndef WOLFSSL_SMALL_STACK
 2183            ecc_key  privKey[1];
 2184        #else
 2185            ecc_key* privKey;
 2186            privKey = (ecc_key*)XMALLOC(sizeof(ecc_key), pkcs7->heap,
 2187                DYNAMIC_TYPE_TMP_BUFFER);
 2188            if (privKey == NULL)
 2189                return MEMORY_E;
 2190        #endif
 2191
 2192            ret = wc_PKCS7_ImportECC(pkcs7, privKey);
 2193            if (ret == 0) {
 2194                ret = wc_ecc_sig_size(privKey);
 2195            }
 2196            wc_ecc_free(privKey);
 2197            WC_FREE_VAR_EX(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 2198        }
 2199        break;
 2200    #endif
 2201    }
 2202
 2203    return ret;
 2204}
 2205
 2206
 2207/* builds up SignedData signed attributes, including default ones.
 2208 *
 2209 * pkcs7 - pointer to initialized PKCS7 structure
 2210 * esd   - pointer to initialized ESD structure, used for output
 2211 *
 2212 * return 0 on success, negative on error */
 2213static int wc_PKCS7_BuildSignedAttributes(wc_PKCS7* pkcs7, ESD* esd,
 2214                    const byte* contentType, word32 contentTypeSz,
 2215                    const byte* contentTypeOid, word32 contentTypeOidSz,
 2216                    const byte* messageDigestOid, word32 messageDigestOidSz,
 2217                    const byte* signingTimeOid, word32 signingTimeOidSz,
 2218                    byte* signingTime, word32 signingTimeSz)
 2219{
 2220    int hashSz;
 2221#ifdef NO_ASN_TIME
 2222    PKCS7Attrib cannedAttribs[2];
 2223#else
 2224    time_t tm;
 2225    int timeSz;
 2226    PKCS7Attrib cannedAttribs[3];
 2227#endif
 2228    word32 idx    = 0;
 2229    word32 atrIdx = 0;
 2230
 2231    if (pkcs7 == NULL || esd == NULL || contentType == NULL ||
 2232        contentTypeOid == NULL || messageDigestOid == NULL ||
 2233        signingTimeOid == NULL) {
 2234        return BAD_FUNC_ARG;
 2235    }
 2236
 2237    if (pkcs7->defaultSignedAttribs != WOLFSSL_NO_ATTRIBUTES) {
 2238        hashSz = wc_HashGetDigestSize(esd->hashType);
 2239        if (hashSz < 0)
 2240            return hashSz;
 2241
 2242    #ifndef NO_ASN_TIME
 2243        if (signingTime == NULL || signingTimeSz == 0)
 2244            return BAD_FUNC_ARG;
 2245
 2246        tm = wc_Time(0);
 2247        timeSz = GetAsnTimeString(&tm, signingTime, signingTimeSz);
 2248        if (timeSz < 0)
 2249            return timeSz;
 2250    #endif
 2251
 2252        XMEMSET(&cannedAttribs[idx], 0, sizeof(cannedAttribs[idx]));
 2253
 2254        if ((pkcs7->defaultSignedAttribs & WOLFSSL_CONTENT_TYPE_ATTRIBUTE) ||
 2255            pkcs7->defaultSignedAttribs == 0) {
 2256            cannedAttribs[idx].oid     = contentTypeOid;
 2257            cannedAttribs[idx].oidSz   = contentTypeOidSz;
 2258            cannedAttribs[idx].value   = contentType;
 2259            cannedAttribs[idx].valueSz = contentTypeSz;
 2260            idx++;
 2261        }
 2262
 2263    #ifndef NO_ASN_TIME
 2264        if ((pkcs7->defaultSignedAttribs & WOLFSSL_SIGNING_TIME_ATTRIBUTE) ||
 2265            pkcs7->defaultSignedAttribs == 0) {
 2266            cannedAttribs[idx].oid     = signingTimeOid;
 2267            cannedAttribs[idx].oidSz   = signingTimeOidSz;
 2268            cannedAttribs[idx].value   = signingTime;
 2269            cannedAttribs[idx].valueSz = (word32)timeSz;
 2270            idx++;
 2271        }
 2272    #endif
 2273
 2274        if ((pkcs7->defaultSignedAttribs & WOLFSSL_MESSAGE_DIGEST_ATTRIBUTE) ||
 2275            pkcs7->defaultSignedAttribs == 0) {
 2276            cannedAttribs[idx].oid     = messageDigestOid;
 2277            cannedAttribs[idx].oidSz   = messageDigestOidSz;
 2278            cannedAttribs[idx].value   = esd->contentDigest;
 2279            cannedAttribs[idx].valueSz = (word32)hashSz + 2;  /* ASN.1 heading */
 2280            idx++;
 2281        }
 2282
 2283        esd->signedAttribsCount += idx;
 2284        esd->signedAttribsSz += (word32)EncodeAttributes(
 2285            &esd->signedAttribs[atrIdx], (int)idx, cannedAttribs,
 2286            (int)idx);
 2287        atrIdx += idx;
 2288    } else {
 2289        esd->signedAttribsCount = 0;
 2290        esd->signedAttribsSz = 0;
 2291    }
 2292
 2293    /* add custom signed attributes if set */
 2294    if (pkcs7->signedAttribsSz > 0 && pkcs7->signedAttribs != NULL) {
 2295        word32 availableSpace = MAX_SIGNED_ATTRIBS_SZ - atrIdx;
 2296
 2297        if (pkcs7->signedAttribsSz > availableSpace)
 2298            return BUFFER_E;
 2299
 2300        esd->signedAttribsCount += pkcs7->signedAttribsSz;
 2301        esd->signedAttribsSz += (word32)EncodeAttributes(
 2302            &esd->signedAttribs[atrIdx], (int)esd->signedAttribsCount,
 2303            pkcs7->signedAttribs, (int)pkcs7->signedAttribsSz);
 2304    }
 2305
 2306#ifdef NO_ASN_TIME
 2307    (void)signingTimeOidSz;
 2308    (void)signingTime;
 2309    (void)signingTimeSz;
 2310#endif
 2311
 2312    return 0;
 2313}
 2314
 2315
 2316/* gets correct encryption algo ID for SignedData, either CTC_<hash>wRSA or
 2317 * CTC_<hash>wECDSA, from pkcs7->publicKeyOID and pkcs7->hashOID.
 2318 *
 2319 * pkcs7          - pointer to PKCS7 structure
 2320 * digEncAlgoId   - [OUT] output int to store correct algo ID in
 2321 * digEncAlgoType - [OUT] output for algo ID type
 2322 *
 2323 * return 0 on success, negative on error */
 2324static int wc_PKCS7_SignedDataGetEncAlgoId(wc_PKCS7* pkcs7, int* digEncAlgoId,
 2325                                           int* digEncAlgoType)
 2326{
 2327    int algoId   = 0;
 2328    int algoType = 0;
 2329
 2330    if (pkcs7 == NULL || digEncAlgoId == NULL || digEncAlgoType == NULL)
 2331        return BAD_FUNC_ARG;
 2332
 2333    if (pkcs7->publicKeyOID == RSAk) {
 2334
 2335        algoType = oidSigType;
 2336
 2337        switch (pkcs7->hashOID) {
 2338        #ifndef NO_SHA
 2339            case SHAh:
 2340                algoId = CTC_SHAwRSA;
 2341                break;
 2342        #endif
 2343        #ifdef WOLFSSL_SHA224
 2344            case SHA224h:
 2345                algoId = CTC_SHA224wRSA;
 2346                break;
 2347        #endif
 2348        #ifndef NO_SHA256
 2349            case SHA256h:
 2350                algoId = CTC_SHA256wRSA;
 2351                break;
 2352        #endif
 2353        #ifdef WOLFSSL_SHA384
 2354            case SHA384h:
 2355                algoId = CTC_SHA384wRSA;
 2356                break;
 2357        #endif
 2358        #ifdef WOLFSSL_SHA512
 2359            case SHA512h:
 2360                algoId = CTC_SHA512wRSA;
 2361                break;
 2362        #endif
 2363        #ifdef WOLFSSL_SHA3
 2364        #ifndef WOLFSSL_NOSHA3_224
 2365            case SHA3_224h:
 2366                algoId = CTC_SHA3_224wRSA;
 2367                break;
 2368        #endif
 2369        #ifndef WOLFSSL_NOSHA3_256
 2370            case SHA3_256h:
 2371                algoId = CTC_SHA3_256wRSA;
 2372                break;
 2373        #endif
 2374        #ifndef WOLFSSL_NOSHA3_384
 2375            case SHA3_384h:
 2376                algoId = CTC_SHA3_384wRSA;
 2377                break;
 2378        #endif
 2379        #ifndef WOLFSSL_NOSHA3_512
 2380            case SHA3_512h:
 2381                algoId = CTC_SHA3_512wRSA;
 2382                break;
 2383        #endif
 2384        #endif
 2385        }
 2386
 2387    }
 2388#ifdef HAVE_ECC
 2389    else if (pkcs7->publicKeyOID == ECDSAk) {
 2390
 2391        algoType = oidSigType;
 2392
 2393        switch (pkcs7->hashOID) {
 2394        #ifndef NO_SHA
 2395            case SHAh:
 2396                algoId = CTC_SHAwECDSA;
 2397                break;
 2398        #endif
 2399        #ifdef WOLFSSL_SHA224
 2400            case SHA224h:
 2401                algoId = CTC_SHA224wECDSA;
 2402                break;
 2403        #endif
 2404        #ifndef NO_SHA256
 2405            case SHA256h:
 2406                algoId = CTC_SHA256wECDSA;
 2407                break;
 2408        #endif
 2409        #ifdef WOLFSSL_SHA384
 2410            case SHA384h:
 2411                algoId = CTC_SHA384wECDSA;
 2412                break;
 2413        #endif
 2414        #ifdef WOLFSSL_SHA512
 2415            case SHA512h:
 2416                algoId = CTC_SHA512wECDSA;
 2417                break;
 2418        #endif
 2419        #ifdef WOLFSSL_SHA3
 2420        #ifndef WOLFSSL_NOSHA3_224
 2421            case SHA3_224h:
 2422                algoId = CTC_SHA3_224wECDSA;
 2423                break;
 2424        #endif
 2425        #ifndef WOLFSSL_NOSHA3_256
 2426            case SHA3_256h:
 2427                algoId = CTC_SHA3_256wECDSA;
 2428                break;
 2429        #endif
 2430        #ifndef WOLFSSL_NOSHA3_384
 2431            case SHA3_384h:
 2432                algoId = CTC_SHA3_384wECDSA;
 2433                break;
 2434        #endif
 2435        #ifndef WOLFSSL_NOSHA3_512
 2436            case SHA3_512h:
 2437                algoId = CTC_SHA3_512wECDSA;
 2438                break;
 2439        #endif
 2440        #endif
 2441        }
 2442    }
 2443#endif /* HAVE_ECC */
 2444
 2445#ifdef WC_RSA_PSS
 2446    else if (pkcs7->publicKeyOID == RSAPSSk) {
 2447        algoType = oidSigType;
 2448        algoId = CTC_RSASSAPSS;
 2449        /* Hash/MGF/salt conveyed via PSS params in AlgorithmIdentifier */
 2450    }
 2451#endif
 2452#ifndef WC_RSA_PSS
 2453    else if (pkcs7->publicKeyOID == RSAPSSk) {
 2454        WOLFSSL_MSG("RSA-PSS requested but WC_RSA_PSS not compiled in");
 2455        return NOT_COMPILED_IN;
 2456    }
 2457#endif
 2458
 2459    if (algoId == 0) {
 2460        WOLFSSL_MSG("Invalid signature algorithm type");
 2461        return BAD_FUNC_ARG;
 2462    }
 2463
 2464    *digEncAlgoId = algoId;
 2465    *digEncAlgoType = algoType;
 2466
 2467    return 0;
 2468}
 2469
 2470
 2471/* build SignedData DigestInfo for use with PKCS#7/RSA
 2472 *
 2473 * pkcs7 - pointer to initialized PKCS7 struct
 2474 * flatSignedAttribs - flattened, signed attributes
 2475 * flatSignedAttrbsSz - size of flatSignedAttribs, octets
 2476 * esd - pointer to initialized ESD struct
 2477 * digestInfo - [OUT] output array for DigestInfo
 2478 * digestInfoSz - [IN/OUT] - input size of array, size of digestInfo
 2479 *
 2480 * return 0 on success, negative on error */
 2481static int wc_PKCS7_BuildDigestInfo(wc_PKCS7* pkcs7, byte* flatSignedAttribs,
 2482                                    word32 flatSignedAttribsSz, ESD* esd,
 2483                                    byte* digestInfo, word32* digestInfoSz)
 2484{
 2485    int ret, digIdx = 0;
 2486    byte digestInfoSeq[MAX_SEQ_SZ];
 2487    byte digestStr[MAX_OCTET_STR_SZ];
 2488    byte attribSet[MAX_SET_SZ];
 2489    byte algoId[MAX_ALGO_SZ];
 2490    word32 digestInfoSeqSz, digestStrSz, algoIdSz, dgstInfoSz, hashSz;
 2491    word32 attribSetSz;
 2492
 2493    if (pkcs7 == NULL || esd == NULL || digestInfo == NULL ||
 2494        digestInfoSz == NULL) {
 2495        return BAD_FUNC_ARG;
 2496    }
 2497
 2498    ret = wc_HashGetDigestSize(esd->hashType);
 2499    if (ret < 0)
 2500        return ret;
 2501    hashSz = (word32)ret;
 2502
 2503    if (flatSignedAttribsSz != 0) {
 2504
 2505        if (flatSignedAttribs == NULL)
 2506            return BAD_FUNC_ARG;
 2507
 2508        attribSetSz = SetSet(flatSignedAttribsSz, attribSet);
 2509
 2510        ret = wc_HashInit(&esd->hash, esd->hashType);
 2511        if (ret < 0)
 2512            return ret;
 2513
 2514        ret = wc_HashUpdate(&esd->hash, esd->hashType,
 2515                            attribSet, attribSetSz);
 2516        if (ret == 0)
 2517            ret = wc_HashUpdate(&esd->hash, esd->hashType,
 2518                                flatSignedAttribs, flatSignedAttribsSz);
 2519        if (ret == 0)
 2520            ret = wc_HashFinal(&esd->hash, esd->hashType,
 2521                               esd->contentAttribsDigest);
 2522        wc_HashFree(&esd->hash, esd->hashType);
 2523
 2524        if (ret < 0)
 2525            return ret;
 2526
 2527    } else {
 2528        /* when no attrs, digest is contentDigest without tag and length */
 2529        XMEMCPY(esd->contentAttribsDigest, esd->contentDigest + 2, hashSz);
 2530    }
 2531
 2532    /* Set algoID, allow absent hash params */
 2533    algoIdSz = SetAlgoIDEx(pkcs7->hashOID, algoId, oidHashType,
 2534                           0, pkcs7->hashParamsAbsent);
 2535
 2536    digestStrSz = SetOctetString(hashSz, digestStr);
 2537    dgstInfoSz = algoIdSz + digestStrSz + hashSz;
 2538    digestInfoSeqSz = SetSequence(dgstInfoSz, digestInfoSeq);
 2539
 2540    if (*digestInfoSz < (digestInfoSeqSz + dgstInfoSz)) {
 2541        return BUFFER_E;
 2542    }
 2543
 2544    XMEMCPY(digestInfo + digIdx, digestInfoSeq, digestInfoSeqSz);
 2545    digIdx += (int)digestInfoSeqSz;
 2546    XMEMCPY(digestInfo + digIdx, algoId, algoIdSz);
 2547    digIdx += (int)algoIdSz;
 2548    XMEMCPY(digestInfo + digIdx, digestStr, digestStrSz);
 2549    digIdx += (int)digestStrSz;
 2550    XMEMCPY(digestInfo + digIdx, esd->contentAttribsDigest, hashSz);
 2551    digIdx += (int)hashSz;
 2552
 2553    *digestInfoSz = (word32)digIdx;
 2554
 2555    return 0;
 2556}
 2557
 2558
 2559/* build SignedData signature over DigestInfo or content digest
 2560 *
 2561 * pkcs7 - pointer to initialized PKCS7 struct
 2562 * flatSignedAttribs - flattened, signed attributes
 2563 * flatSignedAttribsSz - size of flatSignedAttribs, octets
 2564 * esd - pointer to initialized ESD struct
 2565 *
 2566 * returns length of signature on success, negative on error */
 2567static int wc_PKCS7_SignedDataBuildSignature(wc_PKCS7* pkcs7,
 2568                                             byte* flatSignedAttribs,
 2569                                             word32 flatSignedAttribsSz,
 2570                                             ESD* esd)
 2571{
 2572    int ret = 0;
 2573#if defined(HAVE_ECC) || \
 2574    (defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK) && !defined(NO_RSA)) || \
 2575    (defined(WC_RSA_PSS) && !defined(NO_RSA))
 2576    int hashSz = 0;
 2577#endif
 2578#if defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK) && !defined(NO_RSA)
 2579    int hashOID;
 2580#endif
 2581    word32 digestInfoSz = MAX_PKCS7_DIGEST_SZ;
 2582    WC_DECLARE_VAR(digestInfo, byte, MAX_PKCS7_DIGEST_SZ, 0);
 2583
 2584    if (pkcs7 == NULL || esd == NULL)
 2585        return BAD_FUNC_ARG;
 2586
 2587    WC_ALLOC_VAR_EX(digestInfo, byte, digestInfoSz, pkcs7->heap,
 2588        DYNAMIC_TYPE_TMP_BUFFER, return MEMORY_E);
 2589    XMEMSET(digestInfo, 0, digestInfoSz);
 2590
 2591    ret = wc_PKCS7_BuildDigestInfo(pkcs7, flatSignedAttribs,
 2592                                   flatSignedAttribsSz, esd, digestInfo,
 2593                                   &digestInfoSz);
 2594    if (ret < 0) {
 2595        WC_FREE_VAR_EX(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 2596        return ret;
 2597    }
 2598
 2599#if defined(HAVE_ECC) || \
 2600    (defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK) && !defined(NO_RSA)) || \
 2601    (defined(WC_RSA_PSS) && !defined(NO_RSA))
 2602    /* get digest size from hash type */
 2603    hashSz = wc_HashGetDigestSize(esd->hashType);
 2604    if (hashSz < 0) {
 2605        WC_FREE_VAR_EX(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 2606        return hashSz;
 2607    }
 2608#endif
 2609
 2610    /* sign digestInfo */
 2611    switch (pkcs7->publicKeyOID) {
 2612
 2613#ifndef NO_RSA
 2614        case RSAk:
 2615        #ifdef HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK
 2616            if (pkcs7->rsaSignRawDigestCb != NULL) {
 2617                /* get hash OID */
 2618                hashOID = wc_HashGetOID(esd->hashType);
 2619
 2620                /* user signing plain digest, build DigestInfo themselves */
 2621                ret = pkcs7->rsaSignRawDigestCb(pkcs7,
 2622                           esd->contentAttribsDigest, hashSz,
 2623                           esd->encContentDigest, sizeof(esd->encContentDigest),
 2624                           pkcs7->privateKey, pkcs7->privateKeySz, pkcs7->devId,
 2625                           hashOID);
 2626                break;
 2627            }
 2628        #endif
 2629            ret = wc_PKCS7_RsaSign(pkcs7, digestInfo, digestInfoSz, esd);
 2630            break;
 2631#endif
 2632
 2633#ifdef HAVE_ECC
 2634        case ECDSAk:
 2635        #ifdef HAVE_PKCS7_ECC_RAW_SIGN_CALLBACK
 2636            if (pkcs7->eccSignRawDigestCb != NULL) {
 2637                /* get hash OID */
 2638                int eccHashOID = wc_HashGetOID(esd->hashType);
 2639                if (eccHashOID < 0) {
 2640                    ret = eccHashOID;
 2641                    break;
 2642                }
 2643
 2644                /* user signing plain digest */
 2645                ret = pkcs7->eccSignRawDigestCb(pkcs7,
 2646                           esd->contentAttribsDigest, hashSz,
 2647                           esd->encContentDigest, sizeof(esd->encContentDigest),
 2648                           pkcs7->privateKey, pkcs7->privateKeySz, pkcs7->devId,
 2649                           eccHashOID);
 2650                /* validate return value doesn't exceed buffer size */
 2651                if (ret > 0 && (word32)ret > sizeof(esd->encContentDigest)) {
 2652                    ret = BUFFER_E;
 2653                }
 2654                break;
 2655            }
 2656        #endif
 2657            /* CMS with ECDSA does not sign DigestInfo structure
 2658             * like PKCS#7 with RSA does */
 2659            ret = wc_PKCS7_EcdsaSign(pkcs7, esd->contentAttribsDigest,
 2660                                     (word32)hashSz, esd);
 2661            break;
 2662#endif
 2663
 2664#if defined(WC_RSA_PSS) && !defined(NO_RSA)
 2665        case RSAPSSk:
 2666            /* RSA-PSS signs the digest directly (no DigestInfo), like ECDSA */
 2667            ret = wc_PKCS7_RsaPssSign(pkcs7, esd->contentAttribsDigest,
 2668                                      (word32)hashSz, esd);
 2669            break;
 2670#endif
 2671
 2672        default:
 2673            WOLFSSL_MSG("Unsupported public key type");
 2674            ret = BAD_FUNC_ARG;
 2675    }
 2676
 2677    WC_FREE_VAR_EX(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 2678
 2679    if (ret >= 0) {
 2680        esd->encContentDigestSz = (word32)ret;
 2681    }
 2682
 2683    return ret;
 2684}
 2685
 2686#ifndef BER_OCTET_LENGTH
 2687    #define BER_OCTET_LENGTH 4096
 2688#endif
 2689
 2690/**
 2691 * This helper function encodes a chunk of content stream and writes it out.
 2692 *
 2693 * @param pkcs7 Pointer to a PKCS7 structure.
 2694 * @param cipherType The type of cipher to use for encryption.
 2695 * @param aes Optional pointer to an Aes structure for AES encryption.
 2696 * @param encContentOut Buffer to hold the encrypted content.
 2697 * @param contentData Buffer holding the content to be encrypted.
 2698 * @param contentDataSz Size of the content to be encrypted.
 2699 * @param out Buffer to hold the output data.
 2700 * @param outIdx Pointer to an index into the output buffer.
 2701 * @param esd Pointer to an ESD structure for digest calculation.
 2702 * @return Returns 0 on success, and a negative value on failure.
 2703 */
 2704static int wc_PKCS7_EncodeContentStreamHelper(wc_PKCS7* pkcs7, int cipherType,
 2705    Aes* aes, byte* encContentOut, byte* contentData, int contentDataSz,
 2706    byte* out, word32* outIdx, ESD* esd)
 2707{
 2708    int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG);
 2709    byte   encContentOutOct[MAX_OCTET_STR_SZ];
 2710    word32 encContentOutOctSz = 0;
 2711
 2712    switch (cipherType) {
 2713        case WC_CIPHER_NONE:
 2714            XMEMCPY(encContentOut, contentData, (word32)contentDataSz);
 2715            if (esd && esd->contentDigestSet != 1) {
 2716                ret = wc_HashUpdate(&esd->hash, esd->hashType,
 2717                    contentData, (word32)contentDataSz);
 2718            }
 2719            break;
 2720
 2721    #ifndef NO_AES
 2722        case WC_CIPHER_AES_CBC:
 2723            ret = wc_AesCbcEncrypt(aes, encContentOut,
 2724                contentData, (word32)contentDataSz);
 2725            break;
 2726    #endif
 2727
 2728    #ifdef WOLFSSL_AESGCM_STREAM
 2729        case WC_CIPHER_AES_GCM:
 2730            ret = wc_AesGcmEncryptUpdate(aes, encContentOut,
 2731                    contentData, (word32)contentDataSz, NULL, 0);
 2732            break;
 2733    #endif
 2734    }
 2735
 2736    #ifdef WOLFSSL_ASYNC_CRYPT
 2737        /* async encrypt not available here, so block till done */
 2738        if (ret == WC_NO_ERR_TRACE(WC_PENDING_E) &&
 2739            cipherType != WC_CIPHER_NONE) {
 2740            ret = wc_AsyncWait(ret, &aes->asyncDev, WC_ASYNC_FLAG_NONE);
 2741        }
 2742    #endif
 2743
 2744    if (ret == 0) {
 2745        encContentOutOctSz = SetOctetString((word32)contentDataSz, encContentOutOct);
 2746        wc_PKCS7_WriteOut(pkcs7, (out)? out + *outIdx: NULL,
 2747                          encContentOutOct, encContentOutOctSz);
 2748        *outIdx += encContentOutOctSz;
 2749        wc_PKCS7_WriteOut(pkcs7, (out)? out + *outIdx : NULL,
 2750                                            encContentOut, (word32)contentDataSz);
 2751        *outIdx += (word32)contentDataSz;
 2752    }
 2753
 2754    return ret;
 2755}
 2756
 2757
 2758/* Used for encoding the content, potentially one octet chunk at a time if
 2759 * in streaming mode with IO callbacks set.
 2760 * Can handle the cipher types:
 2761 *      - WC_CIPHER_NONE, used for encoding signed bundle where no encryption is
 2762 *                        done.
 2763 *      - WC_CIPHER_AES_CBC
 2764 *      - WC_CIPHER_AES_GCM, requires WOLFSSL_AESGCM_STREAM for streaming
 2765 *                           encryption
 2766 * If ESD is passed in then hash of the conentet is collected as processed.
 2767 *
 2768 * Returns 0 on success */
 2769#ifndef NO_AES
 2770static int wc_PKCS7_EncodeContentStream(wc_PKCS7* pkcs7, ESD* esd, Aes* aes,
 2771    const byte* in, int inSz, byte* out, int cipherType)
 2772#else
 2773static int wc_PKCS7_EncodeContentStream(wc_PKCS7* pkcs7, ESD* esd, void* aes,
 2774    const byte* in, int inSz, byte* out, int cipherType)
 2775#endif
 2776{
 2777    int ret = 0;
 2778    int devId  = pkcs7->devId;
 2779    void* heap = pkcs7->heap;
 2780
 2781    if (pkcs7->encodeStream) {
 2782        int    sz;
 2783        word32 totalSz = 0;
 2784        const byte* buf;
 2785        byte*  encContentOut;
 2786        byte*  contentData;
 2787        word32 idx = 0, outIdx = 0;
 2788        word32 padSz = 0;
 2789
 2790        if (cipherType != WC_CIPHER_NONE) {
 2791            padSz = (word32)wc_PKCS7_GetPadSize(pkcs7->contentSz,
 2792                   (word32)wc_PKCS7_GetOIDBlockSize(pkcs7->encryptOID));
 2793        }
 2794
 2795        if (cipherType == WC_CIPHER_NONE && esd && esd->contentDigestSet != 1) {
 2796            /* calculate hash for content */
 2797            ret = wc_HashInit(&esd->hash, esd->hashType);
 2798            if (ret != 0) {
 2799                return ret;
 2800            }
 2801        }
 2802
 2803        encContentOut = (byte *)XMALLOC(BER_OCTET_LENGTH + MAX_OCTET_STR_SZ,
 2804                heap, DYNAMIC_TYPE_PKCS7);
 2805        contentData = (byte *)XMALLOC(BER_OCTET_LENGTH + padSz,
 2806                heap, DYNAMIC_TYPE_PKCS7);
 2807
 2808        if (encContentOut == NULL || contentData == NULL) {
 2809            XFREE(encContentOut, heap, DYNAMIC_TYPE_PKCS7);
 2810            XFREE(contentData, heap, DYNAMIC_TYPE_PKCS7);
 2811            WOLFSSL_MSG("Memory allocation failed for content data");
 2812            return MEMORY_E;
 2813        }
 2814
 2815        /* keep pulling from content until empty */
 2816        do {
 2817            int contentDataRead = 0;
 2818
 2819        #ifdef ASN_BER_TO_DER
 2820            if (pkcs7->getContentCb) {
 2821                contentDataRead =
 2822                    pkcs7->getContentCb(pkcs7, (byte **)(wc_ptr_t)&buf,
 2823                                        pkcs7->streamCtx);
 2824
 2825                if (buf == NULL) {
 2826                    WOLFSSL_MSG("Get content callback returned null "
 2827                        "buffer pointer");
 2828                    XFREE(encContentOut, heap, DYNAMIC_TYPE_PKCS7);
 2829                    XFREE(contentData, heap, DYNAMIC_TYPE_PKCS7);
 2830                    return BAD_FUNC_ARG;
 2831                }
 2832            }
 2833            else
 2834        #endif
 2835            {
 2836                int szLeft = BER_OCTET_LENGTH;
 2837
 2838                if (in == NULL) {
 2839                    XFREE(encContentOut, heap, DYNAMIC_TYPE_PKCS7);
 2840                    XFREE(contentData, heap, DYNAMIC_TYPE_PKCS7);
 2841                    return BAD_FUNC_ARG;
 2842                }
 2843
 2844                if ((word32)szLeft + totalSz > (word32)inSz)
 2845                    szLeft = inSz - (int)totalSz;
 2846
 2847                contentDataRead = szLeft;
 2848                buf = in + totalSz;
 2849            }
 2850
 2851            if (contentDataRead <= 0) {
 2852                /* no more data returned from callback */
 2853                break;
 2854            }
 2855            totalSz += (word32)contentDataRead;
 2856
 2857            /* check and handle octet boundary */
 2858            sz = contentDataRead;
 2859            if ((int)idx + sz > BER_OCTET_LENGTH) {
 2860                int amtWritten = 0;
 2861
 2862                /* loop over current buffer until it is empty */
 2863                while (idx + (word32)sz > BER_OCTET_LENGTH) {
 2864                    sz = BER_OCTET_LENGTH;
 2865                    if (idx > 0) { /* account for previously stored data */
 2866                        sz = BER_OCTET_LENGTH - (int)idx;
 2867                    }
 2868                    contentDataRead -= sz;
 2869
 2870                    XMEMCPY(contentData + idx, buf, (word32)sz);
 2871                    ret = wc_PKCS7_EncodeContentStreamHelper(pkcs7, cipherType,
 2872                        aes, encContentOut, contentData, BER_OCTET_LENGTH, out,
 2873                        &outIdx, esd);
 2874                    if (ret != 0) {
 2875                        XFREE(encContentOut, heap, DYNAMIC_TYPE_PKCS7);
 2876                        XFREE(contentData, heap, DYNAMIC_TYPE_PKCS7);
 2877                        return ret;
 2878                    }
 2879                    idx = 0; /* cleared out previously stored data */
 2880                    amtWritten += sz;
 2881                    sz  = contentDataRead;
 2882                }
 2883
 2884                /* copy over any remaining data */
 2885                XMEMCPY(contentData, buf + amtWritten, (word32)contentDataRead);
 2886                idx = (word32)contentDataRead;
 2887            }
 2888            else {
 2889                /* was not on an octet boundary, copy full
 2890                 * amount over */
 2891                XMEMCPY(contentData + idx, buf, (word32)sz);
 2892                idx += (word32)sz;
 2893            }
 2894        } while (totalSz < pkcs7->contentSz);
 2895
 2896        /* add in padding to the end */
 2897        if ((cipherType != WC_CIPHER_NONE) && (totalSz == pkcs7->contentSz)) {
 2898            word32 i;
 2899
 2900            if (BER_OCTET_LENGTH < idx) {
 2901                XFREE(encContentOut, heap, DYNAMIC_TYPE_PKCS7);
 2902                XFREE(contentData, heap, DYNAMIC_TYPE_PKCS7);
 2903                return BAD_FUNC_ARG;
 2904            }
 2905
 2906            for (i = 0; i < padSz; i++) {
 2907                contentData[idx + i] = (byte)padSz;
 2908            }
 2909            idx += (word32)padSz;
 2910        }
 2911
 2912        /* encrypt and flush out remainder of content data */
 2913        ret = wc_PKCS7_EncodeContentStreamHelper(pkcs7, cipherType, aes,
 2914                    encContentOut, contentData, (int)idx, out, &outIdx, esd);
 2915        if (ret == 0) {
 2916            if (cipherType == WC_CIPHER_NONE && esd &&
 2917                    esd->contentDigestSet != 1) {
 2918                ret = wc_HashFinal(&esd->hash, esd->hashType,
 2919                    esd->contentDigest + 2);
 2920                wc_HashFree(&esd->hash, esd->hashType);
 2921            }
 2922        }
 2923
 2924        XFREE(encContentOut, heap, DYNAMIC_TYPE_PKCS7);
 2925        XFREE(contentData, heap, DYNAMIC_TYPE_PKCS7);
 2926    }
 2927    else {
 2928        if (in == NULL || out == NULL) {
 2929            return BAD_FUNC_ARG;
 2930        }
 2931
 2932        switch (cipherType) {
 2933            case WC_CIPHER_NONE:
 2934                if (!pkcs7->detached) {
 2935                    XMEMCPY(out, in, (word32)inSz);
 2936                }
 2937                if (esd && esd->contentDigestSet != 1) {
 2938                    ret = wc_HashInit(&esd->hash, esd->hashType);
 2939                    if (ret == 0)
 2940                        ret = wc_HashUpdate(&esd->hash, esd->hashType, in,
 2941                                            (word32)inSz);
 2942                    if (ret == 0)
 2943                        ret = wc_HashFinal(&esd->hash, esd->hashType,
 2944                                           esd->contentDigest + 2);
 2945                    wc_HashFree(&esd->hash, esd->hashType);
 2946                }
 2947                break;
 2948
 2949        #ifndef NO_AES
 2950            case WC_CIPHER_AES_CBC:
 2951                ret = wc_AesCbcEncrypt(aes, out, in, (word32)inSz);
 2952                break;
 2953        #endif
 2954
 2955        #ifdef WOLFSSL_AESGCM_STREAM
 2956            case WC_CIPHER_AES_GCM:
 2957                ret = wc_AesGcmEncryptUpdate(aes, out, in, (word32)inSz, NULL, 0);
 2958                break;
 2959        #endif
 2960        }
 2961    #ifdef WOLFSSL_ASYNC_CRYPT
 2962        /* async encrypt not available here, so block till done */
 2963        if (cipherType != WC_CIPHER_NONE) {
 2964            ret = wc_AsyncWait(ret, &aes->asyncDev, WC_ASYNC_FLAG_NONE);
 2965        }
 2966    #endif
 2967    }
 2968
 2969    (void)devId;
 2970    (void)heap;
 2971
 2972    return ret;
 2973}
 2974
 2975
 2976/* build PKCS#7 signedData content type */
 2977/* To get the output size then set output = 0 and *outputSz = 0 */
 2978static int PKCS7_EncodeSigned(wc_PKCS7* pkcs7,
 2979    const byte* hashBuf, word32 hashSz, byte* output, word32* outputSz,
 2980    byte* output2, word32* output2Sz)
 2981{
 2982    /* contentType OID (1.2.840.113549.1.9.3) */
 2983    static const byte contentTypeOid[] =
 2984            { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0d, 0x01,
 2985                             0x09, 0x03 };
 2986
 2987    /* messageDigest OID (1.2.840.113549.1.9.4) */
 2988    static const byte messageDigestOid[] =
 2989            { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
 2990                             0x09, 0x04 };
 2991
 2992    /* signingTime OID () */
 2993    static const byte signingTimeOid[] =
 2994            { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
 2995                             0x09, 0x05};
 2996
 2997    Pkcs7Cert* certPtr = NULL;
 2998    word32 certSetSz = 0;
 2999
 3000    word32 signerInfoSz = 0;
 3001    word32 totalSz, total2Sz;
 3002    int idx = 0, ret = 0;
 3003    int digEncAlgoId, digEncAlgoType;
 3004    int keyIdSize;
 3005    byte* flatSignedAttribs = NULL;
 3006    word32 flatSignedAttribsSz = 0;
 3007
 3008    WC_DECLARE_VAR(esd, ESD, 1, 0);
 3009#ifdef ASN_BER_TO_DER
 3010    word32 streamSz = 0;
 3011#endif
 3012    WC_DECLARE_VAR(signedDataOid, byte, MAX_OID_SZ, 0);
 3013    word32 signedDataOidSz;
 3014
 3015    byte signingTime[MAX_TIME_STRING_SZ];
 3016
 3017    if (pkcs7 == NULL || pkcs7->hashOID == 0 ||
 3018        outputSz == NULL) {
 3019        WOLFSSL_MSG("PKCS7 struct / outputSz null, or hashOID is 0");
 3020        return BAD_FUNC_ARG;
 3021    }
 3022
 3023    if (hashSz == 0 && hashBuf != NULL) {
 3024        return BAD_FUNC_ARG;
 3025    }
 3026
 3027    /* signature size varies with ECDSA; RSA-PSS signs digest directly like
 3028     * ECDSA. For both, content hash must be known to build ASN.1 before signing */
 3029#if defined(HAVE_ECC) || defined(WC_RSA_PSS)
 3030    if (hashBuf == NULL &&
 3031        (pkcs7->publicKeyOID == ECDSAk
 3032#ifdef WC_RSA_PSS
 3033         || pkcs7->publicKeyOID == RSAPSSk
 3034#endif
 3035        )) {
 3036        WOLFSSL_MSG("Pre-calculated content hash is needed in this case");
 3037        return BAD_FUNC_ARG;
 3038    }
 3039#endif
 3040
 3041#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
 3042    keyIdSize = wc_HashGetDigestSize(wc_HashTypeConvert(HashIdAlg(
 3043           pkcs7->publicKeyOID)));
 3044#else
 3045    keyIdSize = KEYID_SIZE;
 3046#endif
 3047
 3048    /* use custom SKID if set */
 3049    if (pkcs7->customSKIDSz > 0) {
 3050        if (pkcs7->customSKID == NULL) {
 3051            WOLFSSL_MSG("Bad custom SKID setup, size > 0 and was NULL");
 3052            return BAD_FUNC_ARG;
 3053        }
 3054        keyIdSize = pkcs7->customSKIDSz;
 3055    }
 3056
 3057#ifdef WOLFSSL_SMALL_STACK
 3058    signedDataOid = (byte *)XMALLOC(MAX_OID_SZ, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 3059    if (signedDataOid == NULL) {
 3060        idx = MEMORY_E;
 3061        goto out;
 3062    }
 3063
 3064    esd = (ESD*)XMALLOC(sizeof(ESD), pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 3065    if (esd == NULL) {
 3066        idx = MEMORY_E;
 3067        goto out;
 3068    }
 3069#endif
 3070
 3071    XMEMSET(esd, 0, sizeof(ESD));
 3072
 3073    /* set content type based on contentOID, unless user has set custom one
 3074       with wc_PKCS7_SetContentType() */
 3075    if (pkcs7->contentTypeSz == 0) {
 3076
 3077        /* default to DATA content type if user has not set */
 3078        if (pkcs7->contentOID == 0) {
 3079            pkcs7->contentOID = DATA;
 3080        }
 3081
 3082        ret = wc_SetContentType(pkcs7->contentOID, pkcs7->contentType,
 3083                                sizeof(pkcs7->contentType));
 3084        if (ret < 0) {
 3085            idx = ret;
 3086            goto out;
 3087        }
 3088        pkcs7->contentTypeSz = (word32)ret;
 3089    }
 3090
 3091    /* set signedData outer content type */
 3092    ret = wc_SetContentType(SIGNED_DATA, signedDataOid, MAX_OID_SZ);
 3093    if (ret < 0) {
 3094        idx = ret;
 3095        goto out;
 3096    }
 3097    signedDataOidSz = (word32)ret;
 3098
 3099    if (pkcs7->sidType != DEGENERATE_SID) {
 3100        esd->hashType = wc_OidGetHash(pkcs7->hashOID);
 3101        if (hashBuf != NULL &&
 3102                wc_HashGetDigestSize(esd->hashType) != (int)hashSz) {
 3103            WOLFSSL_MSG("hashSz did not match hashOID");
 3104            idx = BUFFER_E;
 3105            goto out;
 3106        }
 3107
 3108        /* include hash if provided, otherwise create hash when processing
 3109         * content data */
 3110        esd->contentDigest[0] = ASN_OCTET_STRING;
 3111        if (hashBuf != NULL) {
 3112            esd->contentDigestSet = 1;
 3113            esd->contentDigest[1] = (byte)hashSz;
 3114            XMEMCPY(&esd->contentDigest[2], hashBuf, hashSz);
 3115        }
 3116        else {
 3117            esd->contentDigest[1] = (byte)wc_HashGetDigestSize(esd->hashType);
 3118        }
 3119    }
 3120
 3121    if (pkcs7->detached == 1) {
 3122        /* do not include content if generating detached signature */
 3123        esd->innerOctetsSz = 0;
 3124        esd->innerContSeqSz = 0;
 3125        esd->contentInfoSeqSz = SetSequence(pkcs7->contentTypeSz,
 3126                                            esd->contentInfoSeq);
 3127    }
 3128    else {
 3129        esd->innerOctetsSz = SetOctetStringEx(pkcs7->contentSz, esd->innerOctets,
 3130                                    pkcs7->encodeStream);
 3131        esd->innerContSeqSz = SetExplicit(0, esd->innerOctetsSz +
 3132                                    pkcs7->contentSz, esd->innerContSeq,
 3133                                    pkcs7->encodeStream);
 3134        esd->contentInfoSeqSz = SetSequenceEx(pkcs7->contentSz +
 3135                                    esd->innerOctetsSz + pkcs7->contentTypeSz +
 3136                                    esd->innerContSeqSz, esd->contentInfoSeq,
 3137                                    pkcs7->encodeStream);
 3138    }
 3139
 3140    /* SignerIdentifier */
 3141    if (pkcs7->sidType == CMS_ISSUER_AND_SERIAL_NUMBER) {
 3142        /* IssuerAndSerialNumber */
 3143        ret = SetSerialNumber(pkcs7->issuerSn, pkcs7->issuerSnSz,
 3144                                          esd->issuerSn, MAX_SN_SZ, MAX_SN_SZ);
 3145        if (ret < 0) {
 3146            idx = ret;
 3147            goto out;
 3148        }
 3149        esd->issuerSnSz = (word32)ret;
 3150        signerInfoSz += esd->issuerSnSz;
 3151        esd->issuerNameSz = SetSequence(pkcs7->issuerSz, esd->issuerName);
 3152        signerInfoSz += esd->issuerNameSz + pkcs7->issuerSz;
 3153        esd->issuerSnSeqSz = SetSequence(signerInfoSz, esd->issuerSnSeq);
 3154        signerInfoSz += esd->issuerSnSeqSz;
 3155
 3156        if (pkcs7->version == 3) {
 3157            /* RFC 4108 version MUST be 3 for firmware package signer */
 3158            esd->signerVersionSz = (word32)SetMyVersion(3, esd->signerVersion, 0);
 3159        }
 3160        else {
 3161            /* version MUST be 1 otherwise*/
 3162            esd->signerVersionSz = (word32)SetMyVersion(1, esd->signerVersion, 0);
 3163        }
 3164
 3165    } else if (pkcs7->sidType == CMS_SKID) {
 3166        /* SubjectKeyIdentifier */
 3167        esd->issuerSKIDSz = SetOctetString((word32)keyIdSize, esd->issuerSKID);
 3168        esd->issuerSKIDSeqSz = SetExplicit(0, esd->issuerSKIDSz +
 3169                                           (word32)keyIdSize,
 3170                                           esd->issuerSKIDSeq, 0);
 3171        signerInfoSz += (esd->issuerSKIDSz + esd->issuerSKIDSeqSz +
 3172                         (word32)keyIdSize);
 3173
 3174        /* version MUST be 3 */
 3175        esd->signerVersionSz = (word32)SetMyVersion(3, esd->signerVersion, 0);
 3176    } else if (pkcs7->sidType == DEGENERATE_SID) {
 3177        /* no signer info added */
 3178    } else {
 3179        idx = SKID_E;
 3180        goto out;
 3181    }
 3182
 3183    if (pkcs7->sidType != DEGENERATE_SID) {
 3184        signerInfoSz += esd->signerVersionSz;
 3185        esd->signerDigAlgoIdSz = SetAlgoIDEx(pkcs7->hashOID, esd->signerDigAlgoId,
 3186                                          oidHashType, 0, pkcs7->hashParamsAbsent);
 3187        signerInfoSz += esd->signerDigAlgoIdSz;
 3188
 3189        /* set signatureAlgorithm */
 3190        ret = wc_PKCS7_SignedDataGetEncAlgoId(pkcs7, &digEncAlgoId,
 3191                                              &digEncAlgoType);
 3192        if (ret < 0) {
 3193            idx = ret;
 3194            goto out;
 3195        }
 3196#if !defined(NO_RSA) && defined(WC_RSA_PSS)
 3197        if (digEncAlgoId == CTC_RSASSAPSS) {
 3198            /* Salt length policy: always encode as hash digest length.
 3199             * This is the common CMS/RFC 4055 profile and matches OpenSSL
 3200             * defaults.  The decoder (pssSaltLen) handles arbitrary values
 3201             * from external blobs.  A future pkcs7->pssSaltLen override for
 3202             * encode could be added here if custom salt lengths are needed. */
 3203            int saltLen = wc_HashGetDigestSize(wc_OidGetHash(pkcs7->hashOID));
 3204            if (saltLen < 0) {
 3205                idx = saltLen;
 3206                goto out;
 3207            }
 3208            esd->digEncAlgoIdSz = wc_EncodeRsaPssAlgoId(pkcs7->hashOID,
 3209                                (int)(word32)saltLen, esd->digEncAlgoId,
 3210                                (word32)sizeof(esd->digEncAlgoId));
 3211            if (esd->digEncAlgoIdSz == 0) {
 3212                idx = ASN_PARSE_E;
 3213                goto out;
 3214            }
 3215        } else
 3216#endif
 3217        {
 3218            esd->digEncAlgoIdSz = SetAlgoIDEx(digEncAlgoId, esd->digEncAlgoId,
 3219                                            digEncAlgoType, 0, pkcs7->hashParamsAbsent);
 3220        }
 3221        signerInfoSz += esd->digEncAlgoIdSz;
 3222
 3223        /* build up signed attributes, include contentType, signingTime, and
 3224           messageDigest by default */
 3225        ret = wc_PKCS7_BuildSignedAttributes(pkcs7, esd, pkcs7->contentType,
 3226                                     pkcs7->contentTypeSz,
 3227                                     contentTypeOid, sizeof(contentTypeOid),
 3228                                     messageDigestOid, sizeof(messageDigestOid),
 3229                                     signingTimeOid, sizeof(signingTimeOid),
 3230                                     signingTime, sizeof(signingTime));
 3231        if (ret < 0) {
 3232            idx = ret;
 3233            goto out;
 3234        }
 3235
 3236        if (esd->signedAttribsSz > 0) {
 3237            flatSignedAttribs = (byte*)XMALLOC(esd->signedAttribsSz, pkcs7->heap,
 3238                                                             DYNAMIC_TYPE_PKCS7);
 3239            if (flatSignedAttribs == NULL) {
 3240                idx = MEMORY_E;
 3241                goto out;
 3242            }
 3243
 3244            flatSignedAttribsSz = esd->signedAttribsSz;
 3245
 3246            FlattenAttributes(pkcs7, flatSignedAttribs, esd->signedAttribs,
 3247                                                  (int)esd->signedAttribsCount);
 3248            esd->signedAttribSetSz = SetImplicit(ASN_SET, 0, esd->signedAttribsSz,
 3249                                                              esd->signedAttribSet, 0);
 3250        } else {
 3251            esd->signedAttribSetSz = 0;
 3252        }
 3253
 3254        if (pkcs7->publicKeyOID != ECDSAk && hashBuf == NULL) {
 3255            ret = wc_PKCS7_GetSignSize(pkcs7);
 3256            esd->encContentDigestSz = (word32)ret;
 3257        }
 3258        else {
 3259            ret = wc_PKCS7_SignedDataBuildSignature(pkcs7, flatSignedAttribs,
 3260                                            flatSignedAttribsSz, esd);
 3261        }
 3262        if (ret < 0) {
 3263            idx = ret;
 3264            goto out;
 3265        }
 3266
 3267        signerInfoSz += flatSignedAttribsSz + esd->signedAttribSetSz;
 3268
 3269        esd->signerDigestSz = SetOctetString(esd->encContentDigestSz,
 3270                                                                 esd->signerDigest);
 3271        signerInfoSz += esd->signerDigestSz + esd->encContentDigestSz;
 3272
 3273        esd->signerInfoSeqSz = SetSequence(signerInfoSz, esd->signerInfoSeq);
 3274        signerInfoSz += esd->signerInfoSeqSz;
 3275    }
 3276    esd->signerInfoSetSz = SetSet(signerInfoSz, esd->signerInfoSet);
 3277    signerInfoSz += esd->signerInfoSetSz;
 3278
 3279    /* certificates [0] IMPLICIT CertificateSet */
 3280    /* get total certificates size */
 3281    if (pkcs7->noCerts != 1) {
 3282        certPtr = pkcs7->certList;
 3283        while (certPtr != NULL) {
 3284            certSetSz += certPtr->derSz;
 3285            certPtr = certPtr->next;
 3286        }
 3287    }
 3288    certPtr = NULL;
 3289
 3290    if (certSetSz > 0)
 3291        esd->certsSetSz = SetImplicit(ASN_SET, 0, certSetSz, esd->certsSet, 0);
 3292
 3293    if (pkcs7->sidType != DEGENERATE_SID) {
 3294        esd->singleDigAlgoIdSz = SetAlgoIDEx(pkcs7->hashOID, esd->singleDigAlgoId,
 3295                                      oidHashType, 0, pkcs7->hashParamsAbsent);
 3296    }
 3297    esd->digAlgoIdSetSz = SetSet(esd->singleDigAlgoIdSz, esd->digAlgoIdSet);
 3298
 3299    if (pkcs7->version == 3) {
 3300        /* RFC 4108 version MUST be 3 for firmware package signer */
 3301        esd->versionSz = (word32)SetMyVersion(3, esd->version, 0);
 3302    }
 3303    else {
 3304        esd->versionSz = (word32)SetMyVersion(1, esd->version, 0);
 3305    }
 3306
 3307    totalSz = esd->versionSz + esd->singleDigAlgoIdSz + esd->digAlgoIdSetSz +
 3308              esd->contentInfoSeqSz + pkcs7->contentTypeSz +
 3309              esd->innerContSeqSz + esd->innerOctetsSz;
 3310
 3311#ifdef ASN_BER_TO_DER
 3312    if (pkcs7->encodeStream) {
 3313        word32 tmpIdx = 0;
 3314        totalSz += (3 * ASN_INDEF_END_SZ) ; /* 00's for BER with inner content */
 3315
 3316        StreamOctetString(pkcs7->content, pkcs7->contentSz, NULL, &streamSz,
 3317            &tmpIdx);
 3318        totalSz += streamSz + (3 * ASN_INDEF_END_SZ);
 3319    }
 3320    else
 3321#endif
 3322    {
 3323        totalSz += pkcs7->contentSz;
 3324    }
 3325    total2Sz = esd->certsSetSz + certSetSz + signerInfoSz;
 3326
 3327    if (pkcs7->detached) {
 3328        totalSz -= pkcs7->contentSz;
 3329    }
 3330
 3331    esd->innerSeqSz = SetSequenceEx(totalSz + total2Sz, esd->innerSeq,
 3332        pkcs7->encodeStream);
 3333    totalSz += esd->innerSeqSz;
 3334    if (pkcs7->encodeStream) {
 3335        totalSz += ASN_INDEF_END_SZ;
 3336    }
 3337
 3338    esd->outerContentSz = SetExplicit(0, totalSz + total2Sz,
 3339        esd->outerContent, pkcs7->encodeStream);
 3340    totalSz += esd->outerContentSz + signedDataOidSz;
 3341    if (pkcs7->encodeStream) {
 3342        totalSz += ASN_INDEF_END_SZ;
 3343    }
 3344
 3345    esd->outerSeqSz = SetSequenceEx(totalSz + total2Sz, esd->outerSeq,
 3346        pkcs7->encodeStream);
 3347    totalSz += esd->outerSeqSz;
 3348    if (pkcs7->encodeStream) {
 3349        totalSz += ASN_INDEF_END_SZ;
 3350    }
 3351
 3352    /* if using header/footer, we are not returning the content */
 3353    if (output2 && output2Sz) {
 3354        if (total2Sz > *output2Sz) {
 3355            if (*outputSz == 0 && *output2Sz == 0) {
 3356                *outputSz = totalSz;
 3357                *output2Sz = total2Sz;
 3358                idx = 0;
 3359                goto out;
 3360            }
 3361            idx = BUFFER_E;
 3362            goto out;
 3363        }
 3364
 3365        if (!pkcs7->detached) {
 3366            totalSz -= pkcs7->contentSz;
 3367        }
 3368    }
 3369    else {
 3370        /* if using single output buffer include content and footer */
 3371        totalSz += total2Sz;
 3372    }
 3373
 3374    if (totalSz > *outputSz
 3375    #ifdef ASN_BER_TO_DER
 3376        && pkcs7->streamOutCb == NULL
 3377    #endif
 3378    ) {
 3379        if (*outputSz == 0) {
 3380        #ifdef HAVE_ECC
 3381            if (pkcs7->publicKeyOID == ECDSAk) {
 3382                totalSz += ECC_MAX_PAD_SZ; /* signatures size can vary */
 3383            }
 3384        #endif
 3385            *outputSz = totalSz;
 3386            idx = (int)totalSz;
 3387            goto out;
 3388        }
 3389        idx = BUFFER_E;
 3390        goto out;
 3391    }
 3392
 3393#ifdef ASN_BER_TO_DER
 3394    if (output == NULL && pkcs7->streamOutCb == NULL) {
 3395#else
 3396    if (output == NULL) {
 3397#endif
 3398        idx = BUFFER_E;
 3399        goto out;
 3400    }
 3401
 3402    idx = 0;
 3403    wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL,
 3404            esd->outerSeq, esd->outerSeqSz);
 3405    idx += (int)esd->outerSeqSz;
 3406    wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL,
 3407            signedDataOid, signedDataOidSz);
 3408    idx += (int)signedDataOidSz;
 3409    wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL,
 3410            esd->outerContent, esd->outerContentSz);
 3411    idx += (int)esd->outerContentSz;
 3412    wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL,
 3413            esd->innerSeq, esd->innerSeqSz);
 3414    idx += (int)esd->innerSeqSz;
 3415    wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL,
 3416            esd->version, esd->versionSz);
 3417    idx += (int)esd->versionSz;
 3418    wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL,
 3419            esd->digAlgoIdSet, esd->digAlgoIdSetSz);
 3420    idx += (int)esd->digAlgoIdSetSz;
 3421    wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL,
 3422            esd->singleDigAlgoId, esd->singleDigAlgoIdSz);
 3423    idx += (int)esd->singleDigAlgoIdSz;
 3424    wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL,
 3425            esd->contentInfoSeq, esd->contentInfoSeqSz);
 3426    idx += (int)esd->contentInfoSeqSz;
 3427    wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL,
 3428            pkcs7->contentType, pkcs7->contentTypeSz);
 3429    idx += (int)pkcs7->contentTypeSz;
 3430    wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL,
 3431            esd->innerContSeq, esd->innerContSeqSz);
 3432    idx += (int)esd->innerContSeqSz;
 3433    wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL,
 3434            esd->innerOctets, esd->innerOctetsSz);
 3435    idx += (int)esd->innerOctetsSz;
 3436
 3437    /* support returning header and footer without content */
 3438    if (output2 && output2Sz) {
 3439        *outputSz = (word32)idx;
 3440        idx = 0;
 3441    }
 3442    else {
 3443        if (
 3444        #ifdef ASN_BER_TO_DER
 3445            (pkcs7->content != NULL || pkcs7->getContentCb != NULL)
 3446        #else
 3447            pkcs7->content != NULL
 3448        #endif
 3449             && pkcs7->contentSz > 0) {
 3450            wc_PKCS7_EncodeContentStream(pkcs7, esd, NULL, pkcs7->content,
 3451                (int)pkcs7->contentSz, (output)? output + idx : NULL,
 3452                WC_CIPHER_NONE);
 3453            if (!pkcs7->detached) {
 3454            #ifdef ASN_BER_TO_DER
 3455                if (pkcs7->encodeStream) {
 3456                    byte indefEnd[ASN_INDEF_END_SZ * 3];
 3457                    word32 localIdx = 0;
 3458
 3459                    idx += (int)streamSz;
 3460
 3461                    /* end of content octet string */
 3462                    localIdx += SetIndefEnd(indefEnd + localIdx);
 3463
 3464                    /* end of inner content seq */
 3465                    localIdx += SetIndefEnd(indefEnd + localIdx);
 3466
 3467                    /* end of inner content info seq */
 3468                    localIdx += SetIndefEnd(indefEnd + localIdx);
 3469
 3470                    wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL,
 3471                        indefEnd, localIdx);
 3472                    idx += (int)localIdx;
 3473                }
 3474                else
 3475            #endif
 3476                {
 3477                        idx += (int)pkcs7->contentSz;
 3478                }
 3479            }
 3480        }
 3481        output2 = output;
 3482    }
 3483
 3484    /* certificates */
 3485    wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL,
 3486        esd->certsSet, esd->certsSetSz);
 3487    idx += (int)esd->certsSetSz;
 3488
 3489    if (pkcs7->noCerts != 1) {
 3490        certPtr = pkcs7->certList;
 3491        while (certPtr != NULL) {
 3492            wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL,
 3493                certPtr->der, certPtr->derSz);
 3494            idx += (int)certPtr->derSz;
 3495            certPtr = certPtr->next;
 3496        }
 3497    }
 3498
 3499    wc_PKCS7_FreeCertSet(pkcs7);
 3500
 3501    wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL,
 3502                esd->signerInfoSet, esd->signerInfoSetSz);
 3503    idx += (int)esd->signerInfoSetSz;
 3504    wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL,
 3505                esd->signerInfoSeq, esd->signerInfoSeqSz);
 3506    idx += (int)esd->signerInfoSeqSz;
 3507    wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL,
 3508                esd->signerVersion, esd->signerVersionSz);
 3509    idx += (int)esd->signerVersionSz;
 3510    /* SignerIdentifier */
 3511    if (pkcs7->sidType == CMS_ISSUER_AND_SERIAL_NUMBER) {
 3512        /* IssuerAndSerialNumber */
 3513        wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL,
 3514                esd->issuerSnSeq, esd->issuerSnSeqSz);
 3515        idx += (int)esd->issuerSnSeqSz;
 3516        wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL,
 3517                esd->issuerName, esd->issuerNameSz);
 3518        idx += (int)esd->issuerNameSz;
 3519        wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL,
 3520                pkcs7->issuer, pkcs7->issuerSz);
 3521        idx += (int)pkcs7->issuerSz;
 3522        wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL,
 3523                esd->issuerSn, esd->issuerSnSz);
 3524        idx += (int)esd->issuerSnSz;
 3525    } else if (pkcs7->sidType == CMS_SKID) {
 3526        /* SubjectKeyIdentifier */
 3527        wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL,
 3528                esd->issuerSKIDSeq, esd->issuerSKIDSeqSz);
 3529        idx += (int)esd->issuerSKIDSeqSz;
 3530        wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL,
 3531                esd->issuerSKID, esd->issuerSKIDSz);
 3532        idx += (int)esd->issuerSKIDSz;
 3533
 3534        if (pkcs7->customSKID) {
 3535            wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL,
 3536                pkcs7->customSKID, (word32)keyIdSize);
 3537        }
 3538        else {
 3539            wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL,
 3540                pkcs7->issuerSubjKeyId, (word32)keyIdSize);
 3541        }
 3542        idx += keyIdSize;
 3543    } else if (pkcs7->sidType == DEGENERATE_SID) {
 3544        /* no signer infos in degenerate case */
 3545    } else {
 3546        idx = SKID_E;
 3547        goto out;
 3548    }
 3549    wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL,
 3550                esd->signerDigAlgoId, esd->signerDigAlgoIdSz);
 3551    idx += (int)esd->signerDigAlgoIdSz;
 3552
 3553    /* SignerInfo:Attributes */
 3554    if (flatSignedAttribsSz > 0) {
 3555        /* if the original hash buffer passed in was null then recreate the
 3556        * signature */
 3557        if (hashBuf == NULL && pkcs7->sidType != DEGENERATE_SID) {
 3558            /* recreate flat attribs after the content hash is known if needed
 3559             * build up signed attributes, include contentType, signingTime, and
 3560               messageDigest by default */
 3561            esd->signedAttribsCount = 0;
 3562            esd->signedAttribsSz = 0;
 3563            ret = wc_PKCS7_BuildSignedAttributes(pkcs7, esd, pkcs7->contentType,
 3564                                     pkcs7->contentTypeSz,
 3565                                     contentTypeOid, sizeof(contentTypeOid),
 3566                                     messageDigestOid, sizeof(messageDigestOid),
 3567                                     signingTimeOid, sizeof(signingTimeOid),
 3568                                     signingTime, sizeof(signingTime));
 3569            if (ret < 0) {
 3570                idx = ret;
 3571                goto out;
 3572            }
 3573
 3574            if (esd->signedAttribsSz > 0) {
 3575                if (flatSignedAttribs == NULL) {
 3576                    idx = MEMORY_E;
 3577                    goto out;
 3578                }
 3579
 3580                flatSignedAttribsSz = esd->signedAttribsSz;
 3581                FlattenAttributes(pkcs7, flatSignedAttribs,
 3582                                  esd->signedAttribs,
 3583                                  (int)esd->signedAttribsCount);
 3584            } else {
 3585                esd->signedAttribSetSz = 0;
 3586            }
 3587        }
 3588
 3589        wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL,
 3590                esd->signedAttribSet, esd->signedAttribSetSz);
 3591        idx += (int)esd->signedAttribSetSz;
 3592        wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL,
 3593                flatSignedAttribs, flatSignedAttribsSz);
 3594        idx += (int)flatSignedAttribsSz;
 3595    }
 3596
 3597    if (hashBuf == NULL && pkcs7->sidType != DEGENERATE_SID) {
 3598        /* Calculate the final hash and encrypt it. */
 3599        WOLFSSL_MSG("Recreating signature with new hash");
 3600        ret = wc_PKCS7_SignedDataBuildSignature(pkcs7, flatSignedAttribs,
 3601                                                flatSignedAttribsSz, esd);
 3602        if (ret < 0) {
 3603            idx = ret;
 3604            goto out;
 3605        }
 3606    }
 3607
 3608    wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL,
 3609                esd->digEncAlgoId, esd->digEncAlgoIdSz);
 3610    idx += (int)esd->digEncAlgoIdSz;
 3611    wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL,
 3612                esd->signerDigest, esd->signerDigestSz);
 3613    idx += (int)esd->signerDigestSz;
 3614
 3615    wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL,
 3616                esd->encContentDigest, esd->encContentDigestSz);
 3617    idx += (int)esd->encContentDigestSz;
 3618
 3619#ifdef ASN_BER_TO_DER
 3620    if (pkcs7->encodeStream) {
 3621        byte indefEnd[ASN_INDEF_END_SZ * 3];
 3622        word32 localIdx = 0;
 3623
 3624        /* end of signedData seq */
 3625        localIdx += SetIndefEnd(indefEnd + localIdx);
 3626
 3627        /* end of outer content set */
 3628        localIdx += SetIndefEnd(indefEnd + localIdx);
 3629
 3630        /* end of outer content info seq */
 3631        localIdx += SetIndefEnd(indefEnd + localIdx);
 3632
 3633        wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL,
 3634                    indefEnd, localIdx);
 3635        idx += (int)localIdx;
 3636    }
 3637#endif
 3638
 3639    if (output2Sz) {
 3640        *output2Sz = (word32)idx;
 3641        idx = 0; /* success */
 3642    }
 3643    else {
 3644        *outputSz = (word32)idx;
 3645    }
 3646
 3647  out:
 3648
 3649    XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 3650
 3651    WC_FREE_VAR_EX(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 3652    WC_FREE_VAR_EX(signedDataOid, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 3653
 3654    return idx;
 3655}
 3656
 3657/* hashBuf: The computed digest for the pkcs7->content
 3658 * hashSz: The size of computed digest for the pkcs7->content based on hashOID
 3659 * outputHead: The PKCS7 header that goes on top of the raw data signed.
 3660 * outputFoot: The PKCS7 footer that goes at the end of the raw data signed.
 3661 * pkcs7->content: Not used
 3662 * pkcs7->contentSz: Must be provided as actual sign of raw data
 3663 * return codes: 0=success, negative=error
 3664 */
 3665int wc_PKCS7_EncodeSignedData_ex(wc_PKCS7* pkcs7, const byte* hashBuf,
 3666    word32 hashSz, byte* outputHead, word32* outputHeadSz, byte* outputFoot,
 3667    word32* outputFootSz)
 3668{
 3669    int ret;
 3670
 3671    /* other args checked in wc_PKCS7_EncodeSigned_ex */
 3672    if (pkcs7 == NULL) {
 3673        return BAD_FUNC_ARG;
 3674    }
 3675
 3676#ifndef ASN_BER_TO_DER
 3677    if (outputFoot == NULL || outputFootSz == NULL)
 3678#else
 3679    if (pkcs7->getContentCb == NULL &&
 3680        (outputFoot == NULL || outputFootSz == NULL))
 3681#endif
 3682    {
 3683        return BAD_FUNC_ARG;
 3684    }
 3685
 3686    ret = PKCS7_EncodeSigned(pkcs7, hashBuf, hashSz,
 3687        outputHead, outputHeadSz, outputFoot, outputFootSz);
 3688
 3689    return ret;
 3690}
 3691
 3692
 3693/* Sets a custom SKID in PKCS7 struct, used before calling an encode operation
 3694 * Returns 0 on success, negative upon error. */
 3695int wc_PKCS7_SetCustomSKID(wc_PKCS7* pkcs7, const byte* in, word16 inSz)
 3696{
 3697    int ret = 0;
 3698
 3699    if (pkcs7 == NULL || (in == NULL && inSz > 0)) {
 3700        return BAD_FUNC_ARG;
 3701    }
 3702
 3703    if (in == NULL) {
 3704        if (pkcs7->customSKID != NULL) {
 3705            XFREE(pkcs7->customSKID, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 3706        }
 3707        pkcs7->customSKIDSz = 0;
 3708        pkcs7->customSKID   = NULL;
 3709    }
 3710    else {
 3711        pkcs7->customSKID = (byte*)XMALLOC(inSz, pkcs7->heap,
 3712            DYNAMIC_TYPE_PKCS7);
 3713        if (pkcs7->customSKID == NULL) {
 3714            ret = MEMORY_E;
 3715        }
 3716        else {
 3717            XMEMCPY(pkcs7->customSKID, in, inSz);
 3718            pkcs7->customSKIDSz = inSz;
 3719        }
 3720    }
 3721
 3722    return ret;
 3723}
 3724
 3725
 3726/* Toggle detached signature mode on/off for PKCS#7/CMS SignedData content type.
 3727 * By default wolfCrypt includes the data to be signed in the SignedData
 3728 * bundle. This data can be omitted in the case when a detached signature is
 3729 * being created. To enable generation of detached signatures, set flag to "1",
 3730 * otherwise set to "0":
 3731 *
 3732 *     flag 1 turns on support
 3733 *     flag 0 turns off support
 3734 *
 3735 * pkcs7 - pointer to initialized PKCS7 structure
 3736 * flag  - turn on/off detached signature generation (1 or 0)
 3737 *
 3738 * Returns 0 on success, negative upon error. */
 3739int wc_PKCS7_SetDetached(wc_PKCS7* pkcs7, word16 flag)
 3740{
 3741    if (pkcs7 == NULL || (flag != 0 && flag != 1))
 3742        return BAD_FUNC_ARG;
 3743
 3744    pkcs7->detached = (flag != 0);
 3745
 3746    return 0;
 3747}
 3748
 3749/* By default, SignedData bundles have the following signed attributes attached:
 3750 *     contentType (1.2.840.113549.1.9.3)
 3751 *     signingTime (1.2.840.113549.1.9.5)
 3752 *     messageDigest (1.2.840.113549.1.9.4)
 3753 *
 3754 * Calling this API before wc_PKCS7_EncodeSignedData() will disable the
 3755 * inclusion of those attributes.
 3756 *
 3757 * pkcs7 - pointer to initialized PKCS7 structure
 3758 *
 3759 * Returns 0 on success, negative upon error. */
 3760int wc_PKCS7_NoDefaultSignedAttribs(wc_PKCS7* pkcs7)
 3761{
 3762    return wc_PKCS7_SetDefaultSignedAttribs(pkcs7, WOLFSSL_NO_ATTRIBUTES);
 3763}
 3764
 3765
 3766/* By default, SignedData bundles have the following signed attributes attached:
 3767 *     contentType (1.2.840.113549.1.9.3)
 3768 *     signingTime (1.2.840.113549.1.9.5)
 3769 *     messageDigest (1.2.840.113549.1.9.4)
 3770 *
 3771 * Calling this API before wc_PKCS7_EncodeSignedData() allows control over which
 3772 * default attributes are added.
 3773 *
 3774 * pkcs7 - pointer to initialized PKCS7 structure
 3775 *
 3776 * Returns 0 on success, negative upon error. */
 3777int  wc_PKCS7_SetDefaultSignedAttribs(wc_PKCS7* pkcs7, word16 flag)
 3778{
 3779    if (pkcs7 == NULL) {
 3780        return BAD_FUNC_ARG;
 3781    }
 3782
 3783    if (flag & WOLFSSL_NO_ATTRIBUTES) {
 3784        if (flag ^ WOLFSSL_NO_ATTRIBUTES) {
 3785            WOLFSSL_MSG("Error, can not have additional flags with no "
 3786                "attributes flag set");
 3787            return BAD_FUNC_ARG;
 3788        }
 3789        pkcs7->defaultSignedAttribs = 0;
 3790    }
 3791
 3792    /* check for unknown flags */
 3793    if (flag & ~(WOLFSSL_CONTENT_TYPE_ATTRIBUTE |
 3794                WOLFSSL_SIGNING_TIME_ATTRIBUTE |
 3795                WOLFSSL_MESSAGE_DIGEST_ATTRIBUTE | WOLFSSL_NO_ATTRIBUTES)) {
 3796        WOLFSSL_MSG("Unknown attribute flags found");
 3797        return BAD_FUNC_ARG;
 3798    }
 3799
 3800    pkcs7->defaultSignedAttribs |= flag;
 3801    return 0;
 3802}
 3803
 3804
 3805/* return codes: >0: Size of signed PKCS7 output buffer, negative: error */
 3806int wc_PKCS7_EncodeSignedData(wc_PKCS7* pkcs7, byte* output, word32 outputSz)
 3807{
 3808    int ret;
 3809
 3810    /* other args checked in wc_PKCS7_EncodeSigned_ex */
 3811    if (pkcs7 == NULL || (pkcs7->contentSz > 0 &&
 3812    #ifdef ASN_BER_TO_DER
 3813        (pkcs7->content == NULL && pkcs7->getContentCb == NULL))
 3814    #else
 3815        pkcs7->content == NULL)
 3816    #endif
 3817    ) {
 3818        return BAD_FUNC_ARG;
 3819    }
 3820
 3821    /* pre-calculate content hash for ECDSA and RSA-PSS (both sign digest directly) */
 3822    if (pkcs7->publicKeyOID == ECDSAk
 3823#ifdef WC_RSA_PSS
 3824        || pkcs7->publicKeyOID == RSAPSSk
 3825#endif
 3826        ) {
 3827        int hashSz;
 3828        enum wc_HashType hashType;
 3829        byte hashBuf[WC_MAX_DIGEST_SIZE];
 3830        WC_DECLARE_VAR(hash, wc_HashAlg, 1, pkcs7->heap);
 3831
 3832        WC_ALLOC_VAR_EX(hash, wc_HashAlg, 1, pkcs7->heap, DYNAMIC_TYPE_HASHES,
 3833                        return MEMORY_E);
 3834
 3835        /* get hash type and size, validate hashOID */
 3836        hashType = wc_OidGetHash(pkcs7->hashOID);
 3837        hashSz = wc_HashGetDigestSize(hashType);
 3838        if (hashSz < 0) {
 3839            WC_FREE_VAR_EX(hash, pkcs7->heap, DYNAMIC_TYPE_HASHES);
 3840            return hashSz;
 3841        }
 3842
 3843        /* calculate hash for content */
 3844        ret = wc_HashInit(hash, hashType);
 3845        if (ret == 0) {
 3846            ret = wc_HashUpdate(hash, hashType,
 3847                            pkcs7->content, pkcs7->contentSz);
 3848            if (ret == 0) {
 3849                ret = wc_HashFinal(hash, hashType, hashBuf);
 3850            }
 3851            wc_HashFree(hash, hashType);
 3852        }
 3853        WC_FREE_VAR_EX(hash, pkcs7->heap, DYNAMIC_TYPE_HASHES);
 3854        if (ret == 0) {
 3855            ret = PKCS7_EncodeSigned(pkcs7, hashBuf, (word32)hashSz,
 3856                output, &outputSz, NULL, NULL);
 3857        }
 3858    }
 3859    else {
 3860        ret = PKCS7_EncodeSigned(pkcs7, NULL, 0, output, &outputSz,
 3861            NULL, NULL);
 3862    }
 3863    return ret;
 3864}
 3865
 3866
 3867/* Single-shot API to generate a CMS SignedData bundle that encapsulates a
 3868 * content of type FirmwarePkgData. Any recipient certificates should be
 3869 * loaded into the PKCS7 structure prior to calling this function, using
 3870 * wc_PKCS7_InitWithCert() and/or wc_PKCS7_AddCertificate().
 3871 *
 3872 * pkcs7                - pointer to initialized PKCS7 struct
 3873 * privateKey           - private RSA/ECC key, used for signing SignedData
 3874 * privateKeySz         - size of privateKey, octets
 3875 * signOID              - public key algorithm OID, used for sign operation
 3876 * hashOID              - hash algorithm OID, used for signature generation
 3877 * content              - content to be encapsulated, of type FirmwarePkgData
 3878 * contentSz            - size of content, octets
 3879 * signedAttribs        - optional signed attributes
 3880 * signedAttribsSz      - number of PKCS7Attrib members in signedAttribs
 3881 * output               - output buffer for final bundle
 3882 * outputSz             - size of output buffer, octets
 3883 *
 3884 * Returns length of generated bundle on success, negative upon error. */
 3885int wc_PKCS7_EncodeSignedFPD(wc_PKCS7* pkcs7, byte* privateKey,
 3886                             word32 privateKeySz, int signOID, int hashOID,
 3887                             byte* content, word32 contentSz,
 3888                             PKCS7Attrib* signedAttribs, word32 signedAttribsSz,
 3889                             byte* output, word32 outputSz)
 3890{
 3891    int ret = 0;
 3892    WC_RNG rng;
 3893
 3894    if (pkcs7 == NULL || privateKey == NULL || privateKeySz == 0 ||
 3895        content == NULL || contentSz == 0 || output == NULL || outputSz == 0)
 3896        return BAD_FUNC_ARG;
 3897
 3898    ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId);
 3899    if (ret != 0)
 3900        return ret;
 3901
 3902    pkcs7->rng = &rng;
 3903    pkcs7->content = content;
 3904    pkcs7->contentSz = contentSz;
 3905    pkcs7->contentOID = FIRMWARE_PKG_DATA;
 3906    pkcs7->hashOID = hashOID;
 3907    pkcs7->encryptOID = signOID;
 3908    pkcs7->privateKey = privateKey;
 3909    pkcs7->privateKeySz = privateKeySz;
 3910    pkcs7->signedAttribs = signedAttribs;
 3911    pkcs7->signedAttribsSz = signedAttribsSz;
 3912    pkcs7->version = 3;
 3913
 3914    ret = wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz);
 3915    if (ret <= 0) {
 3916        WOLFSSL_MSG("Error encoding CMS SignedData content type");
 3917    }
 3918
 3919    pkcs7->rng = NULL;
 3920    wc_FreeRng(&rng);
 3921
 3922    return ret;
 3923}
 3924
 3925#ifndef NO_PKCS7_ENCRYPTED_DATA
 3926
 3927/* Single-shot API to generate a CMS SignedData bundle that encapsulates a
 3928 * CMS EncryptedData bundle. Content of inner EncryptedData is set to that
 3929 * of FirmwarePkgData. Any recipient certificates should be loaded into the
 3930 * PKCS7 structure prior to calling this function, using wc_PKCS7_InitWithCert()
 3931 * and/or wc_PKCS7_AddCertificate().
 3932 *
 3933 * pkcs7                - pointer to initialized PKCS7 struct
 3934 * encryptKey           - encryption key used for encrypting EncryptedData
 3935 * encryptKeySz         - size of encryptKey, octets
 3936 * privateKey           - private RSA/ECC key, used for signing SignedData
 3937 * privateKeySz         - size of privateKey, octets
 3938 * encryptOID           - encryption algorithm OID, to be used as encryption
 3939 *                        algorithm for EncryptedData
 3940 * signOID              - public key algorithm OID, to be used for sign
 3941 *                        operation in SignedData generation
 3942 * hashOID              - hash algorithm OID, to be used for signature in
 3943 *                        SignedData generation
 3944 * content              - content to be encapsulated
 3945 * contentSz            - size of content, octets
 3946 * unprotectedAttribs   - optional unprotected attributes, for EncryptedData
 3947 * unprotectedAttribsSz - number of PKCS7Attrib members in unprotectedAttribs
 3948 * signedAttribs        - optional signed attributes, for SignedData
 3949 * signedAttribsSz      - number of PKCS7Attrib members in signedAttribs
 3950 * output               - output buffer for final bundle
 3951 * outputSz             - size of output buffer, octets
 3952 *
 3953 * Returns length of generated bundle on success, negative upon error. */
 3954int wc_PKCS7_EncodeSignedEncryptedFPD(wc_PKCS7* pkcs7, byte* encryptKey,
 3955                                      word32 encryptKeySz, byte* privateKey,
 3956                                      word32 privateKeySz, int encryptOID,
 3957                                      int signOID, int hashOID,
 3958                                      byte* content, word32 contentSz,
 3959                                      PKCS7Attrib* unprotectedAttribs,
 3960                                      word32 unprotectedAttribsSz,
 3961                                      PKCS7Attrib* signedAttribs,
 3962                                      word32 signedAttribsSz,
 3963                                      byte* output, word32 outputSz)
 3964{
 3965    int ret = 0, encryptedSz = 0;
 3966    byte* encrypted = NULL;
 3967    WC_RNG rng;
 3968
 3969    if (pkcs7 == NULL || encryptKey == NULL || encryptKeySz == 0 ||
 3970        privateKey == NULL || privateKeySz == 0 || content == NULL ||
 3971        contentSz == 0 || output == NULL || outputSz == 0) {
 3972        return BAD_FUNC_ARG;
 3973    }
 3974
 3975    /* 1: build up EncryptedData using FirmwarePkgData type, use output
 3976     *    buffer as tmp for storage and to get size */
 3977
 3978    /* set struct elements, inner content type is FirmwarePkgData */
 3979    pkcs7->content = content;
 3980    pkcs7->contentSz = contentSz;
 3981    pkcs7->contentOID = FIRMWARE_PKG_DATA;
 3982    pkcs7->encryptOID = encryptOID;
 3983    pkcs7->encryptionKey = encryptKey;
 3984    pkcs7->encryptionKeySz = encryptKeySz;
 3985    pkcs7->unprotectedAttribs = unprotectedAttribs;
 3986    pkcs7->unprotectedAttribsSz = unprotectedAttribsSz;
 3987    pkcs7->version = 3;
 3988
 3989    encryptedSz = wc_PKCS7_EncodeEncryptedData(pkcs7, output, outputSz);
 3990    if (encryptedSz < 0) {
 3991        WOLFSSL_MSG("Error encoding CMS EncryptedData content type");
 3992        return encryptedSz;
 3993    }
 3994
 3995    /* save encryptedData, reset output buffer and struct */
 3996    encrypted = (byte*)XMALLOC((word32)encryptedSz, pkcs7->heap,
 3997                               DYNAMIC_TYPE_PKCS7);
 3998    if (encrypted == NULL) {
 3999        ForceZero(output, outputSz);
 4000        return MEMORY_E;
 4001    }
 4002
 4003    XMEMCPY(encrypted, output, (word32)encryptedSz);
 4004    ForceZero(output, outputSz);
 4005
 4006    ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId);
 4007    if (ret != 0) {
 4008        ForceZero(encrypted, (word32)encryptedSz);
 4009        XFREE(encrypted, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 4010        return ret;
 4011    }
 4012
 4013    /* 2: build up SignedData, encapsulating EncryptedData */
 4014    pkcs7->rng = &rng;
 4015    pkcs7->content = encrypted;
 4016    pkcs7->contentSz = (word32)encryptedSz;
 4017    pkcs7->contentOID = ENCRYPTED_DATA;
 4018    pkcs7->hashOID = hashOID;
 4019    pkcs7->encryptOID = signOID;
 4020    pkcs7->privateKey = privateKey;
 4021    pkcs7->privateKeySz = privateKeySz;
 4022    pkcs7->signedAttribs = signedAttribs;
 4023    pkcs7->signedAttribsSz = signedAttribsSz;
 4024
 4025    ret = wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz);
 4026    if (ret <= 0) {
 4027        WOLFSSL_MSG("Error encoding CMS SignedData content type");
 4028    }
 4029
 4030    ForceZero(encrypted, (word32)encryptedSz);
 4031    XFREE(encrypted, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 4032    pkcs7->rng = NULL;
 4033    wc_FreeRng(&rng);
 4034
 4035    return ret;
 4036}
 4037
 4038#endif /* NO_PKCS7_ENCRYPTED_DATA */
 4039
 4040#if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA)
 4041/* Single-shot API to generate a CMS SignedData bundle that encapsulates a
 4042 * CMS CompressedData bundle. Content of inner CompressedData is set to that
 4043 * of FirmwarePkgData. Any recipient certificates should be loaded into the
 4044 * PKCS7 structure prior to calling this function, using wc_PKCS7_InitWithCert()
 4045 * and/or wc_PKCS7_AddCertificate().
 4046 *
 4047 * pkcs7                - pointer to initialized PKCS7 struct
 4048 * privateKey           - private RSA/ECC key, used for signing SignedData
 4049 * privateKeySz         - size of privateKey, octets
 4050 * signOID              - public key algorithm OID, to be used for sign
 4051 *                        operation in SignedData generation
 4052 * hashOID              - hash algorithm OID, to be used for signature in
 4053 *                        SignedData generation
 4054 * content              - content to be encapsulated
 4055 * contentSz            - size of content, octets
 4056 * signedAttribs        - optional signed attributes, for SignedData
 4057 * signedAttribsSz      - number of PKCS7Attrib members in signedAttribs
 4058 * output               - output buffer for final bundle
 4059 * outputSz             - size of output buffer, octets
 4060 *
 4061 * Returns length of generated bundle on success, negative upon error. */
 4062int wc_PKCS7_EncodeSignedCompressedFPD(wc_PKCS7* pkcs7, byte* privateKey,
 4063                                       word32 privateKeySz, int signOID,
 4064                                       int hashOID, byte* content,
 4065                                       word32 contentSz,
 4066                                       PKCS7Attrib* signedAttribs,
 4067                                       word32 signedAttribsSz, byte* output,
 4068                                       word32 outputSz)
 4069{
 4070    int ret = 0, compressedSz = 0;
 4071    byte* compressed = NULL;
 4072    WC_RNG rng;
 4073
 4074    if (pkcs7 == NULL || privateKey == NULL || privateKeySz == 0 ||
 4075        content == NULL || contentSz == 0 || output == NULL || outputSz == 0) {
 4076        return BAD_FUNC_ARG;
 4077    }
 4078
 4079    /* 1: build up CompressedData using FirmwarePkgData type, use output
 4080     *    buffer as tmp for storage and to get size */
 4081
 4082    /* set struct elements, inner content type is FirmwarePkgData */
 4083    pkcs7->content = content;
 4084    pkcs7->contentSz = contentSz;
 4085    pkcs7->contentOID = FIRMWARE_PKG_DATA;
 4086    pkcs7->version = 3;
 4087
 4088    compressedSz = wc_PKCS7_EncodeCompressedData(pkcs7, output, outputSz);
 4089    if (compressedSz < 0) {
 4090        WOLFSSL_MSG("Error encoding CMS CompressedData content type");
 4091        return compressedSz;
 4092    }
 4093
 4094    /* save compressedData, reset output buffer and struct */
 4095    compressed = (byte*)XMALLOC(compressedSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 4096    if (compressed == NULL) {
 4097        ForceZero(output, outputSz);
 4098        return MEMORY_E;
 4099    }
 4100
 4101    XMEMCPY(compressed, output, compressedSz);
 4102    ForceZero(output, outputSz);
 4103
 4104    ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId);
 4105    if (ret != 0) {
 4106        ForceZero(compressed, compressedSz);
 4107        XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 4108        return ret;
 4109    }
 4110
 4111    /* 2: build up SignedData, encapsulating EncryptedData */
 4112    pkcs7->rng = &rng;
 4113    pkcs7->content = compressed;
 4114    pkcs7->contentSz = compressedSz;
 4115    pkcs7->contentOID = COMPRESSED_DATA;
 4116    pkcs7->hashOID = hashOID;
 4117    pkcs7->encryptOID = signOID;
 4118    pkcs7->privateKey = privateKey;
 4119    pkcs7->privateKeySz = privateKeySz;
 4120    pkcs7->signedAttribs = signedAttribs;
 4121    pkcs7->signedAttribsSz = signedAttribsSz;
 4122
 4123    ret = wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz);
 4124    if (ret <= 0) {
 4125        WOLFSSL_MSG("Error encoding CMS SignedData content type");
 4126    }
 4127
 4128    ForceZero(compressed, compressedSz);
 4129    XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 4130    pkcs7->rng = NULL;
 4131    wc_FreeRng(&rng);
 4132
 4133    return ret;
 4134}
 4135
 4136#ifndef NO_PKCS7_ENCRYPTED_DATA
 4137
 4138/* Single-shot API to generate a CMS SignedData bundle that encapsulates a
 4139 * CMS EncryptedData bundle, which then encapsulates a CMS CompressedData
 4140 * bundle. Content of inner CompressedData is set to that of FirmwarePkgData.
 4141 * Any recipient certificates should be loaded into the PKCS7 structure prior
 4142 * to calling this function, using wc_PKCS7_InitWithCert() and/or
 4143 * wc_PKCS7_AddCertificate().
 4144 *
 4145 * pkcs7                - pointer to initialized PKCS7 struct
 4146 * encryptKey           - encryption key used for encrypting EncryptedData
 4147 * encryptKeySz         - size of encryptKey, octets
 4148 * privateKey           - private RSA/ECC key, used for signing SignedData
 4149 * privateKeySz         - size of privateKey, octets
 4150 * encryptOID           - encryption algorithm OID, to be used as encryption
 4151 *                        algorithm for EncryptedData
 4152 * signOID              - public key algorithm OID, to be used for sign
 4153 *                        operation in SignedData generation
 4154 * hashOID              - hash algorithm OID, to be used for signature in
 4155 *                        SignedData generation
 4156 * content              - content to be encapsulated
 4157 * contentSz            - size of content, octets
 4158 * unprotectedAttribs   - optional unprotected attributes, for EncryptedData
 4159 * unprotectedAttribsSz - number of PKCS7Attrib members in unprotectedAttribs
 4160 * signedAttribs        - optional signed attributes, for SignedData
 4161 * signedAttribsSz      - number of PKCS7Attrib members in signedAttribs
 4162 * output               - output buffer for final bundle
 4163 * outputSz             - size of output buffer, octets
 4164 *
 4165 * Returns length of generated bundle on success, negative upon error. */
 4166int  wc_PKCS7_EncodeSignedEncryptedCompressedFPD(wc_PKCS7* pkcs7, byte* encryptKey,
 4167                                       word32 encryptKeySz, byte* privateKey,
 4168                                       word32 privateKeySz, int encryptOID,
 4169                                       int signOID, int hashOID, byte* content,
 4170                                       word32 contentSz,
 4171                                       PKCS7Attrib* unprotectedAttribs,
 4172                                       word32 unprotectedAttribsSz,
 4173                                       PKCS7Attrib* signedAttribs,
 4174                                       word32 signedAttribsSz,
 4175                                       byte* output, word32 outputSz)
 4176{
 4177    int ret = 0, compressedSz = 0, encryptedSz = 0;
 4178    byte* compressed = NULL;
 4179    byte* encrypted = NULL;
 4180    WC_RNG rng;
 4181
 4182    if (pkcs7 == NULL || encryptKey == NULL || encryptKeySz == 0 ||
 4183        privateKey == NULL || privateKeySz == 0 || content == NULL ||
 4184        contentSz == 0 || output == NULL || outputSz == 0) {
 4185        return BAD_FUNC_ARG;
 4186    }
 4187
 4188    /* 1: build up CompressedData using FirmwarePkgData type, use output
 4189     *    buffer as tmp for storage and to get size */
 4190    pkcs7->content = content;
 4191    pkcs7->contentSz = contentSz;
 4192    pkcs7->contentOID = FIRMWARE_PKG_DATA;
 4193    pkcs7->version = 3;
 4194
 4195    compressedSz = wc_PKCS7_EncodeCompressedData(pkcs7, output, outputSz);
 4196    if (compressedSz < 0) {
 4197        WOLFSSL_MSG("Error encoding CMS CompressedData content type");
 4198        return compressedSz;
 4199    }
 4200
 4201    /* save compressedData, reset output buffer and struct */
 4202    compressed = (byte*)XMALLOC(compressedSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 4203    if (compressed == NULL)
 4204        return MEMORY_E;
 4205
 4206    XMEMCPY(compressed, output, compressedSz);
 4207    ForceZero(output, outputSz);
 4208
 4209    /* 2: build up EncryptedData using CompressedData, use output
 4210     *    buffer as tmp for storage and to get size */
 4211    pkcs7->content = compressed;
 4212    pkcs7->contentSz = compressedSz;
 4213    pkcs7->contentOID = COMPRESSED_DATA;
 4214    pkcs7->encryptOID = encryptOID;
 4215    pkcs7->encryptionKey = encryptKey;
 4216    pkcs7->encryptionKeySz = encryptKeySz;
 4217    pkcs7->unprotectedAttribs = unprotectedAttribs;
 4218    pkcs7->unprotectedAttribsSz = unprotectedAttribsSz;
 4219
 4220    encryptedSz = wc_PKCS7_EncodeEncryptedData(pkcs7, output, outputSz);
 4221    if (encryptedSz < 0) {
 4222        WOLFSSL_MSG("Error encoding CMS EncryptedData content type");
 4223        XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 4224        return encryptedSz;
 4225    }
 4226
 4227    /* save encryptedData, reset output buffer and struct */
 4228    encrypted = (byte*)XMALLOC(encryptedSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 4229    if (encrypted == NULL) {
 4230        ForceZero(compressed, compressedSz);
 4231        XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 4232        return MEMORY_E;
 4233    }
 4234
 4235    XMEMCPY(encrypted, output, encryptedSz);
 4236    ForceZero(compressed, compressedSz);
 4237    XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 4238    ForceZero(output, outputSz);
 4239
 4240    ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId);
 4241    if (ret != 0) {
 4242        ForceZero(encrypted, encryptedSz);
 4243        XFREE(encrypted, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 4244        return ret;
 4245    }
 4246
 4247    /* 3: build up SignedData, encapsulating EncryptedData */
 4248    pkcs7->rng = &rng;
 4249    pkcs7->content = encrypted;
 4250    pkcs7->contentSz = encryptedSz;
 4251    pkcs7->contentOID = ENCRYPTED_DATA;
 4252    pkcs7->hashOID = hashOID;
 4253    pkcs7->encryptOID = signOID;
 4254    pkcs7->privateKey = privateKey;
 4255    pkcs7->privateKeySz = privateKeySz;
 4256    pkcs7->signedAttribs = signedAttribs;
 4257    pkcs7->signedAttribsSz = signedAttribsSz;
 4258
 4259    ret = wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz);
 4260    if (ret <= 0) {
 4261        WOLFSSL_MSG("Error encoding CMS SignedData content type");
 4262    }
 4263
 4264    ForceZero(encrypted, encryptedSz);
 4265    XFREE(encrypted, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 4266    pkcs7->rng = NULL;
 4267    wc_FreeRng(&rng);
 4268
 4269    return ret;
 4270}
 4271
 4272#endif /* !NO_PKCS7_ENCRYPTED_DATA */
 4273#endif /* HAVE_LIBZ && !NO_PKCS7_COMPRESSED_DATA */
 4274
 4275
 4276#ifndef NO_RSA
 4277
 4278#ifdef HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK
 4279/* register raw RSA sign digest callback */
 4280int wc_PKCS7_SetRsaSignRawDigestCb(wc_PKCS7* pkcs7, CallbackRsaSignRawDigest cb)
 4281{
 4282    if (pkcs7 == NULL || cb == NULL) {
 4283        return BAD_FUNC_ARG;
 4284    }
 4285
 4286    pkcs7->rsaSignRawDigestCb = cb;
 4287
 4288    return 0;
 4289}
 4290#endif
 4291
 4292#endif /* NO_RSA */
 4293
 4294
 4295#ifdef HAVE_ECC
 4296
 4297#ifdef HAVE_PKCS7_ECC_RAW_SIGN_CALLBACK
 4298/* register raw ECC sign digest callback */
 4299int wc_PKCS7_SetEccSignRawDigestCb(wc_PKCS7* pkcs7, CallbackEccSignRawDigest cb)
 4300{
 4301    if (pkcs7 == NULL || cb == NULL) {
 4302        return BAD_FUNC_ARG;
 4303    }
 4304
 4305    pkcs7->eccSignRawDigestCb = cb;
 4306
 4307    return 0;
 4308}
 4309#endif
 4310
 4311#endif /* HAVE_ECC */
 4312
 4313
 4314#if !defined(NO_RSA) || defined(HAVE_ECC)
 4315/* Check whether the given decoded certificate matches the SignerIdentifier
 4316 * (sid) field of the currently parsed SignerInfo. Per RFC 5652 Section 5.3,
 4317 * the sid selects which certificate's public key must be used to verify the
 4318 * signature. Returns 1 on match, 0 on no match or when the sid is not
 4319 * available for comparison. */
 4320static int wc_PKCS7_CertMatchesSignerInfo(wc_PKCS7* pkcs7, DecodedCert* dCert)
 4321{
 4322    PKCS7SignerInfo* signerInfo;
 4323
 4324    if (pkcs7 == NULL || dCert == NULL)
 4325        return 0;
 4326
 4327    signerInfo = pkcs7->signerInfo;
 4328    if (signerInfo == NULL || signerInfo->sid == NULL ||
 4329            signerInfo->sidSz == 0) {
 4330        /* No SID parsed, cannot perform an identity binding check. */
 4331        return 0;
 4332    }
 4333
 4334    if (signerInfo->sidType == CMS_ISSUER_AND_SERIAL_NUMBER) {
 4335        /* IssuerAndSerialNumber: SID blob stores the content of the outer
 4336         * SEQUENCE (issuer Name followed by INTEGER serialNumber). */
 4337        word32 idx = 0;
 4338        byte sidIssuerHash[KEYID_SIZE];
 4339        WC_DECLARE_VAR(sidSerial, mp_int, 1, pkcs7->heap);
 4340        WC_DECLARE_VAR(certSerial, mp_int, 1, pkcs7->heap);
 4341        int cmp;
 4342        int match = 0;
 4343
 4344        if (GetNameHash_ex(signerInfo->sid, &idx, sidIssuerHash,
 4345                (int)signerInfo->sidSz, dCert->signatureOID) < 0) {
 4346            return 0;
 4347        }
 4348        if (XMEMCMP(sidIssuerHash, dCert->issuerHash, KEYID_SIZE) != 0)
 4349            return 0;
 4350
 4351        WC_ALLOC_VAR_EX(sidSerial, mp_int, 1, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER,
 4352            { return 0; });
 4353        WC_ALLOC_VAR_EX(certSerial, mp_int, 1, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER,
 4354            { WC_FREE_VAR_EX(sidSerial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 4355              return 0; });
 4356
 4357        if (mp_init(sidSerial) != MP_OKAY) {
 4358            WC_FREE_VAR_EX(sidSerial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 4359            WC_FREE_VAR_EX(certSerial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 4360            return 0;
 4361        }
 4362        if (mp_init(certSerial) != MP_OKAY) {
 4363            mp_clear(sidSerial);
 4364            WC_FREE_VAR_EX(sidSerial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 4365            WC_FREE_VAR_EX(certSerial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 4366            return 0;
 4367        }
 4368
 4369        if (GetInt(sidSerial, signerInfo->sid, &idx, signerInfo->sidSz) == 0 &&
 4370                mp_read_unsigned_bin(certSerial, dCert->serial,
 4371                                     (word32)dCert->serialSz) == MP_OKAY) {
 4372            cmp = mp_cmp(sidSerial, certSerial);
 4373            if (cmp == MP_EQ)
 4374                match = 1;
 4375        }
 4376
 4377        mp_clear(sidSerial);
 4378        mp_clear(certSerial);
 4379        WC_FREE_VAR_EX(sidSerial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 4380        WC_FREE_VAR_EX(certSerial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 4381        return match;
 4382    }
 4383    else if (signerInfo->sidType == CMS_SKID) {
 4384        /* SubjectKeyIdentifier: SID blob is the raw SKID octet string
 4385         * content. Normalize the same way the certificate side does so
 4386         * that comparisons between SHA-1 SKIDs and other lengths match. */
 4387        byte sidKid[KEYID_SIZE];
 4388
 4389        if (GetHashId(signerInfo->sid, (int)signerInfo->sidSz, sidKid,
 4390                      HashIdAlg(dCert->signatureOID)) != 0) {
 4391            return 0;
 4392        }
 4393        if (XMEMCMP(sidKid, dCert->extSubjKeyId, KEYID_SIZE) == 0)
 4394            return 1;
 4395        return 0;
 4396    }
 4397
 4398    return 0;
 4399}
 4400#endif /* !NO_RSA || HAVE_ECC */
 4401
 4402#ifndef NO_RSA
 4403
 4404/* returns size of signature put into out, negative on error */
 4405static int wc_PKCS7_RsaVerify(wc_PKCS7* pkcs7, byte* sig, int sigSz,
 4406                              byte* hash, word32 hashSz)
 4407{
 4408    int ret = 0, i;
 4409    word32 scratch = 0, verified = 0;
 4410#ifdef WOLFSSL_SMALL_STACK
 4411    byte* digest;
 4412    RsaKey* key;
 4413    DecodedCert* dCert;
 4414#else
 4415#ifdef WOLFSSL_NO_MALLOC
 4416    byte digest[RSA_MAX_SIZE / WOLFSSL_BIT_SIZE]; /* accessed in-place with size
 4417                                                   * key->dataLen
 4418                                                   */
 4419#else
 4420    byte digest[MAX_PKCS7_DIGEST_SZ];
 4421#endif
 4422    RsaKey key[1];
 4423    DecodedCert dCert[1];
 4424#endif
 4425
 4426    if (pkcs7 == NULL || sig == NULL || hash == NULL) {
 4427        return BAD_FUNC_ARG;
 4428    }
 4429
 4430#ifdef WOLFSSL_SMALL_STACK
 4431    digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, pkcs7->heap,
 4432                            DYNAMIC_TYPE_TMP_BUFFER);
 4433    if (digest == NULL)
 4434        return MEMORY_E;
 4435
 4436    key = (RsaKey*)XMALLOC(sizeof(RsaKey), pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 4437    if (key == NULL) {
 4438        XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 4439        return MEMORY_E;
 4440    }
 4441
 4442    dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), pkcs7->heap,
 4443                                  DYNAMIC_TYPE_DCERT);
 4444    if (dCert == NULL) {
 4445        XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 4446        XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 4447        return MEMORY_E;
 4448    }
 4449#endif
 4450
 4451    XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ);
 4452
 4453    /* loop over certs received in certificates set, try to find one
 4454     * that will validate signature */
 4455    for (i = 0; i < MAX_PKCS7_CERTS; i++) {
 4456
 4457        verified = 0;
 4458        scratch  = 0;
 4459
 4460        if (pkcs7->certSz[i] == 0)
 4461            continue;
 4462
 4463        ret = wc_InitRsaKey_ex(key, pkcs7->heap, pkcs7->devId);
 4464        if (ret != 0) {
 4465            WC_FREE_VAR_EX(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 4466            WC_FREE_VAR_EX(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 4467            WC_FREE_VAR_EX(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT);
 4468            return ret;
 4469        }
 4470
 4471        InitDecodedCert(dCert, pkcs7->cert[i], pkcs7->certSz[i], pkcs7->heap);
 4472        /* not verifying, only using this to extract public key */
 4473        ret = ParseCert(dCert, CA_TYPE, NO_VERIFY, 0);
 4474        if (ret < 0) {
 4475            WOLFSSL_MSG("ASN RSA cert parse error");
 4476            FreeDecodedCert(dCert);
 4477            wc_FreeRsaKey(key);
 4478            continue;
 4479        }
 4480
 4481        /* If the SignerInfo sid was parsed, only try the certificate whose
 4482         * identity matches it. This binds the verifying public key to the
 4483         * signer identity advertised in the CMS message and prevents signer
 4484         * confusion when multiple certificates are embedded. */
 4485        if (pkcs7->signerInfo != NULL && pkcs7->signerInfo->sid != NULL &&
 4486                !wc_PKCS7_CertMatchesSignerInfo(pkcs7, dCert)) {
 4487            FreeDecodedCert(dCert);
 4488            wc_FreeRsaKey(key);
 4489            continue;
 4490        }
 4491
 4492        /* Defense in depth: the sid-matched cert must actually carry an
 4493         * RSA-family key before we feed its SPKI to the RSA key decoder.
 4494         * Rejecting here avoids depending on wc_RsaPublicKeyDecode to reject
 4495         * wrong-type SPKIs. */
 4496        if (dCert->keyOID != RSAk
 4497        #ifdef WC_RSA_PSS
 4498                && dCert->keyOID != RSAPSSk
 4499        #endif
 4500                ) {
 4501            FreeDecodedCert(dCert);
 4502            wc_FreeRsaKey(key);
 4503            continue;
 4504        }
 4505
 4506        if (wc_RsaPublicKeyDecode(dCert->publicKey, &scratch, key,
 4507                                  dCert->pubKeySize) < 0) {
 4508            WOLFSSL_MSG("ASN RSA key decode error");
 4509            FreeDecodedCert(dCert);
 4510            wc_FreeRsaKey(key);
 4511            continue;
 4512        }
 4513
 4514    #ifdef WOLFSSL_ASYNC_CRYPT
 4515        do {
 4516            ret = wc_AsyncWait(ret, &key->asyncDev,
 4517                WC_ASYNC_FLAG_CALL_AGAIN);
 4518    #endif
 4519            if (ret >= 0) {
 4520                ret = wc_RsaSSL_Verify(sig, (word32)sigSz, digest, MAX_PKCS7_DIGEST_SZ,
 4521                    key);
 4522            }
 4523    #ifdef WOLFSSL_ASYNC_CRYPT
 4524        } while (ret == WC_NO_ERR_TRACE(WC_PENDING_E));
 4525    #endif
 4526        FreeDecodedCert(dCert);
 4527        wc_FreeRsaKey(key);
 4528
 4529        if ((ret > 0) && (hashSz == (word32)ret)) {
 4530            if (XMEMCMP(digest, hash, hashSz) == 0) {
 4531                /* found signer that successfully verified signature */
 4532                verified = 1;
 4533                pkcs7->verifyCert   = pkcs7->cert[i];
 4534                pkcs7->verifyCertSz = pkcs7->certSz[i];
 4535                break;
 4536            }
 4537        }
 4538    }
 4539
 4540    if (verified == 0) {
 4541        ret = SIG_VERIFY_E;
 4542    }
 4543
 4544    WC_FREE_VAR_EX(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 4545    WC_FREE_VAR_EX(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 4546    WC_FREE_VAR_EX(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT);
 4547
 4548    return ret;
 4549}
 4550
 4551#if defined(WC_RSA_PSS)
 4552/* returns 0 when signature verifies, negative on error */
 4553static int wc_PKCS7_RsaPssVerify(wc_PKCS7* pkcs7, byte* sig, int sigSz,
 4554                                  byte* hash, word32 hashSz)
 4555{
 4556    int ret = 0, i;
 4557    word32 scratch = 0, verified = 0;
 4558    word32 pkSz;
 4559    int saltLen, verify;
 4560    enum wc_HashType hashType;
 4561    int hashDigSz, mgf;
 4562    /* wc_RsaPSS_Verify_ex output is PSS-encoded message (RSA_PSS_PAD_SZ +
 4563     * saltLen + 2*hLen bytes), which can exceed MAX_PKCS7_DIGEST_SZ.
 4564     * Use MAX_ENCRYPTED_KEY_SZ (512) to cover RSA keys up to 4096-bit. */
 4565    WC_DECLARE_VAR(digest, byte, MAX_ENCRYPTED_KEY_SZ, 0);
 4566    WC_DECLARE_VAR(key, RsaKey, 1, 0);
 4567    WC_DECLARE_VAR(dCert, DecodedCert, 1, 0);
 4568
 4569    if (pkcs7 == NULL || sig == NULL || hash == NULL)
 4570        return BAD_FUNC_ARG;
 4571
 4572    /* Use SignerInfo.signatureAlgorithm params when decoded; else digestAlgo */
 4573    if (pkcs7->pssParamsPresent)
 4574        hashType = (enum wc_HashType)pkcs7->pssHashType;
 4575    else
 4576        hashType = wc_OidGetHash(pkcs7->hashOID);
 4577    hashDigSz = wc_HashGetDigestSize(hashType);
 4578    if (hashDigSz < 0)
 4579        return ASN_PARSE_E;
 4580    if (hashSz != (word32)hashDigSz)
 4581        return ASN_PARSE_E;
 4582    mgf = pkcs7->pssParamsPresent
 4583        ? pkcs7->pssMgf : pkcs7_hash2mgf(hashType);
 4584    if (mgf == WC_MGF1NONE)
 4585        return ASN_PARSE_E;
 4586
 4587    WC_ALLOC_VAR_EX(digest, byte, MAX_ENCRYPTED_KEY_SZ, pkcs7->heap,
 4588        DYNAMIC_TYPE_TMP_BUFFER, return MEMORY_E);
 4589    WC_ALLOC_VAR_EX(key, RsaKey, 1, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER,
 4590        { WC_FREE_VAR_EX(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 4591          return MEMORY_E; });
 4592    WC_ALLOC_VAR_EX(dCert, DecodedCert, 1, pkcs7->heap, DYNAMIC_TYPE_DCERT,
 4593        { WC_FREE_VAR_EX(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 4594          WC_FREE_VAR_EX(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 4595          return MEMORY_E; });
 4596
 4597    XMEMSET(digest, 0, MAX_ENCRYPTED_KEY_SZ);
 4598
 4599    for (i = 0; i < MAX_PKCS7_CERTS; i++) {
 4600        if (pkcs7->certSz[i] == 0)
 4601            continue;
 4602
 4603        scratch = 0;
 4604        ret = wc_InitRsaKey_ex(key, pkcs7->heap, pkcs7->devId);
 4605        if (ret != 0)
 4606            break;
 4607
 4608        InitDecodedCert(dCert, pkcs7->cert[i], pkcs7->certSz[i], pkcs7->heap);
 4609        ret = ParseCert(dCert, CA_TYPE, NO_VERIFY, 0);
 4610        if (ret < 0) {
 4611            FreeDecodedCert(dCert);
 4612            wc_FreeRsaKey(key);
 4613            continue;
 4614        }
 4615
 4616        /* Only try the certificate identified by the SignerInfo sid (see
 4617         * matching comment in wc_PKCS7_RsaVerify). */
 4618        if (pkcs7->signerInfo != NULL && pkcs7->signerInfo->sid != NULL &&
 4619                !wc_PKCS7_CertMatchesSignerInfo(pkcs7, dCert)) {
 4620            FreeDecodedCert(dCert);
 4621            wc_FreeRsaKey(key);
 4622            continue;
 4623        }
 4624
 4625        /* Defense in depth: reject non-RSA SPKIs before key decode. RSA
 4626         * rsaEncryption certs (keyOID=RSAk) are accepted for PSS signatures
 4627         * per RFC 8017 - a RSASSA-PSS cert is not required. */
 4628        if (dCert->keyOID != RSAk && dCert->keyOID != RSAPSSk) {
 4629            FreeDecodedCert(dCert);
 4630            wc_FreeRsaKey(key);
 4631            continue;
 4632        }
 4633
 4634        pkSz = dCert->pubKeySize;
 4635        if (pkSz > (MAX_RSA_INT_SZ + MAX_RSA_E_SZ))
 4636            pkSz = (MAX_RSA_INT_SZ + MAX_RSA_E_SZ);
 4637
 4638        if (wc_RsaPublicKeyDecode(dCert->publicKey, &scratch, key,
 4639                                  pkSz) < 0) {
 4640            FreeDecodedCert(dCert);
 4641            wc_FreeRsaKey(key);
 4642            continue;
 4643        }
 4644
 4645        saltLen = pkcs7->pssParamsPresent
 4646                      ? pkcs7->pssSaltLen : RSA_PSS_SALT_LEN_DEFAULT;
 4647
 4648        /* wc_RsaPSS_Verify_ex returns PSS encoded message length, not
 4649         * the recovered hash. Must then call wc_RsaPSS_CheckPadding_ex
 4650         * to verify the PSS padding against the expected hash. */
 4651        verify = wc_RsaPSS_Verify_ex(sig, (word32)sigSz, digest,
 4652                                     MAX_ENCRYPTED_KEY_SZ,
 4653                                     hashType, mgf, saltLen, key);
 4654        if (verify > 0) {
 4655            /* wc_RsaPSS_CheckPadding_ex signature varies across
 4656             * FIPS / selftest versions; match the pattern in asn.c */
 4657        #if (defined(HAVE_SELFTEST) && \
 4658             (!defined(HAVE_SELFTEST_VERSION) || \
 4659              (HAVE_SELFTEST_VERSION < 2))) || \
 4660            (defined(HAVE_FIPS) && defined(HAVE_FIPS_VERSION) && \
 4661             (HAVE_FIPS_VERSION < 2))
 4662            ret = wc_RsaPSS_CheckPadding_ex(hash, hashSz, digest,
 4663                                            (word32)verify, hashType,
 4664                                            saltLen);
 4665        #elif (defined(HAVE_SELFTEST) && \
 4666               (HAVE_SELFTEST_VERSION == 2)) || \
 4667              (defined(HAVE_FIPS) && defined(HAVE_FIPS_VERSION) && \
 4668               (HAVE_FIPS_VERSION == 2))
 4669            ret = wc_RsaPSS_CheckPadding_ex(hash, hashSz, digest,
 4670                                            (word32)verify, hashType,
 4671                                            saltLen, 0);
 4672        #else
 4673            ret = wc_RsaPSS_CheckPadding_ex2(hash, hashSz, digest,
 4674                                            (word32)verify, hashType,
 4675                                            saltLen,
 4676                                            mp_count_bits(&key->n),
 4677                                            pkcs7->heap);
 4678        #endif
 4679        }
 4680        else {
 4681            ret = verify;
 4682        }
 4683
 4684        FreeDecodedCert(dCert);
 4685        wc_FreeRsaKey(key);
 4686
 4687        if (ret == 0) {
 4688            verified = 1;
 4689            pkcs7->verifyCert   = pkcs7->cert[i];
 4690            pkcs7->verifyCertSz = pkcs7->certSz[i];
 4691            break;
 4692        }
 4693        ret = 0;
 4694    }
 4695
 4696    if (verified == 0)
 4697        ret = SIG_VERIFY_E;
 4698
 4699    WC_FREE_VAR_EX(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 4700    WC_FREE_VAR_EX(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 4701    WC_FREE_VAR_EX(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT);
 4702
 4703    return ret;
 4704}
 4705#endif /* WC_RSA_PSS */
 4706
 4707#endif /* NO_RSA */
 4708
 4709
 4710#ifdef HAVE_ECC
 4711
 4712/* returns size of signature put into out, negative on error */
 4713static int wc_PKCS7_EcdsaVerify(wc_PKCS7* pkcs7, byte* sig, int sigSz,
 4714                                byte* hash, word32 hashSz)
 4715{
 4716    int ret = 0, i;
 4717    int res = 0;
 4718    int verified = 0;
 4719#ifdef WOLFSSL_SMALL_STACK
 4720    byte* digest;
 4721    ecc_key* key;
 4722    DecodedCert* dCert;
 4723#else
 4724    byte digest[MAX_PKCS7_DIGEST_SZ];
 4725    ecc_key key[1];
 4726    DecodedCert dCert[1];
 4727#endif
 4728    word32 idx = 0;
 4729
 4730    if (pkcs7 == NULL || sig == NULL)
 4731        return BAD_FUNC_ARG;
 4732
 4733    /* Check hash length */
 4734    if ((hashSz > WC_MAX_DIGEST_SIZE) ||
 4735        (hashSz < WC_MIN_DIGEST_SIZE)) {
 4736        return BAD_LENGTH_E;
 4737    }
 4738
 4739#ifdef WOLFSSL_SMALL_STACK
 4740    digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, pkcs7->heap,
 4741                            DYNAMIC_TYPE_TMP_BUFFER);
 4742    if (digest == NULL)
 4743        return MEMORY_E;
 4744
 4745    key = (ecc_key*)XMALLOC(sizeof(ecc_key), pkcs7->heap,
 4746                            DYNAMIC_TYPE_TMP_BUFFER);
 4747    if (key == NULL) {
 4748        XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 4749        return MEMORY_E;
 4750    }
 4751
 4752    dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), pkcs7->heap,
 4753                                  DYNAMIC_TYPE_DCERT);
 4754    if (dCert == NULL) {
 4755        XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 4756        XFREE(key,    pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 4757        return MEMORY_E;
 4758    }
 4759#endif
 4760
 4761    XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ);
 4762
 4763    /* loop over certs received in certificates set, try to find one
 4764     * that will validate signature */
 4765    for (i = 0; i < MAX_PKCS7_CERTS; i++) {
 4766
 4767        verified = 0;
 4768        idx = 0;
 4769
 4770        if (pkcs7->certSz[i] == 0)
 4771            continue;
 4772
 4773        ret = wc_ecc_init_ex(key, pkcs7->heap, pkcs7->devId);
 4774        if (ret != 0) {
 4775            WC_FREE_VAR_EX(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 4776            WC_FREE_VAR_EX(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 4777            WC_FREE_VAR_EX(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT);
 4778            return ret;
 4779        }
 4780
 4781        InitDecodedCert(dCert, pkcs7->cert[i], pkcs7->certSz[i], pkcs7->heap);
 4782
 4783        /* This allows the user to not error out in the case of extensions that
 4784         * we are not aware of. */
 4785#ifdef WC_ASN_UNKNOWN_EXT_CB
 4786        if (pkcs7->unknownExtCallback != NULL)
 4787            wc_SetUnknownExtCallback(dCert, pkcs7->unknownExtCallback);
 4788#endif
 4789
 4790        /* not verifying, only using this to extract public key */
 4791        ret = ParseCert(dCert, CA_TYPE, NO_VERIFY, 0);
 4792        if (ret < 0) {
 4793            WOLFSSL_MSG("ASN ECC cert parse error");
 4794            FreeDecodedCert(dCert);
 4795            wc_ecc_free(key);
 4796            continue;
 4797        }
 4798
 4799        /* Only try the certificate identified by the SignerInfo sid (see
 4800         * matching comment in wc_PKCS7_RsaVerify). */
 4801        if (pkcs7->signerInfo != NULL && pkcs7->signerInfo->sid != NULL &&
 4802                !wc_PKCS7_CertMatchesSignerInfo(pkcs7, dCert)) {
 4803            FreeDecodedCert(dCert);
 4804            wc_ecc_free(key);
 4805            continue;
 4806        }
 4807
 4808        /* Defense in depth: reject non-ECDSA SPKIs before key decode. */
 4809        if (dCert->keyOID != ECDSAk) {
 4810            FreeDecodedCert(dCert);
 4811            wc_ecc_free(key);
 4812            continue;
 4813        }
 4814
 4815        if (wc_EccPublicKeyDecode(dCert->publicKey, &idx, key,
 4816                                  dCert->pubKeySize) < 0) {
 4817            WOLFSSL_MSG("ASN ECC key decode error");
 4818            FreeDecodedCert(dCert);
 4819            wc_ecc_free(key);
 4820            continue;
 4821        }
 4822
 4823    #ifdef WOLFSSL_ASYNC_CRYPT
 4824        do {
 4825            ret = wc_AsyncWait(ret, &key->asyncDev,
 4826                WC_ASYNC_FLAG_CALL_AGAIN);
 4827    #endif
 4828            if (ret >= 0) {
 4829                ret = wc_ecc_verify_hash(sig, (word32)sigSz, hash, hashSz, &res, key);
 4830            }
 4831    #ifdef WOLFSSL_ASYNC_CRYPT
 4832        } while (ret == WC_NO_ERR_TRACE(WC_PENDING_E));
 4833    #endif
 4834
 4835        if (ret == 0 && res == 1) {
 4836            /* found signer that successfully verified signature */
 4837            verified = 1;
 4838            XMEMCPY(pkcs7->issuerSubjKeyId, dCert->extSubjKeyId, KEYID_SIZE);
 4839            pkcs7->verifyCert   = pkcs7->cert[i];
 4840            pkcs7->verifyCertSz = pkcs7->certSz[i];
 4841        }
 4842
 4843        wc_ecc_free(key);
 4844        FreeDecodedCert(dCert);
 4845
 4846        if (ret == 0 && res == 1) {
 4847            break;
 4848        }
 4849    }
 4850
 4851    if (verified == 0) {
 4852        ret = SIG_VERIFY_E;
 4853    }
 4854
 4855    WC_FREE_VAR_EX(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 4856    WC_FREE_VAR_EX(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 4857    WC_FREE_VAR_EX(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT);
 4858
 4859    return ret;
 4860}
 4861
 4862#endif /* HAVE_ECC */
 4863
 4864
 4865/* build SignedData digest, both in PKCS#7 DigestInfo format and
 4866 * as plain digest for CMS.
 4867 *
 4868 * pkcs7          - pointer to initialized PKCS7 struct
 4869 * signedAttrib   - signed attributes
 4870 * signedAttribSz - size of signedAttrib, octets
 4871 * pkcs7Digest    - [OUT] PKCS#7 DigestInfo
 4872 * pkcs7DigestSz  - [IN/OUT] size of pkcs7Digest
 4873 * plainDigest    - [OUT] pointer to plain digest, offset into pkcs7Digest
 4874 * plainDigestSz  - [OUT] size of digest at plainDigest
 4875 *
 4876 * returns 0 on success, negative on error */
 4877static int wc_PKCS7_BuildSignedDataDigest(wc_PKCS7* pkcs7, byte* signedAttrib,
 4878                                      word32 signedAttribSz, byte* pkcs7Digest,
 4879                                      word32* pkcs7DigestSz, byte** plainDigest,
 4880                                      word32* plainDigestSz,
 4881                                      const byte* hashBuf, word32 hashBufSz)
 4882{
 4883    int ret = 0, digIdx = 0;
 4884    word32 attribSetSz = 0, hashSz = 0;
 4885    byte attribSet[MAX_SET_SZ];
 4886    byte digest[WC_MAX_DIGEST_SIZE];
 4887    byte digestInfoSeq[MAX_SEQ_SZ];
 4888    byte digestStr[MAX_OCTET_STR_SZ];
 4889    byte algoId[MAX_ALGO_SZ];
 4890    word32 digestInfoSeqSz, digestStrSz, algoIdSz;
 4891    WC_DECLARE_VAR(digestInfo, byte, MAX_PKCS7_DIGEST_SZ, 0);
 4892    WC_DECLARE_VAR(hash, wc_HashAlg, 1, pkcs7 ? pkcs7->heap : NULL);
 4893    enum wc_HashType hashType;
 4894
 4895    /* check arguments */
 4896    if (pkcs7 == NULL || pkcs7Digest == NULL ||
 4897        pkcs7DigestSz == NULL || plainDigest == NULL) {
 4898        return BAD_FUNC_ARG;
 4899    }
 4900
 4901    hashType = wc_OidGetHash(pkcs7->hashOID);
 4902    ret = wc_HashGetDigestSize(hashType);
 4903    if (ret < 0)
 4904        return ret;
 4905    hashSz = (word32)ret;
 4906
 4907    if (signedAttribSz > 0) {
 4908        if (signedAttrib == NULL)
 4909            return BAD_FUNC_ARG;
 4910    }
 4911    else {
 4912        if (hashBuf && hashBufSz > 0) {
 4913            if (hashSz != hashBufSz)
 4914                return BAD_FUNC_ARG;
 4915        }
 4916        else if (pkcs7->content == NULL)
 4917            return BAD_FUNC_ARG;
 4918    }
 4919
 4920    WC_ALLOC_VAR_EX(digestInfo, byte, MAX_PKCS7_DIGEST_SZ, pkcs7->heap,
 4921        DYNAMIC_TYPE_TMP_BUFFER, return MEMORY_E);
 4922    WC_ALLOC_VAR_EX(hash, wc_HashAlg, 1, pkcs7->heap, DYNAMIC_TYPE_HASHES,
 4923        { WC_FREE_VAR_EX(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 4924          return MEMORY_E; });
 4925
 4926    XMEMSET(pkcs7Digest, 0, *pkcs7DigestSz);
 4927    XMEMSET(digest,      0, WC_MAX_DIGEST_SIZE);
 4928    XMEMSET(digestInfo,  0, MAX_PKCS7_DIGEST_SZ);
 4929
 4930
 4931    /* calculate digest */
 4932    if (hashBuf && hashBufSz > 0 && signedAttribSz == 0) {
 4933        XMEMCPY(digest, hashBuf, hashBufSz);
 4934    }
 4935    else {
 4936        ret = wc_HashInit(hash, hashType);
 4937        if (ret < 0) {
 4938            WC_FREE_VAR_EX(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 4939            WC_FREE_VAR_EX(hash, pkcs7->heap, DYNAMIC_TYPE_HASHES);
 4940            return ret;
 4941        }
 4942
 4943        if (signedAttribSz > 0) {
 4944            attribSetSz = SetSet(signedAttribSz, attribSet);
 4945
 4946            /* calculate digest */
 4947            ret = wc_HashUpdate(hash, hashType, attribSet, attribSetSz);
 4948            if (ret == 0)
 4949                ret = wc_HashUpdate(hash, hashType, signedAttrib, signedAttribSz);
 4950            if (ret == 0)
 4951                ret = wc_HashFinal(hash, hashType, digest);
 4952        } else {
 4953            ret = wc_HashUpdate(hash, hashType, pkcs7->content, pkcs7->contentSz);
 4954            if (ret == 0)
 4955                ret = wc_HashFinal(hash, hashType, digest);
 4956        }
 4957
 4958        wc_HashFree(hash, hashType);
 4959        if (ret < 0) {
 4960            WC_FREE_VAR_EX(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 4961            WC_FREE_VAR_EX(hash, pkcs7->heap, DYNAMIC_TYPE_HASHES);
 4962            return ret;
 4963        }
 4964    }
 4965
 4966    /* Set algoID, match whatever was input to match either NULL or absent */
 4967    algoIdSz = SetAlgoIDEx(pkcs7->hashOID, algoId, oidHashType,
 4968                            0, pkcs7->hashParamsAbsent);
 4969
 4970    digestStrSz = SetOctetString(hashSz, digestStr);
 4971    digestInfoSeqSz = SetSequence(algoIdSz + digestStrSz + hashSz,
 4972                                  digestInfoSeq);
 4973
 4974    XMEMCPY(digestInfo + digIdx, digestInfoSeq, digestInfoSeqSz);
 4975    digIdx += (int)digestInfoSeqSz;
 4976    XMEMCPY(digestInfo + digIdx, algoId, algoIdSz);
 4977    digIdx += (int)algoIdSz;
 4978    XMEMCPY(digestInfo + digIdx, digestStr, digestStrSz);
 4979    digIdx += (int)digestStrSz;
 4980    XMEMCPY(digestInfo + digIdx, digest, hashSz);
 4981    digIdx += (int)hashSz;
 4982
 4983    XMEMCPY(pkcs7Digest, digestInfo, (word32)digIdx);
 4984    *pkcs7DigestSz = (word32)digIdx;
 4985
 4986    /* set plain digest pointer */
 4987    *plainDigest = pkcs7Digest + digIdx - hashSz;
 4988    *plainDigestSz = hashSz;
 4989
 4990    WC_FREE_VAR_EX(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 4991    WC_FREE_VAR_EX(hash, pkcs7->heap, DYNAMIC_TYPE_HASHES);
 4992    return 0;
 4993}
 4994
 4995
 4996/* Verifies CMS/PKCS7 SignedData content digest matches that which is
 4997 * included in the messageDigest signed attribute. Only called when
 4998 * signed attributes are present, otherwise original signature verification
 4999 * is done over content.
 5000 *
 5001 * pkcs7          - pointer to initialized PKCS7 struct
 5002 * hashBuf        - pointer to user-provided hash buffer, used with
 5003 *                  wc_PKCS7_VerifySignedData_ex()
 5004 * hashBufSz      - size of hashBuf, octets
 5005 *
 5006 * return 0 on success, negative on error */
 5007static int wc_PKCS7_VerifyContentMessageDigest(wc_PKCS7* pkcs7,
 5008                                               const byte* hashBuf,
 5009                                               word32 hashSz)
 5010{
 5011    int ret = 0, digestSz = 0, innerAttribSz = 0;
 5012    int contentLen = 0;
 5013    word32 idx = 0;
 5014    word32 contentIdx = 0;
 5015    byte* content = NULL;
 5016    const byte* digestBuf = NULL;
 5017    WC_DECLARE_VAR(digest, byte, MAX_PKCS7_DIGEST_SZ, 0);
 5018    PKCS7DecodedAttrib* attrib;
 5019    enum wc_HashType hashType;
 5020
 5021    /* messageDigest OID (1.2.840.113549.1.9.4) */
 5022    const byte mdOid[] =
 5023            { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x04 };
 5024
 5025    if (pkcs7 == NULL)
 5026        return BAD_FUNC_ARG;
 5027
 5028    if ((pkcs7->content == NULL || pkcs7->contentSz == 0) &&
 5029        (hashBuf == NULL || hashSz == 0)) {
 5030        WOLFSSL_MSG("SignedData bundle has no content or hash to verify");
 5031        return BAD_FUNC_ARG;
 5032    }
 5033
 5034    /* lookup messageDigest attribute */
 5035    attrib = findAttrib(pkcs7, mdOid, sizeof(mdOid));
 5036    if (attrib == NULL) {
 5037        WOLFSSL_MSG("messageDigest attribute not in bundle, must be when "
 5038                    "signed attribs are present");
 5039        return ASN_PARSE_E;
 5040    }
 5041
 5042    /* advance past attrib->value ASN.1 header and length */
 5043    if (attrib->value == NULL || attrib->valueSz == 0)
 5044        return ASN_PARSE_E;
 5045
 5046    if (attrib->value[idx++] != ASN_OCTET_STRING)
 5047        return ASN_PARSE_E;
 5048
 5049    if (GetLength(attrib->value, &idx, &innerAttribSz, attrib->valueSz) < 0)
 5050        return ASN_PARSE_E;
 5051
 5052    /* get hash type and size */
 5053    hashType = wc_OidGetHash(pkcs7->hashOID);
 5054    if (hashType == WC_HASH_TYPE_NONE) {
 5055        WOLFSSL_MSG("Error getting hash type for PKCS7 content verification");
 5056        return BAD_FUNC_ARG;
 5057    }
 5058
 5059    /* build content hash if needed, or use existing hash value */
 5060    if (hashBuf == NULL) {
 5061
 5062        WC_ALLOC_VAR_EX(digest, byte, MAX_PKCS7_DIGEST_SZ, pkcs7->heap,
 5063            DYNAMIC_TYPE_TMP_BUFFER, return MEMORY_E);
 5064        XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ);
 5065
 5066        content = pkcs7->content;
 5067        contentLen = (int)pkcs7->contentSz;
 5068
 5069        if (pkcs7->contentIsPkcs7Type == 1) {
 5070            /* Content follows PKCS#7 RFC, which defines type as ANY. CMS
 5071             * mandates OCTET_STRING which has already been stripped off.
 5072             * For PKCS#7 message digest calculation, digest is calculated
 5073             * only on the "value" of the DER encoding. As such, advance past
 5074             * the tag and length */
 5075            if (contentLen > 1) {
 5076                contentIdx++;
 5077            }
 5078
 5079            if (GetLength_ex(content, &contentIdx, &contentLen,
 5080                    (word32)contentLen, 1) < 0) {
 5081                    WC_FREE_VAR_EX(digest, pkcs7->heap,
 5082                        DYNAMIC_TYPE_TMP_BUFFER);
 5083                return ASN_PARSE_E;
 5084            }
 5085        }
 5086
 5087        ret = wc_Hash(hashType, content + contentIdx, (word32)contentLen, digest,
 5088                      MAX_PKCS7_DIGEST_SZ);
 5089        if (ret < 0) {
 5090            WOLFSSL_MSG("Error hashing PKCS7 content for verification");
 5091            WC_FREE_VAR_EX(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 5092            return ret;
 5093        }
 5094
 5095        digestBuf = digest;
 5096        digestSz = wc_HashGetDigestSize(hashType);
 5097        if (digestSz < 0) {
 5098            WOLFSSL_MSG("Invalid hash type");
 5099            WC_FREE_VAR_EX(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 5100            return digestSz;
 5101        }
 5102    } else {
 5103
 5104        /* user passed in pre-computed hash */
 5105        digestBuf = (const byte*)hashBuf;
 5106        digestSz  = (int)hashSz;
 5107    }
 5108
 5109    /* compare generated to hash in messageDigest attribute */
 5110    if ((innerAttribSz != digestSz) ||
 5111        (XMEMCMP(attrib->value + idx, digestBuf, (size_t)digestSz) != 0)) {
 5112        WOLFSSL_MSG("Content digest does not match messageDigest attrib value");
 5113        WC_FREE_VAR_EX(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 5114        return SIG_VERIFY_E;
 5115    }
 5116
 5117    if (hashBuf == NULL) {
 5118        WC_FREE_VAR_EX(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 5119    }
 5120
 5121    return 0;
 5122}
 5123
 5124
 5125/* verifies SignedData signature, over either PKCS#7 DigestInfo or
 5126 * content digest.
 5127 *
 5128 * pkcs7          - pointer to initialized PKCS7 struct
 5129 * sig            - signature to verify
 5130 * sigSz          - size of sig
 5131 * signedAttrib   - signed attributes, or null if empty
 5132 * signedAttribSz - size of signedAttributes
 5133 *
 5134 * return 0 on success, negative on error */
 5135static int wc_PKCS7_SignedDataVerifySignature(wc_PKCS7* pkcs7, byte* sig,
 5136                                             word32 sigSz, byte* signedAttrib,
 5137                                             word32 signedAttribSz,
 5138                                             const byte* hashBuf, word32 hashSz)
 5139{
 5140    int ret = 0;
 5141    word32 plainDigestSz = 0, pkcs7DigestSz;
 5142    byte* plainDigest = NULL; /* offset into pkcs7Digest */
 5143    WC_DECLARE_VAR(pkcs7Digest, byte, MAX_PKCS7_DIGEST_SZ, 0);
 5144
 5145    if (pkcs7 == NULL)
 5146        return BAD_FUNC_ARG;
 5147
 5148    /* allocate space to build hash */
 5149    pkcs7DigestSz = MAX_PKCS7_DIGEST_SZ;
 5150    WC_ALLOC_VAR_EX(pkcs7Digest, byte, pkcs7DigestSz, pkcs7->heap,
 5151        DYNAMIC_TYPE_TMP_BUFFER, return MEMORY_E);
 5152
 5153    XMEMSET(pkcs7Digest, 0, pkcs7DigestSz);
 5154
 5155    /* verify signed attrib digest matches that of content */
 5156    if (signedAttrib != NULL) {
 5157        ret = wc_PKCS7_VerifyContentMessageDigest(pkcs7, hashBuf, hashSz);
 5158        if (ret != 0) {
 5159            WC_FREE_VAR_EX(pkcs7Digest, pkcs7->heap,
 5160                DYNAMIC_TYPE_TMP_BUFFER);
 5161            return ret;
 5162        }
 5163    }
 5164
 5165    /* build hash to verify against */
 5166    ret = wc_PKCS7_BuildSignedDataDigest(pkcs7, signedAttrib,
 5167                                         signedAttribSz, pkcs7Digest,
 5168                                         &pkcs7DigestSz, &plainDigest,
 5169                                         &plainDigestSz, hashBuf, hashSz);
 5170    if (ret < 0) {
 5171        WC_FREE_VAR_EX(pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 5172        return ret;
 5173    }
 5174
 5175    /* If no certificates are available then store the signature and hash for
 5176     * user to verify. Make sure that different return value than success is
 5177     * returned because the signature was not verified here. */
 5178    if (ret == 0) {
 5179        byte haveCert = 0;
 5180        int  i;
 5181
 5182        for (i = 0; i < MAX_PKCS7_CERTS; i++) {
 5183            if (pkcs7->certSz[i] == 0)
 5184                continue;
 5185            haveCert = 1;
 5186        }
 5187
 5188        if (!haveCert) {
 5189            WOLFSSL_MSG("No certificates in bundle to verify signature");
 5190
 5191            /* store signature */
 5192            XFREE(pkcs7->signature, pkcs7->heap, DYNAMIC_TYPE_SIGNATURE);
 5193            pkcs7->signature = NULL;
 5194            pkcs7->signatureSz = 0;
 5195            pkcs7->signature = (byte*)XMALLOC(sigSz, pkcs7->heap,
 5196                    DYNAMIC_TYPE_SIGNATURE);
 5197            if (pkcs7->signature == NULL) {
 5198                WC_FREE_VAR_EX(pkcs7Digest, pkcs7->heap,
 5199                    DYNAMIC_TYPE_TMP_BUFFER);
 5200                return MEMORY_E;
 5201            }
 5202            XMEMCPY(pkcs7->signature, sig, sigSz);
 5203            pkcs7->signatureSz = sigSz;
 5204
 5205            /* store plain digest (CMS and ECC) */
 5206            XFREE(pkcs7->plainDigest, pkcs7->heap, DYNAMIC_TYPE_DIGEST);
 5207            pkcs7->plainDigest = NULL;
 5208            pkcs7->plainDigestSz = 0;
 5209            pkcs7->plainDigest = (byte*)XMALLOC(plainDigestSz, pkcs7->heap,
 5210                    DYNAMIC_TYPE_DIGEST);
 5211            if (pkcs7->plainDigest == NULL) {
 5212                WC_FREE_VAR_EX(pkcs7Digest, pkcs7->heap,
 5213                    DYNAMIC_TYPE_TMP_BUFFER);
 5214                return MEMORY_E;
 5215            }
 5216            XMEMCPY(pkcs7->plainDigest, plainDigest, plainDigestSz);
 5217            pkcs7->plainDigestSz = plainDigestSz;
 5218
 5219            /* store pkcs7 digest (default RSA) */
 5220            XFREE(pkcs7->pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_DIGEST);
 5221            pkcs7->pkcs7Digest = NULL;
 5222            pkcs7->pkcs7DigestSz = 0;
 5223            pkcs7->pkcs7Digest = (byte*)XMALLOC(pkcs7DigestSz, pkcs7->heap,
 5224                    DYNAMIC_TYPE_DIGEST);
 5225            if (pkcs7->pkcs7Digest == NULL) {
 5226                WC_FREE_VAR_EX(pkcs7Digest, pkcs7->heap,
 5227                    DYNAMIC_TYPE_TMP_BUFFER);
 5228                return MEMORY_E;
 5229            }
 5230            XMEMCPY(pkcs7->pkcs7Digest, pkcs7Digest, pkcs7DigestSz);
 5231            pkcs7->pkcs7DigestSz = pkcs7DigestSz;
 5232
 5233            WC_FREE_VAR_EX(pkcs7Digest, pkcs7->heap,
 5234                DYNAMIC_TYPE_TMP_BUFFER);
 5235            return PKCS7_SIGNEEDS_CHECK;
 5236        }
 5237    }
 5238
 5239
 5240
 5241    switch (pkcs7->publicKeyOID) {
 5242
 5243#ifndef NO_RSA
 5244        case RSAk:
 5245            ret = wc_PKCS7_RsaVerify(pkcs7, sig, (int)sigSz, pkcs7Digest,
 5246                                     pkcs7DigestSz);
 5247            if (ret < 0) {
 5248                WOLFSSL_MSG("PKCS#7 verification failed, trying CMS");
 5249                ret = wc_PKCS7_RsaVerify(pkcs7, sig, (int)sigSz, plainDigest,
 5250                                         plainDigestSz);
 5251            }
 5252            break;
 5253
 5254    #ifdef WC_RSA_PSS
 5255        /* RSA-PSS signs the raw hash (plainDigest), not DigestInfo */
 5256        case RSAPSSk:
 5257            ret = wc_PKCS7_RsaPssVerify(pkcs7, sig, (int)sigSz, plainDigest,
 5258                                       plainDigestSz);
 5259            break;
 5260    #endif
 5261#endif
 5262
 5263#ifdef HAVE_ECC
 5264        case ECDSAk:
 5265            ret = wc_PKCS7_EcdsaVerify(pkcs7, sig, (int)sigSz, plainDigest,
 5266                                       plainDigestSz);
 5267            break;
 5268#endif
 5269
 5270        default:
 5271            WOLFSSL_MSG("Unsupported public key type");
 5272            ret = BAD_FUNC_ARG;
 5273    }
 5274
 5275     WC_FREE_VAR_EX(pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 5276    return ret;
 5277}
 5278
 5279
 5280/* set correct public key OID based on signature OID, stores in
 5281 * pkcs7->publicKeyOID and returns same value */
 5282static int wc_PKCS7_SetPublicKeyOID(wc_PKCS7* pkcs7, int sigOID)
 5283{
 5284    if (pkcs7 == NULL)
 5285        return BAD_FUNC_ARG;
 5286
 5287    pkcs7->publicKeyOID = 0;
 5288
 5289    switch (sigOID) {
 5290
 5291    #ifndef NO_RSA
 5292        /* RSA signature types */
 5293        case CTC_MD2wRSA:
 5294        case CTC_MD5wRSA:
 5295        case CTC_SHAwRSA:
 5296        case CTC_SHA224wRSA:
 5297        case CTC_SHA256wRSA:
 5298        case CTC_SHA384wRSA:
 5299        case CTC_SHA512wRSA:
 5300        case CTC_SHA3_224wRSA:
 5301        case CTC_SHA3_256wRSA:
 5302        case CTC_SHA3_384wRSA:
 5303        case CTC_SHA3_512wRSA:
 5304            pkcs7->publicKeyOID = RSAk;
 5305            break;
 5306
 5307    #ifdef WC_RSA_PSS
 5308        /* CTC_RSASSAPSS and RSAPSSk are the same OID value */
 5309        case CTC_RSASSAPSS:
 5310            pkcs7->publicKeyOID = RSAPSSk;
 5311            break;
 5312    #endif
 5313
 5314        /* if sigOID is already RSAk */
 5315        case RSAk:
 5316            pkcs7->publicKeyOID = (word32)sigOID;
 5317            break;
 5318    #endif
 5319
 5320    #ifndef NO_DSA
 5321        /* DSA signature types */
 5322        case CTC_SHAwDSA:
 5323            pkcs7->publicKeyOID = DSAk;
 5324            break;
 5325
 5326        /* if sigOID is already DSAk */
 5327        case DSAk:
 5328            pkcs7->publicKeyOID = (word32)sigOID;
 5329            break;
 5330    #endif
 5331
 5332    #ifdef HAVE_ECC
 5333        /* ECDSA signature types */
 5334        case CTC_SHAwECDSA:
 5335        case CTC_SHA224wECDSA:
 5336        case CTC_SHA256wECDSA:
 5337        case CTC_SHA384wECDSA:
 5338        case CTC_SHA512wECDSA:
 5339        case CTC_SHA3_224wECDSA:
 5340        case CTC_SHA3_256wECDSA:
 5341        case CTC_SHA3_384wECDSA:
 5342        case CTC_SHA3_512wECDSA:
 5343            pkcs7->publicKeyOID = ECDSAk;
 5344            break;
 5345
 5346        /* if sigOID is already ECDSAk */
 5347        case ECDSAk:
 5348            pkcs7->publicKeyOID = (word32)sigOID;
 5349            break;
 5350    #endif
 5351
 5352        default:
 5353            WOLFSSL_MSG("Unsupported public key algorithm");
 5354            return ASN_SIG_KEY_E;
 5355    }
 5356
 5357    return (int)pkcs7->publicKeyOID;
 5358}
 5359
 5360
 5361/* Parses through the attributes and adds them to the PKCS7 structure
 5362 * Creates dynamic attribute structures that are free'd with calling
 5363 * wc_PKCS7_Free()
 5364 *
 5365 * NOTE: An attribute has the ASN1 format of
 5366 ** Sequence
 5367 ****** Object ID
 5368 ****** Set
 5369 ********** {PrintableString, UTCTime, OCTET STRING ...}
 5370 *
 5371 * pkcs7  the PKCS7 structure to put the parsed attributes into
 5372 * in     buffer holding all attributes
 5373 * inSz   size of in buffer
 5374 *
 5375 * returns the number of attributes parsed on success
 5376 */
 5377static int wc_PKCS7_ParseAttribs(wc_PKCS7* pkcs7, byte* in, int inSz)
 5378{
 5379    int    found = 0;
 5380    word32 idx   = 0;
 5381    word32 oid;
 5382
 5383    if (pkcs7 == NULL || in == NULL || inSz < 0) {
 5384        return BAD_FUNC_ARG;
 5385    }
 5386
 5387    while (idx < (word32)inSz) {
 5388        int length  = 0;
 5389        word32 oidIdx;
 5390        PKCS7DecodedAttrib* attrib;
 5391
 5392        if (GetSequence(in, &idx, &length, (word32)inSz) < 0)
 5393            return ASN_PARSE_E;
 5394
 5395        attrib = (PKCS7DecodedAttrib*)XMALLOC(sizeof(PKCS7DecodedAttrib),
 5396                pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 5397        if (attrib == NULL) {
 5398            return MEMORY_E;
 5399        }
 5400        XMEMSET(attrib, 0, sizeof(PKCS7DecodedAttrib));
 5401
 5402        oidIdx = idx;
 5403        if (GetObjectId(in, &idx, &oid, oidIgnoreType, (word32)inSz)
 5404                < 0) {
 5405            XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 5406            return ASN_PARSE_E;
 5407        }
 5408        attrib->oidSz = idx - oidIdx;
 5409        attrib->oid = (byte*)XMALLOC(attrib->oidSz, pkcs7->heap,
 5410                                     DYNAMIC_TYPE_PKCS7);
 5411        if (attrib->oid == NULL) {
 5412            XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 5413            return MEMORY_E;
 5414        }
 5415        XMEMCPY(attrib->oid, in + oidIdx, attrib->oidSz);
 5416
 5417        /* Get Set that contains the printable string value */
 5418        if (GetSet(in, &idx, &length, (word32)inSz) < 0) {
 5419            XFREE(attrib->oid, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 5420            XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 5421            return ASN_PARSE_E;
 5422        }
 5423
 5424        if ((inSz - (int)idx) < length) {
 5425            XFREE(attrib->oid, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 5426            XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 5427            return ASN_PARSE_E;
 5428        }
 5429
 5430        attrib->valueSz = (word32)length;
 5431        attrib->value = (byte*)XMALLOC(attrib->valueSz, pkcs7->heap,
 5432                                       DYNAMIC_TYPE_PKCS7);
 5433        if (attrib->value == NULL) {
 5434            XFREE(attrib->oid, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 5435            XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 5436            return MEMORY_E;
 5437        }
 5438        XMEMCPY(attrib->value, in + idx, attrib->valueSz);
 5439        idx += (word32)length;
 5440
 5441        /* store attribute in linked list */
 5442        if (pkcs7->decodedAttrib != NULL) {
 5443            attrib->next = pkcs7->decodedAttrib;
 5444            pkcs7->decodedAttrib = attrib;
 5445        } else {
 5446            pkcs7->decodedAttrib = attrib;
 5447        }
 5448        found++;
 5449    }
 5450
 5451    return found;
 5452}
 5453
 5454
 5455/* option to turn off support for degenerate cases
 5456 * flag 0 turns off support
 5457 * flag 1 turns on support
 5458 *
 5459 * by default support for SignedData degenerate cases is on
 5460 */
 5461void wc_PKCS7_AllowDegenerate(wc_PKCS7* pkcs7, word16 flag)
 5462{
 5463    if (pkcs7) {
 5464        if (flag) { /* flag of 1 turns on support for degenerate */
 5465            pkcs7->noDegenerate = 0;
 5466        }
 5467        else { /* flag of 0 turns off support */
 5468            pkcs7->noDegenerate = 1;
 5469        }
 5470    }
 5471}
 5472
 5473/* Parses through a signerInfo set. Reads buffer "in" from "idxIn" to "idxIn" +
 5474 * length treating the current "idxIn" plus the length of set as max possible
 5475 * index.
 5476 *
 5477 * In the case that signed attributes are found "signedAttrib" gets set to point
 5478 *  at their location in the buffer "in". Also in this case signedAttribSz gets
 5479 *  set to the size of the signedAttrib buffer.
 5480 *
 5481 * returns 0 on success
 5482 */
 5483static int wc_PKCS7_ParseSignerInfo(wc_PKCS7* pkcs7, byte* in, word32 inSz,
 5484        word32* idxIn, int degenerate, byte** signedAttrib, int* signedAttribSz)
 5485{
 5486    int ret = 0;
 5487    int length = 0;
 5488    int version = 0;
 5489    word32 sigOID = 0, hashOID = 0;
 5490    word32 idx = *idxIn, localIdx;
 5491    byte tag;
 5492    byte absentParams = FALSE;
 5493
 5494    WOLFSSL_ENTER("wc_PKCS7_ParseSignerInfo");
 5495    /* require a signer if degenerate case not allowed */
 5496    if (inSz == 0 && pkcs7->noDegenerate == 1) {
 5497        WOLFSSL_MSG("Set to not allow degenerate cases");
 5498        return PKCS7_NO_SIGNER_E;
 5499    }
 5500
 5501    if (inSz == 0 && degenerate == 0) {
 5502        WOLFSSL_MSG("PKCS7 signers expected");
 5503        return PKCS7_NO_SIGNER_E;
 5504    }
 5505
 5506    /* not a degenerate case and there is elements in the set */
 5507    if (inSz > 0 && degenerate == 0) {
 5508        ret = wc_PKCS7_SignerInfoNew(pkcs7);
 5509
 5510        /* Get the sequence of the first signerInfo */
 5511        if (ret == 0 && GetSequence(in, &idx, &length, inSz) < 0)
 5512            ret = ASN_PARSE_E;
 5513
 5514        /* Get the version */
 5515        if (ret == 0 && GetMyVersion(in, &idx, &version, inSz) < 0)
 5516            ret = ASN_PARSE_E;
 5517
 5518        if (ret == 0) {
 5519            pkcs7->signerInfo->version = version;
 5520        }
 5521
 5522        if (ret == 0 && version == 1) {
 5523            /* Get the sequence of IssuerAndSerialNumber */
 5524            if (GetSequence(in, &idx, &length, inSz) < 0)
 5525                ret = ASN_PARSE_E;
 5526
 5527            if (ret == 0) {
 5528                pkcs7->signerInfo->sidType = CMS_ISSUER_AND_SERIAL_NUMBER;
 5529                ret = wc_PKCS7_SignerInfoSetSID(pkcs7, in + idx, length);
 5530                idx += (word32)length;
 5531            }
 5532
 5533        } else if (ret == 0 && version == 3) {
 5534            /* Default: SignerInfo version 3 carries SubjectKeyIdentifier.
 5535             * May be overridden below if the parser instead finds a
 5536             * SEQUENCE (IssuerAndSerialNumber fallback). */
 5537            pkcs7->signerInfo->sidType = CMS_SKID;
 5538            /* Get the sequence of SubjectKeyIdentifier */
 5539            if (idx + 1 > inSz)
 5540                ret = BUFFER_E;
 5541
 5542            localIdx = idx;
 5543            if (ret == 0 && GetASNTag(in, &localIdx, &tag, inSz) == 0 &&
 5544                   tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) {
 5545                idx++;
 5546
 5547                if (GetLength(in, &idx, &length, inSz) <= 0)
 5548                    ret = ASN_PARSE_E;
 5549
 5550                if (ret == 0 && idx + 1 > inSz)
 5551                    ret = BUFFER_E;
 5552
 5553                if (ret == 0 && GetASNTag(in, &idx, &tag, inSz) < 0)
 5554                    ret = ASN_PARSE_E;
 5555
 5556                if (ret == 0 && tag != ASN_OCTET_STRING)
 5557                    ret = ASN_PARSE_E;
 5558
 5559                if (ret == 0 && GetLength(in, &idx, &length, inSz) < 0)
 5560                    ret = ASN_PARSE_E;
 5561            }
 5562            else {
 5563                /* check if SKID with ASN_CONTEXT_SPECIFIC otherwise in version
 5564                 * 3 try to get issuerAndSerial */
 5565                localIdx = idx;
 5566                if (GetASNTag(in, &localIdx, &tag, inSz) == 0 &&
 5567                        tag == ASN_CONTEXT_SPECIFIC) {
 5568                    idx++;
 5569                    if (ret == 0 && GetLength(in, &idx, &length, inSz) < 0)
 5570                        ret = ASN_PARSE_E;
 5571                }
 5572                else {
 5573                    if (pkcs7->version != 3) {
 5574                        WOLFSSL_MSG("Unexpected signer info found with version");
 5575                        ret = ASN_PARSE_E;
 5576                    }
 5577
 5578                    if (ret == 0 && GetSequence(in, &idx, &length, inSz) < 0)
 5579                        ret = ASN_PARSE_E;
 5580
 5581                    if (ret == 0) {
 5582                        /* v3 carrying IssuerAndSerialNumber fallback */
 5583                        pkcs7->signerInfo->sidType =
 5584                                CMS_ISSUER_AND_SERIAL_NUMBER;
 5585                    }
 5586                }
 5587            }
 5588
 5589            if (ret == 0) {
 5590                if (length > (int)inSz - (int)idx)
 5591                    ret = BUFFER_E;
 5592            }
 5593
 5594            if (ret == 0) {
 5595                ret = wc_PKCS7_SignerInfoSetSID(pkcs7, in + idx, length);
 5596                idx += (word32)length;
 5597            }
 5598
 5599        } else {
 5600            WOLFSSL_MSG("PKCS#7 signerInfo version must be 1 or 3");
 5601            ret = ASN_VERSION_E;
 5602        }
 5603
 5604        /* Get the sequence of digestAlgorithm */
 5605        if (ret == 0 && GetAlgoIdEx(in, &idx, &hashOID, oidHashType,
 5606                                    inSz, &absentParams) < 0) {
 5607            ret = ASN_PARSE_E;
 5608        }
 5609        pkcs7->hashOID = (int)hashOID;
 5610        pkcs7->hashParamsAbsent = (absentParams != 0);
 5611
 5612        /* Get the IMPLICIT[0] SET OF signedAttributes */
 5613        localIdx = idx;
 5614        if (ret == 0 && GetASNTag(in, &localIdx, &tag, inSz) == 0 &&
 5615                tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) {
 5616            idx++;
 5617
 5618            if (GetLength(in, &idx, &length, inSz) < 0)
 5619                ret = ASN_PARSE_E;
 5620
 5621            /* save pointer and length */
 5622            *signedAttrib = &in[idx];
 5623            *signedAttribSz = length;
 5624
 5625            if (ret == 0 && wc_PKCS7_ParseAttribs(pkcs7, *signedAttrib,
 5626                        *signedAttribSz) < 0) {
 5627                WOLFSSL_MSG("Error parsing signed attributes");
 5628                ret = ASN_PARSE_E;
 5629            }
 5630
 5631            idx += (word32)length;
 5632        }
 5633
 5634        /* Get digestEncryptionAlgorithm (signatureAlgorithm) - parse manually
 5635         * so we can decode id-RSASSA-PSS parameters in all builds. */
 5636#if defined(WC_RSA_PSS) && !defined(NO_RSA)
 5637        pkcs7->pssParamsPresent = 0;
 5638#endif
 5639        if (ret == 0) {
 5640            int algoSeqLen = 0;
 5641            word32 algoContentStart = 0;
 5642            if (GetSequence(in, &idx, &algoSeqLen, (word32)inSz) < 0) {
 5643                ret = ASN_PARSE_E;
 5644            }
 5645            else {
 5646                algoContentStart = idx; /* first byte of AlgorithmIdentifier content */
 5647                if (GetObjectId(in, &idx, &sigOID, oidSigType, inSz) < 0) {
 5648                    ret = ASN_PARSE_E;
 5649                }
 5650                /* Only parse params when still inside the AlgorithmIdentifier;
 5651                 * when optional params are absent, idx is already past the sequence. */
 5652                else if (algoContentStart + (word32)algoSeqLen > idx) {
 5653#if defined(WC_RSA_PSS) && !defined(NO_RSA)
 5654                    word32 paramsStart = idx;
 5655#endif
 5656                    byte paramTag;
 5657                    int paramLen = 0;
 5658                    if (GetASNTag(in, &idx, &paramTag, inSz) != 0 ||
 5659                        GetLength(in, &idx, &paramLen, inSz) < 0) {
 5660                        ret = ASN_PARSE_E;
 5661                    }
 5662                    else {
 5663#if defined(WC_RSA_PSS) && !defined(NO_RSA)
 5664                        if ((word32)sigOID == (word32)CTC_RSASSAPSS &&
 5665                            paramTag == (ASN_SEQUENCE | ASN_CONSTRUCTED)) {
 5666                            word32 tlvLen = (idx - paramsStart) +
 5667                                            (word32)paramLen;
 5668                            enum wc_HashType pssHash = WC_HASH_TYPE_SHA;
 5669                            int pssMgfVal = 0, pssSalt = 0;
 5670                            if (paramsStart + tlvLen > (word32)inSz) {
 5671                                return ASN_PARSE_E;
 5672                            }
 5673                            ret = wc_DecodeRsaPssParams(in + paramsStart, tlvLen,
 5674                                                        &pssHash, &pssMgfVal,
 5675                                                        &pssSalt);
 5676                            if (ret == 0) {
 5677                                pkcs7->pssSaltLen = pssSalt;
 5678                                pkcs7->pssHashType = (int)pssHash;
 5679                                pkcs7->pssMgf = pssMgfVal;
 5680                                pkcs7->pssParamsPresent = 1;
 5681                            }
 5682                            else {
 5683                                WOLFSSL_MSG("RSASSA-PSS parameters invalid - failing parse");
 5684                                return ASN_PARSE_E;
 5685                            }
 5686                        }
 5687#endif
 5688                        idx += (word32)paramLen;
 5689                    }
 5690                }
 5691            }
 5692        }
 5693
 5694        /* store public key type based on digestEncryptionAlgorithm */
 5695        if (ret == 0) {
 5696            ret = wc_PKCS7_SetPublicKeyOID(pkcs7, (int)sigOID);
 5697            if (ret < 0) {
 5698                WOLFSSL_MSG("Failed to set public key OID from signature");
 5699            }
 5700            else {
 5701                /* if previous return was positive then was success */
 5702                ret = 0;
 5703            }
 5704        }
 5705    }
 5706
 5707    /* update index on success */
 5708    if (ret == 0) {
 5709        *idxIn = idx;
 5710    }
 5711
 5712    return ret;
 5713}
 5714
 5715/* parse input to get single/multiple octet strings.
 5716 * get each octet string from stream up to the size defined by
 5717 * MAX_PKCS7_STREAM_BUFFER then hash and store them to the content buffer.
 5718 * hash is stored to pkcs7->stream->hashBuf and its size in
 5719 * pkcs7->stream->hashBufSz if keepContent is true, accumulates content into
 5720 * pkcs7->stream->content and stores its size in pkcs7->stream->contentSz.
 5721 */
 5722#ifndef NO_PKCS7_STREAM
 5723static int wc_PKCS7_HandleOctetStrings(wc_PKCS7* pkcs7, byte* in, word32 inSz,
 5724                                word32* tmpIdx, word32* idx, int keepContent)
 5725{
 5726    int ret, length = 0;
 5727    word32 msgSz, i, contBufSz;
 5728    byte tag;
 5729    byte* msg = NULL;
 5730    byte* tempBuf = NULL;
 5731
 5732    /* allow 0 for inSz in streaming */
 5733    if (inSz == 0) {
 5734        return WC_PKCS7_WANT_READ_E;
 5735    }
 5736
 5737    if (pkcs7 == NULL || in == NULL || idx == NULL)
 5738        return BAD_FUNC_ARG;
 5739
 5740    /* no content case, do nothing */
 5741    if (pkcs7->stream->noContent) {
 5742        if (pkcs7->content && pkcs7->contentSz > 0) {
 5743            XFREE(pkcs7->stream->content, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 5744            pkcs7->stream->content = NULL;
 5745
 5746            pkcs7->stream->content = (byte*)XMALLOC(pkcs7->contentSz,
 5747                                            pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 5748            if (pkcs7->stream->content == NULL) {
 5749                WOLFSSL_MSG("Failed to grow content buffer.");
 5750                return MEMORY_E;
 5751            }
 5752            XMEMCPY(pkcs7->stream->content, pkcs7->content, pkcs7->contentSz);
 5753            pkcs7->stream->contentSz = pkcs7->contentSz;
 5754        }
 5755        return 0;
 5756    }
 5757
 5758    /* free pkcs7->contentDynamic buffer */
 5759    XFREE(pkcs7->contentDynamic, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 5760    pkcs7->contentDynamic = NULL;
 5761
 5762    while(1) {
 5763        if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
 5764                            pkcs7->stream->expected, &msg, idx)) != 0) {
 5765            break;
 5766        }
 5767
 5768        msgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length:inSz;
 5769
 5770        if (pkcs7->stream->currContRmnSz == 0) {
 5771
 5772            /* processed single OCTET STRING, try to find another one. */
 5773            if ((ret = GetASNTag(msg, idx, &tag, msgSz)) < 0) {
 5774                break;
 5775            }
 5776
 5777            /* if another OCTET STRING is found, get its length */
 5778            if (ret == 0 && tag == ASN_OCTET_STRING) {
 5779
 5780                if (ret == 0 && GetLength_ex(msg, idx, &length, msgSz,
 5781                                                            NO_USER_CHECK) < 0){
 5782                    ret = ASN_PARSE_E;
 5783                    break;
 5784                }
 5785
 5786                /* set up for next octet string */
 5787                pkcs7->stream->currContSz    = (word32)length;
 5788                pkcs7->stream->currContRmnSz = (word32)length;
 5789                pkcs7->stream->expected      = min(pkcs7->stream->currContRmnSz,
 5790                                                   MAX_PKCS7_STREAM_BUFFER);
 5791
 5792                /* advance read index */
 5793                if (wc_PKCS7_StreamEndCase(pkcs7, tmpIdx, idx) != 0) {
 5794                    break;
 5795                }
 5796
 5797                /* check if expected data is available in stream */
 5798                ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
 5799                            pkcs7->stream->expected, &msg, idx);
 5800                if (ret == WC_NO_ERR_TRACE(WC_PKCS7_WANT_READ_E)) {
 5801                    break;  /* ask user more input */
 5802                }
 5803
 5804                /* data available, continue processing */
 5805                continue;
 5806            }
 5807            /* reached to the end of contents. trailing zeros may follow. */
 5808            else if (ret == 0 && tag == ASN_EOC) {
 5809
 5810                /* ASN_EOC tag and one zero follows to show the end of
 5811                 * in-definite length encoding.
 5812                 * number of indef is stored in pkcs7->stream->cntIdfCnt.
 5813                 */
 5814                pkcs7->stream->expected = (word32)(ASN_TAG_SZ + TRAILING_ZERO) *
 5815                                               (word32)pkcs7->stream->cntIdfCnt;
 5816
 5817                /* dec idx by one since already consumed to get ASN_EOC */
 5818                (*idx)--;
 5819
 5820                if (wc_PKCS7_StreamEndCase(pkcs7, tmpIdx, idx) != 0) {
 5821                    break;
 5822                }
 5823
 5824                /* check if expected data is available in stream */
 5825                ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
 5826                            pkcs7->stream->expected, &msg, idx);
 5827                if (ret == WC_NO_ERR_TRACE(WC_PKCS7_WANT_READ_E)) {
 5828                    break;  /* ask user more input */
 5829                }
 5830
 5831                /* data available, continue processing trailing zeros */
 5832                for (i = 0; i < pkcs7->stream->expected; i++) {
 5833                    if (msg[*idx + i] != 0) {
 5834                        ret = ASN_PARSE_E;
 5835                        break;
 5836                    }
 5837                }
 5838                /* reset indef-length count */
 5839                pkcs7->stream->cntIdfCnt = 0;
 5840
 5841                /* advance read index */
 5842                *idx += pkcs7->stream->expected;
 5843
 5844                if (wc_PKCS7_StreamEndCase(pkcs7, tmpIdx, idx) != 0) {
 5845                    break;
 5846                }
 5847
 5848                /* handled OCTET STRINGs successfully */
 5849                ret = 0;
 5850                break;
 5851            }
 5852            /* reached to the end of contents without trailing zeros */
 5853            else if (ret == 0) {
 5854
 5855                /* dec idx by one since already consumed to get ASN_EOC */
 5856                (*idx)--;
 5857
 5858                if (wc_PKCS7_StreamEndCase(pkcs7, tmpIdx, idx) != 0) {
 5859                    break;
 5860                }
 5861
 5862                ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
 5863                            pkcs7->stream->expected, &msg, idx);
 5864                if (ret == WC_NO_ERR_TRACE(WC_PKCS7_WANT_READ_E)) {
 5865                    break;
 5866                }
 5867
 5868                /* handled OCTET STRINGs successfully */
 5869                ret = 0;
 5870                break;
 5871            }
 5872            else {
 5873                break;
 5874            }
 5875        }
 5876        else {
 5877            /* got partial octet string data */
 5878            /* accumulate partial octet string to buffer */
 5879            if (keepContent) {
 5880            #ifdef ASN_BER_TO_DER
 5881                if (pkcs7->streamOutCb) {
 5882                    ret = wc_HashUpdate(&pkcs7->stream->hashAlg,
 5883                        pkcs7->stream->hashType,
 5884                        msg + *idx, pkcs7->stream->expected);
 5885                    if (ret != 0)
 5886                        break;
 5887                    pkcs7->streamOutCb(pkcs7, msg + *idx,
 5888                        pkcs7->stream->expected, pkcs7->streamCtx);
 5889                }
 5890                else
 5891            #endif /* ASN_BER_TO_DER */
 5892                {
 5893                    /* store current content buffer temporarily */
 5894                    tempBuf = pkcs7->stream->content;
 5895                    pkcs7->stream->content = NULL;
 5896
 5897                    /* grow content buffer */
 5898                    contBufSz = pkcs7->stream->accumContSz;
 5899                    pkcs7->stream->accumContSz += pkcs7->stream->expected;
 5900
 5901                    pkcs7->stream->content =
 5902                                    (byte*)XMALLOC(pkcs7->stream->accumContSz,
 5903                                               pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 5904
 5905                    if (pkcs7->stream->content == NULL) {
 5906                        WOLFSSL_MSG("failed to grow content buffer.");
 5907                            if (tempBuf != NULL) {
 5908                        XFREE(tempBuf, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 5909                            }
 5910                        ret = MEMORY_E;
 5911                        break;
 5912                    }
 5913                    else {
 5914                        /* accumulate content */
 5915                        if (tempBuf != NULL && contBufSz != 0) {
 5916                            XMEMCPY(pkcs7->stream->content, tempBuf, contBufSz);
 5917                        }
 5918                        XMEMCPY(pkcs7->stream->content + contBufSz, msg + *idx,
 5919                                                       pkcs7->stream->expected);
 5920                        if (tempBuf != NULL) {
 5921                            XFREE(tempBuf, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 5922                        }
 5923                    }
 5924                }
 5925            }
 5926
 5927            *idx                         += pkcs7->stream->expected;
 5928            pkcs7->stream->currContRmnSz -= pkcs7->stream->expected;
 5929            pkcs7->stream->contentSz     += pkcs7->stream->expected;
 5930
 5931            if (wc_PKCS7_StreamEndCase(pkcs7, tmpIdx, idx) != 0) {
 5932                break;
 5933            }
 5934
 5935            if (pkcs7->stream->currContRmnSz > 0) {
 5936                pkcs7->stream->expected = min(pkcs7->stream->currContRmnSz,
 5937                                              MAX_PKCS7_STREAM_BUFFER);
 5938            }
 5939            else {
 5940                /* Processed current OCTET STRING. Proceed to the next one. */
 5941                pkcs7->stream->currContRmnSz = 0;
 5942                pkcs7->stream->currContSz    = 0;
 5943                pkcs7->stream->expected= ASN_TAG_SZ + MAX_LENGTH_SZ;
 5944
 5945                if (pkcs7->stream->maxLen > 0 &&
 5946                    (pkcs7->stream->maxLen - pkcs7->stream->totalRd)
 5947                                                < ASN_TAG_SZ + MAX_LENGTH_SZ) {
 5948                    /* seems reached to end of content */
 5949                    ret = 0;
 5950                    break;
 5951                }
 5952            }
 5953
 5954            /* data available */
 5955            continue;
 5956        }
 5957    }
 5958    return ret;
 5959}
 5960#endif /* !NO_PKCS7_STREAM */
 5961/* Finds the certificates in the message and saves it. By default allows
 5962 * degenerate cases which can have no signer.
 5963 *
 5964 * By default expects type SIGNED_DATA (SignedData) which can have any number of
 5965 * elements in signerInfos collection, including zero. (RFC2315 section 9.1)
 5966 * When adding support for the case of SignedAndEnvelopedData content types a
 5967 * signer is required. In this case the PKCS7 flag noDegenerate could be set.
 5968 */
 5969static int PKCS7_VerifySignedData(wc_PKCS7* pkcs7, const byte* hashBuf,
 5970    word32 hashSz, byte* in, word32 inSz,
 5971    byte* in2, word32 in2Sz)
 5972{
 5973    word32 idx, maxIdx = inSz, outerContentType = 0, contentTypeSz = 0, totalSz = 0;
 5974    int length = 0, version = 0, ret = 0;
 5975    byte* content = NULL;
 5976    byte* contentDynamic = NULL;
 5977    byte* sig = NULL;
 5978    byte* cert = NULL;
 5979    byte* signedAttrib = NULL;
 5980    byte* contentType = NULL;
 5981    int encapContentInfoLen = 0;
 5982    int contentSz = 0, sigSz = 0, certSz = 0, signedAttribSz = 0;
 5983    word32 localIdx, start;
 5984    word32 certIdx, certIdx2;
 5985    byte degenerate = 0;
 5986    byte detached = 0;
 5987    byte tag = 0;
 5988    word16 contentIsPkcs7Type = 0;
 5989#ifdef ASN_BER_TO_DER
 5990    byte* der;
 5991#endif
 5992    int multiPart = 0, keepContent;
 5993    int contentLen = 0;
 5994
 5995    byte* pkiMsg    = in;
 5996    word32 pkiMsgSz = inSz;
 5997#ifndef NO_PKCS7_STREAM
 5998    word32 stateIdx = 0;
 5999    word32 hashOID = 0;
 6000    enum wc_HashType hashType = WC_HASH_TYPE_NONE;
 6001    byte*   src = NULL;
 6002    word32  srcSz;
 6003#endif
 6004    byte* pkiMsg2 = in2;
 6005    word32 pkiMsg2Sz = in2Sz;
 6006    (void)keepContent;
 6007    if (pkcs7 == NULL)
 6008        return BAD_FUNC_ARG;
 6009
 6010#ifndef NO_PKCS7_STREAM
 6011    /* allow for 0 size inputs with stream mode */
 6012    if (pkiMsg == NULL && pkiMsgSz > 0)
 6013        return BAD_FUNC_ARG;
 6014
 6015#else
 6016    if (pkiMsg == NULL || pkiMsgSz == 0)
 6017        return BAD_FUNC_ARG;
 6018#endif
 6019
 6020    if ((hashSz > 0 && hashBuf == NULL) || (pkiMsg2Sz > 0 && pkiMsg2 == NULL)) {
 6021        return BAD_FUNC_ARG;
 6022    }
 6023    idx = 0;
 6024
 6025#ifdef ASN_BER_TO_DER
 6026    if (pkcs7->derSz > 0 && pkcs7->der) {
 6027        pkiMsg = pkcs7->der;
 6028    }
 6029#endif
 6030
 6031#ifndef NO_PKCS7_STREAM
 6032    if (pkcs7->stream == NULL) {
 6033        if ((ret = wc_PKCS7_CreateStream(pkcs7)) != 0) {
 6034            return ret;
 6035        }
 6036    }
 6037#endif
 6038
 6039    switch (pkcs7->state) {
 6040        case WC_PKCS7_START:
 6041        #ifndef NO_PKCS7_STREAM
 6042            /* The expected size calculation originally assumed digest OID
 6043             * with NULL params, -2 to also accept with absent params */
 6044            if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, (MAX_SEQ_SZ +
 6045                            MAX_VERSION_SZ + MAX_SEQ_SZ + MAX_LENGTH_SZ +
 6046                            ASN_TAG_SZ + MAX_OID_SZ + MAX_SEQ_SZ) - 2,
 6047                            &pkiMsg, &idx)) != 0) {
 6048                break;
 6049            }
 6050
 6051            pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
 6052
 6053            /* get content info size */
 6054            localIdx = 0;
 6055            if (GetSequence_ex(pkiMsg, &localIdx, &length, pkiMsgSz,
 6056                                        NO_USER_CHECK) < 0) {
 6057                break;
 6058            }
 6059            if (ret == 0 && length > 0)
 6060                pkcs7->stream->maxLen = (word32)length + localIdx;
 6061            else
 6062                pkcs7->stream->maxLen = inSz;
 6063
 6064        #endif
 6065
 6066            /* determine total message size */
 6067            totalSz = pkiMsgSz;
 6068            if (pkiMsg2 && pkiMsg2Sz > 0) {
 6069                totalSz += pkiMsg2Sz + pkcs7->contentSz;
 6070            }
 6071
 6072            /* Get the contentInfo sequence */
 6073            if (ret == 0 && GetSequence_ex(pkiMsg, &idx, &length, totalSz,
 6074                        NO_USER_CHECK) < 0)
 6075                ret = ASN_PARSE_E;
 6076
 6077            if (ret == 0 && length == 0 && pkiMsg[idx-1] == ASN_INDEF_LENGTH) {
 6078
 6079    #if defined(NO_PKCS7_STREAM)
 6080        #ifdef ASN_BER_TO_DER
 6081                word32 len = 0;
 6082
 6083                ret = wc_BerToDer(pkiMsg, pkiMsgSz, NULL, &len);
 6084                if (ret != WC_NO_ERR_TRACE(LENGTH_ONLY_E))
 6085                    return ret;
 6086                pkcs7->der = (byte*)XMALLOC(len, pkcs7->heap,
 6087                                                        DYNAMIC_TYPE_PKCS7);
 6088                if (pkcs7->der == NULL)
 6089                    return MEMORY_E;
 6090                ret = wc_BerToDer(pkiMsg, pkiMsgSz, pkcs7->der, &len);
 6091                if (ret < 0)
 6092                    return ret;
 6093
 6094                pkiMsg   = in = pkcs7->der;
 6095                inSz = pkcs7->derSz = len;
 6096                idx = 0;
 6097            #ifdef NO_PKCS7_STREAM
 6098                pkiMsgSz = len;
 6099            #else
 6100                wc_PKCS7_ResetStream(pkcs7);
 6101                if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
 6102                                MAX_SEQ_SZ + MAX_VERSION_SZ + MAX_SEQ_SZ +
 6103                                MAX_LENGTH_SZ + ASN_TAG_SZ + MAX_OID_SZ +
 6104                                MAX_SEQ_SZ, &pkiMsg, &idx)) != 0) {
 6105                    break;
 6106                }
 6107
 6108                pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length:
 6109                                                        inSz;
 6110
 6111                totalSz = pkiMsgSz;
 6112                if (pkiMsg2 && pkiMsg2Sz > 0) {
 6113                    totalSz += pkiMsg2Sz + pkcs7->contentSz;
 6114                }
 6115
 6116                if ((ret = wc_PKCS7_SetMaxStream(pkcs7, in, len)) != 0) {
 6117                    break;
 6118                }
 6119            #endif
 6120                if (GetSequence_ex(pkiMsg, &idx, &length, pkiMsgSz,
 6121                            NO_USER_CHECK) < 0)
 6122                    return ASN_PARSE_E;
 6123        #else
 6124                ret = BER_INDEF_E;
 6125        #endif
 6126    #else
 6127                /* the bundle has indefinite length encoding */
 6128                pkcs7->stream->indefLen = 1;
 6129
 6130    #endif /* NO_PKCS7_STREAM */
 6131            }
 6132
 6133            /* Get the contentInfo contentType */
 6134            if (ret == 0 && wc_GetContentType(pkiMsg, &idx, &outerContentType,
 6135                        pkiMsgSz) < 0)
 6136                ret = ASN_PARSE_E;
 6137
 6138            if (ret == 0 && outerContentType != SIGNED_DATA) {
 6139                WOLFSSL_MSG("PKCS#7 input not of type SignedData");
 6140                ret = PKCS7_OID_E;
 6141            }
 6142
 6143            /* get the ContentInfo content */
 6144            if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, totalSz) != 0)
 6145                ret = ASN_PARSE_E;
 6146
 6147            if (ret == 0 && tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
 6148                ret = ASN_PARSE_E;
 6149
 6150            if (ret == 0 && GetLength_ex(pkiMsg, &idx, &length, totalSz,
 6151                        NO_USER_CHECK) < 0)
 6152                ret = ASN_PARSE_E;
 6153
 6154            /* Get the signedData sequence */
 6155            if (ret == 0 && GetSequence_ex(pkiMsg, &idx, &length, totalSz,
 6156                        NO_USER_CHECK) < 0)
 6157                ret = ASN_PARSE_E;
 6158
 6159            /* Get the version */
 6160            if (ret == 0 && GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0)
 6161                ret = ASN_PARSE_E;
 6162
 6163            /* version 1 follows RFC 2315 */
 6164            /* version 3 follows RFC 4108 */
 6165            if (ret == 0 && (version != 1 && version != 3)) {
 6166                WOLFSSL_MSG("PKCS#7 signedData needs to be version 1 or 3");
 6167                ret = ASN_VERSION_E;
 6168            }
 6169            pkcs7->version = (byte)version;
 6170
 6171            /* Get the set of DigestAlgorithmIdentifiers */
 6172            if (ret == 0 && GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0)
 6173                ret = ASN_PARSE_E;
 6174
 6175            localIdx = idx;
 6176
 6177        #ifndef NO_PKCS7_STREAM
 6178            /* initialize hashType*/
 6179            pkcs7->stream->hashType = WC_HASH_TYPE_NONE;
 6180
 6181            /* Get the first DigestAlgorithmIdentifier from the SET */
 6182            if (ret == 0 && length > 0) {
 6183                if (GetAlgoId(pkiMsg, &idx, &hashOID, oidHashType, pkiMsgSz)
 6184                                                                          < 0)
 6185                    ret = ASN_PARSE_E;
 6186
 6187                pkcs7->hashOID = (int)hashOID;
 6188                /* get hash type */
 6189                hashType = wc_OidGetHash(pkcs7->hashOID);
 6190
 6191                if (hashType == WC_HASH_TYPE_NONE) {
 6192                    WOLFSSL_MSG("Error getting hash type for PKCS7 content"
 6193                                                            " verification");
 6194                    ret = ASN_PARSE_E;
 6195                }
 6196                if (wc_HashGetDigestSize(hashType) < 0) {
 6197                    WOLFSSL_MSG("Error getting digest size");
 6198                    ret = ASN_PARSE_E;
 6199                }
 6200                /* store hashType for later hashing */
 6201                pkcs7->stream->hashType = hashType;
 6202
 6203                /* restore idx */
 6204                idx = localIdx;
 6205
 6206                WOLFSSL_MSG("DigestAlgorithmIdentifier found in bundle");
 6207            }
 6208        #endif /* !NO_PKCS7_STREAM */
 6209
 6210            /* Skip the set. */
 6211            idx += (word32)length;
 6212            degenerate = (length == 0) ? 1 : 0;
 6213        #ifndef NO_PKCS7_STREAM
 6214            pkcs7->stream->degenerate = (degenerate != 0);
 6215        #endif /* !NO_PKCS7_STREAM */
 6216            if (pkcs7->noDegenerate == 1 && degenerate != 0) {
 6217                ret = PKCS7_NO_SIGNER_E;
 6218            }
 6219
 6220            if (ret != 0)
 6221                break;
 6222
 6223        #ifndef NO_PKCS7_STREAM
 6224            if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) {
 6225                break;
 6226            }
 6227            if (pkiMsg2 && pkiMsg2Sz > 0) {
 6228                pkcs7->stream->maxLen += pkiMsg2Sz + pkcs7->contentSz;
 6229            }
 6230            wc_PKCS7_StreamStoreVar(pkcs7, totalSz, 0, 0);
 6231
 6232        #endif
 6233
 6234            wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE2);
 6235
 6236        #ifndef NO_PKCS7_STREAM
 6237            pkcs7->stream->expected = MAX_SEQ_SZ + MAX_OID_SZ + ASN_TAG_SZ +
 6238                                    MAX_LENGTH_SZ + ASN_TAG_SZ + MAX_LENGTH_SZ;
 6239        #endif /* !NO_PKCS7_STREAM */
 6240            FALL_THROUGH;
 6241
 6242        case WC_PKCS7_VERIFY_STAGE2:
 6243        #ifndef NO_PKCS7_STREAM
 6244            if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz + in2Sz,
 6245                           pkcs7->stream->expected, &pkiMsg, &idx)) != 0) {
 6246                break;
 6247            }
 6248            degenerate = pkcs7->stream->degenerate;
 6249
 6250            wc_PKCS7_StreamGetVar(pkcs7, &totalSz, 0, 0);
 6251            if (pkcs7->stream->length > 0)
 6252                pkiMsgSz = pkcs7->stream->length;
 6253        #ifdef ASN_BER_TO_DER
 6254            else if (pkcs7->der)
 6255                pkiMsgSz = pkcs7->derSz;
 6256        #endif
 6257            else
 6258                pkiMsgSz = inSz;
 6259
 6260        #endif
 6261            /* Get the inner ContentInfo sequence */
 6262            if (GetSequence_ex(pkiMsg, &idx, &encapContentInfoLen, pkiMsgSz,
 6263                        NO_USER_CHECK) < 0)
 6264                ret = ASN_PARSE_E;
 6265
 6266            /* Get the inner ContentInfo contentType */
 6267            if (ret == 0) {
 6268                int isIndef = 0;
 6269                word32 tmpIdx = idx;
 6270                if (encapContentInfoLen == 0 &&
 6271                    pkiMsg[idx-1] == ASN_INDEF_LENGTH) {
 6272                    isIndef = 1;
 6273            #ifndef NO_PKCS7_STREAM
 6274                    /* count up indef-length count  */
 6275                    pkcs7->stream->cntIdfCnt++;
 6276            #endif
 6277                }
 6278                if (GetASNObjectId(pkiMsg, &idx, &length, pkiMsgSz) == 0) {
 6279                    contentType = pkiMsg + tmpIdx;
 6280                    contentTypeSz = (word32)length + (idx - tmpIdx);
 6281                    idx += (word32)length;
 6282                }
 6283                else {
 6284                    ret = ASN_PARSE_E;
 6285                }
 6286                /* if indef, skip EOF */
 6287                if (isIndef) {
 6288                    if (idx + 1 >= pkiMsgSz) {
 6289                        ret = ASN_PARSE_E;
 6290                    }
 6291                    else if (pkiMsg[idx] == ASN_EOC && pkiMsg[idx+1] == 0) {
 6292                        idx += 2; /* skip EOF + zero byte */
 6293            #ifndef NO_PKCS7_STREAM
 6294                        pkcs7->stream->cntIdfCnt--;
 6295            #endif
 6296                    }
 6297                }
 6298            }
 6299
 6300            if (ret != 0)
 6301                break;
 6302
 6303            /* Check for content, it could be omitted when degenerate */
 6304            localIdx = idx;
 6305            ret = 0;
 6306            if (localIdx + 1 > pkiMsgSz) {
 6307                ret = BUFFER_E;
 6308                break;
 6309            }
 6310
 6311            /* Set error state if no more data left in ContentInfo, meaning
 6312             * no content - may be detached. Will recover from error below */
 6313            if ((encapContentInfoLen != 0) &&
 6314                ((word32)encapContentInfoLen - contentTypeSz == 0)) {
 6315                ret = ASN_PARSE_E;
 6316            #ifndef NO_PKCS7_STREAM
 6317                pkcs7->stream->noContent = 1;
 6318            #endif
 6319            }
 6320
 6321            /* PKCS#7 spec:
 6322             *     content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL
 6323             * CMS spec:
 6324             *     eContent [0] EXPLICIT OCTET STRING OPTIONAL
 6325             */
 6326            if (ret == 0 && GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) != 0)
 6327                ret = ASN_PARSE_E;
 6328
 6329            if (ret == 0 && tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
 6330                ret = ASN_PARSE_E;
 6331
 6332            /* Get length of inner eContent payload. For CMS, spec defines
 6333             * OCTET_STRING will be next. If so, we use the length retrieved
 6334             * there. PKCS#7 spec defines ANY as eContent type. In this case
 6335             * we fall back and save this content length for use later */
 6336            if (ret == 0 && localIdx >= pkiMsgSz) {
 6337                /* Truncated input: don't dereference past the buffer.
 6338                 * Break out of the switch directly so the degenerate-
 6339                 * recovery path below cannot mask this error. */
 6340                ret = BUFFER_E;
 6341                break;
 6342            }
 6343
 6344            if (ret == 0 && pkiMsg[localIdx] != ASN_INDEF_LENGTH) {
 6345                if (GetLength_ex(pkiMsg, &localIdx, &length, pkiMsgSz,
 6346                        NO_USER_CHECK) <= 0) {
 6347                    ret = ASN_PARSE_E;
 6348                }
 6349
 6350                if (localIdx >= pkiMsgSz) {
 6351                    ret = BUFFER_E;
 6352                }
 6353            }
 6354            else if (ret == 0 && pkiMsg[localIdx] == ASN_INDEF_LENGTH) {
 6355        #ifndef NO_PKCS7_STREAM
 6356                pkcs7->stream->cntIdfCnt++;    /* count up indef-length count */
 6357        #endif
 6358                length = 0;
 6359                localIdx++;
 6360            }
 6361            else {
 6362                length = 0;
 6363                localIdx++;
 6364            }
 6365
 6366            /* Save idx to back up in case of PKCS#7 eContent */
 6367            start = localIdx;
 6368
 6369            /* get length of content in the case that there is multiple parts */
 6370            if (ret == 0 && GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) < 0)
 6371                ret = ASN_PARSE_E;
 6372
 6373            if (ret == 0 &&
 6374                (tag != (ASN_OCTET_STRING | ASN_CONSTRUCTED) &&
 6375                (tag != ASN_OCTET_STRING))) {
 6376
 6377                /* If reached end of ContentInfo, or we see the next element
 6378                 * ([0] IMPLICIT CertificateSet), set error state. Either
 6379                 * true error or detached */
 6380                if (tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) {
 6381                    ret = ASN_PARSE_E;
 6382                }
 6383
 6384                /* Back up before getting tag, process as PKCS#7 ANY and use
 6385                 * this as start of content. */
 6386                localIdx = start;
 6387                pkcs7->contentIsPkcs7Type = 1;
 6388
 6389                #ifndef NO_PKCS7_STREAM
 6390                    /* Set streaming variables for PKCS#7 type content.
 6391                     * length contains the size from [0] EXPLICIT wrapper */
 6392                    pkcs7->stream->multi         = 0;
 6393                    pkcs7->stream->currContIdx   = localIdx;
 6394                    pkcs7->stream->currContSz    = (word32)length;
 6395                    pkcs7->stream->currContRmnSz = (word32)length;
 6396                #endif
 6397            }
 6398            else {
 6399                /* CMS eContent OCTET_STRING */
 6400                if (ret == 0 && tag == (ASN_OCTET_STRING | ASN_CONSTRUCTED)) {
 6401                    multiPart = 1;
 6402
 6403                    /* Get length of all OCTET_STRINGs. */
 6404                    if (GetLength_ex(pkiMsg, &localIdx, &contentLen, pkiMsgSz,
 6405                                NO_USER_CHECK) < 0)
 6406                        ret = ASN_PARSE_E;
 6407                #ifndef NO_PKCS7_STREAM
 6408                    if (ret == 0 && pkiMsg[localIdx - 1] == ASN_INDEF_LENGTH) {
 6409                        pkcs7->stream->cntIdfCnt++;  /* indef-length count  */
 6410                    }
 6411                #endif
 6412                    /* Check whether there is one OCTET_STRING inside. */
 6413                    start = localIdx;
 6414                    if (localIdx >= pkiMsgSz) {
 6415                        ret = BUFFER_E;
 6416                    }
 6417
 6418                    if (ret == 0 && GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz)
 6419                            != 0)
 6420                        ret = ASN_PARSE_E;
 6421
 6422                    if (ret == 0 && tag != ASN_OCTET_STRING)
 6423                        ret = ASN_PARSE_E;
 6424
 6425                    if (ret == 0 && GetLength_ex(pkiMsg, &localIdx, &length,
 6426                                pkiMsgSz, NO_USER_CHECK) < 0)
 6427                        ret = ASN_PARSE_E;
 6428
 6429                    if (ret == 0) {
 6430                        /* Use single OCTET_STRING directly, or reset length. */
 6431                        if (localIdx - start + (word32)length ==
 6432                                                           (word32)contentLen) {
 6433                            multiPart = 0;
 6434                        } else {
 6435                        #ifndef NO_PKCS7_STREAM
 6436                            pkcs7->stream->multi         = (multiPart != 0);
 6437                            pkcs7->stream->currContIdx   = localIdx;
 6438                            pkcs7->stream->currContSz    = (word32)length;
 6439                            pkcs7->stream->currContRmnSz = (word32)length;
 6440                        #endif
 6441                            /* reset length to outer OCTET_STRING for bundle
 6442                             * size check below */
 6443                            length = contentLen;
 6444                        }
 6445                        localIdx = start;
 6446                    }
 6447
 6448                    if (ret != 0) {
 6449                        /* failed ASN1 parsing during OCTET_STRING checks */
 6450                        break;
 6451                    }
 6452                }
 6453
 6454                /* get length of content in case of single part */
 6455                if (ret == 0 && !multiPart) {
 6456                    if (tag != ASN_OCTET_STRING)
 6457                        ret = ASN_PARSE_E;
 6458
 6459                    if (ret == 0 && GetLength_ex(pkiMsg, &localIdx,
 6460                                &length, pkiMsgSz, NO_USER_CHECK) < 0)
 6461                        ret = ASN_PARSE_E;
 6462                #ifndef NO_PKCS7_STREAM
 6463                    if (ret == 0) {
 6464                        pkcs7->stream->multi         = (multiPart != 0);
 6465                        pkcs7->stream->currContIdx   = localIdx;
 6466                        pkcs7->stream->currContSz    = (word32)length;
 6467                        pkcs7->stream->currContRmnSz = (word32)length;
 6468                    }
 6469                #endif
 6470                }
 6471            }
 6472
 6473            /* update idx if successful */
 6474            if (ret == 0) {
 6475                /* support using header and footer without content */
 6476                if (pkiMsg2 && pkiMsg2Sz > 0 && hashBuf && hashSz > 0) {
 6477                    localIdx = 0;
 6478            #ifndef NO_PKCS7_STREAM
 6479                    pkcs7->stream->noContent = 1;
 6480            #endif
 6481
 6482                }
 6483                idx = localIdx;
 6484            }
 6485            else {
 6486                /* If either pkcs7->content and pkcs7->contentSz are set
 6487                 * (detached signature where user has set content explicitly
 6488                 * into pkcs7->content/contentSz) OR pkcs7->hashBuf and
 6489                 * pkcs7->hashSz are set (user has pre-computed content
 6490                 * digest and passed in instead of content directly), try to
 6491                 * process as a detached signature */
 6492                if (!degenerate &&
 6493                    ((pkcs7->content != NULL && pkcs7->contentSz != 0) ||
 6494                     (hashBuf != NULL && hashSz > 0)) ) {
 6495                    WOLFSSL_MSG("Trying to process as detached signature");
 6496                    detached = 1;
 6497                }
 6498
 6499                if (!degenerate && !detached && ret != 0)
 6500                    break;
 6501
 6502                /* no content to read */
 6503                length = 0;
 6504                contentLen = 0;
 6505
 6506                pkiMsg2   = pkiMsg;
 6507                pkiMsg2Sz = pkiMsgSz;
 6508
 6509                /* reset ret */
 6510                ret = 0;
 6511            }
 6512
 6513        #ifndef NO_PKCS7_STREAM
 6514            /* save detached flag value */
 6515            pkcs7->stream->detached = (detached != 0);
 6516
 6517            /* save contentType */
 6518            pkcs7->stream->nonce = (byte*)XMALLOC(contentTypeSz, pkcs7->heap,
 6519                    DYNAMIC_TYPE_PKCS7);
 6520            if (pkcs7->stream->nonce == NULL) {
 6521                ret = MEMORY_E;
 6522                break;
 6523            }
 6524            else {
 6525                pkcs7->stream->nonceSz = contentTypeSz;
 6526                XMEMCPY(pkcs7->stream->nonce, contentType, contentTypeSz);
 6527            }
 6528            if (ret < 0)
 6529                break;
 6530
 6531            if (pkcs7->stream->noContent) {
 6532                pkcs7->stream->expected = 0;
 6533            }
 6534            else {
 6535                if (multiPart) {
 6536                    idx = pkcs7->stream->currContIdx;
 6537                }
 6538                if (in2Sz > 0 && hashSz > 0) {
 6539                    /* seems no content included */
 6540                    pkcs7->stream->expected = + ASN_TAG_SZ + MAX_LENGTH_SZ;
 6541                }
 6542                else {
 6543                    pkcs7->stream->expected = pkcs7->stream->currContSz;
 6544                }
 6545            }
 6546
 6547            if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) {
 6548                break;
 6549            }
 6550            wc_PKCS7_StreamStoreVar(pkcs7, pkiMsg2Sz, (int)localIdx, length);
 6551
 6552
 6553        #endif /* !NO_PKCS7_STREAM */
 6554
 6555            wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE3);
 6556
 6557        #ifndef NO_PKCS7_STREAM
 6558        #ifdef ASN_BER_TO_DER
 6559            /* setup hash struct for creating hash of content if needed */
 6560            if (pkcs7->streamOutCb) {
 6561                ret = wc_HashInit_ex(&pkcs7->stream->hashAlg,
 6562                    pkcs7->stream->hashType, pkcs7->heap, pkcs7->devId);
 6563                if (ret != 0)
 6564                    break;
 6565            }
 6566        #endif /* ASN_BER_TO_DER */
 6567
 6568        /* free pkcs7->stream->content buffer */
 6569        XFREE(pkcs7->stream->content, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 6570        pkcs7->stream->content = NULL;
 6571        #endif /* !NO_PKCS7_STREAM */
 6572
 6573            FALL_THROUGH;
 6574
 6575        case WC_PKCS7_VERIFY_STAGE3:
 6576            keepContent = !(pkiMsg2 && pkiMsg2Sz > 0 && hashBuf && hashSz > 0);
 6577        #ifndef NO_PKCS7_STREAM
 6578            ret = wc_PKCS7_HandleOctetStrings(pkcs7, in, inSz,
 6579                                                &stateIdx, &idx, keepContent);
 6580            if (ret != 0)
 6581                break;
 6582
 6583            /* copy content to pkcs7->contentDynamic */
 6584            if (keepContent && pkcs7->stream->content &&
 6585                                            pkcs7->stream->contentSz > 0) {
 6586                pkcs7->contentDynamic = (byte*)XMALLOC(pkcs7->stream->contentSz,
 6587                                              pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 6588                if (pkcs7->contentDynamic == NULL) {
 6589                    ret = MEMORY_E;
 6590                    break;
 6591                }
 6592                XMEMCPY(pkcs7->contentDynamic, pkcs7->stream->content,
 6593                                               pkcs7->stream->contentSz);
 6594
 6595                pkcs7->contentSz = pkcs7->stream->contentSz;
 6596                pkcs7->content   = pkcs7->contentDynamic;
 6597            }
 6598
 6599            /* check if bundle has more elements or footer, if not, set content
 6600             * to pkcs7->content and hash to pkcs7->hash.
 6601             *
 6602             * NOTE: this check returns success whenever fewer than 6 bytes
 6603             * follow the content within the outer ContentInfo, which also
 6604             * accepts truncated bundles whose footer was cut short (e.g. a
 6605             * lone certificates [0] tag with no length). Distinguishing a
 6606             * legitimate degenerate end (such as an empty signerInfos SET
 6607             * "31 00") from truncated junk would require peeking at the
 6608             * remaining bytes or making stage 4's `expected` window smaller.
 6609             */
 6610            if (ret == 0 && pkcs7->stream->maxLen > 0 &&
 6611                    (pkcs7->stream->maxLen - pkcs7->stream->totalRd)
 6612                                                < ASN_TAG_SZ + MAX_LENGTH_SZ) {
 6613
 6614                ret = 0;
 6615                break;
 6616            }
 6617            /* expect data length to be enough to check set and seq of certs */
 6618            pkcs7->stream->expected = (ASN_TAG_SZ + MAX_LENGTH_SZ) * 2;
 6619
 6620        #else
 6621            /* Break out before content because it can be optional in degenerate
 6622             * cases. */
 6623            if (ret != 0 && !degenerate)
 6624                break;
 6625
 6626            /* get parts of content */
 6627            if (ret == 0 && multiPart) {
 6628                int i = 0;
 6629                keepContent = !(pkiMsg2 && pkiMsg2Sz > 0 && hashBuf &&
 6630                                                                hashSz > 0);
 6631
 6632                if (keepContent) {
 6633                    /* Create a buffer to hold content of OCTET_STRINGs. */
 6634                    pkcs7->contentDynamic = (byte*)XMALLOC(contentLen,
 6635                                            pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 6636                    if (pkcs7->contentDynamic == NULL)
 6637                        ret = MEMORY_E;
 6638                }
 6639
 6640                start = localIdx;
 6641                /* Use the data from each OCTET_STRING. */
 6642                while (ret == 0 && localIdx < start + contentLen) {
 6643                    if (GetASNTag(pkiMsg, &localIdx, &tag, totalSz) < 0)
 6644                        ret = ASN_PARSE_E;
 6645                    if (ret == 0 && tag != ASN_OCTET_STRING)
 6646                        ret = ASN_PARSE_E;
 6647
 6648                    if (ret == 0 && GetLength(pkiMsg, &localIdx, &length,
 6649                                                                totalSz) < 0)
 6650                        ret = ASN_PARSE_E;
 6651                    if (ret == 0 && length + localIdx > start + contentLen)
 6652                        ret = ASN_PARSE_E;
 6653
 6654                    if (ret == 0) {
 6655                        if (keepContent) {
 6656                            XMEMCPY(pkcs7->contentDynamic + i,
 6657                                                    pkiMsg + localIdx, length);
 6658                        }
 6659                        i += length;
 6660                        localIdx += length;
 6661                    }
 6662                }
 6663                localIdx = start; /* reset for sanity check, increment later */
 6664                length = i;
 6665            }
 6666
 6667            /* Save the inner data as the content. */
 6668            if (ret == 0 && length > 0) {
 6669                contentSz = length;
 6670
 6671                /* support using header and footer without content */
 6672                if (pkiMsg2 && pkiMsg2Sz > 0 && hashBuf && hashSz > 0) {
 6673                    /* Content not provided, use provided pkiMsg2 footer */
 6674                    content = NULL;
 6675                    localIdx = 0;
 6676                    if (contentSz != (int)pkcs7->contentSz) {
 6677                        WOLFSSL_MSG("Data signed does not match contentSz"
 6678                                                                " provided");
 6679                        ret = BUFFER_E;
 6680                    }
 6681                }
 6682                else {
 6683                    if ((word32)length > pkiMsgSz - localIdx) {
 6684                        ret = BUFFER_E;
 6685                    }
 6686
 6687                    /* Content pointer for calculating hashes later */
 6688                    if (ret == 0 && !multiPart) {
 6689                        content = &pkiMsg[localIdx];
 6690                    }
 6691                    if (ret == 0 && multiPart) {
 6692                        content = pkcs7->contentDynamic;
 6693                    }
 6694
 6695                    if (ret == 0) {
 6696                        idx += length;
 6697                    }
 6698
 6699                    pkiMsg2   = pkiMsg;
 6700                    pkiMsg2Sz = pkiMsgSz;
 6701                }
 6702            }
 6703            else {
 6704                pkiMsg2 = pkiMsg;
 6705                pkiMsg2Sz = pkiMsgSz;
 6706            }
 6707
 6708            /* If getting the content info failed with non degenerate then
 6709             * return the error case. Otherwise with a degenerate it is ok
 6710             * if the content info was omitted */
 6711            if (!degenerate && !detached && (ret != 0)) {
 6712                break;
 6713            }
 6714            else {
 6715                ret = 0; /* reset ret state on degenerate case */
 6716            }
 6717
 6718            /* save content */
 6719            if (detached == 1) {
 6720                /* if detached, use content from user in pkcs7 struct */
 6721                content = pkcs7->content;
 6722                contentSz = pkcs7->contentSz;
 6723            }
 6724        #endif /* !NO_PKCS7_STREAM */
 6725            wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE4);
 6726
 6727            FALL_THROUGH;
 6728
 6729       case WC_PKCS7_VERIFY_STAGE4:
 6730        #ifndef NO_PKCS7_STREAM
 6731            if (in2 && in2Sz > 0) {
 6732                src     = in2;
 6733                srcSz   = in2Sz;
 6734                pkiMsg2 = in2;
 6735            }
 6736            else {
 6737                src     = in;
 6738                srcSz   = inSz;
 6739                pkiMsg2 = in;
 6740            }
 6741            if ((ret = wc_PKCS7_AddDataToStream(pkcs7, src, srcSz,
 6742                            pkcs7->stream->expected, &pkiMsg2, &idx)) != 0) {
 6743                break;
 6744            }
 6745
 6746        #ifdef ASN_BER_TO_DER
 6747            if (pkcs7->derSz != 0)
 6748                pkiMsg2Sz = pkcs7->derSz;
 6749            else
 6750        #endif
 6751                pkiMsg2Sz = (pkcs7->stream->length > 0)? pkcs7->stream->length:
 6752                    srcSz;
 6753
 6754            if (pkcs7->stream->length > 0) {
 6755                localIdx = 0;
 6756            }
 6757
 6758            maxIdx = idx + pkcs7->stream->expected;
 6759        #endif /* !NO_PKCS7_STREAM */
 6760
 6761            if (pkiMsg2 == NULL || pkiMsg2Sz == 0) {
 6762                pkiMsg2Sz = pkiMsgSz;
 6763                pkiMsg2   = pkiMsg;
 6764            }
 6765
 6766            /* Certificates begin "footer" section (ie pkiMsg2) if being used */
 6767            /* Get the implicit[0] set of certificates */
 6768            if (ret == 0 && idx >= pkiMsg2Sz)
 6769                ret = BUFFER_E;
 6770
 6771            length = 0; /* set length to 0 to check if reading in any certs */
 6772            localIdx = idx;
 6773
 6774            if (ret == 0 && GetASNTag(pkiMsg2, &localIdx, &tag, pkiMsg2Sz) == 0
 6775                    && tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) {
 6776                idx++;
 6777
 6778                if (localIdx >= pkiMsg2Sz) {
 6779                    ret = BUFFER_E;
 6780                }
 6781
 6782                /* if certificates set has indefinite length, try to get
 6783                 * the first certificate length of the set.
 6784                 */
 6785                if (ret == 0 && pkiMsg2[localIdx] == ASN_INDEF_LENGTH) {
 6786
 6787                    localIdx++;
 6788                    certIdx = localIdx;
 6789                #ifndef NO_PKCS7_STREAM
 6790                /* set indef-length count. used for skipping trailing zeros */
 6791                    pkcs7->stream->cntIdfCnt = 1;
 6792                #endif
 6793                    ret = GetASNTag(pkiMsg2, &localIdx, &tag, pkiMsg2Sz);
 6794                    if (ret == 0 && tag == (ASN_CONSTRUCTED | ASN_SEQUENCE)) {
 6795                        if (GetLength_ex(pkiMsg2, &localIdx, &length, maxIdx,
 6796                                                NO_USER_CHECK) < 0)
 6797                    ret = ASN_PARSE_E;
 6798
 6799                        WOLFSSL_MSG("certificate set found");
 6800
 6801                        /* adjust cert length */
 6802                        length += (int)(localIdx - certIdx);
 6803                        idx = certIdx;
 6804                    }
 6805                }
 6806                /* in case certificates set has definite length  */
 6807                else {
 6808
 6809                    if (GetLength_ex(pkiMsg2, &localIdx, &length, maxIdx,
 6810                                                NO_USER_CHECK) < 0)
 6811                        ret = ASN_PARSE_E;
 6812
 6813                    idx = localIdx;
 6814                }
 6815            }
 6816
 6817            if (ret != 0) {
 6818                break;
 6819            }
 6820        #ifndef NO_PKCS7_STREAM
 6821            if (in2 && in2Sz > 0 && hashBuf && hashSz > 0) {
 6822                stateIdx = idx; /* case where all data was read from in2 */
 6823            }
 6824
 6825            if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) {
 6826                break;
 6827            }
 6828            wc_PKCS7_StreamStoreVar(pkcs7, pkiMsg2Sz, 0, length);
 6829            if (length > 0) {
 6830                pkcs7->stream->expected = (word32)length;
 6831            }
 6832            else {
 6833                pkcs7->stream->expected = MAX_SEQ_SZ;
 6834                if (pkcs7->stream->expected > (pkcs7->stream->maxLen -
 6835                            pkcs7->stream->totalRd) + pkcs7->stream->length) {
 6836                    pkcs7->stream->expected = (pkcs7->stream->maxLen -
 6837                                pkcs7->stream->totalRd) + pkcs7->stream->length;
 6838                }
 6839            }
 6840        #endif
 6841            wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE5);
 6842            FALL_THROUGH;
 6843
 6844        case WC_PKCS7_VERIFY_STAGE5:
 6845        #ifndef NO_PKCS7_STREAM
 6846            if (in2 && in2Sz > 0) {
 6847                src     = in2;
 6848                srcSz   = in2Sz;
 6849                pkiMsg2 = in2;
 6850            }
 6851            else {
 6852                src     = in;
 6853                srcSz   = inSz;
 6854                pkiMsg2 = in;
 6855            }
 6856
 6857            if ((ret = wc_PKCS7_AddDataToStream(pkcs7, src, srcSz,
 6858                            pkcs7->stream->expected, &pkiMsg2, &idx)) != 0) {
 6859                break;
 6860            }
 6861            pkiMsg2Sz = (pkcs7->stream->length > 0)? pkcs7->stream->length:
 6862                                                                        srcSz;
 6863
 6864            wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, 0, &length);
 6865
 6866            /* restore content */
 6867            content   = pkcs7->stream->content;
 6868            contentSz = (int)pkcs7->stream->contentSz;
 6869
 6870            /* restore detached flag */
 6871            detached = pkcs7->stream->detached;
 6872
 6873            /* store current index to get the signerInfo index later  */
 6874            certIdx2 = idx;
 6875            /* store certificate if needed */
 6876            if (length > 0 && in2Sz == 0) {
 6877                /* free tmpCert if not NULL */
 6878                XFREE(pkcs7->stream->tmpCert, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 6879                pkcs7->stream->tmpCert = (byte*)XMALLOC((word32)length,
 6880                        pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 6881                if ((pkiMsg2 == NULL) || (pkcs7->stream->tmpCert == NULL)) {
 6882                    ret = MEMORY_E;
 6883                    break;
 6884                }
 6885                XMEMCPY(pkcs7->stream->tmpCert, pkiMsg2 + idx, (word32)length);
 6886                pkiMsg2 = pkcs7->stream->tmpCert;
 6887                pkiMsg2Sz = (word32)length;
 6888                idx = 0;
 6889            }
 6890        #else
 6891            /* store current index to get the signerInfo index later  */
 6892            certIdx2 = idx;
 6893        #endif
 6894
 6895                if (length > 0) {
 6896                    /* At this point, idx is at the first certificate in
 6897                     * a set of certificates. There may be more than one,
 6898                     * or none, or they may be a PKCS 6 extended
 6899                     * certificate. We want to save the first cert if it
 6900                     * is X.509. */
 6901
 6902                    certIdx = idx;
 6903
 6904                    if (length < MAX_LENGTH_SZ + ASN_TAG_SZ)
 6905                        ret = BUFFER_E;
 6906
 6907                    if (ret == 0)
 6908                        ret = GetASNTag(pkiMsg2, &certIdx, &tag, pkiMsg2Sz);
 6909
 6910                    if (ret == 0 && tag == (ASN_CONSTRUCTED | ASN_SEQUENCE)) {
 6911                        if (GetLength_ex(pkiMsg2, &certIdx, &certSz, pkiMsg2Sz,
 6912                                                        NO_USER_CHECK) < 0)
 6913                            ret = ASN_PARSE_E;
 6914
 6915                        cert = &pkiMsg2[idx];
 6916                        certSz += (int)(certIdx - idx);
 6917                        if (certSz > length) {
 6918                            ret = BUFFER_E;
 6919                            break;
 6920                        }
 6921                    }
 6922        #ifdef ASN_BER_TO_DER
 6923                    der = pkcs7->der;
 6924                    pkcs7->der = NULL;
 6925        #endif
 6926                    version = pkcs7->version;
 6927                    contentIsPkcs7Type = pkcs7->contentIsPkcs7Type;
 6928
 6929                    if (ret == 0) {
 6930                        byte isDynamic = (byte)pkcs7->isDynamic;
 6931                    #ifndef NO_PKCS7_STREAM
 6932                        PKCS7State* stream = pkcs7->stream;
 6933                        pkcs7->stream = NULL;
 6934                    #endif
 6935
 6936                        /* Save dynamic content before freeing PKCS7 struct */
 6937                        if (pkcs7->contentDynamic != NULL) {
 6938                            contentDynamic = (byte*)XMALLOC((word32)contentSz,
 6939                                               pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 6940                            if (contentDynamic == NULL) {
 6941                            #ifndef NO_PKCS7_STREAM
 6942                                pkcs7->stream = stream;
 6943                            #endif
 6944                                ret = MEMORY_E;
 6945                                break;
 6946                            }
 6947                            XMEMCPY(contentDynamic, pkcs7->contentDynamic,
 6948                                    (word32)contentSz);
 6949                        }
 6950
 6951                        /* Free pkcs7 resources but not the structure itself */
 6952                        pkcs7->isDynamic = 0;
 6953                        wc_PKCS7_Free(pkcs7);
 6954                        pkcs7->isDynamic = (isDynamic != 0);
 6955                        /* This will reset PKCS7 structure and then set the
 6956                         * certificate */
 6957                        ret = wc_PKCS7_InitWithCert(pkcs7, cert, (word32)certSz);
 6958
 6959                        /* Restore pkcs7->contentDynamic from above, will be
 6960                         * freed by application with wc_PKCS7_Free() */
 6961                        if (contentDynamic != NULL) {
 6962                            pkcs7->contentDynamic = contentDynamic;
 6963                            contentDynamic = NULL;
 6964                        }
 6965
 6966                        /* Restore content is PKCS#7 flag */
 6967                        pkcs7->contentIsPkcs7Type = (contentIsPkcs7Type != 0);
 6968
 6969                    #ifndef NO_PKCS7_STREAM
 6970                        pkcs7->stream = stream;
 6971                    #endif
 6972                    }
 6973                    pkcs7->version = (byte)version;
 6974        #ifdef ASN_BER_TO_DER
 6975                    pkcs7->der = der;
 6976        #endif
 6977                    if (ret != 0)
 6978                        break;
 6979
 6980                    /* iterate through any additional certificates */
 6981                    if (ret == 0 && MAX_PKCS7_CERTS > 0) {
 6982                        int sz = 0;
 6983                        int i;
 6984
 6985                        pkcs7->cert[0]   = cert;
 6986                        pkcs7->certSz[0] = (word32)certSz;
 6987                        certIdx = idx + (word32)certSz;
 6988
 6989                        for (i = 1; i < MAX_PKCS7_CERTS &&
 6990                                certIdx + 1 < pkiMsg2Sz &&
 6991                                certIdx + 1 < (word32)length; i++) {
 6992                            localIdx = certIdx;
 6993
 6994                            if (ret == 0 && GetASNTag(pkiMsg2, &certIdx, &tag,
 6995                                        pkiMsg2Sz) < 0) {
 6996                                ret = ASN_PARSE_E;
 6997                                break;
 6998                            }
 6999
 7000                            if (ret == 0 &&
 7001                                    tag == (ASN_CONSTRUCTED | ASN_SEQUENCE)) {
 7002                                if (GetLength(pkiMsg2, &certIdx, &sz,
 7003                                            pkiMsg2Sz) < 0) {
 7004                                    ret = ASN_PARSE_E;
 7005                                    break;
 7006                                }
 7007
 7008                                pkcs7->cert[i]   = &pkiMsg2[localIdx];
 7009                                pkcs7->certSz[i] = (word32)sz +
 7010                                                   (certIdx - localIdx);
 7011                                certIdx += (word32)sz;
 7012                            }
 7013                        }
 7014                    }
 7015                }
 7016                idx += (word32)length;
 7017
 7018            if (!detached) {
 7019                /* set content and size after init of PKCS7 structure */
 7020                pkcs7->content   = content;
 7021                pkcs7->contentSz = (word32)contentSz;
 7022            }
 7023
 7024            idx = certIdx2 + (word32)length;
 7025
 7026            if (ret != 0) {
 7027                break;
 7028            }
 7029        #ifndef NO_PKCS7_STREAM
 7030            /* factor in that recent idx was in cert buffer. If in2 buffer was
 7031             * used then don't advance idx. */
 7032            if (length > 0 && pkcs7->stream->flagOne &&
 7033                    pkcs7->stream->length == 0) {
 7034                idx = stateIdx + idx;
 7035                if (idx > inSz) {
 7036                    /* index is more than input size */
 7037                    ret = BUFFER_E;
 7038                    break;
 7039                }
 7040            }
 7041            if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) {
 7042                break;
 7043            }
 7044
 7045            pkcs7->stream->expected = MAX_OID_SZ + ASN_TAG_SZ + MAX_LENGTH_SZ +
 7046                                      MAX_SET_SZ;
 7047            /* if certificate set has indef-length, there maybe trailing zeros.
 7048             * add expected size to include size of zeros. */
 7049            if (pkcs7->stream->cntIdfCnt > 0) {
 7050                pkcs7->stream->expected += (word32)pkcs7->stream->cntIdfCnt * 2;
 7051            }
 7052
 7053            if (pkcs7->stream->expected > (pkcs7->stream->maxLen -
 7054                                pkcs7->stream->totalRd) + pkcs7->stream->length)
 7055                pkcs7->stream->expected = (pkcs7->stream->maxLen -
 7056                                pkcs7->stream->totalRd) + pkcs7->stream->length;
 7057
 7058            wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz,  0, 0);
 7059            wc_PKCS7_StreamStoreVar(pkcs7, pkiMsg2Sz, 0, length);
 7060        #endif
 7061            wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE6);
 7062            FALL_THROUGH;
 7063
 7064        case WC_PKCS7_VERIFY_STAGE6:
 7065        #ifndef NO_PKCS7_STREAM
 7066
 7067            if (in2 && in2Sz > 0) {
 7068                src     = in2;
 7069                srcSz   = in2Sz;
 7070                pkiMsg2 = in2;
 7071            }
 7072            else {
 7073                src     = in;
 7074                srcSz   = inSz;
 7075                pkiMsg2 = in;
 7076            }
 7077            if ((ret = wc_PKCS7_AddDataToStream(pkcs7, src, srcSz,
 7078                            pkcs7->stream->expected, &pkiMsg2, &idx)) != 0) {
 7079                break;
 7080            }
 7081            wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, 0, &length);
 7082
 7083            /* check if using internal stream buffer and should adjust sz */
 7084            pkiMsg2Sz = (pkcs7->stream->length > 0)? pkcs7->stream->length:
 7085                                                                        srcSz;
 7086
 7087            /* restore content type */
 7088            contentType   = pkcs7->stream->nonce;
 7089            contentTypeSz = pkcs7->stream->nonceSz;
 7090
 7091            maxIdx = idx + pkcs7->stream->expected;
 7092            if (maxIdx > pkiMsg2Sz) {
 7093                ret = BUFFER_E;
 7094                break;
 7095            }
 7096            stateIdx = idx;
 7097        #else
 7098            /* if not streaming, maxIdx is just pkiMsg2Sz */
 7099            maxIdx = pkiMsg2Sz;
 7100        #endif
 7101
 7102            /* set contentType and size after init of PKCS7 structure */
 7103            if (ret == 0 && wc_PKCS7_SetContentType(pkcs7, contentType,
 7104                        contentTypeSz) < 0)
 7105                ret = ASN_PARSE_E;
 7106        #ifndef NO_PKCS7_STREAM
 7107            /* prior to find set of crls, remove trailing zeros of
 7108             * set of certificates */
 7109            if (ret == 0 && pkcs7->stream->cntIdfCnt > 0) {
 7110                word32 i;
 7111                word32 sz = (word32)pkcs7->stream->cntIdfCnt * ASN_INDEF_END_SZ;
 7112                localIdx = idx;
 7113                for (i = 0; i < sz; i++) {
 7114                    if (localIdx + i >= pkiMsg2Sz) {
 7115                        ret = ASN_PARSE_E;
 7116                        break;
 7117                    }
 7118                    if (pkiMsg2[localIdx + i] == 0)
 7119                        continue;
 7120                    else {
 7121                        ret = ASN_PARSE_E;
 7122                        break;
 7123                    }
 7124                }
 7125                if (ret == 0) {
 7126                    idx += (word32)pkcs7->stream->cntIdfCnt * ASN_INDEF_END_SZ;
 7127                    pkcs7->stream->cntIdfCnt = 0;
 7128                }
 7129            }
 7130        #endif /* !NO_PKCS7_STREAM */
 7131            /* Get the implicit[1] set of crls */
 7132            if (ret == 0 && idx >= maxIdx)
 7133                ret = BUFFER_E;
 7134
 7135            localIdx = idx;
 7136            if (ret == 0 && GetASNTag(pkiMsg2, &localIdx, &tag, pkiMsg2Sz) == 0
 7137                    && tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) {
 7138                idx++;
 7139                if (GetLength(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0)
 7140                    ret = ASN_PARSE_E;
 7141
 7142                /* Skip the set */
 7143                idx += (word32)length;
 7144            }
 7145
 7146            /* Get the set of signerInfos */
 7147            if (ret == 0 && GetSet_ex(pkiMsg2, &idx, &length, maxIdx,
 7148                        NO_USER_CHECK) < 0)
 7149                ret = ASN_PARSE_E;
 7150
 7151            /* Update degenerate flag based on if signerInfos SET is empty.
 7152             * The earlier degenerate check at digestAlgorithms is an early
 7153             * optimization, but depending on degenerate case may not be
 7154             * detected until here. */
 7155            if (ret == 0) {
 7156                degenerate = (length == 0) ? 1 : 0;
 7157            #ifndef NO_PKCS7_STREAM
 7158                pkcs7->stream->degenerate = (degenerate != 0);
 7159            #endif
 7160            }
 7161
 7162            if (ret != 0)
 7163                break;
 7164        #ifndef NO_PKCS7_STREAM
 7165            if (!pkcs7->stream->flagOne) {
 7166                stateIdx = idx; /* didn't read any from internal buffer */
 7167            }
 7168            if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) {
 7169                break;
 7170            }
 7171            wc_PKCS7_StreamStoreVar(pkcs7, pkiMsg2Sz, 0, length);
 7172
 7173            if (in2 && in2Sz > 0 && hashBuf && hashSz > 0) {
 7174                if (length > 0) {
 7175                    pkcs7->stream->expected = (word32)length;
 7176                }
 7177                else {
 7178                    pkcs7->stream->expected = 0;
 7179                }
 7180            }
 7181            else {
 7182                /* last state expect the rest of the buffer */
 7183                pkcs7->stream->expected = (pkcs7->stream->maxLen -
 7184                    pkcs7->stream->totalRd) + pkcs7->stream->length;
 7185            }
 7186            /* In case of indefinite length used in the bundle, terminating
 7187             * zero's should exist at the end of the bundle.
 7188             */
 7189            if (pkcs7->stream->indefLen == 1) {
 7190                pkcs7->stream->expected = (word32)length + 3 * ASN_INDEF_END_SZ;
 7191            }
 7192            else  {
 7193                pkcs7->stream->expected = (word32)length;
 7194            }
 7195
 7196            wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE7);
 7197        #endif /* !NO_PKCS7_STREAM */
 7198            FALL_THROUGH;
 7199
 7200        case WC_PKCS7_VERIFY_STAGE7:
 7201        #ifndef NO_PKCS7_STREAM
 7202            if (in2 && in2Sz > 0) {
 7203                src     = in2;
 7204                srcSz   = in2Sz;
 7205                pkiMsg2 = in2;
 7206            }
 7207            else {
 7208                src     = in;
 7209                srcSz   = inSz;
 7210                pkiMsg2 = in;
 7211            }
 7212            if ((ret = wc_PKCS7_AddDataToStream(pkcs7, src, srcSz,
 7213                            pkcs7->stream->expected, &pkiMsg2, &idx)) != 0) {
 7214                break;
 7215            }
 7216
 7217            wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, 0, &length);
 7218            pkiMsg2Sz = (pkcs7->stream->length > 0)? pkcs7->stream->length:
 7219                                                                        srcSz;
 7220            degenerate = pkcs7->stream->degenerate;
 7221
 7222            /* restore content */
 7223            content   = pkcs7->stream->content;
 7224            contentSz = (int)pkcs7->stream->contentSz;
 7225        #endif
 7226
 7227            ret = wc_PKCS7_ParseSignerInfo(pkcs7, pkiMsg2, pkiMsg2Sz, &idx,
 7228                    degenerate, &signedAttrib, &signedAttribSz);
 7229
 7230            /* parse out the signature if present and verify it */
 7231            if (ret == 0 && length > 0 && degenerate == 0) {
 7232                WOLFSSL_MSG("Parsing signature and verifying");
 7233                if (idx >= pkiMsg2Sz)
 7234                    ret = BUFFER_E;
 7235
 7236                /* Get the signature */
 7237                localIdx = idx;
 7238                if (ret == 0 && GetASNTag(pkiMsg2, &localIdx, &tag,
 7239                            pkiMsg2Sz) == 0 && tag == ASN_OCTET_STRING) {
 7240                    idx++;
 7241
 7242                    if (GetLength(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0)
 7243                        ret = ASN_PARSE_E;
 7244
 7245                    /* save pointer and length */
 7246                    sig = &pkiMsg2[idx];
 7247                    sigSz = length;
 7248
 7249                    idx += (word32)length;
 7250                }
 7251                else if (ret == 0) {
 7252                    ret = ASN_PARSE_E;
 7253                }
 7254
 7255                pkcs7->content = content;
 7256                pkcs7->contentSz = (word32)contentSz;
 7257
 7258                if (ret == 0) {
 7259                #if !defined(NO_PKCS7_STREAM) && defined(ASN_BER_TO_DER)
 7260                    byte streamHash[WC_MAX_DIGEST_SIZE];
 7261
 7262                    /* get final hash if having done hash updates while
 7263                     * streaming out the content */
 7264                    if (pkcs7->streamOutCb) {
 7265                        ret = wc_HashFinal(&pkcs7->stream->hashAlg,
 7266                            pkcs7->stream->hashType, streamHash);
 7267                        hashBuf = streamHash;
 7268                        length  = wc_HashGetDigestSize(pkcs7->stream->hashType);
 7269                        if (length < 0) {
 7270                            WOLFSSL_MSG("Error getting digest size");
 7271                            ret = ASN_PARSE_E;
 7272                        }
 7273                        else {
 7274                            hashSz = (word32)length;
 7275                        }
 7276                        wc_HashFree(&pkcs7->stream->hashAlg,
 7277                            pkcs7->stream->hashType);
 7278                        if (ret != 0)
 7279                            break;
 7280                    }
 7281                #endif /* !NO_PKCS7_STREAM && ASN_BER_TO_DER */
 7282                    ret = wc_PKCS7_SignedDataVerifySignature(pkcs7, sig,
 7283                            (word32)sigSz, signedAttrib, (word32)signedAttribSz,
 7284                                                   hashBuf, hashSz);
 7285                }
 7286            }
 7287
 7288        #ifndef NO_PKCS7_STREAM
 7289            /* make sure that terminating zero's follow */
 7290            if ((ret == WC_NO_ERR_TRACE(PKCS7_SIGNEEDS_CHECK) || ret >= 0) &&
 7291                    pkcs7->stream->indefLen == 1) {
 7292                if (idx + (3 * ASN_INDEF_END_SZ) > pkiMsg2Sz) {
 7293                    ret = ASN_PARSE_E;
 7294                }
 7295                else {
 7296                    word32 i;
 7297                    for (i = 0; i < 3 * ASN_INDEF_END_SZ; i++) {
 7298                        if (pkiMsg2[idx + i] != 0) {
 7299                            ret = ASN_PARSE_E;
 7300                            break;
 7301                        }
 7302                    }
 7303                }
 7304            }
 7305        #endif /* NO_PKCS7_STREAM */
 7306
 7307            if (ret < 0)
 7308                break;
 7309
 7310
 7311            ret = 0; /* success */
 7312        #ifndef NO_PKCS7_STREAM
 7313            wc_PKCS7_ResetStream(pkcs7);
 7314        #endif
 7315            wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START);
 7316            break;
 7317
 7318        default:
 7319            WOLFSSL_MSG("PKCS7 Unknown verify state");
 7320            ret = BAD_FUNC_ARG;
 7321    }
 7322
 7323    if (ret != 0 && ret != WC_NO_ERR_TRACE(WC_PKCS7_WANT_READ_E)) {
 7324    #ifndef NO_PKCS7_STREAM
 7325        wc_PKCS7_ResetStream(pkcs7);
 7326    #endif
 7327        wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START);
 7328    }
 7329    return ret;
 7330}
 7331
 7332
 7333/* Gets a copy of the SID parsed from signerInfo. This can be called after
 7334 * wc_PKCS7_VerifySignedData has been called. SID can be SKID in version 3 case
 7335 * or issuerAndSerialNumber.
 7336 *
 7337 * return 0 on success and LENGTH_ONLY_E if just setting "outSz" for buffer
 7338 *  length needed.
 7339 */
 7340int wc_PKCS7_GetSignerSID(wc_PKCS7* pkcs7, byte* out, word32* outSz)
 7341{
 7342    if (outSz == NULL || pkcs7 == NULL) {
 7343        return BAD_FUNC_ARG;
 7344    }
 7345
 7346    if (pkcs7->signerInfo == NULL) {
 7347        WOLFSSL_MSG("Either the bundle had no signers or"
 7348                "wc_PKCS7_VerifySignedData needs called yet");
 7349        return PKCS7_NO_SIGNER_E;
 7350    }
 7351
 7352    if (pkcs7->signerInfo->sidSz == 0) {
 7353        WOLFSSL_MSG("Bundle had no signer SID set");
 7354        return PKCS7_NO_SIGNER_E;
 7355    }
 7356
 7357    if (out == NULL) {
 7358        *outSz = pkcs7->signerInfo->sidSz;
 7359        return WC_NO_ERR_TRACE(LENGTH_ONLY_E);
 7360    }
 7361
 7362    if (*outSz < pkcs7->signerInfo->sidSz) {
 7363        WOLFSSL_MSG("Buffer being passed in is not large enough for SKID");
 7364        return BUFFER_E;
 7365    }
 7366    XMEMCPY(out, pkcs7->signerInfo->sid, pkcs7->signerInfo->sidSz);
 7367    *outSz = pkcs7->signerInfo->sidSz;
 7368    return 0;
 7369}
 7370
 7371
 7372/* SignedData verification function variant that allows pre-computed content
 7373 * message digest and optional PKCS7/CMS bundle content header/footer to be
 7374 * used for verification. Useful for large data signing.
 7375 *
 7376 * pkcs7 - pointer to initialized PKCS7 structure
 7377 * hashBuf - message digest of content
 7378 * hashSz - size of hashBuf, octets
 7379 * pkiMsgHead - PKCS7/CMS header that goes on top of the raw data signed,
 7380 *              as output from wc_PKCS7_EncodeSignedData_ex (if also using
 7381 *              pkiMsgFoot). Otherwise, PKCS7/CMS bundle with
 7382 *              detached signature - will use hashBuf/hashSz to verify.
 7383 * pkiMsgHeadSz - size of pkiMsgHead, octets
 7384 * pkiMsgFoot - PKCS7/CMS footer that goes at the end of the raw data signed,
 7385 *              as output from wc_PKCS7_EncodeSignedData_ex. Can be NULL
 7386 *              if pkiMsgHead is a direct detached signature bundle to be used
 7387 *              with hashBuf/hashSz.
 7388 * pkiMsgFootSz - size of pkiMsgFoot, octets. Should be 0 if pkiMsgFoot is NULL.
 7389 *
 7390 * Returns 0 on success, negative upon error.
 7391 *
 7392 */
 7393int wc_PKCS7_VerifySignedData_ex(wc_PKCS7* pkcs7, const byte* hashBuf,
 7394    word32 hashSz, byte* pkiMsgHead, word32 pkiMsgHeadSz, byte* pkiMsgFoot,
 7395    word32 pkiMsgFootSz)
 7396{
 7397    return PKCS7_VerifySignedData(pkcs7, hashBuf, hashSz,
 7398        pkiMsgHead, pkiMsgHeadSz, pkiMsgFoot, pkiMsgFootSz);
 7399}
 7400
 7401int wc_PKCS7_VerifySignedData(wc_PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz)
 7402{
 7403    return PKCS7_VerifySignedData(pkcs7, NULL, 0, pkiMsg, pkiMsgSz, NULL, 0);
 7404}
 7405
 7406
 7407/* Generate random content encryption key, store into pkcs7->cek and
 7408 * pkcs7->cekSz.
 7409 *
 7410 * pkcs7 - pointer to initialized PKCS7 structure
 7411 * len   - length of key to be generated
 7412 *
 7413 * Returns 0 on success, negative upon error */
 7414static int PKCS7_GenerateContentEncryptionKey(wc_PKCS7* pkcs7, word32 len)
 7415{
 7416    int ret;
 7417    WC_RNG rng;
 7418    byte* tmpKey;
 7419
 7420    if (pkcs7 == NULL || len == 0)
 7421        return BAD_FUNC_ARG;
 7422
 7423    /* if key already exists, don't need to re-generate */
 7424    if (pkcs7->cek != NULL && pkcs7->cekSz != 0) {
 7425
 7426        /* if key exists, but is different size, return error */
 7427        if (pkcs7->cekSz != len) {
 7428            WOLFSSL_MSG("Random content-encryption key size is inconsistent "
 7429                        "between CMS recipients");
 7430            return WC_KEY_SIZE_E;
 7431        }
 7432
 7433        return 0;
 7434    }
 7435
 7436    /* allocate space for cek */
 7437    tmpKey = (byte*)XMALLOC(len, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 7438    if (tmpKey == NULL)
 7439        return MEMORY_E;
 7440
 7441    XMEMSET(tmpKey, 0, len);
 7442
 7443    ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId);
 7444    if (ret != 0) {
 7445        XFREE(tmpKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 7446        return ret;
 7447    }
 7448
 7449    ret = wc_RNG_GenerateBlock(&rng, tmpKey, len);
 7450    if (ret != 0) {
 7451        wc_FreeRng(&rng);
 7452        XFREE(tmpKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 7453        return ret;
 7454    }
 7455
 7456    /* store into PKCS7, memory freed during final cleanup */
 7457    pkcs7->cek = tmpKey;
 7458    pkcs7->cekSz = len;
 7459
 7460    wc_FreeRng(&rng);
 7461
 7462    return 0;
 7463}
 7464
 7465
 7466/* wrap CEK (content encryption key) with KEK, returns output size (> 0) on
 7467 * success, < 0 on error */
 7468static int wc_PKCS7_KeyWrap(const wc_PKCS7 * pkcs7, const byte * cek,
 7469        word32 cekSz, const byte * kek, word32 kekSz, byte * out, word32 outSz,
 7470        int keyWrapAlgo, int direction)
 7471{
 7472    int ret = 0;
 7473
 7474    if (pkcs7 == NULL || cek == NULL || kek == NULL || out == NULL)
 7475        return BAD_FUNC_ARG;
 7476
 7477    switch (keyWrapAlgo) {
 7478#ifndef NO_AES
 7479    #ifdef WOLFSSL_AES_128
 7480        case AES128_WRAP:
 7481    #endif
 7482    #ifdef WOLFSSL_AES_192
 7483        case AES192_WRAP:
 7484    #endif
 7485    #ifdef WOLFSSL_AES_256
 7486        case AES256_WRAP:
 7487    #endif
 7488
 7489            if (direction == AES_ENCRYPTION) {
 7490                if (pkcs7->aesKeyWrapUnwrapCb != NULL) {
 7491                    ret = pkcs7->aesKeyWrapUnwrapCb(kek, kekSz, cek, cekSz, 1,
 7492                                                    out, outSz);
 7493                }
 7494                else {
 7495                #ifdef HAVE_AES_KEYWRAP
 7496                    ret = wc_AesKeyWrap(kek, kekSz, cek, cekSz,
 7497                                        out, outSz, NULL);
 7498                #else
 7499                    ret = NOT_COMPILED_IN;
 7500                #endif
 7501                }
 7502
 7503            } else if (direction == AES_DECRYPTION) {
 7504                if (pkcs7->aesKeyWrapUnwrapCb != NULL) {
 7505                    ret = pkcs7->aesKeyWrapUnwrapCb(kek, kekSz, cek, cekSz, 0,
 7506                                                    out, outSz);
 7507                }
 7508                else {
 7509                #ifdef HAVE_AES_KEYWRAP
 7510                    ret = wc_AesKeyUnWrap(kek, kekSz, cek, cekSz,
 7511                                          out, outSz, NULL);
 7512                #else
 7513                    ret = NOT_COMPILED_IN;
 7514                #endif
 7515                }
 7516            } else {
 7517                WOLFSSL_MSG("Bad key un/wrap direction");
 7518                return BAD_FUNC_ARG;
 7519            }
 7520
 7521            if (ret <= 0)
 7522                return ret;
 7523            break;
 7524#endif /* NO_AES */
 7525
 7526        default:
 7527            WOLFSSL_MSG("Unsupported key wrap algorithm");
 7528            return BAD_KEYWRAP_ALG_E;
 7529    };
 7530
 7531    (void)cekSz;
 7532    (void)kekSz;
 7533    (void)outSz;
 7534    (void)direction;
 7535    return ret;
 7536}
 7537
 7538
 7539#ifdef HAVE_ECC
 7540
 7541/* KARI == KeyAgreeRecipientInfo (key agreement) */
 7542typedef struct WC_PKCS7_KARI {
 7543    DecodedCert* decoded;          /* decoded recip cert */
 7544    void*    heap;                 /* user heap, points to PKCS7->heap */
 7545    int      devId;                /* device ID for HW based private key */
 7546    ecc_key* recipKey;             /* recip key  (pub | priv) */
 7547    ecc_key* senderKey;            /* sender key (pub | priv) */
 7548    byte*    senderKeyExport;      /* sender ephemeral key DER */
 7549    byte*    kek;                  /* key encryption key */
 7550    byte*    ukm;                  /* OPTIONAL user keying material */
 7551    byte*    sharedInfo;           /* ECC-CMS-SharedInfo ASN.1 encoded blob */
 7552    word32   senderKeyExportSz;    /* size of sender ephemeral key DER */
 7553    word32   kekSz;                /* size of key encryption key */
 7554    word32   ukmSz;                /* size of user keying material */
 7555    word32   sharedInfoSz;         /* size of ECC-CMS-SharedInfo encoded */
 7556    byte     ukmOwner;             /* do we own ukm buffer? 1:yes, 0:no */
 7557    byte     direction;            /* WC_PKCS7_ENCODE | WC_PKCS7_DECODE */
 7558    WC_BITFIELD decodedInit:1;     /* indicates decoded was initialized */
 7559    WC_BITFIELD recipKeyInit:1;    /* indicates recipKey was initialized */
 7560    WC_BITFIELD senderKeyInit:1;   /* indicates senderKey was initialized */
 7561} WC_PKCS7_KARI;
 7562
 7563
 7564/* allocate and create new WC_PKCS7_KARI struct,
 7565 * returns struct pointer on success, NULL on failure */
 7566static WC_PKCS7_KARI* wc_PKCS7_KariNew(wc_PKCS7* pkcs7, byte direction)
 7567{
 7568    WC_PKCS7_KARI* kari = NULL;
 7569
 7570    if (pkcs7 == NULL)
 7571        return NULL;
 7572
 7573    kari = (WC_PKCS7_KARI*)XMALLOC(sizeof(WC_PKCS7_KARI), pkcs7->heap,
 7574                                   DYNAMIC_TYPE_PKCS7);
 7575    if (kari == NULL) {
 7576        WOLFSSL_MSG("Failed to allocate WC_PKCS7_KARI");
 7577        return NULL;
 7578    }
 7579
 7580    kari->decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), pkcs7->heap,
 7581                                          DYNAMIC_TYPE_PKCS7);
 7582    if (kari->decoded == NULL) {
 7583        WOLFSSL_MSG("Failed to allocate DecodedCert");
 7584        XFREE(kari, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 7585        return NULL;
 7586    }
 7587    XMEMSET(kari->decoded, 0, sizeof(DecodedCert));
 7588
 7589    kari->recipKey = (ecc_key*)XMALLOC(sizeof(ecc_key), pkcs7->heap,
 7590                                       DYNAMIC_TYPE_PKCS7);
 7591    if (kari->recipKey == NULL) {
 7592        WOLFSSL_MSG("Failed to allocate recipient ecc_key");
 7593        XFREE(kari->decoded, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 7594        XFREE(kari, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 7595        return NULL;
 7596    }
 7597
 7598    kari->senderKey = (ecc_key*)XMALLOC(sizeof(ecc_key), pkcs7->heap,
 7599                                        DYNAMIC_TYPE_PKCS7);
 7600    if (kari->senderKey == NULL) {
 7601        WOLFSSL_MSG("Failed to allocate sender ecc_key");
 7602        XFREE(kari->recipKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 7603        XFREE(kari->decoded, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 7604        XFREE(kari, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 7605        return NULL;
 7606    }
 7607
 7608    kari->senderKeyExport = NULL;
 7609    kari->senderKeyExportSz = 0;
 7610    kari->kek = NULL;
 7611    kari->kekSz = 0;
 7612    kari->ukm = NULL;
 7613    kari->ukmSz = 0;
 7614    kari->ukmOwner = 0;
 7615    kari->sharedInfo = NULL;
 7616    kari->sharedInfoSz = 0;
 7617    kari->direction = direction;
 7618    kari->decodedInit = 0;
 7619    kari->recipKeyInit = 0;
 7620    kari->senderKeyInit = 0;
 7621
 7622    kari->heap = pkcs7->heap;
 7623    kari->devId = pkcs7->devId;
 7624
 7625    return kari;
 7626}
 7627
 7628
 7629/* free WC_PKCS7_KARI struct, return 0 on success */
 7630static int wc_PKCS7_KariFree(WC_PKCS7_KARI* kari)
 7631{
 7632    void* heap;
 7633
 7634    if (kari) {
 7635        heap = kari->heap;
 7636
 7637        if (kari->decoded) {
 7638            if (kari->decodedInit)
 7639                FreeDecodedCert(kari->decoded);
 7640            XFREE(kari->decoded, heap, DYNAMIC_TYPE_PKCS7);
 7641        }
 7642        if (kari->senderKey) {
 7643            if (kari->senderKeyInit)
 7644                wc_ecc_free(kari->senderKey);
 7645            XFREE(kari->senderKey, heap, DYNAMIC_TYPE_PKCS7);
 7646        }
 7647        if (kari->recipKey) {
 7648            if (kari->recipKeyInit)
 7649                wc_ecc_free(kari->recipKey);
 7650            XFREE(kari->recipKey, heap, DYNAMIC_TYPE_PKCS7);
 7651        }
 7652        if (kari->senderKeyExport) {
 7653            ForceZero(kari->senderKeyExport, kari->senderKeyExportSz);
 7654            XFREE(kari->senderKeyExport, heap, DYNAMIC_TYPE_PKCS7);
 7655            kari->senderKeyExportSz = 0;
 7656        }
 7657        if (kari->kek) {
 7658            ForceZero(kari->kek, kari->kekSz);
 7659            XFREE(kari->kek, heap, DYNAMIC_TYPE_PKCS7);
 7660            kari->kekSz = 0;
 7661        }
 7662        if (kari->ukm) {
 7663            if (kari->ukmOwner == 1) {
 7664                XFREE(kari->ukm, heap, DYNAMIC_TYPE_PKCS7);
 7665            }
 7666            kari->ukmSz = 0;
 7667        }
 7668        if (kari->sharedInfo) {
 7669            ForceZero(kari->sharedInfo, kari->sharedInfoSz);
 7670            XFREE(kari->sharedInfo, heap, DYNAMIC_TYPE_PKCS7);
 7671            kari->sharedInfoSz = 0;
 7672        }
 7673        XFREE(kari, heap, DYNAMIC_TYPE_PKCS7);
 7674    }
 7675
 7676    (void)heap;
 7677
 7678    return 0;
 7679}
 7680
 7681
 7682/* parse recipient cert/key, return 0 on success, negative on error
 7683 * key/keySz only needed during decoding (WC_PKCS7_DECODE) */
 7684static int wc_PKCS7_KariParseRecipCert(WC_PKCS7_KARI* kari, const byte* cert,
 7685                                       word32 certSz, const byte* key,
 7686                                       word32 keySz)
 7687{
 7688    int ret;
 7689    word32 idx;
 7690
 7691    if (kari == NULL || kari->decoded == NULL) {
 7692        return BAD_FUNC_ARG;
 7693    }
 7694
 7695    /* decode certificate */
 7696    if (cert != NULL) {
 7697        InitDecodedCert(kari->decoded, cert, certSz, kari->heap);
 7698        kari->decodedInit = 1;
 7699        ret = ParseCert(kari->decoded, CA_TYPE, NO_VERIFY, 0);
 7700        if (ret < 0)
 7701            return ret;
 7702
 7703        /* only supports ECDSA for now */
 7704        if (kari->decoded->keyOID != ECDSAk) {
 7705            WOLFSSL_MSG("CMS KARI only supports ECDSA key types");
 7706            return BAD_FUNC_ARG;
 7707        }
 7708
 7709        /* make sure subject key id was read from cert */
 7710        if (kari->decoded->extSubjKeyIdSet == 0) {
 7711            WOLFSSL_MSG("Failed to read subject key ID from recipient cert");
 7712            return BAD_FUNC_ARG;
 7713        }
 7714    }
 7715    ret = wc_ecc_init_ex(kari->recipKey, kari->heap, kari->devId);
 7716    if (ret != 0)
 7717        return ret;
 7718
 7719    kari->recipKeyInit = 1;
 7720
 7721    /* get recip public key */
 7722    if (kari->direction == WC_PKCS7_ENCODE) {
 7723        if (cert == NULL) {
 7724            WOLFSSL_MSG("Error recipient cert can not be null with encode");
 7725            return BAD_FUNC_ARG;
 7726        }
 7727
 7728        idx = 0;
 7729        ret = wc_EccPublicKeyDecode(kari->decoded->publicKey, &idx,
 7730                                    kari->recipKey, kari->decoded->pubKeySize);
 7731        if (ret != 0)
 7732            return ret;
 7733    }
 7734    /* get recip private key */
 7735    else if (kari->direction == WC_PKCS7_DECODE) {
 7736        if (key != NULL && keySz > 0) {
 7737            idx = 0;
 7738            ret = wc_EccPrivateKeyDecode(key, &idx, kari->recipKey, keySz);
 7739        }
 7740        else if (kari->devId == INVALID_DEVID) {
 7741            ret = BAD_FUNC_ARG;
 7742        }
 7743        if (ret != 0)
 7744            return ret;
 7745
 7746    } else {
 7747        /* bad direction */
 7748        return BAD_FUNC_ARG;
 7749    }
 7750
 7751    (void)idx;
 7752
 7753    return 0;
 7754}
 7755
 7756
 7757/* create ephemeral ECC key, places ecc_key in kari->senderKey,
 7758 * DER encoded in kari->senderKeyExport. return 0 on success,
 7759 * negative on error */
 7760static int wc_PKCS7_KariGenerateEphemeralKey(WC_PKCS7_KARI* kari)
 7761{
 7762    int ret;
 7763    WC_RNG rng;
 7764
 7765    if (kari == NULL || kari->decoded == NULL ||
 7766        kari->recipKey == NULL || kari->recipKey->dp == NULL)
 7767        return BAD_FUNC_ARG;
 7768
 7769    kari->senderKeyExport = (byte*)XMALLOC(kari->decoded->pubKeySize,
 7770                                           kari->heap, DYNAMIC_TYPE_PKCS7);
 7771    if (kari->senderKeyExport == NULL)
 7772        return MEMORY_E;
 7773
 7774    kari->senderKeyExportSz = kari->decoded->pubKeySize;
 7775
 7776    ret = wc_ecc_init_ex(kari->senderKey, kari->heap, kari->devId);
 7777    if (ret != 0) {
 7778        XFREE(kari->senderKeyExport, kari->heap, DYNAMIC_TYPE_PKCS7);
 7779        kari->senderKeyExportSz = 0;
 7780        kari->senderKeyExport   = NULL;
 7781        return ret;
 7782    }
 7783
 7784    kari->senderKeyInit = 1;
 7785
 7786    ret = wc_InitRng_ex(&rng, kari->heap, kari->devId);
 7787    if (ret != 0) {
 7788        XFREE(kari->senderKeyExport, kari->heap, DYNAMIC_TYPE_PKCS7);
 7789        kari->senderKeyExportSz = 0;
 7790        kari->senderKeyExport   = NULL;
 7791        return ret;
 7792    }
 7793
 7794    ret = wc_ecc_make_key_ex(&rng, kari->recipKey->dp->size,
 7795                             kari->senderKey, kari->recipKey->dp->id);
 7796    if (ret != 0) {
 7797        XFREE(kari->senderKeyExport, kari->heap, DYNAMIC_TYPE_PKCS7);
 7798        kari->senderKeyExportSz = 0;
 7799        kari->senderKeyExport   = NULL;
 7800        wc_FreeRng(&rng);
 7801        return ret;
 7802    }
 7803
 7804    wc_FreeRng(&rng);
 7805
 7806    /* dump generated key to X.963 DER for output in CMS bundle */
 7807    PRIVATE_KEY_UNLOCK();
 7808    ret = wc_ecc_export_x963(kari->senderKey, kari->senderKeyExport,
 7809                             &kari->senderKeyExportSz);
 7810    PRIVATE_KEY_LOCK();
 7811    if (ret != 0) {
 7812        XFREE(kari->senderKeyExport, kari->heap, DYNAMIC_TYPE_PKCS7);
 7813        kari->senderKeyExportSz = 0;
 7814        kari->senderKeyExport   = NULL;
 7815        return ret;
 7816    }
 7817
 7818    return 0;
 7819}
 7820
 7821
 7822/* create ASN.1 encoded ECC-CMS-SharedInfo using specified key wrap algorithm,
 7823 * place in kari->sharedInfo. returns 0 on success, negative on error */
 7824static int wc_PKCS7_KariGenerateSharedInfo(WC_PKCS7_KARI* kari, int keyWrapOID)
 7825{
 7826    int idx = 0;
 7827    int sharedInfoSeqSz = 0;
 7828    int keyInfoSz = 0;
 7829    int suppPubInfoSeqSz = 0;
 7830    int entityUInfoOctetSz = 0;
 7831    int entityUInfoExplicitSz = 0;
 7832    int kekOctetSz = 0;
 7833    int sharedInfoSz = 0;
 7834
 7835    word32 kekBitSz = 0;
 7836
 7837    byte sharedInfoSeq[MAX_SEQ_SZ];
 7838    byte keyInfo[MAX_ALGO_SZ];
 7839    byte suppPubInfoSeq[MAX_SEQ_SZ];
 7840    byte entityUInfoOctet[MAX_OCTET_STR_SZ];
 7841    byte entityUInfoExplicitSeq[MAX_SEQ_SZ];
 7842    byte kekOctet[MAX_OCTET_STR_SZ];
 7843
 7844    if (kari == NULL)
 7845        return BAD_FUNC_ARG;
 7846
 7847    if ((kari->ukmSz > 0) && (kari->ukm == NULL))
 7848        return BAD_FUNC_ARG;
 7849
 7850    /* kekOctet */
 7851    kekOctetSz = (int)SetOctetString(sizeof(word32), kekOctet);
 7852    sharedInfoSz += (kekOctetSz + (int)sizeof(word32));
 7853
 7854    /* suppPubInfo */
 7855    suppPubInfoSeqSz = (int)SetImplicit(ASN_SEQUENCE, 2,
 7856                                        (word32)kekOctetSz + (word32)sizeof(word32),
 7857                                        suppPubInfoSeq, 0);
 7858    sharedInfoSz += suppPubInfoSeqSz;
 7859
 7860    /* optional ukm/entityInfo */
 7861    if (kari->ukmSz > 0) {
 7862        entityUInfoOctetSz = (int)SetOctetString(kari->ukmSz, entityUInfoOctet);
 7863        sharedInfoSz += (entityUInfoOctetSz + (int)kari->ukmSz);
 7864
 7865        entityUInfoExplicitSz = (int)SetExplicit(0,
 7866                                       (word32)entityUInfoOctetSz + kari->ukmSz,
 7867                                       entityUInfoExplicitSeq, 0);
 7868        sharedInfoSz += entityUInfoExplicitSz;
 7869    }
 7870
 7871    /* keyInfo */
 7872    keyInfoSz = (int)SetAlgoID(keyWrapOID, keyInfo, oidKeyWrapType, 0);
 7873    sharedInfoSz += keyInfoSz;
 7874
 7875    /* sharedInfo */
 7876    sharedInfoSeqSz = (int)SetSequence((word32)sharedInfoSz, sharedInfoSeq);
 7877    sharedInfoSz += sharedInfoSeqSz;
 7878
 7879    kari->sharedInfo = (byte*)XMALLOC((word32)sharedInfoSz, kari->heap,
 7880                                      DYNAMIC_TYPE_PKCS7);
 7881    if (kari->sharedInfo == NULL)
 7882        return MEMORY_E;
 7883
 7884    kari->sharedInfoSz = (word32)sharedInfoSz;
 7885
 7886    XMEMCPY(kari->sharedInfo + idx, sharedInfoSeq, (word32)sharedInfoSeqSz);
 7887    idx += sharedInfoSeqSz;
 7888    XMEMCPY(kari->sharedInfo + idx, keyInfo, (word32)keyInfoSz);
 7889    idx += keyInfoSz;
 7890    if (kari->ukmSz > 0) {
 7891        XMEMCPY(kari->sharedInfo + idx, entityUInfoExplicitSeq,
 7892                (word32)entityUInfoExplicitSz);
 7893        idx += entityUInfoExplicitSz;
 7894        XMEMCPY(kari->sharedInfo + idx, entityUInfoOctet,
 7895                (word32)entityUInfoOctetSz);
 7896        idx += entityUInfoOctetSz;
 7897        XMEMCPY(kari->sharedInfo + idx, kari->ukm, kari->ukmSz);
 7898        idx += (int)kari->ukmSz;
 7899    }
 7900    XMEMCPY(kari->sharedInfo + idx, suppPubInfoSeq, (word32)suppPubInfoSeqSz);
 7901    idx += suppPubInfoSeqSz;
 7902    XMEMCPY(kari->sharedInfo + idx, kekOctet, (word32)kekOctetSz);
 7903    idx += kekOctetSz;
 7904
 7905    kekBitSz = (kari->kekSz) * 8;              /* convert to bits */
 7906#ifdef LITTLE_ENDIAN_ORDER
 7907    kekBitSz = ByteReverseWord32(kekBitSz);    /* network byte order */
 7908#endif
 7909    XMEMCPY(kari->sharedInfo + idx, &kekBitSz, sizeof(kekBitSz));
 7910
 7911    return 0;
 7912}
 7913
 7914
 7915/* create key encryption key (KEK) using key wrap algorithm and key encryption
 7916 * algorithm, place in kari->kek. return 0 on success, <0 on error. */
 7917static int wc_PKCS7_KariGenerateKEK(WC_PKCS7_KARI* kari, WC_RNG* rng,
 7918                                    int keyWrapOID, int keyEncOID)
 7919{
 7920    int ret;
 7921    int kSz;
 7922    enum wc_HashType kdfType;
 7923    byte*  secret;
 7924    word32 secretSz;
 7925
 7926    if (kari == NULL || kari->recipKey == NULL ||
 7927        kari->senderKey == NULL || kari->senderKey->dp == NULL)
 7928        return BAD_FUNC_ARG;
 7929
 7930    /* get KEK size, allocate buff */
 7931    kSz = wc_PKCS7_GetOIDKeySize(keyWrapOID);
 7932    if (kSz < 0)
 7933        return kSz;
 7934
 7935    kari->kek = (byte*)XMALLOC((word32)kSz, kari->heap, DYNAMIC_TYPE_PKCS7);
 7936    if (kari->kek == NULL)
 7937        return MEMORY_E;
 7938
 7939    kari->kekSz = (word32)kSz;
 7940
 7941    /* generate ECC-CMS-SharedInfo */
 7942    ret = wc_PKCS7_KariGenerateSharedInfo(kari, keyWrapOID);
 7943    if (ret != 0)
 7944        return ret;
 7945
 7946    /* generate shared secret */
 7947    secretSz = (word32)kari->senderKey->dp->size;
 7948    secret = (byte*)XMALLOC(secretSz, kari->heap, DYNAMIC_TYPE_PKCS7);
 7949    if (secret == NULL)
 7950        return MEMORY_E;
 7951#ifdef WOLFSSL_CHECK_MEM_ZERO
 7952    wc_MemZero_Add("wc_PKCS7_KariGenerateKEK secret", secret, secretSz);
 7953#endif
 7954
 7955#if defined(ECC_TIMING_RESISTANT) && (!defined(HAVE_FIPS) || \
 7956    (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION != 2))) && \
 7957    !defined(HAVE_SELFTEST)
 7958    ret = wc_ecc_set_rng(kari->senderKey, rng);
 7959    if (ret != 0) {
 7960        XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7);
 7961        return ret;
 7962    }
 7963    ret = wc_ecc_set_rng(kari->recipKey, rng);
 7964    if (ret != 0) {
 7965        XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7);
 7966        return ret;
 7967    }
 7968#else
 7969    (void)rng;
 7970#endif
 7971
 7972    if (kari->direction == WC_PKCS7_ENCODE) {
 7973        PRIVATE_KEY_UNLOCK();
 7974        ret = wc_ecc_shared_secret(kari->senderKey, kari->recipKey,
 7975                                   secret, &secretSz);
 7976        PRIVATE_KEY_LOCK();
 7977    } else if (kari->direction == WC_PKCS7_DECODE) {
 7978        PRIVATE_KEY_UNLOCK();
 7979        ret = wc_ecc_shared_secret(kari->recipKey, kari->senderKey,
 7980                                   secret, &secretSz);
 7981        PRIVATE_KEY_LOCK();
 7982    } else {
 7983        /* bad direction */
 7984        XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7);
 7985        return BAD_FUNC_ARG;
 7986    }
 7987
 7988    if (ret != 0) {
 7989        ForceZero(secret, secretSz);
 7990        XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7);
 7991        return ret;
 7992    }
 7993
 7994    /* run through KDF */
 7995    switch (keyEncOID) {
 7996
 7997    #ifndef NO_SHA
 7998        case dhSinglePass_stdDH_sha1kdf_scheme:
 7999            kdfType = WC_HASH_TYPE_SHA;
 8000            break;
 8001    #endif
 8002    #ifdef WOLFSSL_SHA224
 8003        case dhSinglePass_stdDH_sha224kdf_scheme:
 8004            kdfType = WC_HASH_TYPE_SHA224;
 8005            break;
 8006    #endif
 8007    #ifndef NO_SHA256
 8008        case dhSinglePass_stdDH_sha256kdf_scheme:
 8009            kdfType = WC_HASH_TYPE_SHA256;
 8010            break;
 8011    #endif
 8012    #ifdef WOLFSSL_SHA384
 8013        case dhSinglePass_stdDH_sha384kdf_scheme:
 8014            kdfType = WC_HASH_TYPE_SHA384;
 8015            break;
 8016    #endif
 8017    #ifdef WOLFSSL_SHA512
 8018        case dhSinglePass_stdDH_sha512kdf_scheme:
 8019            kdfType = WC_HASH_TYPE_SHA512;
 8020            break;
 8021    #endif
 8022        default:
 8023            WOLFSSL_MSG("Unsupported key agreement algorithm");
 8024            ForceZero(secret, secretSz);
 8025            XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7);
 8026            return BAD_FUNC_ARG;
 8027    };
 8028
 8029#ifdef HAVE_X963_KDF
 8030    ret = wc_X963_KDF(kdfType, secret, secretSz, kari->sharedInfo,
 8031                      kari->sharedInfoSz, kari->kek, kari->kekSz);
 8032#else
 8033    (void)kdfType;
 8034    ret = NOT_COMPILED_IN;
 8035#endif
 8036
 8037    ForceZero(secret, secretSz);
 8038    XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7);
 8039    return ret;
 8040}
 8041
 8042
 8043/* Encode and add CMS EnvelopedData KARI (KeyAgreeRecipientInfo) RecipientInfo
 8044 * to CMS/PKCS#7 EnvelopedData structure.
 8045 *
 8046 * Returns 0 on success, negative upon error */
 8047int wc_PKCS7_AddRecipient_KARI(wc_PKCS7* pkcs7, const byte* cert, word32 certSz,
 8048                               int keyWrapOID, int keyAgreeOID, byte* ukm,
 8049                               word32 ukmSz, int options)
 8050{
 8051    Pkcs7EncodedRecip* recip;
 8052    Pkcs7EncodedRecip* lastRecip = NULL;
 8053    WC_PKCS7_KARI* kari = NULL;
 8054
 8055    word32 idx = 0;
 8056    word32 encryptedKeySz = MAX_ENCRYPTED_KEY_SZ;
 8057
 8058    int ret = 0;
 8059    int keySz, direction = 0;
 8060    int blockKeySz = 0;
 8061    int keyIdSize;
 8062
 8063    /* ASN.1 layout */
 8064    int totalSz = 0;
 8065    int kariSeqSz = 0;
 8066    byte kariSeq[MAX_SEQ_SZ];           /* IMPLICIT [1] */
 8067    int verSz = 0;
 8068    byte ver[MAX_VERSION_SZ];
 8069
 8070    int origIdOrKeySeqSz = 0;
 8071    byte origIdOrKeySeq[MAX_SEQ_SZ];    /* IMPLICIT [0] */
 8072    int origPubKeySeqSz = 0;
 8073    byte origPubKeySeq[MAX_SEQ_SZ];     /* IMPLICIT [1] */
 8074    int origAlgIdSz = 0;
 8075    byte origAlgId[MAX_ALGO_SZ];
 8076    int origPubKeyStrSz = 0;
 8077    byte origPubKeyStr[MAX_OCTET_STR_SZ];
 8078
 8079    /* optional user keying material */
 8080    int ukmOctetSz = 0;
 8081    byte ukmOctetStr[MAX_OCTET_STR_SZ];
 8082    int ukmExplicitSz = 0;
 8083    byte ukmExplicitSeq[MAX_SEQ_SZ];
 8084
 8085    int keyEncryptAlgoIdSz = 0;
 8086    byte keyEncryptAlgoId[MAX_ALGO_SZ];
 8087    int keyWrapAlgSz = 0;
 8088    byte keyWrapAlg[MAX_ALGO_SZ];
 8089
 8090    int recipEncKeysSeqSz = 0;
 8091    byte recipEncKeysSeq[MAX_SEQ_SZ];
 8092    int recipEncKeySeqSz = 0;
 8093    byte recipEncKeySeq[MAX_SEQ_SZ];
 8094    int recipKeyIdSeqSz = 0;
 8095    byte recipKeyIdSeq[MAX_SEQ_SZ];     /* IMPLICIT [0] */
 8096    int subjKeyIdOctetSz = 0;
 8097    byte subjKeyIdOctet[MAX_OCTET_STR_SZ];
 8098    int encryptedKeyOctetSz = 0;
 8099    byte encryptedKeyOctet[MAX_OCTET_STR_SZ];
 8100
 8101#ifdef WOLFSSL_SMALL_STACK
 8102    byte* encryptedKey;
 8103
 8104    encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap,
 8105                                  DYNAMIC_TYPE_TMP_BUFFER);
 8106    if (encryptedKey == NULL) {
 8107        return MEMORY_E;
 8108    }
 8109#else
 8110    byte encryptedKey[MAX_ENCRYPTED_KEY_SZ];
 8111#endif
 8112
 8113#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
 8114    keyIdSize = wc_HashGetDigestSize(wc_HashTypeConvert(HashIdAlg(
 8115           pkcs7->publicKeyOID)));
 8116#else
 8117    keyIdSize = KEYID_SIZE;
 8118#endif
 8119
 8120    /* allocate and init memory for recipient */
 8121    recip = (Pkcs7EncodedRecip*)XMALLOC(sizeof(Pkcs7EncodedRecip), pkcs7->heap,
 8122                                 DYNAMIC_TYPE_PKCS7);
 8123    if (recip == NULL) {
 8124        WC_FREE_VAR_EX(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8125        return MEMORY_E;
 8126    }
 8127    XMEMSET(recip, 0, sizeof(Pkcs7EncodedRecip));
 8128
 8129    /* get key size for content-encryption key based on algorithm */
 8130    blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID);
 8131    if (blockKeySz < 0) {
 8132        WC_FREE_VAR_EX(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8133        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 8134        return blockKeySz;
 8135    }
 8136
 8137    /* generate random content encryption key, if needed */
 8138    ret = PKCS7_GenerateContentEncryptionKey(pkcs7, (word32)blockKeySz);
 8139    if (ret < 0) {
 8140        WC_FREE_VAR_EX(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8141        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 8142        return ret;
 8143    }
 8144
 8145    /* set direction based on keyWrapAlgo */
 8146    switch (keyWrapOID) {
 8147#ifndef NO_AES
 8148    #ifdef WOLFSSL_AES_128
 8149        case AES128_WRAP:
 8150    #endif
 8151    #ifdef WOLFSSL_AES_192
 8152        case AES192_WRAP:
 8153    #endif
 8154    #ifdef WOLFSSL_AES_256
 8155        case AES256_WRAP:
 8156    #endif
 8157            direction = AES_ENCRYPTION;
 8158            break;
 8159#endif
 8160        default:
 8161            WOLFSSL_MSG("Unsupported key wrap algorithm");
 8162            WC_FREE_VAR_EX(encryptedKey, pkcs7->heap,
 8163                DYNAMIC_TYPE_TMP_BUFFER);
 8164            XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 8165            return BAD_KEYWRAP_ALG_E;
 8166    }
 8167
 8168    kari = wc_PKCS7_KariNew(pkcs7, WC_PKCS7_ENCODE);
 8169    if (kari == NULL) {
 8170        WC_FREE_VAR_EX(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8171        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 8172        return MEMORY_E;
 8173    }
 8174
 8175    /* set user keying material if available */
 8176    if (ukmSz > 0 && ukm != NULL) {
 8177        kari->ukm = ukm;
 8178        kari->ukmSz = ukmSz;
 8179        kari->ukmOwner = 0;
 8180    }
 8181
 8182    /* parse recipient cert, get public key */
 8183    ret = wc_PKCS7_KariParseRecipCert(kari, cert, certSz, NULL, 0);
 8184    if (ret != 0) {
 8185        wc_PKCS7_KariFree(kari);
 8186        WC_FREE_VAR_EX(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8187        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 8188        return ret;
 8189    }
 8190
 8191    /* generate sender ephemeral ECC key */
 8192    ret = wc_PKCS7_KariGenerateEphemeralKey(kari);
 8193    if (ret != 0) {
 8194        wc_PKCS7_KariFree(kari);
 8195        WC_FREE_VAR_EX(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8196        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 8197        return ret;
 8198    }
 8199
 8200    /* generate KEK (key encryption key) */
 8201    ret = wc_PKCS7_KariGenerateKEK(kari, pkcs7->rng, keyWrapOID, keyAgreeOID);
 8202    if (ret != 0) {
 8203        wc_PKCS7_KariFree(kari);
 8204        WC_FREE_VAR_EX(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8205        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 8206        return ret;
 8207    }
 8208
 8209    /* encrypt CEK with KEK */
 8210    keySz = wc_PKCS7_KeyWrap(pkcs7, pkcs7->cek, pkcs7->cekSz, kari->kek,
 8211                             kari->kekSz, encryptedKey, encryptedKeySz,
 8212                             keyWrapOID, direction);
 8213    if (keySz <= 0) {
 8214        wc_PKCS7_KariFree(kari);
 8215        WC_FREE_VAR_EX(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8216        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 8217        return keySz;
 8218    }
 8219    encryptedKeySz = (word32)keySz;
 8220
 8221    /* Start of RecipientEncryptedKeys */
 8222
 8223    /* EncryptedKey */
 8224    encryptedKeyOctetSz = (int)SetOctetString(encryptedKeySz,
 8225                                              encryptedKeyOctet);
 8226    totalSz += (encryptedKeyOctetSz + (int)encryptedKeySz);
 8227
 8228    /* SubjectKeyIdentifier */
 8229    subjKeyIdOctetSz = (int)SetOctetString((word32)keyIdSize, subjKeyIdOctet);
 8230    totalSz += (subjKeyIdOctetSz + keyIdSize);
 8231
 8232    /* RecipientKeyIdentifier IMPLICIT [0] */
 8233    recipKeyIdSeqSz = (int)SetImplicit(ASN_SEQUENCE, 0,
 8234                                       (word32)(subjKeyIdOctetSz + keyIdSize),
 8235                                       recipKeyIdSeq, 0);
 8236    totalSz += recipKeyIdSeqSz;
 8237
 8238    /* RecipientEncryptedKey */
 8239    recipEncKeySeqSz = (int)SetSequence((word32)totalSz, recipEncKeySeq);
 8240    totalSz += recipEncKeySeqSz;
 8241
 8242    /* RecipientEncryptedKeys */
 8243    recipEncKeysSeqSz = (int)SetSequence((word32)totalSz, recipEncKeysSeq);
 8244    totalSz += recipEncKeysSeqSz;
 8245
 8246    /* Start of optional UserKeyingMaterial */
 8247
 8248    if (kari->ukmSz > 0) {
 8249        ukmOctetSz = (int)SetOctetString(kari->ukmSz, ukmOctetStr);
 8250        totalSz += (ukmOctetSz + (int)kari->ukmSz);
 8251
 8252        ukmExplicitSz = (int)SetExplicit(1, (word32)ukmOctetSz + kari->ukmSz,
 8253                                    ukmExplicitSeq, 0);
 8254        totalSz += ukmExplicitSz;
 8255    }
 8256
 8257    /* Start of KeyEncryptionAlgorithmIdentifier */
 8258
 8259    /* KeyWrapAlgorithm */
 8260    keyWrapAlgSz = (int)SetAlgoID(keyWrapOID, keyWrapAlg, oidKeyWrapType, 0);
 8261    totalSz += keyWrapAlgSz;
 8262
 8263    /* KeyEncryptionAlgorithmIdentifier */
 8264    keyEncryptAlgoIdSz = (int)SetAlgoID(keyAgreeOID, keyEncryptAlgoId,
 8265                                   oidCmsKeyAgreeType, keyWrapAlgSz);
 8266    totalSz += keyEncryptAlgoIdSz;
 8267
 8268    /* Start of OriginatorIdentifierOrKey */
 8269
 8270    /* recipient ECPoint, public key */
 8271    XMEMSET(origPubKeyStr, 0, sizeof(origPubKeyStr)); /* no unused bits */
 8272    origPubKeyStr[0] = ASN_BIT_STRING;
 8273    origPubKeyStrSz = (int)SetLength(kari->senderKeyExportSz + 1,
 8274                                origPubKeyStr + 1) + 2;
 8275    totalSz += (origPubKeyStrSz + (int)kari->senderKeyExportSz);
 8276
 8277    /* Originator AlgorithmIdentifier, params set to NULL for interop
 8278       compatibility */
 8279    origAlgIdSz = (int)SetAlgoID(ECDSAk, origAlgId, oidKeyType, 2);
 8280    origAlgId[origAlgIdSz++] = ASN_TAG_NULL;
 8281    origAlgId[origAlgIdSz++] = 0;
 8282    totalSz += origAlgIdSz;
 8283
 8284    /* outer OriginatorPublicKey IMPLICIT [1] */
 8285    origPubKeySeqSz = (int)SetImplicit(ASN_SEQUENCE, 1,
 8286                               (word32)(origAlgIdSz + origPubKeyStrSz +
 8287                               (int)kari->senderKeyExportSz), origPubKeySeq, 0);
 8288    totalSz += origPubKeySeqSz;
 8289
 8290    /* outer OriginatorIdentifierOrKey IMPLICIT [0] */
 8291    origIdOrKeySeqSz = (int)SetImplicit(ASN_SEQUENCE, 0,
 8292                                (word32)(origPubKeySeqSz + origAlgIdSz +
 8293                                origPubKeyStrSz + (int)kari->senderKeyExportSz),
 8294                                origIdOrKeySeq, 0);
 8295    totalSz += origIdOrKeySeqSz;
 8296
 8297    /* version, always 3 */
 8298    verSz = SetMyVersion(3, ver, 0);
 8299    totalSz += verSz;
 8300    recip->recipVersion = 3;
 8301
 8302    /* outer IMPLICIT [1] kari */
 8303    kariSeqSz = (int)SetImplicit(ASN_SEQUENCE, 1, (word32)totalSz, kariSeq, 0);
 8304    totalSz += kariSeqSz;
 8305
 8306    if (totalSz > MAX_RECIP_SZ) {
 8307        WOLFSSL_MSG("KeyAgreeRecipientInfo output buffer too small");
 8308        wc_PKCS7_KariFree(kari);
 8309        WC_FREE_VAR_EX(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8310        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 8311        return BUFFER_E;
 8312    }
 8313
 8314    XMEMCPY(recip->recip + idx, kariSeq, (word32)kariSeqSz);
 8315    idx += (word32)kariSeqSz;
 8316    XMEMCPY(recip->recip + idx, ver, (word32)verSz);
 8317    idx += (word32)verSz;
 8318
 8319    XMEMCPY(recip->recip + idx, origIdOrKeySeq, (word32)origIdOrKeySeqSz);
 8320    idx += (word32)origIdOrKeySeqSz;
 8321    XMEMCPY(recip->recip + idx, origPubKeySeq, (word32)origPubKeySeqSz);
 8322    idx += (word32)origPubKeySeqSz;
 8323
 8324    /* AlgorithmIdentifier with NULL parameter */
 8325    XMEMCPY(recip->recip + idx, origAlgId, (word32)origAlgIdSz);
 8326    idx += (word32)origAlgIdSz;
 8327
 8328    XMEMCPY(recip->recip + idx, origPubKeyStr, (word32)origPubKeyStrSz);
 8329    idx += (word32)origPubKeyStrSz;
 8330    /* ephemeral public key */
 8331    XMEMCPY(recip->recip + idx, kari->senderKeyExport, kari->senderKeyExportSz);
 8332    idx += kari->senderKeyExportSz;
 8333
 8334    if (kari->ukmSz > 0) {
 8335        XMEMCPY(recip->recip + idx, ukmExplicitSeq, (word32)ukmExplicitSz);
 8336        idx += (word32)ukmExplicitSz;
 8337        XMEMCPY(recip->recip + idx, ukmOctetStr, (word32)ukmOctetSz);
 8338        idx += (word32)ukmOctetSz;
 8339        XMEMCPY(recip->recip + idx, kari->ukm, kari->ukmSz);
 8340        idx += kari->ukmSz;
 8341    }
 8342
 8343    XMEMCPY(recip->recip + idx, keyEncryptAlgoId, (word32)keyEncryptAlgoIdSz);
 8344    idx += (word32)keyEncryptAlgoIdSz;
 8345    XMEMCPY(recip->recip + idx, keyWrapAlg, (word32)keyWrapAlgSz);
 8346    idx += (word32)keyWrapAlgSz;
 8347
 8348    XMEMCPY(recip->recip + idx, recipEncKeysSeq, (word32)recipEncKeysSeqSz);
 8349    idx += (word32)recipEncKeysSeqSz;
 8350    XMEMCPY(recip->recip + idx, recipEncKeySeq, (word32)recipEncKeySeqSz);
 8351    idx += (word32)recipEncKeySeqSz;
 8352    XMEMCPY(recip->recip + idx, recipKeyIdSeq, (word32)recipKeyIdSeqSz);
 8353    idx += (word32)recipKeyIdSeqSz;
 8354    XMEMCPY(recip->recip + idx, subjKeyIdOctet, (word32)subjKeyIdOctetSz);
 8355    idx += (word32)subjKeyIdOctetSz;
 8356    /* subject key id */
 8357    XMEMCPY(recip->recip + idx, kari->decoded->extSubjKeyId, (word32)keyIdSize);
 8358    idx += (word32)keyIdSize;
 8359    XMEMCPY(recip->recip + idx, encryptedKeyOctet, (word32)encryptedKeyOctetSz);
 8360    idx += (word32)encryptedKeyOctetSz;
 8361    /* encrypted CEK */
 8362    XMEMCPY(recip->recip + idx, encryptedKey, encryptedKeySz);
 8363    idx += encryptedKeySz;
 8364
 8365    wc_PKCS7_KariFree(kari);
 8366    WC_FREE_VAR_EX(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8367
 8368    /* store recipient size */
 8369    recip->recipSz = idx;
 8370    recip->recipType = PKCS7_KARI;
 8371
 8372    /* add recipient to recip list */
 8373    if (pkcs7->recipList == NULL) {
 8374        pkcs7->recipList = recip;
 8375    } else {
 8376        lastRecip = pkcs7->recipList;
 8377        while (lastRecip->next != NULL) {
 8378            lastRecip = lastRecip->next;
 8379        }
 8380        lastRecip->next = recip;
 8381    }
 8382
 8383    (void)options;
 8384
 8385    return (int)idx;
 8386}
 8387
 8388#endif /* HAVE_ECC */
 8389
 8390#ifndef NO_RSA
 8391
 8392/* Encode and add CMS EnvelopedData KTRI (KeyTransRecipientInfo) RecipientInfo
 8393 * to CMS/PKCS#7 EnvelopedData structure.
 8394 *
 8395 * Returns 0 on success, negative upon error */
 8396int wc_PKCS7_AddRecipient_KTRI(wc_PKCS7* pkcs7, const byte* cert, word32 certSz,
 8397                               int options)
 8398{
 8399    Pkcs7EncodedRecip* recip = NULL;
 8400    Pkcs7EncodedRecip* lastRecip = NULL;
 8401
 8402    WC_RNG rng;
 8403    word32 idx = 0;
 8404    word32 encryptedKeySz = 0;
 8405    int keyIdSize;
 8406
 8407    int ret = 0, blockKeySz;
 8408    int verSz = 0, issuerSz = 0, snSz = 0, keyEncAlgSz = 0;
 8409    int issuerSeqSz = 0, recipSeqSz = 0, issuerSerialSeqSz = 0;
 8410    int encKeyOctetStrSz;
 8411    int sidType;
 8412
 8413    byte ver[MAX_VERSION_SZ];
 8414    byte issuerSerialSeq[MAX_SEQ_SZ];
 8415    byte recipSeq[MAX_SEQ_SZ];
 8416    byte issuerSeq[MAX_SEQ_SZ];
 8417    byte encKeyOctetStr[MAX_OCTET_STR_SZ];
 8418
 8419    byte issuerSKID[MAX_LENGTH_SZ];
 8420    word32 issuerSKIDSz = 0;
 8421
 8422    byte*   encryptedKey;
 8423
 8424#ifdef WOLFSSL_SMALL_STACK
 8425    byte*   serial;
 8426    byte*   keyAlgArray;
 8427    RsaKey* pubKey;
 8428    DecodedCert* decoded;
 8429
 8430    serial = (byte*)XMALLOC(MAX_SN_SZ, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8431    keyAlgArray = (byte*)XMALLOC(MAX_ALGO_SZ, pkcs7->heap,
 8432                                 DYNAMIC_TYPE_TMP_BUFFER);
 8433    decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), pkcs7->heap,
 8434                                    DYNAMIC_TYPE_TMP_BUFFER);
 8435
 8436    if (decoded == NULL || serial == NULL || keyAlgArray == NULL) {
 8437        XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8438        XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8439        XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8440        return MEMORY_E;
 8441    }
 8442#else
 8443    byte serial[MAX_SN_SZ];
 8444    byte keyAlgArray[MAX_ALGO_SZ];
 8445    RsaKey pubKey[1];
 8446    DecodedCert decoded[1];
 8447#endif
 8448
 8449    /* Always allocate to ensure aligned use with RSA */
 8450    encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap,
 8451                                  DYNAMIC_TYPE_WOLF_BIGINT);
 8452    if (encryptedKey == NULL) {
 8453        WC_FREE_VAR_EX(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8454        WC_FREE_VAR_EX(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8455        WC_FREE_VAR_EX(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8456        return MEMORY_E;
 8457    }
 8458
 8459    encryptedKeySz = MAX_ENCRYPTED_KEY_SZ;
 8460    XMEMSET(encryptedKey, 0, encryptedKeySz);
 8461
 8462    /* default to IssuerAndSerialNumber if not set */
 8463    if (pkcs7->sidType != 0) {
 8464        sidType = pkcs7->sidType;
 8465    } else {
 8466        sidType = CMS_ISSUER_AND_SERIAL_NUMBER;
 8467    }
 8468
 8469    /* allow options to override SubjectIdentifier type if set */
 8470    if (options & CMS_SKID) {
 8471        sidType = CMS_SKID;
 8472    } else if (options & CMS_ISSUER_AND_SERIAL_NUMBER) {
 8473        sidType = CMS_ISSUER_AND_SERIAL_NUMBER;
 8474    }
 8475
 8476    /* allocate recipient struct */
 8477    recip = (Pkcs7EncodedRecip*)XMALLOC(sizeof(Pkcs7EncodedRecip), pkcs7->heap,
 8478                                 DYNAMIC_TYPE_PKCS7);
 8479    if (recip == NULL) {
 8480        WC_FREE_VAR_EX(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8481        WC_FREE_VAR_EX(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8482        WC_FREE_VAR_EX(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8483        XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_WOLF_BIGINT);
 8484        return MEMORY_E;
 8485    }
 8486    XMEMSET(recip, 0, sizeof(Pkcs7EncodedRecip));
 8487
 8488    /* get key size for content-encryption key based on algorithm */
 8489    blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID);
 8490    if (blockKeySz < 0) {
 8491        WC_FREE_VAR_EX(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8492        WC_FREE_VAR_EX(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8493        WC_FREE_VAR_EX(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8494        XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_WOLF_BIGINT);
 8495        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 8496        return blockKeySz;
 8497    }
 8498
 8499    /* generate random content encryption key, if needed */
 8500    ret = PKCS7_GenerateContentEncryptionKey(pkcs7, (word32)blockKeySz);
 8501    if (ret < 0) {
 8502        WC_FREE_VAR_EX(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8503        WC_FREE_VAR_EX(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8504        WC_FREE_VAR_EX(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8505        XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_WOLF_BIGINT);
 8506        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 8507        return ret;
 8508    }
 8509
 8510    InitDecodedCert(decoded, cert, certSz, pkcs7->heap);
 8511    ret = ParseCert(decoded, CA_TYPE, NO_VERIFY, 0);
 8512    if (ret < 0) {
 8513        FreeDecodedCert(decoded);
 8514        WC_FREE_VAR_EX(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8515        WC_FREE_VAR_EX(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8516        WC_FREE_VAR_EX(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8517        XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_WOLF_BIGINT);
 8518        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 8519        return ret;
 8520    }
 8521
 8522#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
 8523    keyIdSize = wc_HashGetDigestSize(wc_HashTypeConvert(HashIdAlg(
 8524           decoded->signatureOID)));
 8525#else
 8526    keyIdSize = KEYID_SIZE;
 8527#endif
 8528
 8529    if (sidType == CMS_ISSUER_AND_SERIAL_NUMBER) {
 8530
 8531        /* version, must be 0 for IssuerAndSerialNumber */
 8532        verSz = SetMyVersion(0, ver, 0);
 8533        recip->recipVersion = 0;
 8534
 8535        /* IssuerAndSerialNumber */
 8536        if (decoded->issuerRaw == NULL || decoded->issuerRawLen == 0) {
 8537            WOLFSSL_MSG("DecodedCert lacks raw issuer pointer and length");
 8538            FreeDecodedCert(decoded);
 8539            WC_FREE_VAR_EX(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8540            WC_FREE_VAR_EX(keyAlgArray, pkcs7->heap,
 8541                DYNAMIC_TYPE_TMP_BUFFER);
 8542            WC_FREE_VAR_EX(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8543            XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_WOLF_BIGINT);
 8544            XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 8545            return -1;
 8546        }
 8547        issuerSz    = decoded->issuerRawLen;
 8548        issuerSeqSz = (int)SetSequence((word32)issuerSz, issuerSeq);
 8549
 8550        if (decoded->serialSz == 0) {
 8551            WOLFSSL_MSG("DecodedCert missing serial number");
 8552            FreeDecodedCert(decoded);
 8553            WC_FREE_VAR_EX(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8554            WC_FREE_VAR_EX(keyAlgArray, pkcs7->heap,
 8555                DYNAMIC_TYPE_TMP_BUFFER);
 8556            WC_FREE_VAR_EX(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8557            XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_WOLF_BIGINT);
 8558            XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 8559            return -1;
 8560        }
 8561        snSz = SetSerialNumber(decoded->serial, (word32)decoded->serialSz,
 8562                               serial, MAX_SN_SZ, MAX_SN_SZ);
 8563        if (snSz < 0) {
 8564            WOLFSSL_MSG("Error setting the serial number");
 8565            FreeDecodedCert(decoded);
 8566            WC_FREE_VAR_EX(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8567            WC_FREE_VAR_EX(keyAlgArray, pkcs7->heap,
 8568                DYNAMIC_TYPE_TMP_BUFFER);
 8569            WC_FREE_VAR_EX(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8570            XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_WOLF_BIGINT);
 8571            XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 8572            return -1;
 8573        }
 8574        issuerSerialSeqSz = (int)SetSequence((word32)(issuerSeqSz + issuerSz +
 8575                                             snSz), issuerSerialSeq);
 8576    } else if (sidType == CMS_SKID) {
 8577
 8578        /* version, must be 2 for SubjectKeyIdentifier */
 8579        verSz = SetMyVersion(2, ver, 0);
 8580        recip->recipVersion = 2;
 8581
 8582        issuerSKIDSz = SetLength((word32)keyIdSize, issuerSKID);
 8583    } else {
 8584        FreeDecodedCert(decoded);
 8585        WC_FREE_VAR_EX(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8586        WC_FREE_VAR_EX(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8587        WC_FREE_VAR_EX(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8588        XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_WOLF_BIGINT);
 8589        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 8590        return PKCS7_RECIP_E;
 8591    }
 8592
 8593    pkcs7->publicKeyOID = decoded->keyOID;
 8594
 8595    /* KeyEncryptionAlgorithmIdentifier, only support RSA now */
 8596    if (pkcs7->publicKeyOID != RSAk
 8597#ifdef WC_RSA_PSS
 8598        && pkcs7->publicKeyOID != RSAPSSk
 8599#endif
 8600    ) {
 8601        FreeDecodedCert(decoded);
 8602        WC_FREE_VAR_EX(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8603        WC_FREE_VAR_EX(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8604        WC_FREE_VAR_EX(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8605        XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_WOLF_BIGINT);
 8606        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 8607        return ALGO_ID_E;
 8608    }
 8609
 8610    keyEncAlgSz = (int)SetAlgoID(RSAk, keyAlgArray, oidKeyType, 0);
 8611    if (keyEncAlgSz == 0) {
 8612        FreeDecodedCert(decoded);
 8613        WC_FREE_VAR_EX(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8614        WC_FREE_VAR_EX(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8615        WC_FREE_VAR_EX(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8616        XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_WOLF_BIGINT);
 8617        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 8618        return BAD_FUNC_ARG;
 8619    }
 8620
 8621#ifdef WOLFSSL_SMALL_STACK
 8622    pubKey = (RsaKey*)XMALLOC(sizeof(RsaKey), pkcs7->heap,
 8623            DYNAMIC_TYPE_TMP_BUFFER);
 8624    if (pubKey == NULL) {
 8625        FreeDecodedCert(decoded);
 8626        XFREE(serial,       pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8627        XFREE(keyAlgArray,  pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8628        XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_WOLF_BIGINT);
 8629        XFREE(decoded,      pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8630        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 8631        return MEMORY_E;
 8632    }
 8633#endif
 8634
 8635    /* EncryptedKey */
 8636    ret = wc_InitRsaKey_ex(pubKey, pkcs7->heap, pkcs7->devId);
 8637    if (ret != 0) {
 8638        FreeDecodedCert(decoded);
 8639        WC_FREE_VAR_EX(pubKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8640        WC_FREE_VAR_EX(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8641        WC_FREE_VAR_EX(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8642        WC_FREE_VAR_EX(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8643        XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_WOLF_BIGINT);
 8644        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 8645        return ret;
 8646    }
 8647
 8648    if (wc_RsaPublicKeyDecode(decoded->publicKey, &idx, pubKey,
 8649                              decoded->pubKeySize) < 0) {
 8650        WOLFSSL_MSG("ASN RSA key decode error");
 8651        wc_FreeRsaKey(pubKey);
 8652        FreeDecodedCert(decoded);
 8653        WC_FREE_VAR_EX(pubKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8654        WC_FREE_VAR_EX(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8655        WC_FREE_VAR_EX(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8656        WC_FREE_VAR_EX(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8657        XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_WOLF_BIGINT);
 8658        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 8659        return PUBLIC_KEY_E;
 8660    }
 8661
 8662    ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId);
 8663    if (ret != 0) {
 8664        wc_FreeRsaKey(pubKey);
 8665        FreeDecodedCert(decoded);
 8666        WC_FREE_VAR_EX(pubKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8667        WC_FREE_VAR_EX(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8668        WC_FREE_VAR_EX(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8669        WC_FREE_VAR_EX(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8670        XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_WOLF_BIGINT);
 8671        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 8672        return MEMORY_E;
 8673    }
 8674
 8675
 8676#ifdef WOLFSSL_ASYNC_CRYPT
 8677    /* Currently the call to RSA public encrypt here is blocking @TODO */
 8678    do {
 8679        ret = wc_AsyncWait(ret, &pubKey->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
 8680        if (ret >= 0)
 8681#endif
 8682        {
 8683            ret = wc_RsaPublicEncrypt(pkcs7->cek, pkcs7->cekSz, encryptedKey,
 8684                              encryptedKeySz, pubKey, &rng);
 8685        }
 8686#ifdef WOLFSSL_ASYNC_CRYPT
 8687    } while (ret == WC_NO_ERR_TRACE(WC_PENDING_E));
 8688#endif
 8689    wc_FreeRsaKey(pubKey);
 8690    wc_FreeRng(&rng);
 8691
 8692    WC_FREE_VAR_EX(pubKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8693
 8694    if (ret < 0) {
 8695        WOLFSSL_MSG("RSA Public Encrypt failed");
 8696        FreeDecodedCert(decoded);
 8697        WC_FREE_VAR_EX(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8698        WC_FREE_VAR_EX(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8699        WC_FREE_VAR_EX(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8700        XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_WOLF_BIGINT);
 8701        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 8702        return ret;
 8703    }
 8704    encryptedKeySz = (word32)ret;
 8705
 8706    encKeyOctetStrSz = (int)SetOctetString(encryptedKeySz, encKeyOctetStr);
 8707
 8708    /* RecipientInfo */
 8709    if (sidType == CMS_ISSUER_AND_SERIAL_NUMBER) {
 8710        int recipLen =  verSz + (int)issuerSerialSeqSz + issuerSeqSz +
 8711            issuerSz + snSz + keyEncAlgSz + encKeyOctetStrSz +
 8712            (int)encryptedKeySz;
 8713        recipSeqSz = (int)SetSequence((word32)recipLen, recipSeq);
 8714
 8715        if ((recipSeqSz + recipLen) > MAX_RECIP_SZ) {
 8716            WOLFSSL_MSG("RecipientInfo output buffer too small");
 8717            FreeDecodedCert(decoded);
 8718            WC_FREE_VAR_EX(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8719            WC_FREE_VAR_EX(keyAlgArray, pkcs7->heap,
 8720                DYNAMIC_TYPE_TMP_BUFFER);
 8721            WC_FREE_VAR_EX(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8722            XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_WOLF_BIGINT);
 8723            XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 8724            return BUFFER_E;
 8725        }
 8726
 8727    } else {
 8728        int recipLen =  verSz + ASN_TAG_SZ + (int)issuerSKIDSz + keyIdSize +
 8729                keyEncAlgSz + encKeyOctetStrSz + (int)encryptedKeySz;
 8730        recipSeqSz = (int)SetSequence((word32)recipLen, recipSeq);
 8731        if ((recipSeqSz + recipLen) > MAX_RECIP_SZ) {
 8732            WOLFSSL_MSG("RecipientInfo output buffer too small");
 8733            FreeDecodedCert(decoded);
 8734            WC_FREE_VAR_EX(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8735            WC_FREE_VAR_EX(keyAlgArray, pkcs7->heap,
 8736                DYNAMIC_TYPE_TMP_BUFFER);
 8737            WC_FREE_VAR_EX(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8738            XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_WOLF_BIGINT);
 8739            XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 8740            return BUFFER_E;
 8741        }
 8742    }
 8743
 8744    idx = 0;
 8745    XMEMCPY(recip->recip + idx, recipSeq, (word32)recipSeqSz);
 8746    idx += (word32)recipSeqSz;
 8747    XMEMCPY(recip->recip + idx, ver, (word32)verSz);
 8748    idx += (word32)verSz;
 8749    if (sidType == CMS_ISSUER_AND_SERIAL_NUMBER) {
 8750        XMEMCPY(recip->recip + idx, issuerSerialSeq, (word32)issuerSerialSeqSz);
 8751        idx += (word32)issuerSerialSeqSz;
 8752        XMEMCPY(recip->recip + idx, issuerSeq, (word32)issuerSeqSz);
 8753        idx += (word32)issuerSeqSz;
 8754        XMEMCPY(recip->recip + idx, decoded->issuerRaw, (word32)issuerSz);
 8755        idx += (word32)issuerSz;
 8756        XMEMCPY(recip->recip + idx, serial, (word32)snSz);
 8757        idx += (word32)snSz;
 8758    } else {
 8759        recip->recip[idx] = ASN_CONTEXT_SPECIFIC;
 8760        idx += ASN_TAG_SZ;
 8761        XMEMCPY(recip->recip + idx, issuerSKID, issuerSKIDSz);
 8762        idx += issuerSKIDSz;
 8763        XMEMCPY(recip->recip + idx, pkcs7->issuerSubjKeyId, (word32)keyIdSize);
 8764        idx += (word32)keyIdSize;
 8765    }
 8766    XMEMCPY(recip->recip + idx, keyAlgArray, (word32)keyEncAlgSz);
 8767    idx += (word32)keyEncAlgSz;
 8768    XMEMCPY(recip->recip + idx, encKeyOctetStr, (word32)encKeyOctetStrSz);
 8769    idx += (word32)encKeyOctetStrSz;
 8770    XMEMCPY(recip->recip + idx, encryptedKey, encryptedKeySz);
 8771    idx += encryptedKeySz;
 8772
 8773    FreeDecodedCert(decoded);
 8774
 8775    WC_FREE_VAR_EX(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8776    WC_FREE_VAR_EX(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8777    WC_FREE_VAR_EX(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 8778    XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_WOLF_BIGINT);
 8779
 8780    /* store recipient size */
 8781    recip->recipSz = idx;
 8782    recip->recipType = PKCS7_KTRI;
 8783
 8784    /* add recipient to recip list */
 8785    if (pkcs7->recipList == NULL) {
 8786        pkcs7->recipList = recip;
 8787    } else {
 8788        lastRecip = pkcs7->recipList;
 8789        while (lastRecip->next != NULL) {
 8790            lastRecip = lastRecip->next;
 8791        }
 8792        lastRecip->next = recip;
 8793    }
 8794
 8795    return (int)idx;
 8796}
 8797
 8798#endif /* !NO_RSA */
 8799
 8800/* abstraction for writing out PKCS7 bundle during creation
 8801   returns 0 on success
 8802 */
 8803int wc_PKCS7_WriteOut(wc_PKCS7* pkcs7, byte* output, const byte* input,
 8804    word32 inputSz)
 8805{
 8806    int ret = 0;
 8807
 8808    if (inputSz == 0)
 8809        return 0;
 8810
 8811    if (input == NULL) {
 8812        WOLFSSL_MSG("Internal error, trying to write out NULL buffer");
 8813        return -1;
 8814    }
 8815
 8816#ifdef ASN_BER_TO_DER
 8817    if (pkcs7->streamOutCb) {
 8818        ret = pkcs7->streamOutCb(pkcs7, input, inputSz, pkcs7->streamCtx);
 8819        /* sanity check on user provided ret value */
 8820        if (ret < 0) {
 8821            WOLFSSL_MSG("Return value error from stream out callback");
 8822            ret = BUFFER_E;
 8823        }
 8824    }
 8825    else
 8826#endif
 8827    if (output) {
 8828        XMEMCPY(output, input, inputSz);
 8829    }
 8830    else {
 8831        WOLFSSL_MSG("No way provided to output bundle");
 8832        ret = BUFFER_E;
 8833    }
 8834
 8835    (void)pkcs7;
 8836    return ret;
 8837}
 8838
 8839
 8840/* encrypt content using encryptOID algo */
 8841static int wc_PKCS7_EncryptContent(wc_PKCS7* pkcs7, int encryptOID,
 8842                                   const byte* key, int keySz,
 8843                                   const byte* iv, int ivSz,
 8844                                   const byte* aad, word32 aadSz,
 8845                                   byte* authTag, word32 authTagSz,
 8846                                   const byte* in, int inSz,
 8847                                   byte* out)
 8848{
 8849    int ret;
 8850#ifndef NO_AES
 8851    WC_DECLARE_VAR(aes, Aes, 1, 0);
 8852#endif
 8853#ifndef NO_DES3
 8854    Des  des;
 8855    Des3 des3;
 8856#endif
 8857    int devId  = pkcs7->devId;
 8858    void* heap = pkcs7->heap;
 8859
 8860    if (key == NULL || iv == NULL)
 8861        return BAD_FUNC_ARG;
 8862
 8863#ifdef ASN_BER_TO_DER
 8864    if ((in == NULL && pkcs7->getContentCb == NULL) ||
 8865        (out == NULL && pkcs7->streamOutCb == NULL)) {
 8866        WOLFSSL_MSG("No input or output set for encrypt");
 8867        return BAD_FUNC_ARG;
 8868    }
 8869#else
 8870    if (in == NULL || out == NULL)
 8871        return BAD_FUNC_ARG;
 8872#endif
 8873
 8874    switch (encryptOID) {
 8875#ifndef NO_AES
 8876    #ifdef HAVE_AES_CBC
 8877    #ifdef WOLFSSL_AES_128
 8878        case AES128CBCb:
 8879    #endif
 8880    #ifdef WOLFSSL_AES_192
 8881        case AES192CBCb:
 8882    #endif
 8883    #ifdef WOLFSSL_AES_256
 8884        case AES256CBCb:
 8885    #endif
 8886            if (
 8887                #ifdef WOLFSSL_AES_128
 8888                    (encryptOID == AES128CBCb && keySz != 16 ) ||
 8889                #endif
 8890                #ifdef WOLFSSL_AES_192
 8891                    (encryptOID == AES192CBCb && keySz != 24 ) ||
 8892                #endif
 8893                #ifdef WOLFSSL_AES_256
 8894                    (encryptOID == AES256CBCb && keySz != 32 ) ||
 8895                #endif
 8896                    (ivSz  != WC_AES_BLOCK_SIZE) )
 8897                return BAD_FUNC_ARG;
 8898
 8899#ifdef WOLFSSL_SMALL_STACK
 8900            if ((aes = (Aes *)XMALLOC(sizeof *aes, NULL,
 8901                                      DYNAMIC_TYPE_AES)) == NULL)
 8902                return MEMORY_E;
 8903#endif
 8904            ret = wc_AesInit(aes, heap, devId);
 8905            if (ret == 0) {
 8906                ret = wc_AesSetKey(aes, key, (word32)keySz, iv, AES_ENCRYPTION);
 8907                if (ret == 0) {
 8908                    ret = wc_PKCS7_EncodeContentStream(pkcs7, NULL, aes, in,
 8909                        inSz, out, WC_CIPHER_AES_CBC);
 8910                }
 8911                wc_AesFree(aes);
 8912            }
 8913            WC_FREE_VAR_EX(aes, NULL, DYNAMIC_TYPE_AES);
 8914            break;
 8915    #endif /* HAVE_AES_CBC */
 8916    #ifdef HAVE_AESGCM
 8917        #ifdef WOLFSSL_AES_128
 8918        case AES128GCMb:
 8919        #endif
 8920        #ifdef WOLFSSL_AES_192
 8921        case AES192GCMb:
 8922        #endif
 8923        #ifdef WOLFSSL_AES_256
 8924        case AES256GCMb:
 8925        #endif
 8926        #if defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_192) || \
 8927            defined(WOLFSSL_AES_256)
 8928            if (authTag == NULL)
 8929                return BAD_FUNC_ARG;
 8930
 8931#ifdef WOLFSSL_SMALL_STACK
 8932            if ((aes = (Aes *)XMALLOC(sizeof *aes, NULL,
 8933                                      DYNAMIC_TYPE_AES)) == NULL)
 8934                return MEMORY_E;
 8935#endif
 8936            ret = wc_AesInit(aes, heap, devId);
 8937            if (ret == 0) {
 8938                ret = wc_AesGcmSetKey(aes, key, (word32)keySz);
 8939                if (ret == 0) {
 8940                #ifndef WOLFSSL_AESGCM_STREAM
 8941                    if (pkcs7->encodeStream) {
 8942                        WOLFSSL_MSG("Not AES-GCM stream support compiled in");
 8943                        ret = NOT_COMPILED_IN;
 8944                    }
 8945                    else {
 8946                        ret = wc_AesGcmEncrypt(aes, out, in, (word32)inSz, iv,
 8947                                  (word32)ivSz, authTag, authTagSz, aad, aadSz);
 8948                    #ifdef WOLFSSL_ASYNC_CRYPT
 8949                        /* async encrypt not available here, so block till done
 8950                         */
 8951                        ret = wc_AsyncWait(ret, &aes->asyncDev,
 8952                            WC_ASYNC_FLAG_NONE);
 8953                    #endif
 8954                    }
 8955                #else
 8956                    ret = wc_AesGcmEncryptInit(aes, key, (word32)keySz, iv,
 8957                        (word32)ivSz);
 8958                    if (ret == 0) {
 8959                        ret = wc_AesGcmEncryptUpdate(aes, NULL, NULL, 0, aad,
 8960                            aadSz);
 8961                    }
 8962                    if (ret == 0) {
 8963                        ret = wc_PKCS7_EncodeContentStream(pkcs7, NULL, aes, in,
 8964                            inSz, out, WC_CIPHER_AES_GCM);
 8965                    }
 8966
 8967                    if (ret == 0) {
 8968                        ret = wc_AesGcmEncryptFinal(aes, authTag, authTagSz);
 8969                    }
 8970                #endif
 8971                }
 8972                wc_AesFree(aes);
 8973            }
 8974            WC_FREE_VAR_EX(aes, NULL, DYNAMIC_TYPE_AES);
 8975            break;
 8976        #endif
 8977    #endif /* HAVE_AESGCM */
 8978    #ifdef HAVE_AESCCM
 8979        #ifdef WOLFSSL_AES_128
 8980        case AES128CCMb:
 8981        #endif
 8982        #ifdef WOLFSSL_AES_192
 8983        case AES192CCMb:
 8984        #endif
 8985        #ifdef WOLFSSL_AES_256
 8986        case AES256CCMb:
 8987        #endif
 8988        #if defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_192) || \
 8989            defined(WOLFSSL_AES_256)
 8990            if (authTag == NULL)
 8991                return BAD_FUNC_ARG;
 8992
 8993            if (pkcs7->encodeStream) {
 8994                WOLFSSL_MSG("Streaming encoding not supported with AES-CCM");
 8995                return BAD_FUNC_ARG;
 8996            }
 8997
 8998#ifdef WOLFSSL_SMALL_STACK
 8999            if ((aes = (Aes *)XMALLOC(sizeof *aes, NULL,
 9000                                      DYNAMIC_TYPE_AES)) == NULL)
 9001                return MEMORY_E;
 9002#endif
 9003            ret = wc_AesInit(aes, heap, devId);
 9004            if (ret == 0) {
 9005                ret = wc_AesCcmSetKey(aes, key, (word32)keySz);
 9006                if (ret == 0) {
 9007                    ret = wc_AesCcmEncrypt(aes, out, in, (word32)inSz, iv,
 9008                                           (word32)ivSz, authTag, authTagSz,
 9009                                           aad, aadSz);
 9010                #ifdef WOLFSSL_ASYNC_CRYPT
 9011                    /* async encrypt not available here, so block till done */
 9012                    ret = wc_AsyncWait(ret, &aes->asyncDev, WC_ASYNC_FLAG_NONE);
 9013                #endif
 9014                }
 9015                wc_AesFree(aes);
 9016            }
 9017            WC_FREE_VAR_EX(aes, NULL, DYNAMIC_TYPE_AES);
 9018            break;
 9019        #endif
 9020    #endif /* HAVE_AESCCM */
 9021#endif /* !NO_AES */
 9022#ifndef NO_DES3
 9023        case DESb:
 9024            if (keySz != DES_KEYLEN || ivSz != DES_BLOCK_SIZE)
 9025                return BAD_FUNC_ARG;
 9026
 9027            if (pkcs7->encodeStream) {
 9028                WOLFSSL_MSG("Streaming encoding not supported with DES3");
 9029                return BAD_FUNC_ARG;
 9030            }
 9031
 9032            ret = wc_Des_SetKey(&des, key, iv, DES_ENCRYPTION);
 9033            if (ret == 0)
 9034                ret = wc_Des_CbcEncrypt(&des, out, in, (word32)inSz);
 9035
 9036            break;
 9037
 9038        case DES3b:
 9039            if (keySz != DES3_KEYLEN || ivSz != DES_BLOCK_SIZE)
 9040                return BAD_FUNC_ARG;
 9041
 9042            if (pkcs7->encodeStream) {
 9043                WOLFSSL_MSG("Streaming encoding not supported with DES3");
 9044                return BAD_FUNC_ARG;
 9045            }
 9046
 9047            ret = wc_Des3Init(&des3, heap, devId);
 9048            if (ret == 0) {
 9049                ret = wc_Des3_SetKey(&des3, key, iv, DES_ENCRYPTION);
 9050                if (ret == 0) {
 9051                    ret = wc_Des3_CbcEncrypt(&des3, out, in, (word32)inSz);
 9052                #ifdef WOLFSSL_ASYNC_CRYPT
 9053                    /* async encrypt not available here, so block till done */
 9054                    ret = wc_AsyncWait(ret, &des3.asyncDev, WC_ASYNC_FLAG_NONE);
 9055                #endif
 9056                }
 9057                wc_Des3Free(&des3);
 9058            }
 9059            break;
 9060#endif /* !NO_DES3 */
 9061        default:
 9062            WOLFSSL_MSG("Unsupported content cipher type");
 9063            return ALGO_ID_E;
 9064    };
 9065
 9066#if defined(NO_AES) || (!defined(HAVE_AESGCM) && !defined(HAVE_AESCCM))
 9067    (void)authTag;
 9068    (void)authTagSz;
 9069    (void)aad;
 9070    (void)aadSz;
 9071#endif
 9072    return ret;
 9073}
 9074
 9075
 9076static int wc_PKCS7_DecryptContentInit(wc_PKCS7* pkcs7, word32 encryptOID,
 9077    const byte* key, word32 keySz, const byte* iv, int ivSz,
 9078    int devId, void* heap)
 9079{
 9080    int ret;
 9081#ifndef NO_AES
 9082    Aes  *aes;
 9083#endif
 9084#ifndef NO_DES3
 9085    Des  *des;
 9086    Des3 *des3;
 9087#endif
 9088
 9089    if (iv == NULL)
 9090        return BAD_FUNC_ARG;
 9091
 9092    if (key == NULL)
 9093        return BAD_FUNC_ARG;
 9094
 9095    switch (encryptOID) {
 9096#ifndef NO_AES
 9097    #ifdef HAVE_AES_CBC
 9098    #ifdef WOLFSSL_AES_128
 9099        case AES128CBCb:
 9100    #endif
 9101    #ifdef WOLFSSL_AES_192
 9102        case AES192CBCb:
 9103    #endif
 9104    #ifdef WOLFSSL_AES_256
 9105        case AES256CBCb:
 9106    #endif
 9107            if (
 9108                #ifdef WOLFSSL_AES_128
 9109                    (encryptOID == AES128CBCb && keySz != 16 ) ||
 9110                #endif
 9111                #ifdef WOLFSSL_AES_192
 9112                    (encryptOID == AES192CBCb && keySz != 24 ) ||
 9113                #endif
 9114                #ifdef WOLFSSL_AES_256
 9115                    (encryptOID == AES256CBCb && keySz != 32 ) ||
 9116                #endif
 9117                    (ivSz  != WC_AES_BLOCK_SIZE) )
 9118                return BAD_FUNC_ARG;
 9119
 9120            pkcs7->decryptKey.aes = (Aes *)XMALLOC(sizeof *aes, NULL,
 9121                                      DYNAMIC_TYPE_AES);
 9122            aes = pkcs7->decryptKey.aes;
 9123            if (aes == NULL)
 9124                return MEMORY_E;
 9125            ret = wc_AesInit(aes, heap, devId);
 9126            if (ret == 0) {
 9127                ret = wc_AesSetKey(aes, key, (word32)keySz, iv, AES_DECRYPTION);
 9128            }
 9129            break;
 9130
 9131    #endif /* HAVE_AES_CBC */
 9132    #ifdef HAVE_AESGCM
 9133        #ifdef WOLFSSL_AES_128
 9134        case AES128GCMb:
 9135        #endif
 9136        #ifdef WOLFSSL_AES_192
 9137        case AES192GCMb:
 9138        #endif
 9139        #ifdef WOLFSSL_AES_256
 9140        case AES256GCMb:
 9141        #endif
 9142        #if defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_192) || \
 9143            defined(WOLFSSL_AES_256)
 9144            pkcs7->decryptKey.aes = (Aes *)XMALLOC(sizeof *aes, NULL,
 9145                                      DYNAMIC_TYPE_AES);
 9146            aes = pkcs7->decryptKey.aes;
 9147            if (aes == NULL)
 9148                return MEMORY_E;
 9149            ret = wc_AesInit(aes, heap, devId);
 9150            if (ret == 0) {
 9151                ret = wc_AesGcmSetKey(aes, key, (word32)keySz);
 9152            }
 9153            break;
 9154        #endif
 9155    #endif /* HAVE_AESGCM */
 9156    #ifdef HAVE_AESCCM
 9157        #ifdef WOLFSSL_AES_128
 9158        case AES128CCMb:
 9159        #endif
 9160        #ifdef WOLFSSL_AES_192
 9161        case AES192CCMb:
 9162        #endif
 9163        #ifdef WOLFSSL_AES_256
 9164        case AES256CCMb:
 9165        #endif
 9166        #if defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_192) || \
 9167            defined(WOLFSSL_AES_256)
 9168            pkcs7->decryptKey.aes = (Aes *)XMALLOC(sizeof *aes, NULL,
 9169                                      DYNAMIC_TYPE_AES);
 9170            aes = pkcs7->decryptKey.aes;
 9171            if (aes == NULL)
 9172                return MEMORY_E;
 9173            ret = wc_AesInit(aes, heap, devId);
 9174            if (ret == 0) {
 9175                ret = wc_AesCcmSetKey(aes, key, (word32)keySz);
 9176            }
 9177            break;
 9178        #endif
 9179    #endif /* HAVE_AESCCM */
 9180#endif /* !NO_AES */
 9181#ifndef NO_DES3
 9182        case DESb:
 9183            if (keySz != DES_KEYLEN || ivSz != DES_BLOCK_SIZE)
 9184                return BAD_FUNC_ARG;
 9185
 9186            pkcs7->decryptKey.des = (Des *)XMALLOC(sizeof *des, NULL,
 9187                                      DYNAMIC_TYPE_PKCS7);
 9188            des = pkcs7->decryptKey.des;
 9189            if (des == NULL) {
 9190                return MEMORY_E;
 9191            }
 9192            ret = wc_Des_SetKey(des, key, iv, DES_DECRYPTION);
 9193            break;
 9194        case DES3b:
 9195            if (keySz != DES3_KEYLEN || ivSz != DES_BLOCK_SIZE)
 9196                return BAD_FUNC_ARG;
 9197
 9198            pkcs7->decryptKey.des3 = (Des3 *)XMALLOC(sizeof *des3, NULL,
 9199                                      DYNAMIC_TYPE_PKCS7);
 9200            des3 = pkcs7->decryptKey.des3;
 9201            if (des3 == NULL) {
 9202                return MEMORY_E;
 9203            }
 9204            ret = wc_Des3Init(des3, heap, devId);
 9205            if (ret == 0) {
 9206                ret = wc_Des3_SetKey(des3, key, iv, DES_DECRYPTION);
 9207            }
 9208
 9209            break;
 9210#endif /* !NO_DES3 */
 9211        default:
 9212            WOLFSSL_MSG("Unsupported content cipher type");
 9213            return ALGO_ID_E;
 9214    };
 9215
 9216    return ret;
 9217}
 9218
 9219
 9220/* Only does decryption of content using encryptOID algo and already set keys
 9221 * returns 0 on success */
 9222static int wc_PKCS7_DecryptContentEx(wc_PKCS7* pkcs7, word32 encryptOID,
 9223    const byte* iv, int ivSz, const byte* aad, word32 aadSz,
 9224    const byte* authTag, word32 authTagSz, const byte* in, int inSz, byte* out)
 9225{
 9226    int ret;
 9227
 9228    if (in == NULL
 9229    #ifdef ASN_BER_TO_DER
 9230        && pkcs7->getContentCb == NULL
 9231    #endif
 9232    ) {
 9233        return BAD_FUNC_ARG;
 9234    }
 9235
 9236    switch (encryptOID) {
 9237#ifndef NO_AES
 9238    #ifdef HAVE_AES_CBC
 9239    #ifdef WOLFSSL_AES_128
 9240        case AES128CBCb:
 9241    #endif
 9242    #ifdef WOLFSSL_AES_192
 9243        case AES192CBCb:
 9244    #endif
 9245    #ifdef WOLFSSL_AES_256
 9246        case AES256CBCb:
 9247    #endif
 9248            ret = wc_AesCbcDecrypt(pkcs7->decryptKey.aes, out, in,
 9249                (word32)inSz);
 9250        #ifdef WOLFSSL_ASYNC_CRYPT
 9251            /* async decrypt not available here, so block till done */
 9252            ret = wc_AsyncWait(ret, &pkcs7->decryptKey.aes->asyncDev,
 9253                WC_ASYNC_FLAG_NONE);
 9254        #endif
 9255            break;
 9256    #endif /* HAVE_AES_CBC */
 9257    #ifdef HAVE_AESGCM
 9258        #ifdef WOLFSSL_AES_128
 9259        case AES128GCMb:
 9260        #endif
 9261        #ifdef WOLFSSL_AES_192
 9262        case AES192GCMb:
 9263        #endif
 9264        #ifdef WOLFSSL_AES_256
 9265        case AES256GCMb:
 9266        #endif
 9267        #if defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_192) || \
 9268            defined(WOLFSSL_AES_256)
 9269            if (authTag == NULL)
 9270                return BAD_FUNC_ARG;
 9271
 9272            ret = wc_AesGcmDecrypt(pkcs7->decryptKey.aes, out, in,
 9273                    (word32)inSz, iv, (word32)ivSz, authTag, authTagSz,
 9274                    aad, aadSz);
 9275        #ifdef WOLFSSL_ASYNC_CRYPT
 9276            /* async decrypt not available here, so block till done */
 9277            ret = wc_AsyncWait(ret, &pkcs7->decryptKey.aes->asyncDev,
 9278                WC_ASYNC_FLAG_NONE);
 9279        #endif
 9280            break;
 9281        #endif
 9282    #endif /* HAVE_AESGCM */
 9283    #ifdef HAVE_AESCCM
 9284        #ifdef WOLFSSL_AES_128
 9285        case AES128CCMb:
 9286        #endif
 9287        #ifdef WOLFSSL_AES_192
 9288        case AES192CCMb:
 9289        #endif
 9290        #ifdef WOLFSSL_AES_256
 9291        case AES256CCMb:
 9292        #endif
 9293            ret = wc_AesCcmDecrypt(pkcs7->decryptKey.aes, out, in,
 9294                (word32)inSz, iv, (word32)ivSz, authTag, authTagSz,
 9295                aad, aadSz);
 9296        #ifdef WOLFSSL_ASYNC_CRYPT
 9297            /* async decrypt not available here, so block till done */
 9298            ret = wc_AsyncWait(ret, &pkcs7->decryptKey.aes->asyncDev,
 9299                WC_ASYNC_FLAG_NONE);
 9300        #endif
 9301            break;
 9302    #endif /* HAVE_AESCCM */
 9303#endif /* !NO_AES */
 9304#ifndef NO_DES3
 9305        case DESb:
 9306            ret = wc_Des_CbcDecrypt(pkcs7->decryptKey.des, out, in,
 9307                (word32)inSz);
 9308            break;
 9309
 9310        case DES3b:
 9311            ret = wc_Des3_CbcDecrypt(pkcs7->decryptKey.des3, out, in,
 9312                (word32)inSz);
 9313        #ifdef WOLFSSL_ASYNC_CRYPT
 9314            /* async decrypt not available here, so block till done */
 9315            ret = wc_AsyncWait(ret,
 9316              &pkcs7->decryptKey.des3->asyncDev, WC_ASYNC_FLAG_NONE);
 9317        #endif
 9318            break;
 9319#endif /* !NO_DES3 */
 9320        default:
 9321            WOLFSSL_MSG("Unsupported content cipher type");
 9322            return ALGO_ID_E;
 9323    };
 9324
 9325#if defined(NO_AES) || (!defined(HAVE_AESGCM) && !defined(HAVE_AESCCM))
 9326    (void)authTag;
 9327    (void)authTagSz;
 9328    (void)aad;
 9329    (void)aadSz;
 9330#endif
 9331
 9332    return ret;
 9333}
 9334
 9335
 9336/* clears up struct for algo used and free's memory */
 9337static void wc_PKCS7_DecryptContentFree(wc_PKCS7* pkcs7, word32 encryptOID,
 9338    void* heap)
 9339{
 9340    switch (encryptOID) {
 9341#ifndef NO_AES
 9342    #ifdef HAVE_AES_CBC
 9343    #ifdef WOLFSSL_AES_128
 9344        case AES128CBCb:
 9345    #endif
 9346    #ifdef WOLFSSL_AES_192
 9347        case AES192CBCb:
 9348    #endif
 9349    #ifdef WOLFSSL_AES_256
 9350        case AES256CBCb:
 9351    #endif
 9352    #endif /* HAVE_AES_CBC */
 9353    #ifdef HAVE_AESGCM
 9354        #ifdef WOLFSSL_AES_128
 9355        case AES128GCMb:
 9356        #endif
 9357        #ifdef WOLFSSL_AES_192
 9358        case AES192GCMb:
 9359        #endif
 9360        #ifdef WOLFSSL_AES_256
 9361        case AES256GCMb:
 9362        #endif
 9363    #endif /* HAVE_AESGCM */
 9364    #ifdef HAVE_AESCCM
 9365        #ifdef WOLFSSL_AES_128
 9366        case AES128CCMb:
 9367        #endif
 9368        #ifdef WOLFSSL_AES_192
 9369        case AES192CCMb:
 9370        #endif
 9371        #ifdef WOLFSSL_AES_256
 9372        case AES256CCMb:
 9373        #endif
 9374    #endif /* HAVE_AESCCM */
 9375            if (pkcs7->decryptKey.aes != NULL) {
 9376                wc_AesFree(pkcs7->decryptKey.aes);
 9377                XFREE(pkcs7->decryptKey.aes, heap, DYNAMIC_TYPE_AES);
 9378                pkcs7->decryptKey.aes = NULL;
 9379            }
 9380            break;
 9381#endif /* !NO_AES */
 9382#ifndef NO_DES3
 9383        case DESb:
 9384            if (pkcs7->decryptKey.des != NULL) {
 9385                XFREE(pkcs7->decryptKey.des, heap, DYNAMIC_TYPE_PKCS7);
 9386                pkcs7->decryptKey.des = NULL;
 9387            }
 9388            break;
 9389        case DES3b:
 9390            if (pkcs7->decryptKey.des3 != NULL) {
 9391                wc_Des3Free(pkcs7->decryptKey.des3);
 9392                XFREE(pkcs7->decryptKey.des3, heap, DYNAMIC_TYPE_PKCS7);
 9393                pkcs7->decryptKey.des3 = NULL;
 9394            }
 9395            break;
 9396#endif /* !NO_DES3 */
 9397        default:
 9398            WOLFSSL_MSG("Unsupported content cipher type");
 9399    };
 9400}
 9401
 9402
 9403/* decrypts the content in one shot, doing init / decrypt / free
 9404 * returns 0 on success
 9405 */
 9406static int wc_PKCS7_DecryptContent(wc_PKCS7* pkcs7, word32 encryptOID,
 9407        const byte* key, word32 keySz, const byte* iv, int ivSz,
 9408        const byte* aad, word32 aadSz, const byte* authTag, word32 authTagSz,
 9409        const byte* in, int inSz, byte* out, int devId, void* heap)
 9410{
 9411    int ret;
 9412
 9413    if (pkcs7->decryptionCb != NULL) {
 9414        /* unsafe casts needed for backward compatibility of
 9415         * CallbackDecryptContent.
 9416         */
 9417        return pkcs7->decryptionCb(pkcs7, (int)encryptOID, (byte *)(wc_ptr_t)iv,
 9418                                   ivSz, (byte *)(wc_ptr_t)aad, aadSz,
 9419                                   (byte *)(wc_ptr_t)authTag, authTagSz,
 9420                                   (byte *)(wc_ptr_t)in, inSz, out,
 9421                                   pkcs7->decryptionCtx);
 9422    }
 9423
 9424    ret = wc_PKCS7_DecryptContentInit(pkcs7, encryptOID, key, keySz, iv, ivSz,
 9425        devId, heap);
 9426
 9427    if (ret == 0) {
 9428        ret = wc_PKCS7_DecryptContentEx(pkcs7, encryptOID, iv, ivSz, aad,
 9429            aadSz, authTag, authTagSz, in, inSz, out);
 9430    }
 9431
 9432    wc_PKCS7_DecryptContentFree(pkcs7, encryptOID, heap);
 9433
 9434    return ret;
 9435}
 9436
 9437
 9438/* Generate random block, place in out, return 0 on success negative on error.
 9439 * Used for generation of IV, nonce, etc */
 9440static int wc_PKCS7_GenerateBlock(wc_PKCS7* pkcs7, WC_RNG* rng, byte* out,
 9441                                  word32 outSz)
 9442{
 9443    int ret;
 9444    WC_RNG* rnd = NULL;
 9445
 9446    if (out == NULL || outSz == 0)
 9447        return BAD_FUNC_ARG;
 9448
 9449    /* input RNG is optional, init local one if input rng is NULL */
 9450    if (rng == NULL) {
 9451        rnd = (WC_RNG*)XMALLOC(sizeof(WC_RNG), pkcs7->heap, DYNAMIC_TYPE_RNG);
 9452        if (rnd == NULL)
 9453            return MEMORY_E;
 9454
 9455        ret = wc_InitRng_ex(rnd, pkcs7->heap, pkcs7->devId);
 9456        if (ret != 0) {
 9457            XFREE(rnd, pkcs7->heap, DYNAMIC_TYPE_RNG);
 9458            return ret;
 9459        }
 9460
 9461    } else {
 9462        rnd = rng;
 9463    }
 9464
 9465    ret = wc_RNG_GenerateBlock(rnd, out, outSz);
 9466
 9467    if (rng == NULL) {
 9468        wc_FreeRng(rnd);
 9469        XFREE(rnd, pkcs7->heap, DYNAMIC_TYPE_RNG);
 9470    }
 9471
 9472    return ret;
 9473}
 9474
 9475
 9476/* Set default SignerIdentifier type to be used. Is either
 9477 * IssuerAndSerialNumber or SubjectKeyIdentifier. Encoding defaults to using
 9478 * IssuerAndSerialNumber unless set with this function or explicitly
 9479 * overridden via options when adding RecipientInfo type.
 9480 *
 9481 * Using the type DEGENERATE_SID skips over signer information. In degenerate
 9482 * cases there are no signers.
 9483 *
 9484 * pkcs7 - pointer to initialized PKCS7 structure
 9485 * type  - either CMS_ISSUER_AND_SERIAL_NUMBER, CMS_SKID or DEGENERATE_SID
 9486 *
 9487 * return 0 on success, negative upon error */
 9488int wc_PKCS7_SetSignerIdentifierType(wc_PKCS7* pkcs7, int type)
 9489{
 9490    if (pkcs7 == NULL)
 9491        return BAD_FUNC_ARG;
 9492
 9493    if (type != CMS_ISSUER_AND_SERIAL_NUMBER &&
 9494        type != CMS_SKID &&
 9495        type != DEGENERATE_SID) {
 9496        return BAD_FUNC_ARG;
 9497    }
 9498
 9499    pkcs7->sidType = type;
 9500
 9501    return 0;
 9502}
 9503
 9504
 9505/* Set custom contentType, currently supported with SignedData type
 9506 *
 9507 * pkcs7       - pointer to initialized PKCS7 structure
 9508 * contentType - pointer to array with ASN.1 encoded OID value
 9509 * sz          - length of contentType array, octets
 9510 *
 9511 * return 0 on success, negative upon error */
 9512int wc_PKCS7_SetContentType(wc_PKCS7* pkcs7, byte* contentType, word32 sz)
 9513{
 9514    if (pkcs7 == NULL || contentType == NULL || sz == 0)
 9515        return BAD_FUNC_ARG;
 9516
 9517    if (sz > MAX_OID_SZ) {
 9518        WOLFSSL_MSG("input array too large, bounded by MAX_OID_SZ");
 9519        return BAD_FUNC_ARG;
 9520    }
 9521
 9522    XMEMCPY(pkcs7->contentType, contentType, sz);
 9523    pkcs7->contentTypeSz = sz;
 9524
 9525    return 0;
 9526}
 9527
 9528
 9529/* return size of padded data, padded to blockSz chunks, or negative on error */
 9530int wc_PKCS7_GetPadSize(word32 inputSz, word32 blockSz)
 9531{
 9532    if (blockSz == 0)
 9533        return BAD_FUNC_ARG;
 9534
 9535    return (int)(blockSz - (inputSz % blockSz));
 9536}
 9537
 9538
 9539/* pad input data to blockSz chunk, place in outSz. out must be big enough
 9540 * for input + pad bytes. See wc_PKCS7_GetPadSize() helper. */
 9541int wc_PKCS7_PadData(byte* in, word32 inSz, byte* out, word32 outSz,
 9542                     word32 blockSz)
 9543{
 9544    if (in == NULL  || inSz == 0 ||
 9545        out == NULL || outSz == 0 || blockSz == 0)
 9546        return BAD_FUNC_ARG;
 9547
 9548    if (outSz < wc_PkcsPad(NULL, inSz, blockSz))
 9549        return BAD_FUNC_ARG;
 9550
 9551    XMEMCPY(out, in, inSz);
 9552
 9553    return (int)wc_PkcsPad(out, inSz, blockSz);
 9554}
 9555
 9556
 9557/* Encode and add CMS EnvelopedData ORI (OtherRecipientInfo) RecipientInfo
 9558 * to CMS/PKCS#7 EnvelopedData structure.
 9559 *
 9560 * Return 0 on success, negative upon error */
 9561int wc_PKCS7_AddRecipient_ORI(wc_PKCS7* pkcs7, CallbackOriEncrypt oriEncryptCb,
 9562                              int options)
 9563{
 9564    int oriTypeLenSz, blockKeySz, ret;
 9565    word32 idx, recipSeqSz;
 9566
 9567    Pkcs7EncodedRecip* recip = NULL;
 9568    Pkcs7EncodedRecip* lastRecip = NULL;
 9569
 9570    byte recipSeq[MAX_SEQ_SZ];
 9571    byte oriTypeLen[MAX_LENGTH_SZ];
 9572
 9573    byte oriType[MAX_ORI_TYPE_SZ];
 9574    byte oriValue[MAX_ORI_VALUE_SZ];
 9575    word32 oriTypeSz = MAX_ORI_TYPE_SZ;
 9576    word32 oriValueSz = MAX_ORI_VALUE_SZ;
 9577
 9578    if (pkcs7 == NULL || oriEncryptCb == NULL) {
 9579        return BAD_FUNC_ARG;
 9580    }
 9581
 9582    /* allocate memory for RecipientInfo, KEK, encrypted key */
 9583    recip = (Pkcs7EncodedRecip*)XMALLOC(sizeof(Pkcs7EncodedRecip),
 9584                                        pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 9585    if (recip == NULL)
 9586        return MEMORY_E;
 9587    XMEMSET(recip, 0, sizeof(Pkcs7EncodedRecip));
 9588
 9589    /* get key size for content-encryption key based on algorithm */
 9590    blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID);
 9591    if (blockKeySz < 0) {
 9592        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 9593        return blockKeySz;
 9594    }
 9595
 9596    /* generate random content encryption key, if needed */
 9597    ret = PKCS7_GenerateContentEncryptionKey(pkcs7, (word32)blockKeySz);
 9598    if (ret < 0) {
 9599        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 9600        return ret;
 9601    }
 9602
 9603    /* call user callback to encrypt CEK and get oriType and oriValue
 9604       values back */
 9605    ret = oriEncryptCb(pkcs7, pkcs7->cek, pkcs7->cekSz, oriType, &oriTypeSz,
 9606                       oriValue, &oriValueSz, pkcs7->oriEncryptCtx);
 9607    if (ret != 0) {
 9608        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 9609        return ret;
 9610    }
 9611
 9612    oriTypeLenSz = (int)SetLength(oriTypeSz, oriTypeLen);
 9613
 9614    recipSeqSz = SetImplicit(ASN_SEQUENCE, 4, 1 + (word32)oriTypeLenSz +
 9615                             oriTypeSz + oriValueSz, recipSeq, 0);
 9616
 9617    idx = 0;
 9618    XMEMCPY(recip->recip + idx, recipSeq, recipSeqSz);
 9619    idx += recipSeqSz;
 9620    /* oriType */
 9621    recip->recip[idx] = ASN_OBJECT_ID;
 9622    idx += 1;
 9623    XMEMCPY(recip->recip + idx, oriTypeLen, (word32)oriTypeLenSz);
 9624    idx += (word32)oriTypeLenSz;
 9625    XMEMCPY(recip->recip + idx, oriType, oriTypeSz);
 9626    idx += oriTypeSz;
 9627    /* oriValue, input MUST already be ASN.1 encoded */
 9628    XMEMCPY(recip->recip + idx, oriValue, oriValueSz);
 9629    idx += oriValueSz;
 9630
 9631    /* store recipient size */
 9632    recip->recipSz = idx;
 9633    recip->recipType = PKCS7_ORI;
 9634    recip->recipVersion = 4;
 9635
 9636    /* add recipient to recip list */
 9637    if (pkcs7->recipList == NULL) {
 9638        pkcs7->recipList = recip;
 9639    } else {
 9640        lastRecip = pkcs7->recipList;
 9641        while (lastRecip->next != NULL) {
 9642            lastRecip = lastRecip->next;
 9643        }
 9644        lastRecip->next = recip;
 9645    }
 9646
 9647    (void)options;
 9648
 9649    return (int)idx;
 9650}
 9651
 9652#if !defined(NO_PWDBASED) && !defined(NO_SHA)
 9653
 9654
 9655static int wc_PKCS7_GenerateKEK_PWRI(wc_PKCS7* pkcs7, byte* passwd, word32 pLen,
 9656                                     byte* salt, word32 saltSz, int kdfOID,
 9657                                     int prfOID, int iterations, byte* out,
 9658                                     word32 outSz)
 9659{
 9660    int ret;
 9661
 9662    if (pkcs7 == NULL || passwd == NULL || salt == NULL || out == NULL)
 9663        return BAD_FUNC_ARG;
 9664
 9665    switch (kdfOID) {
 9666
 9667        case PBKDF2_OID:
 9668
 9669            ret = wc_PBKDF2(out, passwd, (int)pLen, salt, (int)saltSz,
 9670                            iterations, (int)outSz, prfOID);
 9671            if (ret != 0) {
 9672                return ret;
 9673            }
 9674
 9675            break;
 9676
 9677        default:
 9678            WOLFSSL_MSG("Unsupported KDF OID");
 9679            return PKCS7_OID_E;
 9680    }
 9681
 9682    return 0;
 9683}
 9684
 9685
 9686/* RFC3211 (Section 2.3.1) key wrap algorithm (id-alg-PWRI-KEK).
 9687 *
 9688 * Returns output size on success, negative upon error */
 9689static int wc_PKCS7_PwriKek_KeyWrap(wc_PKCS7* pkcs7, const byte* kek,
 9690        word32 kekSz, const byte* cek, word32 cekSz,
 9691        byte* out, word32 *outSz, const byte* iv, word32 ivSz, int algID)
 9692{
 9693    WC_RNG rng;
 9694    int blockSz, outLen, ret;
 9695    word32 padSz;
 9696    byte* lastBlock;
 9697
 9698    if (kek == NULL || cek == NULL || iv == NULL || outSz == NULL)
 9699        return BAD_FUNC_ARG;
 9700
 9701    /* get encryption algorithm block size */
 9702    blockSz = wc_PKCS7_GetOIDBlockSize(algID);
 9703    if (blockSz <= 0) {
 9704        if (blockSz < 0)
 9705            return blockSz;
 9706        else
 9707            return ALGO_ID_E;
 9708    }
 9709
 9710    /* get pad bytes needed to block boundary */
 9711    padSz = (word32)blockSz - ((4 + cekSz) % (word32)blockSz);
 9712    outLen = (int)(4 + cekSz + padSz);
 9713
 9714    /* must be at least two blocks long */
 9715    if (outLen < 2 * blockSz)
 9716        padSz += (word32)blockSz;
 9717
 9718    /* if user set out to NULL, give back required length */
 9719    if (out == NULL) {
 9720        *outSz = (word32)outLen;
 9721        return WC_NO_ERR_TRACE(LENGTH_ONLY_E);
 9722    }
 9723
 9724    /* verify output buffer is large enough */
 9725    if (*outSz < (word32)outLen)
 9726        return BUFFER_E;
 9727
 9728    out[0] = (byte)cekSz;
 9729    out[1] = (byte)~cek[0];
 9730    out[2] = (byte)~cek[1];
 9731    out[3] = (byte)~cek[2];
 9732    XMEMCPY(out + 4, cek, cekSz);
 9733
 9734    /* random padding of size padSz */
 9735    ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId);
 9736    if (ret != 0)
 9737        return ret;
 9738
 9739    ret = wc_RNG_GenerateBlock(&rng, out + 4 + cekSz, padSz);
 9740
 9741    if (ret == 0) {
 9742        /* encrypt, normal */
 9743        ret = wc_PKCS7_EncryptContent(pkcs7, algID, kek, (int)kekSz,
 9744                                    iv, (int)ivSz, NULL, 0, NULL, 0, out,
 9745                                    outLen, out);
 9746    }
 9747
 9748    if (ret == 0) {
 9749        /* encrypt again, using last ciphertext block as IV */
 9750        lastBlock = out + (((outLen / blockSz) - 1) * blockSz);
 9751        ret = wc_PKCS7_EncryptContent(pkcs7, algID, kek, (int)kekSz,
 9752                                      lastBlock, blockSz, NULL, 0, NULL, 0, out,
 9753                                      outLen, out);
 9754    }
 9755
 9756    if (ret == 0) {
 9757        *outSz = (word32)outLen;
 9758    } else {
 9759        outLen = ret;
 9760    }
 9761
 9762    wc_FreeRng(&rng);
 9763
 9764    return outLen;
 9765}
 9766
 9767
 9768/* RFC3211 (Section 2.3.2) key unwrap algorithm (id-alg-PWRI-KEK).
 9769 *
 9770 * Returns cek size on success, negative upon error */
 9771static int wc_PKCS7_PwriKek_KeyUnWrap(wc_PKCS7* pkcs7, const byte* kek,
 9772                                      word32 kekSz, const byte* in, word32 inSz,
 9773                                      byte* out, word32 outSz, const byte* iv,
 9774                                      word32 ivSz, word32 algID)
 9775{
 9776    int blockSz, cekLen, ret;
 9777    const byte* tmpIv     = NULL;
 9778    const byte* lastBlock = NULL;
 9779    byte* outTmp    = NULL;
 9780    byte  fail      = 0;
 9781
 9782    if (pkcs7 == NULL || kek == NULL || in == NULL ||
 9783        out == NULL || iv == NULL) {
 9784        return BAD_FUNC_ARG;
 9785    }
 9786
 9787    outTmp = (byte*)XMALLOC(inSz, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 9788    if (outTmp == NULL)
 9789        return MEMORY_E;
 9790
 9791    /* get encryption algorithm block size */
 9792    blockSz = wc_PKCS7_GetOIDBlockSize((int)algID);
 9793    if (blockSz <= 0) {
 9794        XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 9795        if (blockSz < 0)
 9796            return blockSz;
 9797        else
 9798            return ALGO_ID_E;
 9799    }
 9800
 9801    /* input needs to be blockSz multiple and at least 2 * blockSz */
 9802    if (((inSz % (word32)blockSz) != 0) || (inSz < (2 * (word32)blockSz))) {
 9803        WOLFSSL_MSG("PWRI-KEK unwrap input must of block size and >= 2 "
 9804                    "times block size");
 9805        XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 9806        return BAD_FUNC_ARG;
 9807    }
 9808
 9809    /* use block out[n-1] as IV to decrypt block out[n] */
 9810    lastBlock = in + inSz - blockSz;
 9811    tmpIv = lastBlock - blockSz;
 9812
 9813    /* decrypt last block */
 9814    ret = wc_PKCS7_DecryptContent(pkcs7, algID, kek, kekSz, tmpIv,
 9815            blockSz, NULL, 0, NULL, 0, lastBlock, blockSz,
 9816            outTmp + inSz - blockSz, pkcs7->devId, pkcs7->heap);
 9817
 9818    if (ret == 0) {
 9819        /* using last decrypted block as IV, decrypt [0 ... n-1] blocks */
 9820        lastBlock = outTmp + inSz - blockSz;
 9821        ret = wc_PKCS7_DecryptContent(pkcs7, algID, kek, kekSz,
 9822                lastBlock, blockSz, NULL, 0, NULL, 0, in,
 9823                (int)inSz - blockSz, outTmp, pkcs7->devId, pkcs7->heap);
 9824    }
 9825
 9826    if (ret == 0) {
 9827        /* decrypt using original kek and iv */
 9828        ret = wc_PKCS7_DecryptContent(pkcs7, algID, kek, kekSz,
 9829                iv, (int)ivSz, NULL, 0, NULL, 0, outTmp, (int)inSz,
 9830                outTmp, pkcs7->devId, pkcs7->heap);
 9831    }
 9832
 9833    if (ret != 0) {
 9834        ForceZero(outTmp, inSz);
 9835        XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 9836        return ret;
 9837    }
 9838
 9839    cekLen = outTmp[0];
 9840
 9841    /* verify length */
 9842    fail |= ctMaskGT(cekLen, (int)inSz - 4);
 9843    /* verify check bytes */
 9844    fail |= ctMaskNotEq((int)(outTmp[1] ^ outTmp[4]), 0xFF);
 9845    fail |= ctMaskNotEq((int)(outTmp[2] ^ outTmp[5]), 0xFF);
 9846    fail |= ctMaskNotEq((int)(outTmp[3] ^ outTmp[6]), 0xFF);
 9847    /* verify length */
 9848    fail |= ctMaskGT(cekLen, (int)outSz);
 9849
 9850    if (fail) {
 9851        ForceZero(outTmp, inSz);
 9852        XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 9853        return BAD_FUNC_ARG;
 9854    }
 9855
 9856    XMEMCPY(out, outTmp + 4, outTmp[0]);
 9857    ForceZero(outTmp, inSz);
 9858    XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
 9859
 9860    return cekLen;
 9861}
 9862
 9863
 9864/* Encode and add CMS EnvelopedData PWRI (PasswordRecipientInfo) RecipientInfo
 9865 * to CMS/PKCS#7 EnvelopedData structure.
 9866 *
 9867 * Return 0 on success, negative upon error */
 9868int wc_PKCS7_AddRecipient_PWRI(wc_PKCS7* pkcs7, byte* passwd, word32 pLen,
 9869                               byte* salt, word32 saltSz, int kdfOID,
 9870                               int hashOID, int iterations, int kekEncryptOID,
 9871                               int options)
 9872{
 9873    Pkcs7EncodedRecip* recip = NULL;
 9874    Pkcs7EncodedRecip* lastRecip = NULL;
 9875
 9876    /* PasswordRecipientInfo */
 9877    byte recipSeq[MAX_SEQ_SZ];
 9878    byte ver[MAX_VERSION_SZ];
 9879    word32 recipSeqSz, verSz;
 9880
 9881    /* KeyDerivationAlgorithmIdentifier */
 9882    byte kdfAlgoIdSeq[MAX_SEQ_SZ];
 9883    byte kdfAlgoId[MAX_OID_SZ];
 9884    byte kdfParamsSeq[MAX_SEQ_SZ];              /* PBKDF2-params */
 9885    byte kdfSaltOctetStr[MAX_OCTET_STR_SZ];     /* salt OCTET STRING */
 9886    byte kdfIterations[MAX_VERSION_SZ];
 9887    word32 kdfAlgoIdSeqSz, kdfAlgoIdSz;
 9888    word32 kdfParamsSeqSz, kdfSaltOctetStrSz, kdfIterationsSz;
 9889    /* OPTIONAL: keyLength, not supported yet */
 9890    /* OPTIONAL: prf AlgorithmIdentifier, not supported yet */
 9891
 9892    /* KeyEncryptionAlgorithmIdentifier */
 9893    byte keyEncAlgoIdSeq[MAX_SEQ_SZ];
 9894    byte keyEncAlgoId[MAX_OID_SZ];              /* id-alg-PWRI-KEK */
 9895    byte pwriEncAlgoId[MAX_ALGO_SZ];
 9896    byte ivOctetString[MAX_OCTET_STR_SZ];
 9897    word32 keyEncAlgoIdSeqSz, keyEncAlgoIdSz;
 9898    word32 pwriEncAlgoIdSz, ivOctetStringSz;
 9899
 9900    /* EncryptedKey */
 9901    byte encKeyOctetStr[MAX_OCTET_STR_SZ];
 9902    word32 encKeyOctetStrSz;
 9903
 9904    byte tmpIv[MAX_CONTENT_IV_SIZE];
 9905    byte* encryptedKey = NULL;
 9906    byte* kek = NULL;
 9907
 9908    int cekKeySz = 0, kekKeySz = 0, kekBlockSz = 0, ret = 0;
 9909    int encryptOID;
 9910    word32 idx, totalSz = 0, encryptedKeySz;
 9911
 9912    if (pkcs7 == NULL || passwd == NULL || pLen == 0 ||
 9913        salt == NULL || saltSz == 0) {
 9914        return BAD_FUNC_ARG;
 9915    }
 9916
 9917    /* allow user to use different KEK encryption algorithm than used for
 9918     * main content encryption algorithm, if passed in */
 9919    if (kekEncryptOID != 0) {
 9920        encryptOID = kekEncryptOID;
 9921    } else {
 9922        encryptOID = pkcs7->encryptOID;
 9923    }
 9924
 9925    /* get content-encryption key size, based on algorithm */
 9926    cekKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID);
 9927    if (cekKeySz < 0)
 9928        return cekKeySz;
 9929
 9930    /* get KEK encryption key size, based on algorithm */
 9931    if (encryptOID != pkcs7->encryptOID) {
 9932        kekKeySz = wc_PKCS7_GetOIDKeySize(encryptOID);
 9933    } else {
 9934        kekKeySz = cekKeySz;
 9935    }
 9936
 9937    /* get KEK encryption block size */
 9938    kekBlockSz = wc_PKCS7_GetOIDBlockSize(encryptOID);
 9939    if (kekBlockSz < 0)
 9940        return kekBlockSz;
 9941
 9942    /* generate random CEK */
 9943    ret = PKCS7_GenerateContentEncryptionKey(pkcs7, (word32)cekKeySz);
 9944    if (ret < 0)
 9945        return ret;
 9946
 9947    /* generate random IV */
 9948    ret = wc_PKCS7_GenerateBlock(pkcs7, NULL, tmpIv, (word32)kekBlockSz);
 9949    if (ret != 0)
 9950        return ret;
 9951
 9952    /* allocate memory for RecipientInfo, KEK, encrypted key */
 9953    recip = (Pkcs7EncodedRecip*)XMALLOC(sizeof(Pkcs7EncodedRecip),
 9954                                        pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 9955    if (recip == NULL)
 9956        return MEMORY_E;
 9957
 9958    kek = (byte*)XMALLOC((word32)kekKeySz, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 9959    if (kek == NULL) {
 9960        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 9961        return MEMORY_E;
 9962    }
 9963
 9964    encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ,
 9965                                  pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 9966    if (encryptedKey == NULL) {
 9967        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 9968        XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 9969        return MEMORY_E;
 9970    }
 9971
 9972    encryptedKeySz = MAX_ENCRYPTED_KEY_SZ;
 9973    XMEMSET(recip, 0, sizeof(Pkcs7EncodedRecip));
 9974    XMEMSET(kek, 0, (word32)kekKeySz);
 9975    XMEMSET(encryptedKey, 0, encryptedKeySz);
 9976
 9977    /* generate KEK: expand password into KEK */
 9978    ret = wc_PKCS7_GenerateKEK_PWRI(pkcs7, passwd, pLen, salt, saltSz,
 9979                                    kdfOID, hashOID, iterations, kek,
 9980                                    (word32)kekKeySz);
 9981    if (ret < 0) {
 9982        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 9983        ForceZero(kek, (word32)kekKeySz);
 9984        XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 9985        XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 9986        return ret;
 9987    }
 9988
 9989    /* generate encrypted key: encrypt CEK with KEK */
 9990    ret = wc_PKCS7_PwriKek_KeyWrap(pkcs7, kek, (word32)kekKeySz, pkcs7->cek,
 9991                                   pkcs7->cekSz, encryptedKey, &encryptedKeySz,
 9992                                   tmpIv, (word32)kekBlockSz, encryptOID);
 9993    if (ret < 0) {
 9994        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 9995        ForceZero(kek, (word32)kekKeySz);
 9996        XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 9997        XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
 9998        return ret;
 9999    }
10000    encryptedKeySz = (word32)ret;
10001
10002    /* put together encrypted key OCTET STRING */
10003    encKeyOctetStrSz = SetOctetString(encryptedKeySz, encKeyOctetStr);
10004    totalSz += (encKeyOctetStrSz + encryptedKeySz);
10005
10006    /* put together IV OCTET STRING */
10007    ivOctetStringSz = SetOctetString((word32)kekBlockSz, ivOctetString);
10008    totalSz += (ivOctetStringSz + (word32)kekBlockSz);
10009
10010    /* set PWRIAlgorithms AlgorithmIdentifier, adding (ivOctetStringSz +
10011       blockKeySz) for IV OCTET STRING */
10012    pwriEncAlgoIdSz = SetAlgoID(encryptOID, pwriEncAlgoId,
10013                                oidBlkType, (int)ivOctetStringSz + kekBlockSz);
10014    totalSz += pwriEncAlgoIdSz;
10015
10016    /* set KeyEncryptionAlgorithms OID */
10017    ret = wc_SetContentType(PWRI_KEK_WRAP, keyEncAlgoId, sizeof(keyEncAlgoId));
10018    if (ret <= 0) {
10019        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10020        ForceZero(kek, (word32)kekKeySz);
10021        XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10022        XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10023        return ret;
10024    }
10025    keyEncAlgoIdSz = (word32)ret;
10026    totalSz += keyEncAlgoIdSz;
10027
10028    /* KeyEncryptionAlgorithm SEQ */
10029    keyEncAlgoIdSeqSz = SetSequence(keyEncAlgoIdSz + pwriEncAlgoIdSz +
10030                                    ivOctetStringSz + (word32)kekBlockSz,
10031                                    keyEncAlgoIdSeq);
10032    totalSz += keyEncAlgoIdSeqSz;
10033
10034    /* set KDF salt */
10035    kdfSaltOctetStrSz = SetOctetString(saltSz, kdfSaltOctetStr);
10036    totalSz += (kdfSaltOctetStrSz + saltSz);
10037
10038    /* set KDF iteration count */
10039    kdfIterationsSz = (word32)SetMyVersion((word32)iterations, kdfIterations,
10040        0);
10041    totalSz += kdfIterationsSz;
10042
10043    /* set KDF params SEQ */
10044    kdfParamsSeqSz = SetSequence(kdfSaltOctetStrSz + saltSz + kdfIterationsSz,
10045                                 kdfParamsSeq);
10046    totalSz += kdfParamsSeqSz;
10047
10048    /* set KDF algo OID */
10049    ret = wc_SetContentType(kdfOID, kdfAlgoId, sizeof(kdfAlgoId));
10050    if (ret <= 0) {
10051        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10052        ForceZero(kek, (word32)kekKeySz);
10053        XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10054        XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10055        return ret;
10056    }
10057    kdfAlgoIdSz = (word32)ret;
10058    totalSz += kdfAlgoIdSz;
10059
10060    /* set KeyDerivationAlgorithmIdentifier EXPLICIT [0] SEQ */
10061    kdfAlgoIdSeqSz = SetExplicit(0, kdfAlgoIdSz + kdfParamsSeqSz +
10062                                 kdfSaltOctetStrSz + saltSz + kdfIterationsSz,
10063                                 kdfAlgoIdSeq, 0);
10064    totalSz += kdfAlgoIdSeqSz;
10065
10066    /* set PasswordRecipientInfo CMSVersion, MUST be 0 */
10067    verSz = (word32)SetMyVersion(0, ver, 0);
10068    totalSz += verSz;
10069    recip->recipVersion = 0;
10070
10071    /* set PasswordRecipientInfo SEQ */
10072    recipSeqSz = SetImplicit(ASN_SEQUENCE, 3, totalSz, recipSeq, 0);
10073    totalSz += recipSeqSz;
10074
10075    if (totalSz > MAX_RECIP_SZ) {
10076        WOLFSSL_MSG("CMS Recipient output buffer too small");
10077        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10078        ForceZero(kek, (word32)kekKeySz);
10079        XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10080        XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10081        return BUFFER_E;
10082    }
10083
10084    idx = 0;
10085    XMEMCPY(recip->recip + idx, recipSeq, recipSeqSz);
10086    idx += recipSeqSz;
10087    XMEMCPY(recip->recip + idx, ver, verSz);
10088    idx += verSz;
10089    XMEMCPY(recip->recip + idx, kdfAlgoIdSeq, kdfAlgoIdSeqSz);
10090    idx += kdfAlgoIdSeqSz;
10091    XMEMCPY(recip->recip + idx, kdfAlgoId, kdfAlgoIdSz);
10092    idx += kdfAlgoIdSz;
10093    XMEMCPY(recip->recip + idx, kdfParamsSeq, kdfParamsSeqSz);
10094    idx += kdfParamsSeqSz;
10095    XMEMCPY(recip->recip + idx, kdfSaltOctetStr, kdfSaltOctetStrSz);
10096    idx += kdfSaltOctetStrSz;
10097    XMEMCPY(recip->recip + idx, salt, saltSz);
10098    idx += saltSz;
10099    XMEMCPY(recip->recip + idx, kdfIterations, kdfIterationsSz);
10100    idx += kdfIterationsSz;
10101    XMEMCPY(recip->recip + idx, keyEncAlgoIdSeq, keyEncAlgoIdSeqSz);
10102    idx += keyEncAlgoIdSeqSz;
10103    XMEMCPY(recip->recip + idx, keyEncAlgoId, keyEncAlgoIdSz);
10104    idx += keyEncAlgoIdSz;
10105    XMEMCPY(recip->recip + idx, pwriEncAlgoId, pwriEncAlgoIdSz);
10106    idx += pwriEncAlgoIdSz;
10107    XMEMCPY(recip->recip + idx, ivOctetString, ivOctetStringSz);
10108    idx += ivOctetStringSz;
10109    XMEMCPY(recip->recip + idx, tmpIv, (word32)kekBlockSz);
10110    idx += (word32)kekBlockSz;
10111    XMEMCPY(recip->recip + idx, encKeyOctetStr, encKeyOctetStrSz);
10112    idx += encKeyOctetStrSz;
10113    XMEMCPY(recip->recip + idx, encryptedKey, encryptedKeySz);
10114    idx += encryptedKeySz;
10115
10116    ForceZero(kek, (word32)kekKeySz);
10117    ForceZero(encryptedKey, encryptedKeySz);
10118    XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10119    XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10120
10121    /* store recipient size */
10122    recip->recipSz = idx;
10123    recip->recipType = PKCS7_PWRI;
10124
10125    /* add recipient to recip list */
10126    if (pkcs7->recipList == NULL) {
10127        pkcs7->recipList = recip;
10128    } else {
10129        lastRecip = pkcs7->recipList;
10130        while (lastRecip->next != NULL) {
10131            lastRecip = lastRecip->next;
10132        }
10133        lastRecip->next = recip;
10134    }
10135
10136    (void)options;
10137
10138    return (int)idx;
10139}
10140
10141/* Import password and KDF settings into a PKCS7 structure. Used for setting
10142 * the password info for decryption a EnvelopedData PWRI RecipientInfo.
10143 *
10144 * Returns 0 on success, negative upon error */
10145int wc_PKCS7_SetPassword(wc_PKCS7* pkcs7, byte* passwd, word32 pLen)
10146{
10147    if (pkcs7 == NULL || passwd == NULL || pLen == 0)
10148        return BAD_FUNC_ARG;
10149
10150    pkcs7->pass = passwd;
10151    pkcs7->passSz = pLen;
10152
10153    return 0;
10154}
10155
10156#endif /* NO_PWDBASED */
10157
10158
10159/* Encode and add CMS EnvelopedData KEKRI (KEKRecipientInfo) RecipientInfo
10160 * to CMS/PKCS#7 EnvelopedData structure.
10161 *
10162 * pkcs7 - pointer to initialized PKCS7 structure
10163 * keyWrapOID - OID sum of key wrap algorithm identifier
10164 * kek        - key encryption key
10165 * kekSz      - size of kek, bytes
10166 * keyID      - key-encryption key identifier, pre-distributed to endpoints
10167 * keyIDSz    - size of keyID, bytes
10168 * timePtr    - pointer to "time_t", which is typically "long" (OPTIONAL)
10169 * otherOID   - ASN.1 encoded OID of other attribute (OPTIONAL)
10170 * otherOIDSz - size of otherOID, bytes (OPTIONAL)
10171 * other      - other attribute (OPTIONAL)
10172 * otherSz    - size of other (OPTIONAL)
10173 *
10174 * Returns 0 on success, negative upon error */
10175int wc_PKCS7_AddRecipient_KEKRI(wc_PKCS7* pkcs7, int keyWrapOID, byte* kek,
10176                                word32 kekSz, byte* keyId, word32 keyIdSz,
10177                                void* timePtr, byte* otherOID,
10178                                word32 otherOIDSz, byte* other, word32 otherSz,
10179                                int options)
10180{
10181    Pkcs7EncodedRecip* recip = NULL;
10182    Pkcs7EncodedRecip* lastRecip = NULL;
10183
10184    byte recipSeq[MAX_SEQ_SZ];
10185    byte ver[MAX_VERSION_SZ];
10186    byte kekIdSeq[MAX_SEQ_SZ];
10187    byte kekIdOctetStr[MAX_OCTET_STR_SZ];
10188    byte genTime[ASN_GENERALIZED_TIME_SIZE];
10189    byte otherAttSeq[MAX_SEQ_SZ];
10190    byte encAlgoId[MAX_ALGO_SZ];
10191    byte encKeyOctetStr[MAX_OCTET_STR_SZ];
10192    WC_DECLARE_VAR(encryptedKey, byte, MAX_ENCRYPTED_KEY_SZ, 0);
10193
10194    int blockKeySz = 0, ret = 0, direction;
10195    word32 idx = 0;
10196    word32 totalSz = 0;
10197    word32 recipSeqSz = 0, verSz = 0;
10198    word32 kekIdSeqSz = 0, kekIdOctetStrSz = 0;
10199    word32 otherAttSeqSz = 0, encAlgoIdSz = 0, encKeyOctetStrSz = 0;
10200    int encryptedKeySz;
10201
10202    int timeSz = 0;
10203#ifndef NO_ASN_TIME
10204    time_t* tm = NULL;
10205#endif
10206
10207    if (pkcs7 == NULL || kek == NULL || keyId == NULL)
10208        return BAD_FUNC_ARG;
10209
10210    recip = (Pkcs7EncodedRecip*)XMALLOC(sizeof(Pkcs7EncodedRecip), pkcs7->heap,
10211                                 DYNAMIC_TYPE_PKCS7);
10212    if (recip == NULL)
10213        return MEMORY_E;
10214
10215    XMEMSET(recip, 0, sizeof(Pkcs7EncodedRecip));
10216
10217    /* get key size for content-encryption key based on algorithm */
10218    blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID);
10219    if (blockKeySz < 0) {
10220        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10221        return blockKeySz;
10222    }
10223
10224    /* generate random content encryption key, if needed */
10225    ret = PKCS7_GenerateContentEncryptionKey(pkcs7, (word32)blockKeySz);
10226    if (ret < 0) {
10227        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10228        return ret;
10229    }
10230
10231    /* EncryptedKey */
10232#ifdef WOLFSSL_SMALL_STACK
10233    encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap,
10234                                  DYNAMIC_TYPE_PKCS7);
10235    if (encryptedKey == NULL) {
10236        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10237        return MEMORY_E;
10238    }
10239#endif
10240    encryptedKeySz = MAX_ENCRYPTED_KEY_SZ;
10241    XMEMSET(encryptedKey, 0, (word32)encryptedKeySz);
10242
10243    #ifndef NO_AES
10244        direction = AES_ENCRYPTION;
10245    #else
10246        direction = DES_ENCRYPTION;
10247    #endif
10248
10249    encryptedKeySz = wc_PKCS7_KeyWrap(pkcs7, pkcs7->cek, pkcs7->cekSz, kek,
10250            kekSz, encryptedKey, (word32)encryptedKeySz, keyWrapOID, direction);
10251    if (encryptedKeySz < 0) {
10252        WC_FREE_VAR_EX(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10253        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10254        return encryptedKeySz;
10255    }
10256    /* handle a zero size encKey case as WC_KEY_SIZE_E */
10257    if (encryptedKeySz == 0 || encryptedKeySz > MAX_ENCRYPTED_KEY_SZ) {
10258        WC_FREE_VAR_EX(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10259        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10260        return WC_KEY_SIZE_E;
10261    }
10262
10263    encKeyOctetStrSz = SetOctetString((word32)encryptedKeySz, encKeyOctetStr);
10264    totalSz += (encKeyOctetStrSz + (word32)encryptedKeySz);
10265
10266    /* KeyEncryptionAlgorithmIdentifier */
10267    encAlgoIdSz = SetAlgoID(keyWrapOID, encAlgoId, oidKeyWrapType, 0);
10268    totalSz += encAlgoIdSz;
10269
10270    /* KEKIdentifier: keyIdentifier */
10271    kekIdOctetStrSz = SetOctetString(keyIdSz, kekIdOctetStr);
10272    totalSz += (kekIdOctetStrSz + keyIdSz);
10273
10274    /* KEKIdentifier: GeneralizedTime (OPTIONAL) */
10275#ifndef NO_ASN_TIME
10276    if (timePtr != NULL) {
10277        tm = (time_t*)timePtr;
10278        timeSz = GetAsnTimeString(tm, genTime, sizeof(genTime));
10279        if (timeSz < 0) {
10280            XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10281            WC_FREE_VAR_EX(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10282            return timeSz;
10283        }
10284        totalSz += (word32)timeSz;
10285    }
10286#endif
10287
10288    /* KEKIdentifier: OtherKeyAttribute SEQ (OPTIONAL) */
10289    if (other != NULL && otherSz > 0) {
10290        otherAttSeqSz = SetSequence(otherOIDSz + otherSz, otherAttSeq);
10291        totalSz += otherAttSeqSz + otherOIDSz + otherSz;
10292    }
10293
10294    /* KEKIdentifier SEQ */
10295    kekIdSeqSz = SetSequence(kekIdOctetStrSz + keyIdSz + (word32)timeSz +
10296                             otherAttSeqSz + otherOIDSz + otherSz, kekIdSeq);
10297    totalSz += kekIdSeqSz;
10298
10299    /* version */
10300    verSz = (word32)SetMyVersion(4, ver, 0);
10301    totalSz += verSz;
10302    recip->recipVersion = 4;
10303
10304    /* KEKRecipientInfo SEQ */
10305    recipSeqSz = SetImplicit(ASN_SEQUENCE, 2, totalSz, recipSeq, 0);
10306    totalSz += recipSeqSz;
10307
10308    if (totalSz > MAX_RECIP_SZ) {
10309        WOLFSSL_MSG("CMS Recipient output buffer too small");
10310        XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10311        WC_FREE_VAR_EX(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10312        return BUFFER_E;
10313    }
10314
10315    XMEMCPY(recip->recip + idx, recipSeq, recipSeqSz);
10316    idx += recipSeqSz;
10317    XMEMCPY(recip->recip + idx, ver, verSz);
10318    idx += verSz;
10319    XMEMCPY(recip->recip + idx, kekIdSeq, kekIdSeqSz);
10320    idx += kekIdSeqSz;
10321    XMEMCPY(recip->recip + idx, kekIdOctetStr, kekIdOctetStrSz);
10322    idx += kekIdOctetStrSz;
10323    XMEMCPY(recip->recip + idx, keyId, keyIdSz);
10324    idx += keyIdSz;
10325    if (timePtr != NULL) {
10326        XMEMCPY(recip->recip + idx, genTime, (word32)timeSz);
10327        idx += (word32)timeSz;
10328    }
10329    if (other != NULL && otherSz > 0) {
10330        XMEMCPY(recip->recip + idx, otherAttSeq, otherAttSeqSz);
10331        idx += otherAttSeqSz;
10332        XMEMCPY(recip->recip + idx, otherOID, otherOIDSz);
10333        idx += otherOIDSz;
10334        XMEMCPY(recip->recip + idx, other, otherSz);
10335        idx += otherSz;
10336    }
10337    XMEMCPY(recip->recip + idx, encAlgoId, encAlgoIdSz);
10338    idx += encAlgoIdSz;
10339    XMEMCPY(recip->recip + idx, encKeyOctetStr, encKeyOctetStrSz);
10340    idx += encKeyOctetStrSz;
10341    XMEMCPY(recip->recip + idx, encryptedKey, (word32)encryptedKeySz);
10342    idx += (word32)encryptedKeySz;
10343
10344    WC_FREE_VAR_EX(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10345
10346    /* store recipient size */
10347    recip->recipSz = idx;
10348    recip->recipType = PKCS7_KEKRI;
10349
10350    /* add recipient to recip list */
10351    if (pkcs7->recipList == NULL) {
10352        pkcs7->recipList = recip;
10353    } else {
10354        lastRecip = pkcs7->recipList;
10355        while(lastRecip->next != NULL) {
10356            lastRecip = lastRecip->next;
10357        }
10358        lastRecip->next = recip;
10359    }
10360
10361    (void)options;
10362
10363    return (int)idx;
10364}
10365
10366
10367static int wc_PKCS7_GetCMSVersion(wc_PKCS7* pkcs7, int cmsContentType)
10368{
10369    int version = -1;
10370
10371    if (pkcs7 == NULL)
10372        return BAD_FUNC_ARG;
10373
10374    switch (cmsContentType) {
10375        case ENVELOPED_DATA:
10376
10377            /* NOTE: EnvelopedData does not currently support
10378               originatorInfo or unprotectedAttributes. When either of these
10379               are added, version checking below needs to be updated to match
10380               Section 6.1 of RFC 5652 */
10381
10382            /* if RecipientInfos include pwri or ori, version is 3 */
10383            if (wc_PKCS7_RecipientListIncludesType(pkcs7, PKCS7_PWRI) ||
10384                wc_PKCS7_RecipientListIncludesType(pkcs7, PKCS7_ORI)) {
10385                version = 3;
10386                break;
10387            }
10388
10389            /* if unprotectedAttrs is absent AND all RecipientInfo structs
10390               are version 0, version is 0 */
10391            if (wc_PKCS7_RecipientListVersionsAllZero(pkcs7)) {
10392                version = 0;
10393                break;
10394            }
10395
10396            /* otherwise, version is 2 */
10397            version = 2;
10398            break;
10399
10400        default:
10401            break;
10402    }
10403
10404    return version;
10405}
10406
10407
10408/* build PKCS#7 envelopedData content type, return enveloped size */
10409int wc_PKCS7_EncodeEnvelopedData(wc_PKCS7* pkcs7, byte* output, word32 outputSz)
10410{
10411    int ret, idx = 0;
10412    int totalSz, padSz, encryptedOutSz;
10413
10414    int contentInfoSeqSz = 0, outerContentTypeSz = 0, outerContentSz;
10415    byte contentInfoSeq[MAX_SEQ_SZ];
10416    byte outerContentType[MAX_ALGO_SZ];
10417    byte outerContent[MAX_SEQ_SZ];
10418
10419    int kariVersion;
10420    int envDataSeqSz, verSz;
10421    byte envDataSeq[MAX_SEQ_SZ];
10422    byte ver[MAX_VERSION_SZ];
10423
10424    WC_RNG rng;
10425    int blockSz, blockKeySz;
10426    byte* plain            = NULL;
10427    byte* encryptedContent = NULL;
10428
10429    Pkcs7EncodedRecip* tmpRecip = NULL;
10430    int recipSz, recipSetSz;
10431    byte recipSet[MAX_SET_SZ];
10432
10433    int encContentOctetSz, encContentSeqSz, contentTypeSz;
10434    int contentEncAlgoSz, ivOctetStringSz;
10435    byte encContentSeq[MAX_SEQ_SZ];
10436    byte contentType[MAX_ALGO_SZ];
10437    byte contentEncAlgo[MAX_ALGO_SZ];
10438    byte tmpIv[MAX_CONTENT_IV_SIZE];
10439    byte ivOctetString[MAX_OCTET_STR_SZ];
10440    byte encContentOctet[MAX_OCTET_STR_SZ];
10441#ifdef ASN_BER_TO_DER
10442    word32 streamSz = 0;
10443#endif
10444
10445    if (pkcs7 == NULL
10446        #ifndef ASN_BER_TO_DER
10447            || pkcs7->content == NULL
10448        #endif
10449            || pkcs7->contentSz == 0) {
10450        return BAD_FUNC_ARG;
10451    }
10452
10453#ifndef ASN_BER_TO_DER
10454    if (output == NULL || outputSz == 0) {
10455        return BAD_FUNC_ARG;
10456    }
10457#else
10458    /* if both output and callback are not set then error out */
10459    if ((output == NULL || outputSz == 0) && (pkcs7->streamOutCb == NULL)) {
10460        return BAD_FUNC_ARG;
10461    }
10462#endif
10463
10464    blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID);
10465    if (blockKeySz < 0)
10466        return blockKeySz;
10467
10468    blockSz = wc_PKCS7_GetOIDBlockSize(pkcs7->encryptOID);
10469    if (blockSz < 0)
10470        return blockSz;
10471
10472    if (pkcs7->contentOID != FIRMWARE_PKG_DATA) {
10473        /* outer content type */
10474        ret = wc_SetContentType(ENVELOPED_DATA, outerContentType,
10475                                sizeof(outerContentType));
10476        if (ret < 0)
10477            return ret;
10478
10479        outerContentTypeSz = ret;
10480    }
10481
10482    /* generate random content encryption key */
10483    ret = PKCS7_GenerateContentEncryptionKey(pkcs7, (word32)blockKeySz);
10484    if (ret != 0) {
10485        return ret;
10486    }
10487
10488    /* build RecipientInfo, only if user manually set singleCert and size */
10489    if (pkcs7->singleCert != NULL && pkcs7->singleCertSz > 0) {
10490        switch (pkcs7->publicKeyOID) {
10491        #ifndef NO_RSA
10492        #ifdef WC_RSA_PSS
10493            case RSAPSSk:
10494                FALL_THROUGH;
10495        #endif
10496            case RSAk:
10497                ret = wc_PKCS7_AddRecipient_KTRI(pkcs7, pkcs7->singleCert,
10498                                                 pkcs7->singleCertSz, 0);
10499                break;
10500        #endif
10501        #ifdef HAVE_ECC
10502            case ECDSAk:
10503                ret = wc_PKCS7_AddRecipient_KARI(pkcs7, pkcs7->singleCert,
10504                                                 pkcs7->singleCertSz,
10505                                                 pkcs7->keyWrapOID,
10506                                                 pkcs7->keyAgreeOID, pkcs7->ukm,
10507                                                 pkcs7->ukmSz, 0);
10508                break;
10509        #endif
10510
10511            default:
10512                WOLFSSL_MSG("Unsupported RecipientInfo public key type");
10513                return BAD_FUNC_ARG;
10514        };
10515
10516        if (ret < 0) {
10517            WOLFSSL_MSG("Failed to create RecipientInfo");
10518            return ret;
10519        }
10520    }
10521
10522    recipSz = wc_PKCS7_GetRecipientListSize(pkcs7);
10523    if (recipSz < 0) {
10524        return ret;
10525
10526    } else if (recipSz == 0) {
10527        WOLFSSL_MSG("You must add at least one CMS recipient");
10528        return PKCS7_RECIP_E;
10529    }
10530    recipSetSz = (int)SetSet((word32)recipSz, recipSet);
10531
10532    /* version, defined in Section 6.1 of RFC 5652 */
10533    kariVersion = wc_PKCS7_GetCMSVersion(pkcs7, ENVELOPED_DATA);
10534    if (kariVersion < 0) {
10535        wc_PKCS7_FreeEncodedRecipientSet(pkcs7);
10536        WOLFSSL_MSG("Failed to set CMS EnvelopedData version");
10537        return PKCS7_RECIP_E;
10538    }
10539
10540    verSz = SetMyVersion((word32)kariVersion, ver, 0);
10541
10542    ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId);
10543    if (ret != 0) {
10544        wc_PKCS7_FreeEncodedRecipientSet(pkcs7);
10545        return ret;
10546    }
10547
10548    /* generate IV for block cipher */
10549    ret = wc_PKCS7_GenerateBlock(pkcs7, &rng, tmpIv, (word32)blockSz);
10550    wc_FreeRng(&rng);
10551    if (ret != 0) {
10552        wc_PKCS7_FreeEncodedRecipientSet(pkcs7);
10553        return ret;
10554    }
10555
10556    /* EncryptedContentInfo */
10557    ret = wc_SetContentType(pkcs7->contentOID, contentType,
10558                            sizeof(contentType));
10559    if (ret < 0) {
10560        wc_PKCS7_FreeEncodedRecipientSet(pkcs7);
10561        return ret;
10562    }
10563
10564    contentTypeSz = ret;
10565
10566    /* allocate encrypted content buffer and PKCS#7 padding */
10567    padSz = wc_PKCS7_GetPadSize(pkcs7->contentSz, (word32)blockSz);
10568    if (padSz < 0) {
10569        wc_PKCS7_FreeEncodedRecipientSet(pkcs7);
10570        return padSz;
10571    }
10572
10573    encryptedOutSz = (int)pkcs7->contentSz + padSz;
10574
10575#ifdef ASN_BER_TO_DER
10576    if (pkcs7->getContentCb == NULL)
10577#endif
10578    {
10579        plain = (byte*)XMALLOC((word32)encryptedOutSz, pkcs7->heap,
10580                               DYNAMIC_TYPE_PKCS7);
10581        if (plain == NULL) {
10582            wc_PKCS7_FreeEncodedRecipientSet(pkcs7);
10583            return MEMORY_E;
10584        }
10585
10586        ret = wc_PKCS7_PadData(pkcs7->content, pkcs7->contentSz, plain,
10587                               (word32)encryptedOutSz, (word32)blockSz);
10588        if (ret < 0) {
10589            ForceZero(plain, (word32)encryptedOutSz);
10590            XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10591            wc_PKCS7_FreeEncodedRecipientSet(pkcs7);
10592            return ret;
10593        }
10594
10595    }
10596
10597#ifdef ASN_BER_TO_DER
10598    if (pkcs7->streamOutCb == NULL)
10599#endif
10600    {
10601        encryptedContent = (byte*)XMALLOC((word32)encryptedOutSz, pkcs7->heap,
10602                                          DYNAMIC_TYPE_PKCS7);
10603        if (encryptedContent == NULL) {
10604            if (plain != NULL)
10605                ForceZero(plain, (word32)encryptedOutSz);
10606            XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10607            wc_PKCS7_FreeEncodedRecipientSet(pkcs7);
10608            return MEMORY_E;
10609        }
10610    }
10611
10612    /* put together IV OCTET STRING */
10613    ivOctetStringSz = (int)SetOctetString((word32)blockSz, ivOctetString);
10614
10615    /* build up our ContentEncryptionAlgorithmIdentifier sequence,
10616     * adding (ivOctetStringSz + blockSz) for IV OCTET STRING */
10617    contentEncAlgoSz = (int)SetAlgoID(pkcs7->encryptOID, contentEncAlgo,
10618                                 oidBlkType, ivOctetStringSz + blockSz);
10619
10620    if (contentEncAlgoSz == 0) {
10621        XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10622        if (plain != NULL)
10623            ForceZero(plain, (word32)encryptedOutSz);
10624        XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10625        wc_PKCS7_FreeEncodedRecipientSet(pkcs7);
10626        return BAD_FUNC_ARG;
10627    }
10628
10629    encContentOctetSz = (int)SetImplicit(ASN_OCTET_STRING, 0,
10630            (word32)encryptedOutSz, encContentOctet, pkcs7->encodeStream);
10631    encContentSeqSz = (int)SetSequenceEx((word32)(contentTypeSz +
10632                              contentEncAlgoSz + ivOctetStringSz + blockSz +
10633                              encContentOctetSz + encryptedOutSz),
10634                              encContentSeq, pkcs7->encodeStream);
10635
10636    /* keep track of sizes for outer wrapper layering */
10637    totalSz = verSz + recipSetSz + recipSz + encContentSeqSz + contentTypeSz +
10638              contentEncAlgoSz + ivOctetStringSz + blockSz +
10639              encContentOctetSz + encryptedOutSz;
10640
10641    /* EnvelopedData */
10642#ifdef ASN_BER_TO_DER
10643    if (pkcs7->encodeStream) {
10644        word32 tmpIdx = 0;
10645
10646        /* account for ending of encContentOctet */
10647        totalSz += ASN_INDEF_END_SZ;
10648
10649        /* account for ending of encContentSeq */
10650        totalSz += ASN_INDEF_END_SZ;
10651
10652        /* account for asn1 syntax around octet strings */
10653        StreamOctetString(NULL, (word32)encryptedOutSz, NULL, &streamSz,
10654                                                                       &tmpIdx);
10655        totalSz += ((int)streamSz - encryptedOutSz);
10656
10657        /* resize encrypted content buffer */
10658        if (encryptedContent != NULL) {
10659            XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10660            encryptedContent = (byte*)XMALLOC(streamSz, pkcs7->heap,
10661                                              DYNAMIC_TYPE_PKCS7);
10662            if (encryptedContent == NULL) {
10663                if (plain != NULL)
10664                    ForceZero(plain, (word32)encryptedOutSz);
10665                XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10666                wc_PKCS7_FreeEncodedRecipientSet(pkcs7);
10667                return MEMORY_E;
10668            }
10669        }
10670    }
10671#endif
10672    envDataSeqSz = (int)SetSequenceEx((word32)totalSz, envDataSeq,
10673        pkcs7->encodeStream);
10674    totalSz += envDataSeqSz;
10675#ifdef ASN_BER_TO_DER
10676    if (pkcs7->encodeStream) {
10677        totalSz += ASN_INDEF_END_SZ;
10678    }
10679#endif
10680
10681    /* outer content */
10682    outerContentSz = (int)SetExplicit(0, (word32)totalSz, outerContent,
10683        pkcs7->encodeStream);
10684#ifdef ASN_BER_TO_DER
10685    if (pkcs7->encodeStream) {
10686        totalSz += ASN_INDEF_END_SZ;
10687    }
10688#endif
10689    totalSz += outerContentTypeSz;
10690    totalSz += outerContentSz;
10691
10692    if (pkcs7->contentOID != FIRMWARE_PKG_DATA) {
10693        /* ContentInfo */
10694        contentInfoSeqSz = (int)SetSequenceEx((word32)totalSz, contentInfoSeq,
10695            pkcs7->encodeStream);
10696        totalSz += contentInfoSeqSz;
10697    #ifdef ASN_BER_TO_DER
10698        if (pkcs7->encodeStream) {
10699            totalSz += ASN_INDEF_END_SZ;
10700        }
10701    #endif
10702    }
10703
10704    if ((totalSz > (int)outputSz)
10705    #ifdef ASN_BER_TO_DER
10706         && (pkcs7->streamOutCb == NULL)
10707    #endif
10708    ) {
10709        WOLFSSL_MSG("Pkcs7_encrypt output buffer too small");
10710        XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10711        if (plain != NULL)
10712            ForceZero(plain, (word32)encryptedOutSz);
10713        XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
10714        wc_PKCS7_FreeEncodedRecipientSet(pkcs7);
10715        return BUFFER_E;
10716    }
10717
10718    /* begin writing out PKCS7 bundle */
10719    if (pkcs7->contentOID != FIRMWARE_PKG_DATA) {
10720        wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL,
10721            contentInfoSeq, (word32)contentInfoSeqSz);
10722        idx += contentInfoSeqSz;
10723        wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL,
10724            outerContentType, (word32)outerContentTypeSz);
10725        idx += outerContentTypeSz;
10726        wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL,
10727            outerContent, (word32)outerContentSz);
10728        idx += outerContentSz;
10729    }
10730
10731    wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL,
10732            envDataSeq, (word32)envDataSeqSz);
10733    idx += envDataSeqSz;
10734    wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL,
10735            ver, (word32)verSz);
10736    idx += verSz;
10737    wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL,
10738            recipSet, (word32)recipSetSz);
10739    idx += recipSetSz;
10740    /* copy in recipients from list */
10741    tmpRecip = pkcs7->recipList;
10742    while (tmpRecip != NULL) {
10743        wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL,
10744            tmpRecip->recip, tmpRecip->recipSz);
10745        idx += (int)tmpRecip->recipSz;
10746        tmpRecip = tmpRecip->next;
10747    }
10748    wc_PKCS7_FreeEncodedRecipientSet(pkcs7);
10749
10750    wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL,
10751            encContentSeq, (word32)encContentSeqSz);
10752    idx += encContentSeqSz;
10753    wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL,
10754            contentType, (word32)contentTypeSz);
10755    idx += contentTypeSz;
10756    wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL,
10757            contentEncAlgo, (word32)contentEncAlgoSz);
10758    idx += contentEncAlgoSz;
10759    wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL,
10760            ivOctetString, (word32)ivOctetStringSz);
10761    idx += ivOctetStringSz;
10762    wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL,
10763            tmpIv, (word32)blockSz);
10764    idx += blockSz;
10765    wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL,
10766            encContentOctet, (word32)encContentOctetSz);
10767    idx += encContentOctetSz;
10768
10769    /* encrypt content */
10770    ret = wc_PKCS7_EncryptContent(pkcs7, pkcs7->encryptOID, pkcs7->cek,
10771            (int)pkcs7->cekSz, tmpIv, blockSz, NULL, 0, NULL, 0, plain,
10772            encryptedOutSz, encryptedContent);
10773    if (ret != 0) {
10774        XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10775
10776        if (plain != NULL)
10777            ForceZero(plain, (word32)encryptedOutSz);
10778        XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10779
10780        wc_PKCS7_FreeEncodedRecipientSet(pkcs7);
10781        return ret;
10782    }
10783
10784#ifdef ASN_BER_TO_DER
10785    /* stream the content (octet string with multiple octet elements) */
10786    if (pkcs7->encodeStream) {
10787        byte indefEnd[ASN_INDEF_END_SZ * 5];
10788        word32 localIdx = 0;
10789
10790        /* advance index past encrypted content */
10791        if (!pkcs7->streamOutCb) {
10792            wc_PKCS7_WriteOut(pkcs7, (output)? output + idx : NULL,
10793                encryptedContent, streamSz);
10794        }
10795        idx += (int)streamSz;
10796
10797        /* end of encrypted content */
10798        localIdx += SetIndefEnd(indefEnd + localIdx);
10799
10800        /* end of encrypted content info */
10801        localIdx += SetIndefEnd(indefEnd + localIdx);
10802
10803        /* end of Enveloped Data seq */
10804        localIdx += SetIndefEnd(indefEnd + localIdx);
10805
10806        /* end of outer content set */
10807        localIdx += SetIndefEnd(indefEnd + localIdx);
10808
10809        /* end of outer content info seq */
10810        localIdx += SetIndefEnd(indefEnd + localIdx);
10811
10812        wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL,
10813            indefEnd, localIdx);
10814        idx += (int)localIdx;
10815    }
10816    else
10817#endif
10818    {
10819        wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL,
10820            encryptedContent, (word32)encryptedOutSz);
10821        idx += encryptedOutSz;
10822    }
10823
10824    if (plain != NULL)
10825        ForceZero(plain, (word32)encryptedOutSz);
10826    XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10827
10828    XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
10829
10830    return idx;
10831}
10832
10833#ifndef NO_RSA
10834#if !defined(NO_HMAC) && !defined(NO_SHA256)
10835/* Bleichenbacher padding-oracle mitigation for PKCS#7/CMS KTRI: produce a
10836 * WC_SHA256_DIGEST_SIZE-byte pseudo-random CEK derived from a fresh
10837 * random seed and the encrypted-key ciphertext. The output is random per
10838 * call (driven by the RNG seed); deriving via HMAC of the ciphertext
10839 * simply gives the same value within one call regardless of where it is
10840 * referenced. Called unconditionally so the work is in the timing path
10841 * regardless of RSA padding validity. */
10842static int wc_PKCS7_KtriFakeCEK(wc_PKCS7* pkcs7, const byte* encryptedKey,
10843                                word32 encryptedKeySz, byte* out)
10844{
10845    int ret;
10846    byte seed[WC_SHA256_DIGEST_SIZE];
10847    WC_RNG* rng = NULL;
10848    int ownRng = 0;
10849    WC_DECLARE_VAR(localRng, WC_RNG, 1, pkcs7->heap);
10850    WC_DECLARE_VAR(hmac, Hmac, 1, pkcs7->heap);
10851
10852    if (pkcs7 == NULL || encryptedKey == NULL || out == NULL) {
10853        return BAD_FUNC_ARG;
10854    }
10855
10856    WC_ALLOC_VAR_EX(hmac, Hmac, 1, pkcs7->heap, DYNAMIC_TYPE_HMAC,
10857                    return MEMORY_E);
10858
10859    /* Prefer a caller-provided RNG to avoid paying a DRBG init/reseed cost
10860     * on every decrypt (and to keep the timing envelope flatter on FIPS /
10861     * HW-RNG builds). Fall back to a one-shot RNG when pkcs7->rng is not
10862     * set. */
10863    if (pkcs7->rng != NULL) {
10864        rng = pkcs7->rng;
10865    }
10866    else {
10867        WC_ALLOC_VAR_EX(localRng, WC_RNG, 1, pkcs7->heap, DYNAMIC_TYPE_RNG,
10868                        WC_FREE_VAR_EX(hmac, pkcs7->heap, DYNAMIC_TYPE_HMAC);
10869                        return MEMORY_E);
10870        ret = wc_InitRng_ex(localRng, pkcs7->heap, pkcs7->devId);
10871        if (ret != 0) {
10872            WC_FREE_VAR_EX(localRng, pkcs7->heap, DYNAMIC_TYPE_RNG);
10873            WC_FREE_VAR_EX(hmac, pkcs7->heap, DYNAMIC_TYPE_HMAC);
10874            return ret;
10875        }
10876        rng = localRng;
10877        ownRng = 1;
10878    }
10879
10880    ret = wc_RNG_GenerateBlock(rng, seed, (word32)sizeof(seed));
10881
10882    if (ownRng) {
10883        wc_FreeRng(localRng);
10884        WC_FREE_VAR_EX(localRng, pkcs7->heap, DYNAMIC_TYPE_RNG);
10885    }
10886
10887    if (ret != 0) {
10888        WC_FREE_VAR_EX(hmac, pkcs7->heap, DYNAMIC_TYPE_HMAC);
10889        return ret;
10890    }
10891
10892    ret = wc_HmacInit(hmac, pkcs7->heap, pkcs7->devId);
10893    if (ret == 0) {
10894        ret = wc_HmacSetKey(hmac, WC_SHA256, seed, (word32)sizeof(seed));
10895        if (ret == 0) {
10896            ret = wc_HmacUpdate(hmac, encryptedKey, encryptedKeySz);
10897        }
10898        if (ret == 0) {
10899            ret = wc_HmacFinal(hmac, out);
10900        }
10901        wc_HmacFree(hmac);
10902    }
10903    ForceZero(seed, sizeof(seed));
10904    WC_FREE_VAR_EX(hmac, pkcs7->heap, DYNAMIC_TYPE_HMAC);
10905    return ret;
10906}
10907#endif /* !NO_HMAC && !NO_SHA256 */
10908
10909/* decode KeyTransRecipientInfo (ktri), return 0 on success, <0 on error */
10910static int wc_PKCS7_DecryptKtri(wc_PKCS7* pkcs7, byte* in, word32 inSz,
10911                               word32* idx, byte* decryptedKey,
10912                               word32* decryptedKeySz, int* recipFound)
10913{
10914    int length, encryptedKeySz = 0, ret = 0;
10915    int keySz, version, sidType = 0;
10916    int keyIdSize;
10917    word32 encOID = 0;
10918    word32 keyIdx;
10919    byte   issuerHash[KEYID_SIZE];
10920    byte*  outKey   = NULL;
10921    byte* pkiMsg    = in;
10922    word32 pkiMsgSz = inSz;
10923    byte   tag;
10924
10925#ifndef WC_NO_RSA_OAEP
10926    word32 outKeySz = 0;
10927#endif
10928#ifndef NO_PKCS7_STREAM
10929    word32 tmpIdx = *idx;
10930#endif
10931#ifdef WC_RSA_BLINDING
10932    WC_RNG rng;
10933#endif
10934
10935    byte* encryptedKey = NULL;
10936
10937#ifdef WOLFSSL_SMALL_STACK
10938    mp_int* serialNum  = NULL;
10939    RsaKey* privKey    = NULL;
10940#else
10941    mp_int serialNum[1];
10942    RsaKey privKey[1];
10943#endif
10944    XMEMSET(issuerHash, 0, sizeof(issuerHash));
10945
10946#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
10947    keyIdSize = wc_HashGetDigestSize(wc_HashTypeConvert(HashIdAlg(
10948           pkcs7->publicKeyOID)));
10949#else
10950    keyIdSize = KEYID_SIZE;
10951#endif
10952
10953    switch (pkcs7->state) {
10954        case WC_PKCS7_DECRYPT_KTRI:
10955        #ifndef NO_PKCS7_STREAM
10956            if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_VERSION_SZ,
10957                            &pkiMsg, idx)) != 0) {
10958                return ret;
10959            }
10960            pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
10961        #endif
10962            if (GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0)
10963                return ASN_PARSE_E;
10964
10965            if (version == 0) {
10966                sidType = CMS_ISSUER_AND_SERIAL_NUMBER;
10967            } else if (version == 2) {
10968                sidType = CMS_SKID;
10969            } else {
10970                return ASN_VERSION_E;
10971            }
10972
10973        #ifndef NO_PKCS7_STREAM
10974            if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) {
10975                    break;
10976            }
10977            wc_PKCS7_StreamStoreVar(pkcs7, 0, sidType, version);
10978
10979            /* @TODO getting total amount left because of GetInt call later on
10980             * this could be optimized to stream better */
10981            if (pkcs7->stream->totalRd > pkcs7->stream->maxLen) {
10982                WOLFSSL_MSG("PKCS7 read more than expected");
10983                ret = BUFFER_E;
10984                break;
10985            }
10986        #endif
10987            wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_KTRI_2);
10988            FALL_THROUGH;
10989
10990        case WC_PKCS7_DECRYPT_KTRI_2:
10991        #ifndef NO_PKCS7_STREAM
10992
10993            if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
10994                            pkcs7->stream->expected, &pkiMsg, idx)) != 0) {
10995                return ret;
10996            }
10997
10998            if (in != pkiMsg) {
10999                pkiMsgSz =  pkcs7->stream->length;
11000            }
11001
11002            wc_PKCS7_StreamGetVar(pkcs7, NULL, &sidType, &version);
11003
11004            /* @TODO get expected size for next part, does not account for
11005             * GetInt call well */
11006            if (pkcs7->stream->expected == MAX_SEQ_SZ) {
11007                int sz;
11008                word32 lidx;
11009
11010                if (sidType == CMS_ISSUER_AND_SERIAL_NUMBER) {
11011                    lidx = *idx;
11012                    ret = GetSequence(pkiMsg, &lidx, &sz, pkiMsgSz);
11013                    if (ret < 0)
11014                        return ret;
11015                }
11016                else {
11017                    lidx = *idx + ASN_TAG_SZ;
11018                    ret = GetLength(pkiMsg, &lidx, &sz, pkiMsgSz);
11019                    if (ret < 0)
11020                        return ret;
11021                }
11022
11023                pkcs7->stream->expected = (word32)sz + MAX_ALGO_SZ + ASN_TAG_SZ +
11024                                          MAX_LENGTH_SZ + 512;
11025                if (pkcs7->stream->length > 0 &&
11026                        pkcs7->stream->length < pkcs7->stream->expected) {
11027                    return WC_PKCS7_WANT_READ_E;
11028                }
11029            }
11030        #endif /* !NO_PKCS7_STREAM */
11031
11032            if (sidType == CMS_ISSUER_AND_SERIAL_NUMBER) {
11033
11034                /* remove IssuerAndSerialNumber */
11035                if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0)
11036                    return ASN_PARSE_E;
11037
11038                if (GetNameHash_ex(pkiMsg, idx, issuerHash, (int)pkiMsgSz,
11039                                   pkcs7->publicKeyOID) < 0)
11040                    return ASN_PARSE_E;
11041
11042                /* if we found correct recipient, issuer hashes will match */
11043                if (XMEMCMP(issuerHash, pkcs7->issuerHash,
11044                            (word32)keyIdSize) == 0) {
11045                    *recipFound = 1;
11046                }
11047
11048                WC_ALLOC_VAR_EX(serialNum, mp_int, 1, pkcs7->heap,
11049                    DYNAMIC_TYPE_TMP_BUFFER, return MEMORY_E);
11050
11051                if (GetInt(serialNum, pkiMsg, idx, pkiMsgSz) < 0) {
11052                    WC_FREE_VAR_EX(serialNum, pkcs7->heap,
11053                        DYNAMIC_TYPE_TMP_BUFFER);
11054                    return ASN_PARSE_E;
11055                }
11056
11057                mp_clear(serialNum);
11058
11059                WC_FREE_VAR_EX(serialNum, pkcs7->heap,
11060                    DYNAMIC_TYPE_TMP_BUFFER);
11061
11062            } else {
11063                /* parse SubjectKeyIdentifier
11064                 * RFC 5652 lists SubjectKeyIdentifier as [0] followed by
11065                 * simple type of octet string
11066                 *
11067                 *  RecipientIdentifier ::= CHOICE {
11068                 *  issuerAndSerialNumber IssuerAndSerialNumber,
11069                 *  subjectKeyIdentifier [0] SubjectKeyIdentifier }
11070                 *
11071                 * The choice of subjectKeyIdentifier (where version was 2) is
11072                 * context specific with tag number 0 within the class.
11073                 */
11074
11075                if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0)
11076                    return ASN_PARSE_E;
11077
11078                /* should be context specific and tag number 0: [0] (0x80) */
11079                if (tag != ASN_CONTEXT_SPECIFIC) {
11080                    return ASN_PARSE_E;
11081                }
11082
11083                if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0)
11084                    return ASN_PARSE_E;
11085
11086                /* Validate SKID container is within buffer */
11087                if ((word32)length > pkiMsgSz - (*idx))
11088                    return BUFFER_E;
11089
11090                /* if we found correct recipient, SKID will match */
11091                if (length == keyIdSize &&
11092                        XMEMCMP(pkiMsg + (*idx), pkcs7->issuerSubjKeyId,
11093                            (word32)keyIdSize) == 0) {
11094                    *recipFound = 1;
11095                }
11096                (*idx) += (word32)length;
11097            }
11098
11099            if (GetAlgoId(pkiMsg, idx, &encOID, oidKeyType, pkiMsgSz) < 0)
11100                return ASN_PARSE_E;
11101
11102            /* key encryption algorithm must be RSA for now */
11103            if (encOID != RSAk
11104            #ifndef WC_NO_RSA_OAEP
11105                && encOID != RSAESOAEPk
11106            #endif
11107                )
11108                return ALGO_ID_E;
11109
11110        #ifndef WC_NO_RSA_OAEP
11111            if (encOID == RSAESOAEPk) {
11112                if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) {
11113                    return ASN_PARSE_E;
11114                }
11115                if (length > 0) {
11116                    WOLFSSL_MSG("only supported default OAEP");
11117                    WOLFSSL_ERROR(ALGO_ID_E);
11118                    return ALGO_ID_E;
11119                }
11120            }
11121        #endif
11122
11123            /* read encryptedKey */
11124            if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0)
11125                return ASN_PARSE_E;
11126
11127            if (tag != ASN_OCTET_STRING)
11128                return ASN_PARSE_E;
11129
11130            if (GetLength(pkiMsg, idx, &encryptedKeySz, pkiMsgSz) < 0) {
11131                return ASN_PARSE_E;
11132            }
11133            if (encryptedKeySz > MAX_ENCRYPTED_KEY_SZ) {
11134               return BUFFER_E;
11135            }
11136
11137        #ifndef NO_PKCS7_STREAM
11138            if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) {
11139                    break;
11140            }
11141            wc_PKCS7_StreamStoreVar(pkcs7, (word32)encryptedKeySz, sidType,
11142                version);
11143            pkcs7->stream->expected = (word32)encryptedKeySz;
11144        #endif
11145            wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_KTRI_3);
11146            FALL_THROUGH;
11147
11148        case WC_PKCS7_DECRYPT_KTRI_3:
11149        #ifndef NO_PKCS7_STREAM
11150            if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
11151                            pkcs7->stream->expected, &pkiMsg, idx)) != 0) {
11152                return ret;
11153            }
11154            encryptedKeySz = (int)pkcs7->stream->expected;
11155        #endif
11156
11157            /* Always allocate to ensure aligned use with RSA */
11158            encryptedKey = (byte*)XMALLOC((word32)encryptedKeySz, pkcs7->heap,
11159                                          DYNAMIC_TYPE_WOLF_BIGINT);
11160            if (encryptedKey == NULL)
11161                return MEMORY_E;
11162
11163            if (*recipFound == 1)
11164                XMEMCPY(encryptedKey, &pkiMsg[*idx], (word32)encryptedKeySz);
11165            *idx += (word32)encryptedKeySz;
11166
11167            /* If this is not the correct recipient then do not try to decode
11168             * the encrypted key */
11169            if (*recipFound == 0) {
11170                XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_WOLF_BIGINT);
11171                ret = PKCS7_RECIP_E;
11172                break;
11173            }
11174
11175            /* load private key */
11176        #ifdef WOLFSSL_SMALL_STACK
11177            privKey = (RsaKey*)XMALLOC(sizeof(RsaKey), pkcs7->heap,
11178                DYNAMIC_TYPE_TMP_BUFFER);
11179            if (privKey == NULL) {
11180                XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_WOLF_BIGINT);
11181                return MEMORY_E;
11182            }
11183        #endif
11184
11185            ret = wc_InitRsaKey_ex(privKey, pkcs7->heap, pkcs7->devId);
11186            if (ret != 0) {
11187                XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_WOLF_BIGINT);
11188                WC_FREE_VAR_EX(privKey, pkcs7->heap,
11189                    DYNAMIC_TYPE_TMP_BUFFER);
11190                return ret;
11191            }
11192
11193            if (pkcs7->privateKey != NULL && pkcs7->privateKeySz > 0) {
11194                keyIdx = 0;
11195                ret = wc_RsaPrivateKeyDecode(pkcs7->privateKey, &keyIdx,
11196                        privKey, pkcs7->privateKeySz);
11197            }
11198            else if (pkcs7->devId == INVALID_DEVID) {
11199                ret = BAD_FUNC_ARG;
11200            }
11201            if (ret != 0) {
11202                WOLFSSL_MSG("Failed to decode RSA private key");
11203                wc_FreeRsaKey(privKey);
11204                XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_WOLF_BIGINT);
11205                WC_FREE_VAR_EX(privKey, pkcs7->heap,
11206                    DYNAMIC_TYPE_TMP_BUFFER);
11207                return ret;
11208            }
11209
11210            /* decrypt encryptedKey */
11211            #ifdef WC_RSA_BLINDING
11212            ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId);
11213            if (ret == 0) {
11214                ret = wc_RsaSetRNG(privKey, &rng);
11215            }
11216            #endif
11217            if (ret == 0) {
11218            #ifdef WOLFSSL_ASYNC_CRYPT
11219                /* Currently the call to RSA decrypt here is blocking @TODO */
11220                keySz = 0; /* set initial "ret" value to 0 */
11221                do {
11222                    keySz = wc_AsyncWait(keySz, &privKey->asyncDev,
11223                                         WC_ASYNC_FLAG_CALL_AGAIN);
11224                if (keySz >= 0)
11225            #endif
11226                {
11227            #ifndef WC_NO_RSA_OAEP
11228                    if (encOID != RSAESOAEPk) {
11229            #endif
11230                        keySz = wc_RsaPrivateDecryptInline(encryptedKey,
11231                                                (word32)encryptedKeySz, &outKey,
11232                                                privKey);
11233            #ifndef WC_NO_RSA_OAEP
11234                    }
11235                    else {
11236                        outKeySz = (word32)wc_RsaEncryptSize(privKey);
11237                        outKey = (byte*)XMALLOC(outKeySz, pkcs7->heap,
11238                                                    DYNAMIC_TYPE_TMP_BUFFER);
11239                        if (!outKey) {
11240                            WOLFSSL_MSG("Failed to allocate out key buffer");
11241                            wc_FreeRsaKey(privKey);
11242                            XFREE(encryptedKey, pkcs7->heap,
11243                                                    DYNAMIC_TYPE_WOLF_BIGINT);
11244                                    WC_FREE_VAR_EX(privKey, pkcs7->heap,
11245                                        DYNAMIC_TYPE_TMP_BUFFER);
11246                            WOLFSSL_ERROR_VERBOSE(MEMORY_E);
11247                            return MEMORY_E;
11248                        }
11249
11250                        keySz = wc_RsaPrivateDecrypt_ex(encryptedKey,
11251                                    (word32)encryptedKeySz, outKey, outKeySz,
11252                                    privKey, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA,
11253                                    WC_MGF1SHA1, NULL, 0);
11254                    }
11255            #endif
11256                }
11257            #ifdef WOLFSSL_ASYNC_CRYPT
11258                } while (keySz == WC_NO_ERR_TRACE(WC_PENDING_E));
11259            #endif
11260                #ifdef WC_RSA_BLINDING
11261                    wc_FreeRng(&rng);
11262                #endif
11263            } else {
11264                keySz = ret;
11265            }
11266            wc_FreeRsaKey(privKey);
11267
11268        #if !defined(NO_HMAC) && !defined(NO_SHA256)
11269            {
11270                /* Bleichenbacher padding-oracle mitigation: always compute
11271                 * a pseudo-random fallback CEK so timing and error
11272                 * behaviour do not depend on RSA padding validity. On
11273                 * unwrap failure we substitute the fallback and let
11274                 * content decryption fail indistinguishably from "unwrap
11275                 * succeeded but CEK is wrong". */
11276                byte fakeKey[WC_SHA256_DIGEST_SIZE];
11277                int  fakeRet = wc_PKCS7_KtriFakeCEK(pkcs7, encryptedKey,
11278                                                    (word32)encryptedKeySz,
11279                                                    fakeKey);
11280
11281                if (fakeRet != 0) {
11282                    /* Fallback generation failed (e.g. RNG/HMAC error).
11283                     * Return the fallback-generation status, which does
11284                     * not depend on RSA padding validity, rather than the
11285                     * RSA status which would re-open the oracle. */
11286                    ForceZero(fakeKey, sizeof(fakeKey));
11287                    /* In the non-OAEP path RSA is decrypted in-place via
11288                     * wc_RsaPrivateDecryptInline, so encryptedKey holds
11289                     * the (possibly valid) plaintext CEK. Zero it before
11290                     * free. */
11291                    ForceZero(encryptedKey, (word32)encryptedKeySz);
11292                    XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_WOLF_BIGINT);
11293                    WC_FREE_VAR_EX(privKey, pkcs7->heap,
11294                        DYNAMIC_TYPE_TMP_BUFFER);
11295                #ifndef WC_NO_RSA_OAEP
11296                    if (encOID == RSAESOAEPk) {
11297                        if (outKey != NULL) {
11298                            ForceZero(outKey, outKeySz);
11299                            XFREE(outKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
11300                        }
11301                    }
11302                #endif
11303                    return fakeRet;
11304                }
11305
11306                /* Constant-time select between fake and real CEK. On RSA
11307                 * failure outKey may be NULL or keySz may be <= 0; in
11308                 * both cases the mask selects fakeKey for every byte.
11309                 *
11310                 * To avoid data-dependent branches that leak realLen,
11311                 * copy the real key into a fixed-size zero-padded buffer
11312                 * first, then select byte-by-byte in constant time. */
11313                {
11314                    word32 i;
11315                    byte   useFake;
11316                    int    realLen = keySz;
11317                    byte   realPad[WC_SHA256_DIGEST_SIZE];
11318
11319                    XMEMSET(realPad, 0, sizeof(realPad));
11320                    /* Constant-time copy: avoid data-dependent branches
11321                     * that could leak whether RSA padding was valid.
11322                     * When outKey is NULL (inline RSA failure), use
11323                     * encryptedKey as a safe readable source; the mask
11324                     * will zero out all bytes anyway.  Both encryptedKey
11325                     * and outKey (when non-NULL) are at least
11326                     * sizeof(realPad) bytes for any RSA key size.
11327                     *
11328                     * Use constant-time pointer selection to avoid
11329                     * branching on outKey nullity, which would leak
11330                     * whether RSA PKCS#1 v1.5 padding was valid. */
11331                    {
11332                        byte haveSrc = ctMaskGTE(realLen, 1);
11333                        const byte* srcTbl[2];
11334                        const byte* src;
11335                        word32 j = 0;
11336                        word32 safeJ = 0;
11337
11338                        /* Select source without integer pointer synthesis.
11339                         * Some safety-oriented compilers (e.g. Fil-C) treat
11340                         * int-to-pointer reconstruction as a null-object
11341                         * pointer on dereference. */
11342                        srcTbl[0] = encryptedKey;
11343                        srcTbl[1] = outKey;
11344                        src = srcTbl[haveSrc & 1];
11345
11346                        /* safeJ is clamped to max(0, realLen-1): it
11347                         * only advances while the next index would
11348                         * still be inside realLen, so src[safeJ] is
11349                         * always in bounds.  Bytes at j >= realLen are
11350                         * masked to zero by inBounds anyway. */
11351                        for (j = 0; j < (word32)sizeof(realPad); j++) {
11352                            byte inBounds = ctMaskLT((int)j, realLen);
11353                            byte advance = ctMaskLT((int)(safeJ + 1),
11354                                                    realLen);
11355                            realPad[j] = src[safeJ] & haveSrc & inBounds;
11356                            safeJ += (word32)(advance & 1);
11357                        }
11358                    }
11359                    useFake = ctMaskLT(realLen, 1); /* 0xFF if realLen<=0 */
11360
11361                    for (i = 0; i < (word32)sizeof(fakeKey); i++) {
11362                        decryptedKey[i] = ctMaskSel(useFake, fakeKey[i],
11363                                                    realPad[i]);
11364                    }
11365                    /* Report the real key size on success; on RSA
11366                     * failure (realLen <= 0) report sizeof(fakeKey).
11367                     * Constant-time select avoids branching on RSA
11368                     * padding validity. */
11369                    *decryptedKeySz = (word32)ctMaskSelInt(useFake,
11370                                        (int)sizeof(fakeKey), realLen);
11371                    ForceZero(realPad, sizeof(realPad));
11372                }
11373                ForceZero(fakeKey, sizeof(fakeKey));
11374                /* In the non-OAEP path RSA is decrypted in-place via
11375                 * wc_RsaPrivateDecryptInline, so encryptedKey holds the
11376                 * plaintext CEK after the unwrap. Zero it before free. */
11377                ForceZero(encryptedKey, (word32)encryptedKeySz);
11378            }
11379        #else /* NO_HMAC || NO_SHA256: mitigation unavailable */
11380            #if !defined(WOLFSSL_NO_KTRI_ORACLE_WARNING)
11381                #warning "PKCS7 KTRI Bleichenbacher mitigation requires HMAC " \
11382                    "and SHA256; build without them leaves the RSA unwrap " \
11383                    "error path observable to callers. " \
11384                    "Define WOLFSSL_NO_KTRI_ORACLE_WARNING to silence."
11385            #endif
11386
11387            if (keySz <= 0 || outKey == NULL) {
11388                ForceZero(encryptedKey, (word32)encryptedKeySz);
11389                XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_WOLF_BIGINT);
11390                WC_FREE_VAR_EX(privKey, pkcs7->heap,
11391                    DYNAMIC_TYPE_TMP_BUFFER);
11392            #ifndef WC_NO_RSA_OAEP
11393                if (encOID == RSAESOAEPk) {
11394                    if (outKey) {
11395                        ForceZero(outKey, outKeySz);
11396                        XFREE(outKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
11397                    }
11398                }
11399            #endif
11400                return keySz;
11401            }
11402            else {
11403                *decryptedKeySz = (word32)keySz;
11404                XMEMCPY(decryptedKey, outKey, (word32)keySz);
11405                ForceZero(encryptedKey, (word32)encryptedKeySz);
11406            }
11407        #endif /* !NO_HMAC && !NO_SHA256 */
11408
11409            XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_WOLF_BIGINT);
11410            WC_FREE_VAR_EX(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
11411        #ifndef WC_NO_RSA_OAEP
11412            if (encOID == RSAESOAEPk) {
11413                if (outKey) {
11414                    ForceZero(outKey, outKeySz);
11415                    XFREE(outKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
11416                }
11417            }
11418        #endif
11419        #ifndef NO_PKCS7_STREAM
11420            if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) {
11421                break;
11422            }
11423        #endif
11424            ret = 0; /* success */
11425            break;
11426
11427        default:
11428            WOLFSSL_MSG("PKCS7 Unknown KTRI decrypt state");
11429            ret = BAD_FUNC_ARG;
11430    }
11431
11432    return ret;
11433}
11434#endif /* !NO_RSA */
11435
11436#ifdef HAVE_ECC
11437
11438/* remove ASN.1 OriginatorIdentifierOrKey, return 0 on success, <0 on error */
11439static int wc_PKCS7_KariGetOriginatorIdentifierOrKey(WC_PKCS7_KARI* kari,
11440                        byte* pkiMsg, word32 pkiMsgSz, word32* idx)
11441{
11442    int ret, length;
11443    word32 keyOID, oidSum = 0;
11444    int curve_id = ECC_CURVE_DEF;
11445    byte tag;
11446
11447    if (kari == NULL || pkiMsg == NULL || idx == NULL)
11448        return BAD_FUNC_ARG;
11449
11450    /* remove OriginatorIdentifierOrKey */
11451    if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) == 0 &&
11452            tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) {
11453        if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0)
11454            return ASN_PARSE_E;
11455
11456    } else {
11457        return ASN_PARSE_E;
11458    }
11459
11460    /* remove OriginatorPublicKey */
11461    if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) == 0 &&
11462            tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) {
11463        if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0)
11464            return ASN_PARSE_E;
11465
11466    } else {
11467        return ASN_PARSE_E;
11468    }
11469
11470    /* remove AlgorithmIdentifier */
11471    if (GetAlgoId(pkiMsg, idx, &keyOID, oidKeyType, pkiMsgSz) < 0)
11472        return ASN_PARSE_E;
11473
11474    if (keyOID != ECDSAk)
11475        return ASN_PARSE_E;
11476
11477    /* optional algorithm parameters */
11478    ret = GetObjectId(pkiMsg, idx, &oidSum, oidIgnoreType, pkiMsgSz);
11479    if (ret == 0) {
11480        /* get curve id */
11481        curve_id = wc_ecc_get_oid(oidSum, NULL, 0);
11482        if (curve_id < 0)
11483            return ECC_CURVE_OID_E;
11484    }
11485
11486    /* remove ECPoint BIT STRING */
11487    if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0)
11488        return ASN_PARSE_E;
11489
11490    if (tag != ASN_BIT_STRING)
11491        return ASN_PARSE_E;
11492
11493    if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0)
11494        return ASN_PARSE_E;
11495
11496    /* BIT STRING must have at least unused-bits byte + 1 byte of content */
11497    if (length < 2)
11498        return ASN_PARSE_E;
11499
11500    /* Validate BIT STRING content is within input buffer */
11501    if (*idx > pkiMsgSz || (word32)length > pkiMsgSz - *idx)
11502        return ASN_PARSE_E;
11503
11504    if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0)
11505        return ASN_EXPECT_0_E;
11506
11507    if (tag != ASN_OTHER_TYPE)
11508        return ASN_EXPECT_0_E;
11509
11510    /* get sender ephemeral public ECDSA key */
11511    ret = wc_ecc_init_ex(kari->senderKey, kari->heap, kari->devId);
11512    if (ret != 0)
11513        return ret;
11514
11515    kari->senderKeyInit = 1;
11516
11517    /* length-1 for unused bits counter */
11518    ret = wc_ecc_import_x963_ex(pkiMsg + (*idx), (word32)length - 1,
11519            kari->senderKey, curve_id);
11520    if (ret != 0) {
11521        ret = wc_EccPublicKeyDecode(pkiMsg, idx, kari->senderKey,
11522            *idx + (word32)length - 1);
11523        if (ret != 0)
11524            return ret;
11525    }
11526    else {
11527        (*idx) += (word32)(length - 1);
11528    }
11529
11530    return 0;
11531}
11532
11533
11534/* remove optional UserKeyingMaterial if available, return 0 on success,
11535 * < 0 on error */
11536static int wc_PKCS7_KariGetUserKeyingMaterial(WC_PKCS7_KARI* kari,
11537                        byte* pkiMsg, word32 pkiMsgSz, word32* idx)
11538{
11539    int length;
11540    word32 savedIdx;
11541    byte tag;
11542
11543    if (kari == NULL || pkiMsg == NULL || idx == NULL)
11544        return BAD_FUNC_ARG;
11545
11546    savedIdx = *idx;
11547
11548    /* starts with EXPLICIT [1] */
11549    if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) {
11550        *idx = savedIdx;
11551        return 0;
11552    }
11553    if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) {
11554        *idx = savedIdx;
11555        return 0;
11556    }
11557
11558    if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) {
11559        *idx = savedIdx;
11560        return 0;
11561    }
11562
11563    /* get OCTET STRING */
11564    if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) {
11565        *idx = savedIdx;
11566        return 0;
11567    }
11568    if (tag != ASN_OCTET_STRING) {
11569        *idx = savedIdx;
11570        return 0;
11571    }
11572
11573    if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) {
11574        *idx = savedIdx;
11575        return 0;
11576    }
11577
11578    kari->ukm = NULL;
11579    if (length > 0) {
11580        kari->ukm = (byte*)XMALLOC((word32)length, kari->heap,
11581                                                            DYNAMIC_TYPE_PKCS7);
11582        if (kari->ukm == NULL)
11583            return MEMORY_E;
11584
11585        XMEMCPY(kari->ukm, pkiMsg + (*idx), (word32)length);
11586        kari->ukmOwner = 1;
11587    }
11588
11589    (*idx) += (word32)length;
11590    kari->ukmSz = (word32)length;
11591
11592    return 0;
11593}
11594
11595
11596/* remove ASN.1 KeyEncryptionAlgorithmIdentifier, return 0 on success,
11597 * < 0 on error */
11598static int wc_PKCS7_KariGetKeyEncryptionAlgorithmId(WC_PKCS7_KARI* kari,
11599        byte* pkiMsg, word32 pkiMsgSz, word32* idx,
11600        word32* keyAgreeOID, word32* keyWrapOID)
11601{
11602    int length = 0;
11603    word32 localIdx;
11604
11605    if (kari == NULL || pkiMsg == NULL || idx == NULL ||
11606        keyAgreeOID == NULL || keyWrapOID == NULL)
11607        return BAD_FUNC_ARG;
11608
11609    localIdx = *idx;
11610
11611    /* remove KeyEncryptionAlgorithmIdentifier */
11612    if (GetSequence(pkiMsg, &localIdx, &length, pkiMsgSz) < 0)
11613        return ASN_PARSE_E;
11614
11615    localIdx = *idx;
11616    if (GetAlgoId(pkiMsg, &localIdx, keyAgreeOID, oidCmsKeyAgreeType,
11617              pkiMsgSz) < 0) {
11618        return ASN_PARSE_E;
11619    }
11620
11621    if (localIdx < *idx + (word32)length) {
11622        *idx = localIdx;
11623    }
11624    /* remove KeyWrapAlgorithm, stored in parameter of KeyEncAlgoId */
11625    if (GetAlgoId(pkiMsg, idx, keyWrapOID, oidKeyWrapType, pkiMsgSz) < 0)
11626        return ASN_PARSE_E;
11627
11628    return 0;
11629}
11630
11631
11632/* remove ASN.1 SubjectKeyIdentifier, return 0 on success, < 0 on error
11633 * if subject key ID matches, recipFound is set to 1 */
11634static int wc_PKCS7_KariGetSubjectKeyIdentifier(WC_PKCS7_KARI* kari,
11635                        byte* pkiMsg, word32 pkiMsgSz, word32* idx,
11636                        int* recipFound, byte* rid)
11637{
11638    int length;
11639    byte tag;
11640    int keyIdSize;
11641
11642    if (kari == NULL || pkiMsg == NULL || idx == NULL || recipFound == NULL ||
11643            rid == NULL)
11644        return BAD_FUNC_ARG;
11645
11646#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
11647    keyIdSize = wc_HashGetDigestSize(wc_HashTypeConvert(HashIdAlg(
11648           kari->decoded->signatureOID)));
11649#else
11650    keyIdSize = KEYID_SIZE;
11651#endif
11652
11653    /* remove RecipientKeyIdentifier IMPLICIT [0] */
11654    if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) {
11655        return ASN_PARSE_E;
11656    }
11657
11658    if (tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) {
11659        if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0)
11660            return ASN_PARSE_E;
11661
11662    } else {
11663        return ASN_PARSE_E;
11664    }
11665
11666    /* remove SubjectKeyIdentifier */
11667    if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) {
11668        return ASN_PARSE_E;
11669    }
11670
11671    if (tag != ASN_OCTET_STRING)
11672        return ASN_PARSE_E;
11673
11674    if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0)
11675        return ASN_PARSE_E;
11676
11677    if (length != keyIdSize)
11678        return ASN_PARSE_E;
11679
11680    XMEMCPY(rid, pkiMsg + (*idx), (word32)keyIdSize);
11681    (*idx) += (word32)length;
11682
11683    /* subject key id should match if recipient found */
11684    if (XMEMCMP(rid, kari->decoded->extSubjKeyId, (word32)keyIdSize) == 0) {
11685        *recipFound = 1;
11686    }
11687
11688    return 0;
11689}
11690
11691
11692/* remove ASN.1 IssuerAndSerialNumber, return 0 on success, < 0 on error
11693 * if issuer and serial number match, recipFound is set to 1 */
11694static int wc_PKCS7_KariGetIssuerAndSerialNumber(WC_PKCS7_KARI* kari,
11695                        byte* pkiMsg, word32 pkiMsgSz, word32* idx,
11696                        int* recipFound, byte* rid)
11697{
11698    int length, ret;
11699    int keyIdSize;
11700#ifdef WOLFSSL_SMALL_STACK
11701    mp_int* serial;
11702    mp_int* recipSerial;
11703#else
11704    mp_int  serial[1];
11705    mp_int  recipSerial[1];
11706#endif
11707
11708    if (rid == NULL) {
11709        return BAD_FUNC_ARG;
11710    }
11711
11712#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
11713    keyIdSize = wc_HashGetDigestSize(wc_HashTypeConvert(HashIdAlg(
11714           kari->decoded->signatureOID)));
11715#else
11716    keyIdSize = KEYID_SIZE;
11717#endif
11718
11719    /* remove IssuerAndSerialNumber */
11720    if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0)
11721        return ASN_PARSE_E;
11722
11723    if (GetNameHash_ex(pkiMsg, idx, rid, (int)pkiMsgSz,
11724                       kari->decoded->signatureOID) < 0) {
11725        return ASN_PARSE_E;
11726    }
11727
11728    /* if we found correct recipient, issuer hashes will match */
11729    if (kari->decodedInit == 1) {
11730        if (XMEMCMP(rid, kari->decoded->issuerHash, (word32)keyIdSize) == 0) {
11731            *recipFound = 1;
11732        }
11733    }
11734    else {
11735        /* can not confirm recipient serial number with no cert provided */
11736        WOLFSSL_MSG("No recipient cert loaded to match with CMS serial number");
11737        *recipFound = 1;
11738    }
11739
11740#ifdef WOLFSSL_SMALL_STACK
11741    serial = (mp_int*)XMALLOC(sizeof(mp_int), kari->heap,
11742                              DYNAMIC_TYPE_TMP_BUFFER);
11743    if (serial == NULL)
11744        return MEMORY_E;
11745
11746    recipSerial = (mp_int*)XMALLOC(sizeof(mp_int), kari->heap,
11747                                   DYNAMIC_TYPE_TMP_BUFFER);
11748    if (recipSerial == NULL) {
11749        XFREE(serial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER);
11750        return MEMORY_E;
11751    }
11752#endif
11753
11754    if (GetInt(serial, pkiMsg, idx, pkiMsgSz) < 0) {
11755        WC_FREE_VAR_EX(serial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER);
11756        WC_FREE_VAR_EX(recipSerial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER);
11757        return ASN_PARSE_E;
11758    }
11759
11760    ret = mp_init(recipSerial);
11761    if (ret == MP_OKAY)
11762        ret = mp_read_unsigned_bin(recipSerial, kari->decoded->serial,
11763                             (word32)kari->decoded->serialSz);
11764    if (ret != MP_OKAY) {
11765        mp_clear(serial);
11766        WOLFSSL_MSG("Failed to parse CMS recipient serial number");
11767        WC_FREE_VAR_EX(serial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER);
11768        WC_FREE_VAR_EX(recipSerial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER);
11769        return ret;
11770    }
11771
11772    if (kari->decodedInit == 1 &&
11773            mp_cmp(recipSerial, serial) != MP_EQ) {
11774        mp_clear(serial);
11775        mp_clear(recipSerial);
11776        WOLFSSL_MSG("CMS serial number does not match recipient");
11777        WC_FREE_VAR_EX(serial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER);
11778        WC_FREE_VAR_EX(recipSerial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER);
11779        return PKCS7_RECIP_E;
11780    }
11781
11782    mp_clear(serial);
11783    mp_clear(recipSerial);
11784
11785    WC_FREE_VAR_EX(serial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER);
11786    WC_FREE_VAR_EX(recipSerial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER);
11787
11788    return 0;
11789}
11790
11791
11792/* remove ASN.1 RecipientEncryptedKeys, return 0 on success, < 0 on error */
11793static int wc_PKCS7_KariGetRecipientEncryptedKeys(WC_PKCS7_KARI* kari,
11794                        byte* pkiMsg, word32 pkiMsgSz, word32* idx,
11795                        int* recipFound, byte* encryptedKey,
11796                        int* encryptedKeySz, byte* rid)
11797{
11798    int length;
11799    int ret = 0;
11800    byte tag;
11801    word32 localIdx;
11802
11803    if (kari == NULL || pkiMsg == NULL || idx == NULL ||
11804        recipFound == NULL || encryptedKey == NULL)
11805        return BAD_FUNC_ARG;
11806
11807    /* remove RecipientEncryptedKeys */
11808    if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0)
11809        return ASN_PARSE_E;
11810
11811    /* remove RecipientEncryptedKeys */
11812    if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0)
11813        return ASN_PARSE_E;
11814
11815    /* KeyAgreeRecipientIdentifier is CHOICE of IssuerAndSerialNumber
11816     * or [0] IMPLICIT RecipientKeyIdentifier */
11817    localIdx = *idx;
11818    if (GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) < 0)
11819        return ASN_PARSE_E;
11820
11821    if (tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) {
11822        /* try to get RecipientKeyIdentifier */
11823        ret = wc_PKCS7_KariGetSubjectKeyIdentifier(kari, pkiMsg, pkiMsgSz,
11824                                                   idx, recipFound, rid);
11825    } else {
11826        /* try to get IssuerAndSerialNumber */
11827        ret = wc_PKCS7_KariGetIssuerAndSerialNumber(kari, pkiMsg, pkiMsgSz,
11828                                                    idx, recipFound, rid);
11829    }
11830
11831    /* if we don't have either option, malformed CMS */
11832    if (ret != 0)
11833        return ret;
11834
11835    /* remove EncryptedKey */
11836    if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0)
11837        return ASN_PARSE_E;
11838
11839    if (tag != ASN_OCTET_STRING)
11840        return ASN_PARSE_E;
11841
11842    if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0)
11843        return ASN_PARSE_E;
11844
11845    /* put encrypted CEK in decryptedKey buffer for now, decrypt later */
11846    if (length > *encryptedKeySz)
11847        return BUFFER_E;
11848
11849    XMEMCPY(encryptedKey, pkiMsg + (*idx), (word32)length);
11850    *encryptedKeySz = length;
11851    (*idx) += (word32)length;
11852
11853    return 0;
11854}
11855
11856#endif /* HAVE_ECC */
11857
11858
11859int wc_PKCS7_SetOriEncryptCtx(wc_PKCS7* pkcs7, void* ctx)
11860{
11861    if (pkcs7 == NULL)
11862        return BAD_FUNC_ARG;
11863
11864    pkcs7->oriEncryptCtx = ctx;
11865
11866    return 0;
11867}
11868
11869
11870int wc_PKCS7_SetOriDecryptCtx(wc_PKCS7* pkcs7, void* ctx)
11871{
11872
11873    if (pkcs7 == NULL)
11874        return BAD_FUNC_ARG;
11875
11876    pkcs7->oriDecryptCtx = ctx;
11877
11878    return 0;
11879}
11880
11881
11882int wc_PKCS7_SetOriDecryptCb(wc_PKCS7* pkcs7, CallbackOriDecrypt cb)
11883{
11884    if (pkcs7 == NULL)
11885        return BAD_FUNC_ARG;
11886
11887    pkcs7->oriDecryptCb = cb;
11888
11889    return 0;
11890}
11891
11892
11893/* return 0 on success */
11894int wc_PKCS7_SetWrapCEKCb(wc_PKCS7* pkcs7, CallbackWrapCEK cb)
11895{
11896    if (pkcs7 == NULL)
11897        return BAD_FUNC_ARG;
11898
11899    pkcs7->wrapCEKCb = cb;
11900
11901    return 0;
11902}
11903
11904
11905/* return 0 on success */
11906int wc_PKCS7_SetAESKeyWrapUnwrapCb(wc_PKCS7* pkcs7, CallbackAESKeyWrapUnwrap aesKeyWrapUnwrapCb)
11907{
11908    if (pkcs7 == NULL)
11909        return BAD_FUNC_ARG;
11910
11911    pkcs7->aesKeyWrapUnwrapCb = aesKeyWrapUnwrapCb;
11912
11913    return 0;
11914}
11915
11916
11917/* Decrypt ASN.1 OtherRecipientInfo (ori), as defined by:
11918 *
11919 *   OtherRecipientInfo ::= SEQUENCE {
11920 *     oriType OBJECT IDENTIFIER,
11921 *     oriValue ANY DEFINED BY oriType }
11922 *
11923 * pkcs7          - pointer to initialized PKCS7 structure
11924 * pkiMsg         - pointer to encoded CMS bundle
11925 * pkiMsgSz       - size of pkiMsg, bytes
11926 * idx            - [IN/OUT] pointer to index into pkiMsg
11927 * decryptedKey   - [OUT] output buf for decrypted content encryption key
11928 * decryptedKeySz - [IN/OUT] size of buffer, size of decrypted key
11929 * recipFound     - [OUT] 1 if recipient has been found, 0 if not
11930 *
11931 * Return 0 on success, negative upon error.
11932 */
11933static int wc_PKCS7_DecryptOri(wc_PKCS7* pkcs7, byte* in, word32 inSz,
11934                               word32* idx, byte* decryptedKey,
11935                               word32* decryptedKeySz, int* recipFound)
11936{
11937    int ret, seqSz, oriOIDSz;
11938    word32 oriValueSz, tmpIdx;
11939    byte* oriValue;
11940    byte oriOID[MAX_OID_SZ];
11941
11942    byte* pkiMsg    = in;
11943    word32 pkiMsgSz = inSz;
11944#ifndef NO_PKCS7_STREAM
11945    word32 stateIdx = *idx;
11946#endif
11947
11948    if (pkcs7->oriDecryptCb == NULL) {
11949        WOLFSSL_MSG("You must register an ORI Decrypt callback");
11950        return BAD_FUNC_ARG;
11951    }
11952
11953    switch (pkcs7->state) {
11954
11955        case WC_PKCS7_DECRYPT_ORI:
11956        #ifndef NO_PKCS7_STREAM
11957            /* @TODO for now just get full buffer, needs divided up */
11958            if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
11959                   (pkcs7->stream->maxLen - pkcs7->stream->totalRd) +
11960                   pkcs7->stream->length, &pkiMsg, idx)) != 0) {
11961                return ret;
11962            }
11963            pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
11964        #endif
11965            /* get OtherRecipientInfo sequence length */
11966            if (GetLength(pkiMsg, idx, &seqSz, pkiMsgSz) < 0)
11967                return ASN_PARSE_E;
11968
11969            tmpIdx = *idx;
11970
11971            /* remove and store oriType OBJECT IDENTIFIER */
11972            if (GetASNObjectId(pkiMsg, idx, &oriOIDSz, pkiMsgSz) != 0)
11973                return ASN_PARSE_E;
11974
11975            if (oriOIDSz <= 0 || (word32)oriOIDSz > MAX_OID_SZ) {
11976                WOLFSSL_MSG("ORI oriType OID too large");
11977                return ASN_PARSE_E;
11978            }
11979
11980            XMEMCPY(oriOID, pkiMsg + *idx, (word32)oriOIDSz);
11981            *idx += (word32)oriOIDSz;
11982
11983            /* Validate OID did not consume more than the SEQUENCE declared */
11984            if ((*idx - tmpIdx) > (word32)seqSz) {
11985                WOLFSSL_MSG("ORI oriType OID exceeds SEQUENCE boundary");
11986                return ASN_PARSE_E;
11987            }
11988
11989            /* get oriValue, increment idx */
11990            oriValue = pkiMsg + *idx;
11991            oriValueSz = (word32)seqSz - (*idx - tmpIdx);
11992
11993            /* Validate oriValue region is within input buffer */
11994            if (*idx > pkiMsgSz || oriValueSz > pkiMsgSz - *idx) {
11995                WOLFSSL_MSG("ORI oriValue exceeds input buffer");
11996                return ASN_PARSE_E;
11997            }
11998
11999            *idx += oriValueSz;
12000
12001            /* pass oriOID and oriValue to user callback, expect back
12002               decryptedKey and size */
12003            ret = pkcs7->oriDecryptCb(pkcs7, oriOID, (word32)oriOIDSz, oriValue,
12004                                      oriValueSz, decryptedKey, decryptedKeySz,
12005                                      pkcs7->oriDecryptCtx);
12006
12007            if (ret != 0 || decryptedKey == NULL || *decryptedKeySz == 0) {
12008                /* decrypt operation failed */
12009                *recipFound = 0;
12010                return PKCS7_RECIP_E;
12011            }
12012
12013            /* mark recipFound, since we only support one RecipientInfo for
12014             * now */
12015            *recipFound = 1;
12016
12017        #ifndef NO_PKCS7_STREAM
12018            if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, idx)) != 0) {
12019                break;
12020            }
12021        #endif
12022            ret = 0; /* success */
12023            break;
12024
12025        default:
12026            WOLFSSL_MSG("PKCS7 ORI unknown state");
12027            ret = BAD_FUNC_ARG;
12028
12029    }
12030
12031    return ret;
12032}
12033
12034#if !defined(NO_PWDBASED) && !defined(NO_SHA)
12035
12036/* decode ASN.1 PasswordRecipientInfo (pwri), return 0 on success,
12037 * < 0 on error */
12038static int wc_PKCS7_DecryptPwri(wc_PKCS7* pkcs7, byte* in, word32 inSz,
12039                               word32* idx, byte* decryptedKey,
12040                               word32* decryptedKeySz, int* recipFound)
12041{
12042    byte* salt;
12043    byte* cek;
12044    byte* kek;
12045
12046    byte tmpIv[MAX_CONTENT_IV_SIZE];
12047
12048    int ret = 0, length, saltSz, iterations, blockSz, kekKeySz;
12049    int hashOID = WC_SHA; /* default to SHA1 */
12050    int keyLen = 0;
12051    int keyLenPresent = 0;
12052    word32 pbkdf2End = 0;
12053    word32 kdfAlgoId, pwriEncAlgoId, keyEncAlgoId, cekSz;
12054    byte* pkiMsg = in;
12055    word32 pkiMsgSz = inSz;
12056    byte  tag;
12057#ifndef NO_PKCS7_STREAM
12058    word32 tmpIdx = *idx;
12059#endif
12060
12061    switch (pkcs7->state) {
12062        case WC_PKCS7_DECRYPT_PWRI:
12063        #ifndef NO_PKCS7_STREAM
12064            /*@TODO for now just get full buffer, needs divided up */
12065            if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
12066                   (pkcs7->stream->maxLen - pkcs7->stream->totalRd) +
12067                   pkcs7->stream->length, &pkiMsg, idx)) != 0) {
12068                return ret;
12069            }
12070            #ifdef ASN_BER_TO_DER
12071            /* check if pkcs7->der is being used after BER to DER */
12072            if (pkcs7->derSz > 0) {
12073                pkiMsgSz = pkcs7->derSz;
12074            }
12075            else
12076            #endif
12077            {
12078                pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length:
12079                                                        inSz;
12080            }
12081        #endif
12082            /* remove KeyDerivationAlgorithmIdentifier */
12083            if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0)
12084                return ASN_PARSE_E;
12085
12086            if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
12087                return ASN_PARSE_E;
12088
12089            if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0)
12090                return ASN_PARSE_E;
12091
12092            /* get KeyDerivationAlgorithmIdentifier */
12093            if (wc_GetContentType(pkiMsg, idx, &kdfAlgoId, pkiMsgSz) < 0)
12094                return ASN_PARSE_E;
12095
12096            /* get KDF params SEQ */
12097            if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0)
12098                return ASN_PARSE_E;
12099            pbkdf2End = *idx + (word32)length;
12100
12101            /* get KDF salt OCTET STRING */
12102            if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0)
12103                return ASN_PARSE_E;
12104
12105            if (tag != ASN_OCTET_STRING)
12106                return ASN_PARSE_E;
12107
12108            if (GetLength(pkiMsg, idx, &saltSz, pkiMsgSz) < 0)
12109                return ASN_PARSE_E;
12110
12111            salt = (byte*)XMALLOC((word32)saltSz, pkcs7->heap,
12112                                                            DYNAMIC_TYPE_PKCS7);
12113            if (salt == NULL)
12114                return MEMORY_E;
12115
12116            XMEMCPY(salt, pkiMsg + (*idx), (word32)saltSz);
12117            *idx += (word32)saltSz;
12118
12119            /* get KDF iterations */
12120            if (GetMyVersion(pkiMsg, idx, &iterations, pkiMsgSz) < 0) {
12121                XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12122                return ASN_PARSE_E;
12123            }
12124
12125            /* optional keyLength - validated below once kekKeySz is known */
12126            if (*idx < pbkdf2End && pkiMsg[*idx] == ASN_INTEGER) {
12127                if (GetShortInt(pkiMsg, idx, &keyLen, pbkdf2End) < 0) {
12128                    XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12129                    return ASN_PARSE_E;
12130                }
12131                keyLenPresent = 1;
12132            }
12133
12134            /* optional prf; default hmacWithSHA1 keeps hashOID at WC_SHA */
12135            if (*idx < pbkdf2End &&
12136                    pkiMsg[*idx] == (ASN_SEQUENCE | ASN_CONSTRUCTED)) {
12137                word32 prfOid = 0;
12138                if (GetAlgoId(pkiMsg, idx, &prfOid, oidHmacType,
12139                                                            pbkdf2End) < 0) {
12140                    XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12141                    return ASN_PARSE_E;
12142                }
12143                switch ((int)prfOid) {
12144                #ifdef WOLFSSL_SHA224
12145                    case HMAC_SHA224_OID: hashOID = WC_SHA224; break;
12146                #endif
12147                #ifndef NO_SHA256
12148                    case HMAC_SHA256_OID: hashOID = WC_SHA256; break;
12149                #endif
12150                #ifdef WOLFSSL_SHA384
12151                    case HMAC_SHA384_OID: hashOID = WC_SHA384; break;
12152                #endif
12153                #ifdef WOLFSSL_SHA512
12154                    case HMAC_SHA512_OID: hashOID = WC_SHA512; break;
12155                #endif
12156                    default:
12157                        /* unknown id (incl. explicit hmacWithSHA1) - keep
12158                         * default WC_SHA; MAC unwrap fails if mismatched */
12159                        break;
12160                }
12161            }
12162
12163            /* get KeyEncAlgoId SEQ */
12164            if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) {
12165                XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12166                return ASN_PARSE_E;
12167            }
12168
12169            /* get KeyEncAlgoId */
12170            if (wc_GetContentType(pkiMsg, idx, &keyEncAlgoId, pkiMsgSz) < 0) {
12171                XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12172                return ASN_PARSE_E;
12173            }
12174
12175            /* get pwriEncAlgoId */
12176            if (GetAlgoId(pkiMsg, idx, &pwriEncAlgoId, oidBlkType,
12177                                                                pkiMsgSz) < 0) {
12178                XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12179                return ASN_PARSE_E;
12180            }
12181
12182            blockSz = wc_PKCS7_GetOIDBlockSize((int)pwriEncAlgoId);
12183            if (blockSz < 0) {
12184                XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12185                return blockSz;
12186            }
12187
12188            /* get content-encryption key size, based on algorithm */
12189            kekKeySz = wc_PKCS7_GetOIDKeySize((int)pwriEncAlgoId);
12190            if (kekKeySz < 0) {
12191                XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12192                return kekKeySz;
12193            }
12194
12195            /* RFC 8018: when present, PBKDF2 keyLength must equal the
12196             * derived key length expected by the encryption algorithm */
12197            if (keyLenPresent && keyLen != kekKeySz) {
12198                XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12199                return ASN_PARSE_E;
12200            }
12201
12202            /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */
12203            if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) {
12204                XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12205                return ASN_PARSE_E;
12206            }
12207
12208            if (tag != ASN_OCTET_STRING) {
12209                XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12210                return ASN_PARSE_E;
12211            }
12212
12213            if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) {
12214                XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12215                return ASN_PARSE_E;
12216            }
12217
12218            if (length != blockSz) {
12219                WOLFSSL_MSG("Incorrect IV length, must be of content alg block "
12220                            "size");
12221                XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12222                return ASN_PARSE_E;
12223            }
12224
12225            /* Validate IV is within input buffer */
12226            if (*idx > pkiMsgSz || (word32)length > pkiMsgSz - *idx) {
12227                XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12228                return ASN_PARSE_E;
12229            }
12230
12231            XMEMCPY(tmpIv, pkiMsg + (*idx), (word32)length);
12232            *idx += (word32)length;
12233
12234            /* get EncryptedKey */
12235            if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) {
12236                XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12237                return ASN_PARSE_E;
12238            }
12239
12240            if (tag != ASN_OCTET_STRING) {
12241                XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12242                return ASN_PARSE_E;
12243            }
12244
12245            if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) {
12246                XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12247                return ASN_PARSE_E;
12248            }
12249
12250            /* Validate EncryptedKey is within input buffer */
12251            if (*idx > pkiMsgSz || (word32)length > pkiMsgSz - *idx) {
12252                XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12253                return ASN_PARSE_E;
12254            }
12255
12256            /* allocate temporary space for decrypted key */
12257            cekSz = (word32)length;
12258            cek = (byte*)XMALLOC(cekSz, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
12259            if (cek == NULL) {
12260                XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12261                return MEMORY_E;
12262            }
12263
12264            /* generate KEK */
12265            kek = (byte*)XMALLOC((word32)kekKeySz, pkcs7->heap,
12266                                                            DYNAMIC_TYPE_PKCS7);
12267            if (kek == NULL) {
12268                XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12269                XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12270                return MEMORY_E;
12271            }
12272
12273            ret = wc_PKCS7_GenerateKEK_PWRI(pkcs7, pkcs7->pass, pkcs7->passSz,
12274                                  salt, (word32)saltSz, (int)kdfAlgoId, hashOID,
12275                                  iterations, kek, (word32)kekKeySz);
12276            if (ret < 0) {
12277                XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12278                ForceZero(kek, (word32)kekKeySz);
12279                XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12280                XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12281                return ASN_PARSE_E;
12282            }
12283
12284            /* decrypt CEK with KEK */
12285            ret = wc_PKCS7_PwriKek_KeyUnWrap(pkcs7, kek, (word32)kekKeySz,
12286                                             pkiMsg + (*idx), (word32)length,
12287                                             cek, cekSz, tmpIv, (word32)blockSz,
12288                                             pwriEncAlgoId);
12289            if (ret < 0) {
12290                XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12291                ForceZero(kek, (word32)kekKeySz);
12292                XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12293                ForceZero(cek, cekSz);
12294                XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12295                return ret;
12296            }
12297            cekSz = (word32)ret;
12298
12299            if (*decryptedKeySz < cekSz) {
12300                WOLFSSL_MSG("Decrypted key buffer too small for CEK");
12301                XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12302                ForceZero(kek, (word32)kekKeySz);
12303                XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12304                ForceZero(cek, cekSz);
12305                XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12306                return BUFFER_E;
12307            }
12308
12309            XMEMCPY(decryptedKey, cek, cekSz);
12310            *decryptedKeySz = cekSz;
12311
12312            XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12313            ForceZero(kek, (word32)kekKeySz);
12314            XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12315            ForceZero(cek, cekSz);
12316            XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
12317
12318            /* mark recipFound, since we only support one RecipientInfo for now */
12319            *recipFound = 1;
12320            *idx += (word32)length;
12321        #ifndef NO_PKCS7_STREAM
12322            if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) {
12323                break;
12324            }
12325        #endif
12326            ret = 0; /* success */
12327            break;
12328
12329        default:
12330            WOLFSSL_MSG("PKCS7 PWRI unknown state");
12331            ret = BAD_FUNC_ARG;
12332    }
12333
12334    return ret;
12335}
12336
12337#endif /* NO_PWDBASED | NO_SHA */
12338
12339/* decode ASN.1 KEKRecipientInfo (kekri), return 0 on success,
12340 * < 0 on error */
12341static int wc_PKCS7_DecryptKekri(wc_PKCS7* pkcs7, byte* in, word32 inSz,
12342                               word32* idx, byte* decryptedKey,
12343                               word32* decryptedKeySz, int* recipFound)
12344{
12345    int length, keySz, dateLen, direction;
12346    byte* keyId = NULL;
12347    const byte* datePtr = NULL;
12348    byte  dateFormat, tag;
12349    word32 keyIdSz, kekIdSz, kekIdEnd, keyWrapOID, localIdx;
12350
12351    int ret = 0;
12352    byte* pkiMsg    = in;
12353    word32 pkiMsgSz = inSz;
12354#ifndef NO_PKCS7_STREAM
12355    word32 tmpIdx = *idx;
12356#endif
12357
12358    WOLFSSL_ENTER("wc_PKCS7_DecryptKekri");
12359    switch (pkcs7->state) {
12360        case WC_PKCS7_DECRYPT_KEKRI:
12361        #ifndef NO_PKCS7_STREAM
12362            /* @TODO for now just get full buffer, needs divided up */
12363            if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
12364                   (pkcs7->stream->maxLen - pkcs7->stream->totalRd) +
12365                   pkcs7->stream->length, &pkiMsg, idx)) != 0) {
12366                return ret;
12367            }
12368            pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
12369        #endif
12370            /* remove KEKIdentifier */
12371            if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0)
12372                return ASN_PARSE_E;
12373
12374            kekIdSz = (word32)length;
12375            kekIdEnd = *idx + kekIdSz;
12376
12377            /* Validate KEKIdentifier boundary is within input buffer */
12378            if (kekIdEnd < *idx || kekIdEnd > pkiMsgSz)
12379                return ASN_PARSE_E;
12380
12381            if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0)
12382                return ASN_PARSE_E;
12383
12384            if (tag != ASN_OCTET_STRING)
12385                return ASN_PARSE_E;
12386
12387            if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0)
12388                return ASN_PARSE_E;
12389
12390            /* Validate keyIdentifier is within input buffer */
12391            if (*idx > pkiMsgSz || (word32)length > pkiMsgSz - *idx)
12392                return ASN_PARSE_E;
12393
12394            /* save keyIdentifier and length */
12395            keyId = pkiMsg + *idx;
12396            keyIdSz = (word32)length;
12397            *idx += keyIdSz;
12398
12399            /* may have OPTIONAL GeneralizedTime */
12400            localIdx = *idx;
12401            if ((*idx < kekIdEnd) && GetASNTag(pkiMsg, &localIdx, &tag,
12402                        pkiMsgSz) == 0 && tag == ASN_GENERALIZED_TIME) {
12403                if (wc_GetDateInfo(pkiMsg + *idx, (int)(pkiMsgSz - *idx),
12404                        &datePtr, &dateFormat, &dateLen) != 0) {
12405                    return ASN_PARSE_E;
12406                }
12407                /* datePtr points to the start of the date value
12408                 * within pkiMsg; advance past the full TLV. */
12409                *idx = (word32)(datePtr - pkiMsg) + (word32)dateLen;
12410            }
12411
12412            if (*idx > pkiMsgSz) {
12413                return ASN_PARSE_E;
12414            }
12415
12416            /* may have OPTIONAL OtherKeyAttribute */
12417            localIdx = *idx;
12418            if ((*idx < kekIdEnd) && GetASNTag(pkiMsg, &localIdx, &tag,
12419                            pkiMsgSz) == 0 && tag == (ASN_SEQUENCE |
12420                            ASN_CONSTRUCTED)) {
12421                if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0)
12422                    return ASN_PARSE_E;
12423
12424                /* skip it */
12425                *idx += (word32)length;
12426            }
12427
12428            if (*idx > pkiMsgSz) {
12429                return ASN_PARSE_E;
12430            }
12431
12432            /* get KeyEncryptionAlgorithmIdentifier */
12433            if (GetAlgoId(pkiMsg, idx, &keyWrapOID, oidKeyWrapType, pkiMsgSz)
12434                    < 0)
12435                return ASN_PARSE_E;
12436
12437            /* get EncryptedKey */
12438            if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0)
12439                return ASN_PARSE_E;
12440
12441            if (tag != ASN_OCTET_STRING)
12442                return ASN_PARSE_E;
12443
12444            if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0)
12445                return ASN_PARSE_E;
12446
12447            /* Validate EncryptedKey is within input buffer */
12448            if (*idx > pkiMsgSz || (word32)length > pkiMsgSz - *idx)
12449                return ASN_PARSE_E;
12450
12451            #ifndef NO_AES
12452                direction = AES_DECRYPTION;
12453            #else
12454                direction = DES_DECRYPTION;
12455            #endif
12456
12457            /* decrypt CEK with KEK */
12458            if (pkcs7->wrapCEKCb) {
12459                keySz = pkcs7->wrapCEKCb(pkcs7, pkiMsg + *idx, (word32)length,
12460                                    keyId, keyIdSz, NULL, 0, decryptedKey,
12461                                    *decryptedKeySz, (int)keyWrapOID,
12462                                    (int)PKCS7_KEKRI, direction);
12463            }
12464            else {
12465                keySz = wc_PKCS7_KeyWrap(pkcs7, pkiMsg + *idx, (word32)length,
12466                        pkcs7->privateKey, pkcs7->privateKeySz, decryptedKey,
12467                        *decryptedKeySz, (int)keyWrapOID, direction);
12468            }
12469            if (keySz <= 0)
12470                return keySz;
12471
12472            *decryptedKeySz = (word32)keySz;
12473
12474            /* mark recipFound, since we only support one RecipientInfo for
12475             * now */
12476            *recipFound = 1;
12477            *idx += (word32)length;
12478
12479        #ifndef NO_PKCS7_STREAM
12480            if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) {
12481                break;
12482            }
12483        #endif
12484            ret = 0; /* success */
12485            break;
12486
12487        default:
12488            WOLFSSL_MSG("PKCS7 KEKRI unknown state");
12489            ret = BAD_FUNC_ARG;
12490
12491    }
12492
12493    (void)keyId;
12494    return ret;
12495}
12496
12497
12498/* decode ASN.1 KeyAgreeRecipientInfo (kari), return 0 on success,
12499 * < 0 on error */
12500static int wc_PKCS7_DecryptKari(wc_PKCS7* pkcs7, byte* in, word32 inSz,
12501                               word32* idx, byte* decryptedKey,
12502                               word32* decryptedKeySz, int* recipFound)
12503{
12504#ifdef HAVE_ECC
12505    int ret, keySz;
12506    int encryptedKeySz;
12507    int direction = 0;
12508    int keyIdSize;
12509    word32 keyAgreeOID, keyWrapOID;
12510    byte rid[KEYID_SIZE];
12511
12512    WC_DECLARE_VAR(encryptedKey, byte, MAX_ENCRYPTED_KEY_SZ, 0);
12513
12514    byte* pkiMsg    = in;
12515    word32 pkiMsgSz = inSz;
12516#ifndef NO_PKCS7_STREAM
12517    word32 tmpIdx = (idx) ? *idx : 0;
12518#endif
12519    WOLFSSL_ENTER("wc_PKCS7_DecryptKari");
12520    if (pkcs7 == NULL || pkiMsg == NULL ||
12521        idx == NULL || decryptedKey == NULL || decryptedKeySz == NULL) {
12522        return BAD_FUNC_ARG;
12523    }
12524
12525#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
12526    keyIdSize = wc_HashGetDigestSize(wc_HashTypeConvert(HashIdAlg(
12527           pkcs7->publicKeyOID)));
12528#else
12529    keyIdSize = KEYID_SIZE;
12530#endif
12531
12532    switch (pkcs7->state) {
12533        case WC_PKCS7_DECRYPT_KARI: {
12534            WC_PKCS7_KARI* kari;
12535
12536        #ifndef NO_PKCS7_STREAM
12537            /* @TODO for now just get full buffer, needs divided up */
12538            if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
12539                   (pkcs7->stream->maxLen - pkcs7->stream->totalRd) +
12540                   pkcs7->stream->length, &pkiMsg, idx)) != 0) {
12541                return ret;
12542            }
12543            pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
12544        #endif
12545
12546            kari = wc_PKCS7_KariNew(pkcs7, WC_PKCS7_DECODE);
12547            if (kari == NULL)
12548                return MEMORY_E;
12549
12550            WC_ALLOC_VAR_EX(encryptedKey, byte, MAX_ENCRYPTED_KEY_SZ,
12551                pkcs7->heap, DYNAMIC_TYPE_PKCS7,
12552            {
12553                wc_PKCS7_KariFree(kari);
12554                return MEMORY_E;
12555            });
12556            encryptedKeySz = MAX_ENCRYPTED_KEY_SZ;
12557
12558            /* parse cert and key */
12559            ret = wc_PKCS7_KariParseRecipCert(kari, (byte*)pkcs7->singleCert,
12560                                         pkcs7->singleCertSz, pkcs7->privateKey,
12561                                         pkcs7->privateKeySz);
12562
12563             if (ret != 0) {
12564                wc_PKCS7_KariFree(kari);
12565                WC_FREE_VAR_EX(encryptedKey, pkcs7->heap,
12566                    DYNAMIC_TYPE_PKCS7);
12567                return ret;
12568            }
12569
12570            /* remove OriginatorIdentifierOrKey */
12571            ret = wc_PKCS7_KariGetOriginatorIdentifierOrKey(kari, pkiMsg,
12572                                                            pkiMsgSz, idx);
12573            if (ret != 0) {
12574                wc_PKCS7_KariFree(kari);
12575                    WC_FREE_VAR_EX(encryptedKey, pkcs7->heap,
12576                        DYNAMIC_TYPE_PKCS7);
12577                return ret;
12578            }
12579
12580            /* try and remove optional UserKeyingMaterial */
12581            ret = wc_PKCS7_KariGetUserKeyingMaterial(kari, pkiMsg, pkiMsgSz,
12582                idx);
12583            if (ret != 0) {
12584                wc_PKCS7_KariFree(kari);
12585                    WC_FREE_VAR_EX(encryptedKey, pkcs7->heap,
12586                        DYNAMIC_TYPE_PKCS7);
12587                return ret;
12588            }
12589
12590            /* remove KeyEncryptionAlgorithmIdentifier */
12591            ret = wc_PKCS7_KariGetKeyEncryptionAlgorithmId(kari, pkiMsg,
12592                    pkiMsgSz, idx, &keyAgreeOID, &keyWrapOID);
12593            if (ret != 0) {
12594                wc_PKCS7_KariFree(kari);
12595                    WC_FREE_VAR_EX(encryptedKey, pkcs7->heap,
12596                        DYNAMIC_TYPE_PKCS7);
12597                return ret;
12598            }
12599
12600            /* if user has not explicitly set keyAgreeOID, set from one in
12601             * bundle */
12602            if (pkcs7->keyAgreeOID == 0)
12603                pkcs7->keyAgreeOID = (int)keyAgreeOID;
12604
12605            /* set direction based on key wrap algorithm */
12606            switch (keyWrapOID) {
12607        #ifndef NO_AES
12608            #ifdef WOLFSSL_AES_128
12609                case AES128_WRAP:
12610            #endif
12611            #ifdef WOLFSSL_AES_192
12612                case AES192_WRAP:
12613            #endif
12614            #ifdef WOLFSSL_AES_256
12615                case AES256_WRAP:
12616            #endif
12617                    direction = AES_DECRYPTION;
12618                    break;
12619        #endif
12620                default:
12621                    WOLFSSL_MSG("AES key wrap algorithm unsupported");
12622                    if (pkcs7->wrapCEKCb) {
12623                        WOLFSSL_MSG("Direction not set!");
12624                        break; /* if unwrapping callback is set then do not
12625                                * force restriction of supported wrap
12626                                * algorithms */
12627                    }
12628
12629                    wc_PKCS7_KariFree(kari);
12630                        WC_FREE_VAR_EX(encryptedKey, pkcs7->heap,
12631                            DYNAMIC_TYPE_PKCS7);
12632                    return BAD_KEYWRAP_ALG_E;
12633            }
12634
12635            /* remove RecipientEncryptedKeys */
12636            ret = wc_PKCS7_KariGetRecipientEncryptedKeys(kari, pkiMsg, pkiMsgSz,
12637                           idx, recipFound, encryptedKey, &encryptedKeySz, rid);
12638            if (ret != 0) {
12639                wc_PKCS7_KariFree(kari);
12640                    WC_FREE_VAR_EX(encryptedKey, pkcs7->heap,
12641                        DYNAMIC_TYPE_PKCS7);
12642                return ret;
12643            }
12644
12645            /* decrypt CEK with KEK */
12646            if (pkcs7->wrapCEKCb) {
12647                word32 tmpKeySz = 0;
12648                byte* tmpKeyDer = NULL;
12649
12650                PRIVATE_KEY_UNLOCK();
12651                ret = wc_ecc_export_x963(kari->senderKey, NULL, &tmpKeySz);
12652                PRIVATE_KEY_LOCK();
12653                if (ret != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) {
12654                    wc_PKCS7_KariFree(kari);
12655                    WC_FREE_VAR_EX(encryptedKey, pkcs7->heap,
12656                        DYNAMIC_TYPE_PKCS7);
12657                    return ret;
12658                }
12659
12660                /* buffer space for algorithm/curve */
12661                tmpKeySz += MAX_SEQ_SZ;
12662                tmpKeySz += 2 * MAX_ALGO_SZ;
12663
12664                /* buffer space for public key sequence */
12665                tmpKeySz += MAX_SEQ_SZ;
12666                tmpKeySz += TRAILING_ZERO;
12667
12668                tmpKeyDer = (byte*)XMALLOC(tmpKeySz, pkcs7->heap,
12669                        DYNAMIC_TYPE_TMP_BUFFER);
12670                if (tmpKeyDer == NULL) {
12671                    wc_PKCS7_KariFree(kari);
12672                    WC_FREE_VAR_EX(encryptedKey, pkcs7->heap,
12673                        DYNAMIC_TYPE_PKCS7);
12674                    return MEMORY_E;
12675                }
12676
12677                ret = wc_EccPublicKeyToDer(kari->senderKey, tmpKeyDer,
12678                                         tmpKeySz, 1);
12679                if (ret < 0) {
12680                    wc_PKCS7_KariFree(kari);
12681                    WC_FREE_VAR_EX(encryptedKey, pkcs7->heap,
12682                        DYNAMIC_TYPE_PKCS7);
12683                    XFREE(tmpKeyDer, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
12684                    return ret;
12685                }
12686                tmpKeySz = (word32)ret;
12687
12688                keySz = pkcs7->wrapCEKCb(pkcs7, encryptedKey,
12689                    (word32)encryptedKeySz, rid, (word32)keyIdSize, tmpKeyDer,
12690                    tmpKeySz, decryptedKey, *decryptedKeySz,
12691                    (int)keyWrapOID, (int)PKCS7_KARI, direction);
12692                XFREE(tmpKeyDer, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
12693
12694                if (keySz  > 0) {
12695                    /* If unwrapping was successful then consider recipient
12696                     * found. Checking for NULL singleCert to confirm previous
12697                     * SID check was not done */
12698                    if (pkcs7->singleCert == NULL)
12699                        *recipFound = 1;
12700                }
12701            }
12702            else {
12703                /* create KEK */
12704                ret = wc_PKCS7_KariGenerateKEK(kari, pkcs7->rng,
12705                    (int)keyWrapOID, pkcs7->keyAgreeOID);
12706                if (ret != 0) {
12707                    wc_PKCS7_KariFree(kari);
12708                        WC_FREE_VAR_EX(encryptedKey, pkcs7->heap,
12709                            DYNAMIC_TYPE_PKCS7);
12710                    return ret;
12711                }
12712
12713                /* decrypt CEK with KEK */
12714                keySz = wc_PKCS7_KeyWrap(pkcs7, encryptedKey,
12715                        (word32)encryptedKeySz, kari->kek, kari->kekSz,
12716                        decryptedKey, *decryptedKeySz, (int)keyWrapOID,
12717                        direction);
12718            }
12719            if (keySz <= 0) {
12720                wc_PKCS7_KariFree(kari);
12721                    WC_FREE_VAR_EX(encryptedKey, pkcs7->heap,
12722                        DYNAMIC_TYPE_PKCS7);
12723                return keySz;
12724            }
12725            *decryptedKeySz = (word32)keySz;
12726
12727            wc_PKCS7_KariFree(kari);
12728                WC_FREE_VAR_EX(encryptedKey, pkcs7->heap,
12729                    DYNAMIC_TYPE_PKCS7);
12730            #ifndef NO_PKCS7_STREAM
12731            if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) {
12732                break;
12733            }
12734            #endif
12735            ret = 0; /* success */
12736        }
12737        break;
12738
12739        default:
12740            WOLFSSL_MSG("PKCS7 kari unknown state");
12741            ret = BAD_FUNC_ARG;
12742
12743    }
12744
12745    (void)pkiMsg;
12746    (void)pkiMsgSz;
12747
12748    return ret;
12749#else
12750    (void)in;
12751    (void)inSz;
12752    (void)pkcs7;
12753    (void)idx;
12754    (void)decryptedKey;
12755    (void)decryptedKeySz;
12756    (void)recipFound;
12757
12758    return NOT_COMPILED_IN;
12759#endif /* HAVE_ECC */
12760}
12761
12762
12763/* decode ASN.1 RecipientInfos SET, return 0 on success, < 0 on error */
12764static int wc_PKCS7_DecryptRecipientInfos(wc_PKCS7* pkcs7, byte* in,
12765                            word32  inSz, word32* idx, byte* decryptedKey,
12766                            word32* decryptedKeySz, int* recipFound)
12767{
12768    word32 savedIdx;
12769    int version, ret = 0, length;
12770    byte* pkiMsg = in;
12771    word32 pkiMsgSz = inSz;
12772    byte  tag;
12773#ifndef NO_PKCS7_STREAM
12774    word32 tmpIdx;
12775#endif
12776
12777    if (pkcs7 == NULL || pkiMsg == NULL || idx == NULL ||
12778        decryptedKey == NULL || decryptedKeySz == NULL ||
12779        recipFound == NULL) {
12780        return BAD_FUNC_ARG;
12781    }
12782
12783    WOLFSSL_ENTER("wc_PKCS7_DecryptRecipientInfos");
12784#ifndef NO_PKCS7_STREAM
12785    tmpIdx = *idx;
12786#endif
12787
12788    /* check if in the process of decrypting */
12789    switch (pkcs7->state) {
12790        case WC_PKCS7_DECRYPT_KTRI:
12791        case WC_PKCS7_DECRYPT_KTRI_2:
12792        case WC_PKCS7_DECRYPT_KTRI_3:
12793        #ifndef NO_RSA
12794            ret = wc_PKCS7_DecryptKtri(pkcs7, in, inSz, idx,
12795                                      decryptedKey, decryptedKeySz, recipFound);
12796        #else
12797            return NOT_COMPILED_IN;
12798        #endif
12799            break;
12800
12801        case WC_PKCS7_DECRYPT_KARI:
12802                ret = wc_PKCS7_DecryptKari(pkcs7, in, inSz, idx,
12803                                      decryptedKey, decryptedKeySz, recipFound);
12804                break;
12805
12806        case WC_PKCS7_DECRYPT_KEKRI:
12807                ret = wc_PKCS7_DecryptKekri(pkcs7, in, inSz, idx,
12808                                      decryptedKey, decryptedKeySz, recipFound);
12809                break;
12810
12811        case WC_PKCS7_DECRYPT_PWRI:
12812        #if !defined(NO_PWDBASED) && !defined(NO_SHA)
12813                ret = wc_PKCS7_DecryptPwri(pkcs7, in, inSz, idx,
12814                                      decryptedKey, decryptedKeySz, recipFound);
12815                break;
12816        #else
12817                return NOT_COMPILED_IN;
12818        #endif
12819
12820        case WC_PKCS7_DECRYPT_ORI:
12821            ret = wc_PKCS7_DecryptOri(pkcs7, in, inSz, idx,
12822                                      decryptedKey, decryptedKeySz, recipFound);
12823            break;
12824
12825        default:
12826            /* not in decrypting state */
12827            break;
12828    }
12829
12830    if (ret < 0) {
12831        return ret;
12832    }
12833
12834    savedIdx = *idx;
12835#ifndef NO_PKCS7_STREAM
12836    pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
12837    if (pkcs7->stream->length > 0)
12838        pkiMsg = pkcs7->stream->buffer;
12839#endif
12840
12841    /* when looking for next recipient, use first sequence and version to
12842     * indicate there is another, if not, move on */
12843    while (*recipFound == 0) {
12844
12845        /* remove RecipientInfo, if we don't have a SEQUENCE, back up idx to
12846         * last good saved one */
12847        if (GetSequence_ex(pkiMsg, idx, &length, pkiMsgSz, NO_USER_CHECK) > 0) {
12848
12849        #ifndef NO_RSA
12850            /* found ktri */
12851            #ifndef NO_PKCS7_STREAM
12852            if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) {
12853                break;
12854            }
12855            #endif
12856            wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_KTRI);
12857            ret = wc_PKCS7_DecryptKtri(pkcs7, in, inSz, idx,
12858                                      decryptedKey, decryptedKeySz,
12859                                      recipFound);
12860            if (ret != 0) {
12861                if (ret != WC_NO_ERR_TRACE(WC_PKCS7_WANT_READ_E) &&
12862                        *recipFound == 0) {
12863                    continue; /* try next recipient */
12864                }
12865                else {
12866                    return ret; /* found recipient and failed decrypt */
12867                }
12868            }
12869        #else
12870            return NOT_COMPILED_IN;
12871        #endif
12872        }
12873        else {
12874            word32 localIdx;
12875            /* kari is IMPLICIT[1] */
12876            *idx = savedIdx;
12877            localIdx = *idx;
12878
12879            if (GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) != 0) {
12880                /* no room for recipient info */
12881                break;
12882            }
12883
12884            if (tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) {
12885                (*idx)++;
12886                if (GetLength_ex(pkiMsg, idx, &length, pkiMsgSz,
12887                            NO_USER_CHECK) < 0)
12888                    return ASN_PARSE_E;
12889
12890                if (GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) {
12891                    *idx = savedIdx;
12892                    break;
12893                }
12894
12895                if (version != 3)
12896                    return ASN_VERSION_E;
12897
12898                /* found kari */
12899            #ifndef NO_PKCS7_STREAM
12900                if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) {
12901                    break;
12902                }
12903            #endif
12904                wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_KARI);
12905                ret = wc_PKCS7_DecryptKari(pkcs7, in, inSz, idx,
12906                                          decryptedKey, decryptedKeySz,
12907                                          recipFound);
12908                if (ret != 0)
12909                    return ret;
12910
12911            /* kekri is IMPLICIT[2] */
12912            } else if (tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 2)) {
12913                (*idx)++;
12914
12915                if (GetLength_ex(pkiMsg, idx, &version, pkiMsgSz,
12916                            NO_USER_CHECK) < 0)
12917                    return ASN_PARSE_E;
12918
12919                if (GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) {
12920                    *idx = savedIdx;
12921                    break;
12922                }
12923
12924                if (version != 4)
12925                    return ASN_VERSION_E;
12926
12927                /* found kekri */
12928            #ifndef NO_PKCS7_STREAM
12929                if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) {
12930                    break;
12931                }
12932            #endif
12933                wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_KEKRI);
12934                ret = wc_PKCS7_DecryptKekri(pkcs7, in, inSz, idx,
12935                                           decryptedKey, decryptedKeySz,
12936                                           recipFound);
12937                if (ret != 0)
12938                    return ret;
12939
12940            /* pwri is IMPLICIT[3] */
12941            } else if (tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 3)) {
12942        #if !defined(NO_PWDBASED) && !defined(NO_SHA)
12943                (*idx)++;
12944
12945                if (GetLength_ex(pkiMsg, idx, &version, pkiMsgSz,
12946                            NO_USER_CHECK) < 0)
12947                    return ASN_PARSE_E;
12948
12949                if (GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) {
12950                    *idx = savedIdx;
12951                    break;
12952                }
12953
12954                if (version != 0)
12955                    return ASN_VERSION_E;
12956
12957                /* found pwri */
12958            #ifndef NO_PKCS7_STREAM
12959                if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) {
12960                    break;
12961                }
12962            #endif
12963                wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_PWRI);
12964                ret = wc_PKCS7_DecryptPwri(pkcs7, in, inSz, idx,
12965                                           decryptedKey, decryptedKeySz,
12966                                           recipFound);
12967                if (ret != 0)
12968                    return ret;
12969        #else
12970                return NOT_COMPILED_IN;
12971        #endif
12972
12973            /* ori is IMPLICIT[4] */
12974            } else if (tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 4)) {
12975                (*idx)++;
12976
12977                /* found ori */
12978            #ifndef NO_PKCS7_STREAM
12979                if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) {
12980                    break;
12981                }
12982            #endif
12983                wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_ORI);
12984                ret = wc_PKCS7_DecryptOri(pkcs7, in, inSz, idx,
12985                                          decryptedKey, decryptedKeySz,
12986                                          recipFound);
12987                if (ret != 0)
12988                    return ret;
12989            }
12990            else {
12991                /* failed to find RecipientInfo, restore idx and continue */
12992                *idx = savedIdx;
12993                break;
12994            }
12995        }
12996
12997        /* update good idx */
12998        savedIdx = *idx;
12999    }
13000
13001    return ret;
13002}
13003
13004
13005/* Parse encoded EnvelopedData bundle up to RecipientInfo set.
13006 *
13007 * return size of RecipientInfo SET on success, negative upon error */
13008static int wc_PKCS7_ParseToRecipientInfoSet(wc_PKCS7* pkcs7, byte* in,
13009                                            word32 inSz, word32* idx,
13010                                            int type)
13011{
13012    int version = 0, length = 0, ret = 0;
13013    word32 contentType= 0;
13014    word32 pkiMsgSz = inSz;
13015    byte*  pkiMsg = in;
13016    byte   tag = 0;
13017#ifndef NO_PKCS7_STREAM
13018    word32 tmpIdx = 0;
13019#endif
13020
13021    if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0 || idx == NULL)
13022        return BAD_FUNC_ARG;
13023
13024    if ((type != ENVELOPED_DATA) && (type != AUTH_ENVELOPED_DATA) &&
13025            pkcs7->contentOID != FIRMWARE_PKG_DATA
13026        #if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA)
13027            && pkcs7->contentOID != COMPRESSED_DATA
13028        #endif
13029       )
13030        return BAD_FUNC_ARG;
13031
13032#ifndef NO_PKCS7_STREAM
13033    if (pkcs7->stream == NULL) {
13034        if ((ret = wc_PKCS7_CreateStream(pkcs7)) != 0) {
13035            return ret;
13036        }
13037    }
13038#endif
13039
13040    switch (pkcs7->state) {
13041        case WC_PKCS7_INFOSET_START:
13042        case WC_PKCS7_INFOSET_STAGE1:
13043        case WC_PKCS7_INFOSET_STAGE2:
13044        case WC_PKCS7_INFOSET_END:
13045            break;
13046
13047        default:
13048            WOLFSSL_MSG("Warning, setting PKCS7 info state to start");
13049            wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_INFOSET_START);
13050    }
13051
13052    switch (pkcs7->state) {
13053        case WC_PKCS7_INFOSET_START:
13054        #ifndef NO_PKCS7_STREAM
13055            if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_SEQ_SZ +
13056                            ASN_TAG_SZ, &pkiMsg, idx)) != 0) {
13057                return ret;
13058            }
13059            if ((ret = wc_PKCS7_SetMaxStream(pkcs7, in, inSz)) != 0) {
13060                break;
13061            }
13062            pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
13063        #endif
13064            /* read past ContentInfo, verify type is envelopedData */
13065            if (ret == 0 && GetSequence_ex(pkiMsg, idx, &length, pkiMsgSz,
13066                        NO_USER_CHECK) < 0)
13067            {
13068                ret = ASN_PARSE_E;
13069            }
13070
13071            if (ret == 0 && length == 0 && pkiMsg[(*idx)-1] == 0x80) {
13072        #ifdef ASN_BER_TO_DER
13073                pkcs7->indefDepth++;
13074        #else
13075                return BER_INDEF_E;
13076        #endif
13077            }
13078        #ifndef NO_PKCS7_STREAM
13079            if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) {
13080                break;
13081            }
13082        #endif
13083            wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_INFOSET_STAGE1);
13084            FALL_THROUGH;
13085
13086        case WC_PKCS7_INFOSET_STAGE1:
13087        #ifndef NO_PKCS7_STREAM
13088            if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_OID_SZ +
13089                            MAX_LENGTH_SZ + ASN_TAG_SZ, &pkiMsg, idx)) != 0) {
13090                return ret;
13091            }
13092
13093            pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length :inSz;
13094        #endif
13095            if (pkcs7->contentOID != FIRMWARE_PKG_DATA ||
13096                    type == AUTH_ENVELOPED_DATA) {
13097                if (ret == 0 && wc_GetContentType(pkiMsg, idx, &contentType,
13098                            pkiMsgSz) < 0)
13099                    ret = ASN_PARSE_E;
13100
13101                if (ret == 0) {
13102                    if (type == ENVELOPED_DATA && contentType !=
13103                            ENVELOPED_DATA) {
13104                        WOLFSSL_MSG("PKCS#7 input not of type EnvelopedData");
13105                        ret = PKCS7_OID_E;
13106                    } else if (type == AUTH_ENVELOPED_DATA &&
13107                           contentType != AUTH_ENVELOPED_DATA) {
13108                        WOLFSSL_MSG("PKCS#7 input not of type AuthEnvelopedData");
13109                        ret = PKCS7_OID_E;
13110                    }
13111                }
13112
13113                if (ret == 0 && GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) != 0)
13114                    ret = ASN_PARSE_E;
13115
13116                if (ret == 0 && tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC
13117                            | 0))
13118                    ret = ASN_PARSE_E;
13119
13120                if (ret == 0 && GetLength_ex(pkiMsg, idx, &length, pkiMsgSz,
13121                            NO_USER_CHECK) < 0)
13122                    ret = ASN_PARSE_E;
13123            }
13124
13125            if (ret < 0)
13126                break;
13127
13128        #ifndef NO_PKCS7_STREAM
13129            if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) {
13130                    break;
13131            }
13132        #endif
13133            wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_INFOSET_STAGE2);
13134            FALL_THROUGH;
13135
13136        case WC_PKCS7_INFOSET_STAGE2:
13137        #ifndef NO_PKCS7_STREAM
13138            if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_SEQ_SZ +
13139                            MAX_VERSION_SZ, &pkiMsg, idx)) != 0) {
13140                return ret;
13141            }
13142            pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
13143        #endif
13144            /* remove EnvelopedData and version */
13145            if (pkcs7->contentOID != FIRMWARE_PKG_DATA ||
13146                    type == AUTH_ENVELOPED_DATA) {
13147                if (ret == 0 && GetSequence_ex(pkiMsg, idx, &length, pkiMsgSz,
13148                            NO_USER_CHECK) < 0)
13149                    ret = ASN_PARSE_E;
13150            }
13151
13152            if (ret == 0 && GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0)
13153                ret = ASN_PARSE_E;
13154
13155            if (ret < 0)
13156                break;
13157
13158        #ifndef NO_PKCS7_STREAM
13159            if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) {
13160                break;
13161            }
13162
13163            pkcs7->stream->varOne = (word32)version;
13164        #endif
13165            wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_INFOSET_END);
13166            FALL_THROUGH;
13167
13168        case WC_PKCS7_INFOSET_END:
13169        #ifndef NO_PKCS7_STREAM
13170            if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
13171                            MAX_SET_SZ, &pkiMsg, idx)) != 0) {
13172                return ret;
13173            }
13174            pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
13175            version = (int)pkcs7->stream->varOne;
13176        #endif
13177
13178            if (type == ENVELOPED_DATA) {
13179                /* TODO :: make this more accurate */
13180                if ((pkcs7->publicKeyOID == RSAk &&
13181                     (version != 0 && version != 2))
13182                #ifdef HAVE_ECC
13183                        || (pkcs7->publicKeyOID == ECDSAk &&
13184                            (version != 0 && version != 2 && version != 3))
13185                #endif
13186                        ) {
13187                    WOLFSSL_MSG("PKCS#7 envelopedData version incorrect");
13188                    ret = ASN_VERSION_E;
13189                }
13190            } else {
13191                /* AuthEnvelopedData version MUST be 0 */
13192                if (version != 0) {
13193                    WOLFSSL_MSG(
13194                           "PKCS#7 AuthEnvelopedData needs to be of version 0");
13195                    ret = ASN_VERSION_E;
13196                }
13197            }
13198
13199            /* remove RecipientInfo set, get length of set */
13200            if (ret == 0 && GetSet_ex(pkiMsg, idx, &length, pkiMsgSz,
13201                        NO_USER_CHECK) < 0)
13202                ret = ASN_PARSE_E;
13203
13204            /* GetSet_ex is called with NO_USER_CHECK, which skips the
13205             * (idx + length > maxIdx) bounds check in GetLength_ex. In
13206             * non-streaming mode, validate the SET length against the
13207             * remaining input buffer; in streaming mode the length flows
13208             * into pkcs7->stream->expected and then wc_PKCS7_GrowStream,
13209             * where it is capped by WOLFSSL_PKCS7_MAX_STREAM_ALLOC. */
13210            if (ret == 0 && length < 0)
13211                ret = ASN_PARSE_E;
13212        #ifdef NO_PKCS7_STREAM
13213            if (ret == 0 &&
13214                    (*idx > pkiMsgSz ||
13215                     (word32)length > pkiMsgSz - *idx)) {
13216                ret = ASN_PARSE_E;
13217            }
13218        #endif
13219
13220            if (ret < 0)
13221                break;
13222
13223        #ifndef NO_PKCS7_STREAM
13224            pkcs7->stream->expected = (word32)length;
13225
13226            if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) {
13227                break;
13228            }
13229
13230            /* update the stored max length */
13231            if (pkcs7->stream->totalRd + pkcs7->stream->expected >
13232                    pkcs7->stream->maxLen) {
13233                pkcs7->stream->maxLen = pkcs7->stream->totalRd +
13234                    pkcs7->stream->expected;
13235            }
13236        #endif
13237
13238            if (ret == 0)
13239                ret = length;
13240
13241            break;
13242
13243        default:
13244            WOLFSSL_MSG("Bad PKCS7 info set state");
13245            ret = BAD_FUNC_ARG;
13246            break;
13247    }
13248
13249    return ret;
13250}
13251
13252
13253/* Import secret/private key into a PKCS7 structure. Used for setting
13254 * the secret key for decryption a EnvelopedData KEKRI RecipientInfo.
13255 *
13256 * Returns 0 on success, negative upon error */
13257int wc_PKCS7_SetKey(wc_PKCS7* pkcs7, byte* key, word32 keySz)
13258{
13259    if (pkcs7 == NULL || key == NULL || keySz == 0)
13260        return BAD_FUNC_ARG;
13261
13262    pkcs7->privateKey = key;
13263    pkcs7->privateKeySz = keySz;
13264
13265    return 0;
13266}
13267
13268
13269#if 0
13270/* append data to encrypted content cache in PKCS7 structure
13271 * return 0 on success, negative on error */
13272static int PKCS7_CacheEncryptedContent(wc_PKCS7* pkcs7, byte* in, word32 inSz)
13273{
13274    byte* oldCache;
13275    word32 oldCacheSz;
13276
13277    if (pkcs7 == NULL || in == NULL)
13278        return BAD_FUNC_ARG;
13279
13280    /* save pointer to old cache */
13281    oldCache = pkcs7->cachedEncryptedContent;
13282    oldCacheSz = pkcs7->cachedEncryptedContentSz;
13283
13284    /* re-allocate new buffer to fit appended data */
13285    pkcs7->cachedEncryptedContent = (byte*)XMALLOC(oldCacheSz + inSz,
13286            pkcs7->heap, DYNAMIC_TYPE_PKCS7);
13287    if (pkcs7->cachedEncryptedContent == NULL) {
13288        pkcs7->cachedEncryptedContentSz = 0;
13289        XFREE(oldCache, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
13290        return MEMORY_E;
13291    }
13292
13293    if (oldCache != NULL) {
13294        XMEMCPY(pkcs7->cachedEncryptedContent, oldCache, oldCacheSz);
13295    }
13296    XMEMCPY(pkcs7->cachedEncryptedContent + oldCacheSz, in, inSz);
13297    pkcs7->cachedEncryptedContentSz += inSz;
13298
13299    XFREE(oldCache, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
13300
13301    return 0;
13302}
13303#endif
13304
13305
13306/* unwrap and decrypt PKCS#7 envelopedData object, return decoded size */
13307int wc_PKCS7_DecodeEnvelopedData(wc_PKCS7* pkcs7, byte* in,
13308                                         word32 inSz, byte* output,
13309                                         word32 outputSz)
13310{
13311    int recipFound = 0;
13312    int ret, length = 0;
13313    word32 idx = 0;
13314    word32 tmpIdx = 0;
13315    word32 recipientSetSz = 0;
13316    word32 contentType = 0, encOID = 0;
13317    word32 decryptedKeySz = MAX_ENCRYPTED_KEY_SZ;
13318
13319    int expBlockSz = 0, blockKeySz = 0;
13320    byte  tmpIvBuf[MAX_CONTENT_IV_SIZE];
13321    byte* tmpIv = tmpIvBuf;
13322
13323    byte* pkiMsg    = in;
13324    word32 pkiMsgSz = inSz;
13325    byte* decryptedKey = NULL;
13326    int encryptedContentTotalSz = 0;
13327    int encryptedContentSz = 0;
13328    byte padLen;
13329    byte* encryptedContent = NULL;
13330    int explicitOctet = 0;
13331    word32 localIdx = 0;
13332    byte tag = 0;
13333    byte padCheck = 0;
13334    int padIndex;
13335
13336    if (pkcs7 == NULL)
13337        return BAD_FUNC_ARG;
13338
13339    if (pkiMsg == NULL || pkiMsgSz == 0)
13340        return BAD_FUNC_ARG;
13341
13342    if ((output == NULL || outputSz == 0)
13343    #ifdef ASN_BER_TO_DER
13344        && pkcs7->streamOutCb == NULL
13345    #endif
13346    ) {
13347        return BAD_FUNC_ARG;
13348    }
13349
13350#ifndef NO_PKCS7_STREAM
13351    (void)tmpIv; /* help out static analysis */
13352    if (pkcs7->stream == NULL) {
13353        if ((ret = wc_PKCS7_CreateStream(pkcs7)) != 0) {
13354            return ret;
13355        }
13356    }
13357#endif
13358
13359    switch (pkcs7->state) {
13360        case WC_PKCS7_START:
13361        case WC_PKCS7_INFOSET_START:
13362        case WC_PKCS7_INFOSET_STAGE1:
13363        case WC_PKCS7_INFOSET_STAGE2:
13364        case WC_PKCS7_INFOSET_END:
13365            ret = wc_PKCS7_ParseToRecipientInfoSet(pkcs7, pkiMsg, pkiMsgSz,
13366                    &idx, ENVELOPED_DATA);
13367            if (ret < 0) {
13368                break;
13369            }
13370
13371            decryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap,
13372                                                       DYNAMIC_TYPE_PKCS7);
13373            if (decryptedKey == NULL)
13374                return MEMORY_E;
13375            XMEMSET(decryptedKey, 0, MAX_ENCRYPTED_KEY_SZ);
13376        #ifdef WOLFSSL_CHECK_MEM_ZERO
13377            wc_MemZero_Add("wc_PKCS7 decryptedKey", decryptedKey,
13378                            MAX_ENCRYPTED_KEY_SZ);
13379        #endif
13380            wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_ENV_2);
13381            tmpIdx = idx;
13382            recipientSetSz = (word32)ret;
13383        #ifndef NO_PKCS7_STREAM
13384            pkcs7->stream->aad = decryptedKey;
13385            /* get the full recipient set */
13386            pkcs7->stream->expected     = recipientSetSz;
13387            pkcs7->stream->recipientSz  = ret;
13388        #endif
13389            FALL_THROUGH;
13390
13391        case WC_PKCS7_ENV_2:
13392        #ifndef NO_PKCS7_STREAM
13393            /* store up enough buffer for initial info set decode */
13394            if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
13395                    pkcs7->stream->expected, &pkiMsg, &idx)) != 0) {
13396                return ret;
13397            }
13398        #endif
13399            FALL_THROUGH;
13400
13401        case WC_PKCS7_DECRYPT_KTRI:
13402        case WC_PKCS7_DECRYPT_KTRI_2:
13403        case WC_PKCS7_DECRYPT_KTRI_3:
13404        case WC_PKCS7_DECRYPT_KARI:
13405        case WC_PKCS7_DECRYPT_KEKRI:
13406        case WC_PKCS7_DECRYPT_PWRI:
13407        case WC_PKCS7_DECRYPT_ORI:
13408        #ifndef NO_PKCS7_STREAM
13409            decryptedKey   = pkcs7->stream->aad;
13410            decryptedKeySz = MAX_ENCRYPTED_KEY_SZ;
13411            tmpIdx = idx;
13412        #endif
13413            ret = wc_PKCS7_DecryptRecipientInfos(pkcs7, in, inSz, &idx,
13414                                        decryptedKey, &decryptedKeySz,
13415                                        &recipFound);
13416            if (ret == 0 && recipFound == 0) {
13417                WOLFSSL_MSG(
13418                      "No recipient found in envelopedData that matches input");
13419                ret = PKCS7_RECIP_E;
13420            }
13421
13422            if (ret != 0)
13423                break;
13424        #ifndef NO_PKCS7_STREAM
13425            /* advance idx past recipient info set if not all recipients
13426             * parsed */
13427            if (pkcs7->stream->totalRd < ((word32)pkcs7->stream->recipientSz +
13428                    tmpIdx)) {
13429                idx = tmpIdx + (word32)pkcs7->stream->recipientSz;
13430
13431                /* process additional recipients as read */
13432                if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) {
13433                    break;
13434                }
13435            }
13436
13437            tmpIdx               = idx;
13438            pkcs7->stream->aadSz = decryptedKeySz;
13439            pkcs7->stream->expected = MAX_LENGTH_SZ + MAX_VERSION_SZ +
13440                ASN_TAG_SZ + MAX_LENGTH_SZ;
13441        #else
13442            idx = tmpIdx + recipientSetSz;
13443        #endif
13444            wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_ENV_3);
13445            FALL_THROUGH;
13446
13447        case WC_PKCS7_ENV_3:
13448
13449        #ifndef NO_PKCS7_STREAM
13450            if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
13451                    pkcs7->stream->expected, &pkiMsg, &idx)) != 0) {
13452                return ret;
13453            }
13454            pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
13455        #else
13456            ret = 0;
13457        #endif
13458
13459            /* remove EncryptedContentInfo */
13460            if (GetSequence_ex(pkiMsg, &idx, &length, pkiMsgSz,
13461                        NO_USER_CHECK) < 0) {
13462                ret = ASN_PARSE_E;
13463            }
13464
13465        #ifndef NO_PKCS7_STREAM
13466            if (length == 0) {
13467                /* if indefinite length, assume worst case size
13468                 * - Content Type OID + tag/length
13469                 * - Algorithm ID structure (OID + parameters)
13470                 * - Version
13471                 */
13472                pkcs7->stream->expected = MAX_SEQ_SZ +    /* outer sequence */
13473                                          MAX_OID_SZ +    /* content type OID */
13474                                          MAX_ALGO_SZ +   /* algo identifier */
13475                                          MAX_VERSION_SZ +/* version */
13476                                          ASN_TAG_SZ +    /* tag */
13477                                          MAX_LENGTH_SZ;  /* length */
13478            }
13479            else {
13480                /* revize expected size if known */
13481                pkcs7->stream->expected = (word32)length + ASN_TAG_SZ;
13482            }
13483
13484            /* Did we get enough for the expected length? */
13485            if (pkcs7->stream->expected > pkiMsgSz) {
13486                localIdx = idx;
13487                if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
13488                        pkcs7->stream->expected, &pkiMsg, &idx)) != 0) {
13489                    return ret;
13490                }
13491                pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length:
13492                                                        inSz;
13493                if (pkcs7->stream->length > 0) {
13494                    idx = localIdx; /* account for byte used with seq read */
13495                }
13496            }
13497        #endif
13498
13499            if (ret == 0 && wc_GetContentType(pkiMsg, &idx, &contentType,
13500                        pkiMsgSz) < 0) {
13501                ret = ASN_PARSE_E;
13502            }
13503
13504            if (ret == 0) {
13505                pkcs7->contentOID = (int)contentType;
13506            }
13507
13508            if (ret == 0 && GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType,
13509                        pkiMsgSz) < 0) {
13510                ret = ASN_PARSE_E;
13511            }
13512
13513            blockKeySz = wc_PKCS7_GetOIDKeySize((int)encOID);
13514            if (ret == 0 && blockKeySz < 0) {
13515                ret = blockKeySz;
13516            }
13517
13518            expBlockSz = wc_PKCS7_GetOIDBlockSize((int)encOID);
13519            if (ret == 0 && expBlockSz < 0) {
13520                ret = expBlockSz;
13521            }
13522
13523            /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */
13524            if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) != 0) {
13525                ret = ASN_PARSE_E;
13526            }
13527
13528            if (ret == 0 && tag != ASN_OCTET_STRING) {
13529                ret = ASN_PARSE_E;
13530            }
13531
13532            if (ret == 0 && GetLength_ex(pkiMsg, &idx, &length, pkiMsgSz,
13533                        NO_USER_CHECK) < 0) {
13534                ret = ASN_PARSE_E;
13535            }
13536
13537            if (ret == 0 && length != expBlockSz) {
13538                WOLFSSL_MSG(
13539                      "Incorrect IV length, must be of content alg block size");
13540                ret = ASN_PARSE_E;
13541            }
13542
13543            if (ret != 0)
13544                break;
13545        #ifndef NO_PKCS7_STREAM
13546            if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) {
13547                break;
13548            }
13549            wc_PKCS7_StreamStoreVar(pkcs7, encOID, expBlockSz, length);
13550            pkcs7->stream->contentSz = (word32)blockKeySz;
13551            pkcs7->stream->expected = (word32)length + MAX_LENGTH_SZ +
13552                MAX_LENGTH_SZ + ASN_TAG_SZ + ASN_TAG_SZ;
13553        #endif
13554            wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_ENV_4);
13555            FALL_THROUGH;
13556
13557        case WC_PKCS7_ENV_4:
13558
13559        #ifndef NO_PKCS7_STREAM
13560            if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
13561                            pkcs7->stream->expected, &pkiMsg, &idx)) != 0) {
13562                return ret;
13563            }
13564            pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
13565
13566            wc_PKCS7_StreamGetVar(pkcs7, 0, 0, &length);
13567            tmpIv = pkcs7->stream->tmpIv;
13568            if (tmpIv == NULL) {
13569                /* check added to help out static analysis tool */
13570                ret = MEMORY_E;
13571                break;
13572            }
13573        #else
13574            ret = 0;
13575        #endif
13576
13577            XMEMCPY(tmpIv, &pkiMsg[idx], (word32)length);
13578            idx += (word32)length;
13579
13580            explicitOctet = 0;
13581            localIdx = idx;
13582            if (GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) == 0 &&
13583                    tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) {
13584                explicitOctet = 1;
13585            }
13586
13587            /* read encryptedContent, cont[0] */
13588            if (tag != (ASN_CONTEXT_SPECIFIC | 0) &&
13589                          tag != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) {
13590                ret = ASN_PARSE_E;
13591            }
13592            idx++;
13593
13594            if (ret == 0 && GetLength_ex(pkiMsg, &idx, &encryptedContentTotalSz,
13595                                                            pkiMsgSz, 0) < 0) {
13596                ret = ASN_PARSE_E;
13597            }
13598
13599        #ifdef NO_PKCS7_STREAM
13600            if (ret == 0 && encryptedContentTotalSz > (int)(pkiMsgSz - idx)) {
13601                /* In non-streaming mode, ensure the content fits in the buffer.
13602                 * Streaming mode handles this via AddDataToStream. */
13603                ret = BUFFER_E;
13604            }
13605        #endif
13606
13607            if (ret != 0)
13608                break;
13609
13610        #ifndef NO_PKCS7_STREAM
13611            if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) {
13612                break;
13613            }
13614            pkcs7->stream->expected = (word32)encryptedContentTotalSz;
13615            if (explicitOctet) {
13616                pkcs7->stream->expected = MAX_OCTET_STR_SZ;
13617            }
13618            wc_PKCS7_StreamGetVar(pkcs7, &encOID, &expBlockSz, 0);
13619            wc_PKCS7_StreamStoreVar(pkcs7, encOID, expBlockSz, explicitOctet);
13620
13621            if (explicitOctet) {
13622                /* initialize decryption state in preparation. Use
13623                 * contentSz (blockKeySz from the content algorithm) as
13624                 * the AES key size rather than aadSz (the unwrapped CEK
13625                 * length): the two are equal for well-formed messages,
13626                 * but using blockKeySz avoids BAD_FUNC_ARG on crafted
13627                 * messages where the CEK length does not match the
13628                 * content cipher, which would otherwise be a
13629                 * distinguishable error. */
13630                if (pkcs7->decryptionCb == NULL) {
13631                    ret = wc_PKCS7_DecryptContentInit(pkcs7, encOID,
13632                        pkcs7->stream->aad,
13633                        (word32)pkcs7->stream->contentSz,
13634                        pkcs7->stream->tmpIv, expBlockSz,
13635                        pkcs7->devId, pkcs7->heap);
13636                    if (ret != 0)
13637                        break;
13638                }
13639            }
13640
13641        #endif
13642            pkcs7->totalEncryptedContentSz = 0;
13643            wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_ENV_5);
13644            FALL_THROUGH;
13645
13646        case WC_PKCS7_ENV_5:
13647
13648        #ifndef NO_PKCS7_STREAM
13649
13650            if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
13651                            pkcs7->stream->expected, &pkiMsg, &idx)) != 0) {
13652                if (ret != WC_NO_ERR_TRACE(WC_PKCS7_WANT_READ_E)) {
13653                    wc_PKCS7_StreamGetVar(pkcs7, &encOID, NULL, NULL);
13654                    wc_PKCS7_DecryptContentFree(pkcs7, encOID, pkcs7->heap);
13655                }
13656                return ret;
13657            }
13658
13659            wc_PKCS7_StreamGetVar(pkcs7, &encOID, &expBlockSz, &explicitOctet);
13660            tmpIv = pkcs7->stream->tmpIv;
13661            encryptedContentTotalSz = (int)pkcs7->stream->expected;
13662
13663            pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
13664
13665            /* restore decrypted key */
13666            decryptedKey   = pkcs7->stream->aad;
13667            decryptedKeySz = pkcs7->stream->aadSz;
13668            blockKeySz = (int)pkcs7->stream->contentSz;
13669        #else
13670            ret = 0;
13671        #endif
13672
13673            if (explicitOctet) {
13674                /* encrypted content may be fragmented into multiple
13675                 * consecutive OCTET STRINGs, if so loop through
13676                 * decrypting and outputting or caching contents until the indef
13677                 * ending tag is found */
13678
13679                while (1) {
13680                    encryptedContentSz = 0;
13681                    if (pkiMsgSz <= localIdx + MAX_OCTET_STR_SZ) {
13682                    #ifndef NO_PKCS7_STREAM
13683                        /* ran out of data to parse */
13684                        if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
13685                            pkcs7->stream->expected, &pkiMsg, &idx)) != 0) {
13686                            break;
13687                        }
13688                        pkiMsgSz = (pkcs7->stream->length > 0) ?
13689                            pkcs7->stream->length : inSz;
13690                    #else
13691                        ret = BUFFER_E;
13692                    #endif
13693                    }
13694
13695                    localIdx = idx;
13696                    if (GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) < 0) {
13697                        ret = ASN_PARSE_E;
13698                    }
13699
13700                    if (ret == 0 && (tag != ASN_OCTET_STRING)) {
13701                        ret = ASN_PARSE_E;
13702                    }
13703
13704                    if (ret == 0 && GetLength_ex(pkiMsg, &localIdx,
13705                                &encryptedContentSz, pkiMsgSz, 0) <= 0) {
13706                        ret = ASN_PARSE_E;
13707                    }
13708                #ifndef NO_PKCS7_STREAM
13709                    if (ret == 0) {
13710                        /* always try to get 2 extra bytes to catch indef ending */
13711                        pkcs7->stream->expected = (word32)encryptedContentSz +
13712                            (localIdx - idx) + ASN_INDEF_END_SZ;
13713                    }
13714                #endif
13715
13716                    if (ret == 0 &&
13717                         pkcs7->cachedEncryptedContentSz <
13718                         (word32)encryptedContentSz) {
13719                        if (pkcs7->cachedEncryptedContent != NULL) {
13720                            XFREE(pkcs7->cachedEncryptedContent, pkcs7->heap,
13721                                DYNAMIC_TYPE_PKCS7);
13722                        }
13723                        pkcs7->cachedEncryptedContent = (byte*)XMALLOC(
13724                            (word32)encryptedContentSz, pkcs7->heap,
13725                            DYNAMIC_TYPE_PKCS7);
13726                        if (pkcs7->cachedEncryptedContent == NULL) {
13727                            ret = MEMORY_E;
13728                        }
13729                    }
13730                    pkcs7->cachedEncryptedContentSz =
13731                        (word32)encryptedContentSz;
13732
13733                    /* sanity check that the buffer has all of the data */
13734                    if (ret == 0 && (localIdx + (word32)encryptedContentSz) >
13735                            pkiMsgSz) {
13736                    #ifndef NO_PKCS7_STREAM
13737                        word32 ofsetIdx = localIdx - idx;
13738                        if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
13739                            pkcs7->stream->expected, &pkiMsg, &localIdx))
13740                                != 0) {
13741                            return ret;
13742                        }
13743                        localIdx += ofsetIdx;
13744                        pkiMsgSz = (pkcs7->stream->length > 0)?
13745                            pkcs7->stream->length: inSz;
13746                    #else
13747                        ret = BUFFER_E;
13748                    #endif
13749                    }
13750
13751                    /* Use callback for decryption still, if set */
13752                    if (ret == 0 && pkcs7->decryptionCb != NULL) {
13753                        ret = pkcs7->decryptionCb(pkcs7, (int)encOID, tmpIv,
13754                            expBlockSz, NULL, 0, NULL, 0, &pkiMsg[localIdx],
13755                            encryptedContentSz, pkcs7->cachedEncryptedContent,
13756                            pkcs7->decryptionCtx);
13757                    }
13758
13759                    if (ret == 0) {
13760                        ret = wc_PKCS7_DecryptContentEx(pkcs7, encOID,
13761                            tmpIv, expBlockSz, NULL, 0, NULL, 0,
13762                            &pkiMsg[localIdx], encryptedContentSz,
13763                            pkcs7->cachedEncryptedContent);
13764                    }
13765
13766                #ifndef NO_PKCS7_STREAM
13767                    if (ret != 0) {
13768                        if (ret == WC_NO_ERR_TRACE(WC_PKCS7_WANT_READ_E)) {
13769                            wc_PKCS7_StreamEndCase(pkcs7, &localIdx, &idx);
13770                        }
13771                        break;
13772                    }
13773                #endif
13774
13775                    /* advance idx past encrypted content */
13776                    localIdx += (word32)encryptedContentSz;
13777
13778                    /* keep track of total encrypted content size */
13779                    pkcs7->totalEncryptedContentSz +=
13780                        (word32)encryptedContentSz;
13781
13782                    if (localIdx + ASN_INDEF_END_SZ <= pkiMsgSz) {
13783                        if (pkiMsg[localIdx] == ASN_EOC &&
13784                                pkiMsg[localIdx+1] == ASN_EOC) {
13785                            /* found the end of encrypted content */
13786                            localIdx += ASN_INDEF_END_SZ;
13787                            break;
13788                        }
13789                    }
13790                #ifndef NO_PKCS7_STREAM
13791                    pkcs7->stream->expected = MAX_OCTET_STR_SZ;
13792                    if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &localIdx,
13793                            &localIdx)) != 0) {
13794                        break;
13795                    }
13796                #endif
13797
13798                    /* save last decrypted string to handle padding (this output
13799                     * flush happens outside of the while loop in the case that
13800                     * the indef end was found) */
13801                    if (ret == 0) {
13802                    #ifdef ASN_BER_TO_DER
13803                        if (pkcs7->streamOutCb) {
13804                            ret = pkcs7->streamOutCb(pkcs7,
13805                                pkcs7->cachedEncryptedContent,
13806                                (word32)encryptedContentSz, pkcs7->streamCtx);
13807                        }
13808                    #endif /* ASN_BER_TO_DER */
13809                    }
13810
13811                    idx = localIdx;
13812                }
13813
13814                if (ret != 0) {
13815                    if (ret != WC_NO_ERR_TRACE(WC_PKCS7_WANT_READ_E)) {
13816                        /* free up in an error case if not looking for more
13817                         * data */
13818                        wc_PKCS7_DecryptContentFree(pkcs7, encOID,
13819                            pkcs7->heap);
13820                    }
13821                    break;
13822                }
13823                wc_PKCS7_DecryptContentFree(pkcs7, encOID, pkcs7->heap);
13824            } else {
13825                word32 tmpSum;
13826                if (!WC_SAFE_SUM_WORD32(idx, (word32)encryptedContentTotalSz, tmpSum) ||
13827                    tmpSum > pkiMsgSz) {
13828                    ret = BUFFER_E;
13829                    break;
13830                }
13831
13832                pkcs7->cachedEncryptedContentSz =
13833                    (word32)encryptedContentTotalSz;
13834                pkcs7->totalEncryptedContentSz =
13835                    (word32)encryptedContentTotalSz;
13836                pkcs7->cachedEncryptedContent = (byte*)XMALLOC(
13837                        pkcs7->cachedEncryptedContentSz, pkcs7->heap,
13838                    DYNAMIC_TYPE_PKCS7);
13839
13840                /* decrypt encryptedContent */
13841                ret = wc_PKCS7_DecryptContent(pkcs7, encOID, decryptedKey,
13842                        (word32)blockKeySz, tmpIv, expBlockSz, NULL, 0, NULL, 0,
13843                        &pkiMsg[idx], encryptedContentTotalSz,
13844                        pkcs7->cachedEncryptedContent,
13845                        pkcs7->devId, pkcs7->heap);
13846                if (ret != 0) {
13847                    break;
13848                }
13849
13850                idx += (word32)encryptedContentTotalSz;
13851            }
13852
13853            /* use cached content */
13854            encryptedContent = pkcs7->cachedEncryptedContent;
13855            encryptedContentSz = (int)pkcs7->cachedEncryptedContentSz;
13856
13857            if (encryptedContentSz <= 0) {
13858                ret = BUFFER_E;
13859                break;
13860            }
13861
13862            padLen = encryptedContent[encryptedContentSz-1];
13863
13864            /* Constant-time padding check */
13865            padCheck |= ctMaskEq(padLen, 0);
13866            padCheck |= ctMaskGT(padLen, expBlockSz);
13867            padCheck |= ctMaskGT(padLen, encryptedContentSz);
13868            padCheck |= ctMaskGT(expBlockSz, encryptedContentSz);
13869            for (padIndex = encryptedContentSz < expBlockSz ? 0 :
13870                     encryptedContentSz - expBlockSz;
13871                 padIndex < encryptedContentSz; padIndex++) {
13872                byte inPad = ctMaskGTE(padIndex,
13873                                       encryptedContentSz - (int)padLen);
13874                padCheck |= inPad & (encryptedContent[padIndex] ^ padLen);
13875            }
13876            if (padCheck != 0) {
13877                ret = BUFFER_E;
13878                break;
13879            }
13880
13881        #ifdef ASN_BER_TO_DER
13882            if (pkcs7->streamOutCb) {
13883                ret = pkcs7->streamOutCb(pkcs7, encryptedContent,
13884                                (word32)encryptedContentSz - padLen,
13885                                pkcs7->streamCtx);
13886                if (ret != 0) {
13887                    WOLFSSL_MSG("Stream out callback returned failure");
13888                    ret = BUFFER_E;
13889                    break;
13890                }
13891            }
13892            else
13893        #endif /* ASN_BER_TO_DER */
13894            {
13895                if (output == NULL || (word32)(encryptedContentSz - padLen) >
13896                        outputSz) {
13897                    ret = BUFFER_E;
13898                    break;
13899                }
13900                XMEMCPY(output, encryptedContent,
13901                                           (word32)encryptedContentSz - padLen);
13902            }
13903
13904            /* free memory, zero out keys */
13905            ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ);
13906            XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
13907            if (pkcs7->cachedEncryptedContent != NULL) {
13908                XFREE(pkcs7->cachedEncryptedContent, pkcs7->heap,
13909                      DYNAMIC_TYPE_PKCS7);
13910                pkcs7->cachedEncryptedContent = NULL;
13911                pkcs7->cachedEncryptedContentSz = 0;
13912            }
13913
13914            ret = (int)pkcs7->totalEncryptedContentSz - padLen;
13915        #ifndef NO_PKCS7_STREAM
13916            /* decryptedKey (just freed) is the same buffer stream->aad
13917             * aliases. Null the stream handle so ResetStream doesn't
13918             * double-free it. */
13919            if (pkcs7->stream != NULL) {
13920                pkcs7->stream->aad = NULL;
13921                pkcs7->stream->aadSz = 0;
13922            }
13923            wc_PKCS7_ResetStream(pkcs7);
13924        #endif
13925            wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START);
13926            break;
13927
13928        default:
13929            WOLFSSL_MSG("PKCS#7 unknown decode enveloped state");
13930            ret = BAD_FUNC_ARG;
13931    }
13932
13933#ifndef NO_PKCS7_STREAM
13934    if (ret < 0 && ret != WC_NO_ERR_TRACE(WC_PKCS7_WANT_READ_E)) {
13935        /* stream->aad aliases the MAX_ENCRYPTED_KEY_SZ decryptedKey
13936         * buffer in this flow. ResetStream only zeros aadSz bytes, so
13937         * explicitly zero and release the full buffer here to satisfy
13938         * WOLFSSL_CHECK_MEM_ZERO and avoid leaking key material. */
13939        if (pkcs7->stream != NULL && pkcs7->stream->aad != NULL) {
13940            ForceZero(pkcs7->stream->aad, MAX_ENCRYPTED_KEY_SZ);
13941            XFREE(pkcs7->stream->aad, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
13942            pkcs7->stream->aad = NULL;
13943            pkcs7->stream->aadSz = 0;
13944        }
13945        wc_PKCS7_ResetStream(pkcs7);
13946        wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START);
13947        if (pkcs7->cachedEncryptedContent != NULL) {
13948            XFREE(pkcs7->cachedEncryptedContent, pkcs7->heap,
13949                  DYNAMIC_TYPE_PKCS7);
13950            pkcs7->cachedEncryptedContent = NULL;
13951            pkcs7->cachedEncryptedContentSz = 0;
13952        }
13953    }
13954#else
13955    if (ret < 0) {
13956        wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START);
13957    }
13958    if (decryptedKey != NULL && ret < 0) {
13959        ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ);
13960        XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
13961    }
13962    if (pkcs7->cachedEncryptedContent != NULL && ret < 0) {
13963        XFREE(pkcs7->cachedEncryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
13964        pkcs7->cachedEncryptedContent = NULL;
13965        pkcs7->cachedEncryptedContentSz = 0;
13966    }
13967#endif
13968    return ret;
13969}
13970
13971
13972int wc_PKCS7_GetEnvelopedDataKariRid(const byte * in, word32 inSz,
13973        byte * out, word32 * outSz)
13974{
13975    int ret = 0;
13976    word32 idx = 0;
13977    int length = 0;
13978    word32 contentType = 0;
13979    word32 ridIdx = 0;
13980    byte ridTag = 0;
13981
13982    if (in == NULL || inSz == 0 || out == NULL || outSz == NULL) {
13983        ret = BAD_FUNC_ARG;
13984    }
13985    /* Consume ContentInfo SEQUENCE header. */
13986    else if (GetSequence(in, &idx, &length, inSz) < 0) {
13987        ret = ASN_PARSE_E;
13988    }
13989    /* Validate the EnvelopedData OBJECT IDENTIFIER. */
13990    else if (wc_GetContentType(in, &idx, &contentType, inSz) < 0) {
13991        ret = ASN_PARSE_E;
13992    }
13993    else if (contentType != ENVELOPED_DATA) {
13994        WOLFSSL_MSG("PKCS#7 input not of type EnvelopedData");
13995        ret = PKCS7_OID_E;
13996    }
13997    /* Consume EXPLICIT content [0] header. */
13998    else if (GetASNHeader(in, ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED, &idx,
13999                &length, inSz) < 0) {
14000        ret = ASN_PARSE_E;
14001    }
14002    /* Consume EnvelopedData SEQUENCE header. */
14003    else if (GetSequence(in, &idx, &length, inSz) < 0) {
14004        ret = ASN_PARSE_E;
14005    }
14006    /* Consume version. */
14007    else if (GetMyVersion(in, &idx, &length, inSz) < 0) {
14008        ret = ASN_PARSE_E;
14009    }
14010    /* Consume originatorInfo if present. */
14011    else if (GetASNHeader(in, ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED, &idx,
14012                &length, inSz) >= 0) {
14013        idx += (word32)length;
14014    }
14015    /* Consume recipientInfos SET OF header. */
14016    if (ret == 0 && GetSet(in, &idx, &length, inSz) < 0) {
14017        ret = ASN_PARSE_E;
14018    }
14019    /* Consume kari [1] header. */
14020    if (ret == 0 && GetASNHeader(in, ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1,
14021                &idx, &length, inSz) < 0) {
14022        ret = ASN_PARSE_E;
14023    }
14024    /* Consume KARI version. */
14025    if (ret == 0 && GetMyVersion(in, &idx, &length, inSz) < 0) {
14026        ret = ASN_PARSE_E;
14027    }
14028    /* Consume KARI originator [0] header. */
14029    if (ret == 0 && GetASNHeader(in, ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED,
14030                &idx, &length, inSz) < 0) {
14031        ret = ASN_PARSE_E;
14032    }
14033    /* Skip originator [0] content. */
14034    if (ret == 0)
14035        idx += (word32)length;
14036    /* Consume KARI ukm [1] if present. */
14037    if (ret == 0 && GetASNHeader(in, ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1,
14038                &idx, &length, inSz) >= 0) {
14039        idx += (word32) length;
14040    }
14041    /* Consume KARI keyEncryptionAlgorithm. */
14042    if (ret == 0 && GetSequence(in, &idx, &length, inSz) < 0) {
14043        ret = ASN_PARSE_E;
14044    }
14045    /* Skip keyEncryptionAlgorithm content. */
14046    if (ret == 0)
14047        idx += (word32)length;
14048    /* Consume RecipientEncryptedKeys SEQUENCE OF header. */
14049    if (ret == 0 && GetSequence(in, &idx, &length, inSz) < 0) {
14050        ret = ASN_PARSE_E;
14051    }
14052    /* Consume RecipientEncryptedKey SEQUENCE header. */
14053    if (ret == 0 && GetSequence(in, &idx, &length, inSz) < 0) {
14054        ret = ASN_PARSE_E;
14055    }
14056    if (ret == 0)
14057        ridIdx = idx;
14058    /* Consume KeyAgreeRecipientIdentifier tag. */
14059    if (ret == 0 && GetASNTag(in, &idx, &ridTag, inSz) < 0) {
14060        ret = ASN_PARSE_E;
14061    }
14062    /* Consume KeyAgreeRecipientIdentifier length. */
14063    if (ret == 0 && GetLength(in, &idx, &length, inSz) < 0) {
14064        ret = ASN_PARSE_E;
14065    }
14066    if (ret == 0) {
14067        word32 ridSz = (idx + (word32)length) - ridIdx;
14068        if (ridSz > *outSz) {
14069            /* Not enough room in output buffer. */
14070            ret = BUFFER_E;
14071        }
14072        else {
14073            /* Copy KeyAgreeRecipientIdentifier to output buffer. */
14074            XMEMCPY(out, &in[ridIdx], ridSz);
14075            *outSz = ridSz;
14076        }
14077    }
14078    return ret;
14079}
14080
14081
14082/* build PKCS#7 authEnvelopedData content type, return enveloped size */
14083int wc_PKCS7_EncodeAuthEnvelopedData(wc_PKCS7* pkcs7, byte* output,
14084                                     word32 outputSz)
14085{
14086#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM)
14087    int ret, idx = 0;
14088    int totalSz, encryptedAllocSz, encryptedOutSz;
14089
14090    int contentInfoSeqSz, outerContentTypeSz, outerContentSz;
14091    byte contentInfoSeq[MAX_SEQ_SZ];
14092    byte outerContentType[MAX_ALGO_SZ];
14093    byte outerContent[MAX_SEQ_SZ];
14094
14095    int envDataSeqSz, verSz;
14096    byte envDataSeq[MAX_SEQ_SZ];
14097    byte ver[MAX_VERSION_SZ];
14098
14099    WC_RNG rng;
14100    int blockSz, blockKeySz;
14101    byte* plain;
14102    byte* encryptedContent;
14103
14104    Pkcs7EncodedRecip* tmpRecip = NULL;
14105    int recipSz, recipSetSz;
14106    byte recipSet[MAX_SET_SZ];
14107
14108    int encContentOctetSz, encContentSeqSz, contentTypeSz;
14109    int contentEncAlgoSz, nonceOctetStringSz, macOctetStringSz;
14110    byte encContentSeq[MAX_SEQ_SZ];
14111    byte contentType[MAX_ALGO_SZ];
14112    byte contentEncAlgo[MAX_ALGO_SZ];
14113    byte nonceOctetString[MAX_OCTET_STR_SZ];
14114    byte encContentOctet[MAX_OCTET_STR_SZ];
14115    byte macOctetString[MAX_OCTET_STR_SZ];
14116
14117    byte authTag[WC_AES_BLOCK_SIZE];
14118    byte nonce[GCM_NONCE_MID_SZ];   /* GCM nonce is larger than CCM */
14119    byte macInt[MAX_VERSION_SZ];
14120    byte algoParamSeq[MAX_SEQ_SZ];
14121    word32 nonceSz = 0, macIntSz = 0, algoParamSeqSz = 0;
14122
14123    /* authAttribs */
14124    byte* flatAuthAttribs = NULL;
14125    byte authAttribSet[MAX_SET_SZ];
14126    EncodedAttrib authAttribs[MAX_AUTH_ATTRIBS_SZ];
14127    word32 authAttribsSz = 0, authAttribsCount = 0;
14128    word32 authAttribsSetSz = 0;
14129
14130    byte* aadBuffer = NULL;
14131    word32 aadBufferSz = 0;
14132    byte authAttribAadSet[MAX_SET_SZ];
14133    word32 authAttribsAadSetSz = 0;
14134
14135    /* unauthAttribs */
14136    byte* flatUnauthAttribs = NULL;
14137    byte unauthAttribSet[MAX_SET_SZ];
14138    EncodedAttrib unauthAttribs[MAX_UNAUTH_ATTRIBS_SZ];
14139    word32 unauthAttribsSz = 0, unauthAttribsCount = 0;
14140    word32 unauthAttribsSetSz = 0;
14141
14142
14143    PKCS7Attrib contentTypeAttrib;
14144    byte contentTypeValue[MAX_OID_SZ];
14145    /* contentType OID (1.2.840.113549.1.9.3) */
14146    const byte contentTypeOid[] =
14147            { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0d, 0x01,
14148                             0x09, 0x03 };
14149    if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0)
14150        return BAD_FUNC_ARG;
14151
14152    if (output == NULL || outputSz == 0)
14153        return BAD_FUNC_ARG;
14154
14155    switch (pkcs7->encryptOID) {
14156#ifdef HAVE_AESGCM
14157    #ifdef WOLFSSL_AES_128
14158        case AES128GCMb:
14159            break;
14160    #endif
14161    #ifdef WOLFSSL_AES_192
14162        case AES192GCMb:
14163            break;
14164    #endif
14165    #ifdef WOLFSSL_AES_256
14166        case AES256GCMb:
14167            break;
14168    #endif
14169#endif
14170#ifdef HAVE_AESCCM
14171    #ifdef WOLFSSL_AES_128
14172        case AES128CCMb:
14173            break;
14174    #endif
14175    #ifdef WOLFSSL_AES_192
14176        case AES192CCMb:
14177            break;
14178    #endif
14179    #ifdef WOLFSSL_AES_256
14180        case AES256CCMb:
14181            break;
14182    #endif
14183#endif
14184        default:
14185            WOLFSSL_MSG("CMS AuthEnvelopedData must use AES-GCM or AES-CCM");
14186            return BAD_FUNC_ARG;
14187    }
14188
14189    blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID);
14190    if (blockKeySz < 0)
14191        return blockKeySz;
14192
14193    blockSz = wc_PKCS7_GetOIDBlockSize(pkcs7->encryptOID);
14194    if (blockSz < 0)
14195        return blockSz;
14196
14197    /* outer content type */
14198    ret = wc_SetContentType(AUTH_ENVELOPED_DATA, outerContentType,
14199                            sizeof(outerContentType));
14200    if (ret < 0)
14201        return ret;
14202
14203    outerContentTypeSz = ret;
14204
14205    /* version, defined as 0 in RFC 5083 */
14206    verSz = SetMyVersion(0, ver, 0);
14207
14208    /* generate random content encryption key */
14209    ret = PKCS7_GenerateContentEncryptionKey(pkcs7, (word32)blockKeySz);
14210    if (ret != 0) {
14211        return ret;
14212    }
14213
14214    /* build RecipientInfo, only if user manually set singleCert and size */
14215    if (pkcs7->singleCert != NULL && pkcs7->singleCertSz > 0) {
14216        switch (pkcs7->publicKeyOID) {
14217        #ifndef NO_RSA
14218        #ifdef WC_RSA_PSS
14219            case RSAPSSk:
14220                FALL_THROUGH;
14221        #endif
14222            case RSAk:
14223                ret = wc_PKCS7_AddRecipient_KTRI(pkcs7, pkcs7->singleCert,
14224                                                 pkcs7->singleCertSz, 0);
14225                break;
14226        #endif
14227        #ifdef HAVE_ECC
14228            case ECDSAk:
14229                ret = wc_PKCS7_AddRecipient_KARI(pkcs7, pkcs7->singleCert,
14230                                                 pkcs7->singleCertSz,
14231                                                 pkcs7->keyWrapOID,
14232                                                 pkcs7->keyAgreeOID, pkcs7->ukm,
14233                                                 pkcs7->ukmSz, 0);
14234                break;
14235        #endif
14236
14237            default:
14238                WOLFSSL_MSG("Unsupported RecipientInfo public key type");
14239                return BAD_FUNC_ARG;
14240        };
14241
14242        if (ret < 0) {
14243            WOLFSSL_MSG("Failed to create RecipientInfo");
14244            return ret;
14245        }
14246    }
14247
14248    recipSz = wc_PKCS7_GetRecipientListSize(pkcs7);
14249    if (recipSz < 0) {
14250        return ret;
14251
14252    } else if (recipSz == 0) {
14253        WOLFSSL_MSG("You must add at least one CMS recipient");
14254        return PKCS7_RECIP_E;
14255    }
14256    recipSetSz = (int)SetSet((word32)recipSz, recipSet);
14257
14258    /* generate random nonce and IV for encryption */
14259    switch (pkcs7->encryptOID) {
14260#ifdef HAVE_AESGCM
14261    #ifdef WOLFSSL_AES_128
14262        case AES128GCMb:
14263    #endif
14264    #ifdef WOLFSSL_AES_192
14265        case AES192GCMb:
14266    #endif
14267    #ifdef WOLFSSL_AES_256
14268        case AES256GCMb:
14269    #endif
14270    #if defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_192) || \
14271        defined(WOLFSSL_AES_256)
14272            /* GCM nonce is GCM_NONCE_MID_SZ (12) */
14273            nonceSz = GCM_NONCE_MID_SZ;
14274            break;
14275    #endif
14276#endif /* HAVE_AESGCM */
14277#ifdef HAVE_AESCCM
14278    #ifdef WOLFSSL_AES_128
14279        case AES128CCMb:
14280    #endif
14281    #ifdef WOLFSSL_AES_192
14282        case AES192CCMb:
14283    #endif
14284    #ifdef WOLFSSL_AES_256
14285        case AES256CCMb:
14286    #endif
14287    #if defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_192) || \
14288        defined(WOLFSSL_AES_256)
14289            /* CCM nonce is CCM_NONCE_MIN_SZ (7) */
14290            nonceSz = CCM_NONCE_MIN_SZ;
14291            break;
14292    #endif
14293#endif /* HAVE_AESCCM */
14294    }
14295
14296    ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId);
14297    if (ret != 0) {
14298        wc_PKCS7_FreeEncodedRecipientSet(pkcs7);
14299        return ret;
14300    }
14301
14302    ret = wc_PKCS7_GenerateBlock(pkcs7, &rng, nonce, nonceSz);
14303    wc_FreeRng(&rng);
14304    if (ret != 0) {
14305        wc_PKCS7_FreeEncodedRecipientSet(pkcs7);
14306        return ret;
14307    }
14308
14309
14310    /* authAttribs: add contentType attrib if needed */
14311    if (pkcs7->contentOID != DATA) {
14312
14313        XMEMSET(&contentTypeAttrib, 0, sizeof contentTypeAttrib);
14314
14315        /* if type is not id-data, contentType attribute MUST be added */
14316        contentTypeAttrib.oid = contentTypeOid;
14317        contentTypeAttrib.oidSz = sizeof(contentTypeOid);
14318
14319        /* try to set from contentOID first, known types */
14320        ret = wc_SetContentType(pkcs7->contentOID, contentTypeValue,
14321                                sizeof(contentTypeValue));
14322        if (ret > 0) {
14323            contentTypeAttrib.value = contentTypeValue;
14324            contentTypeAttrib.valueSz = (word32)ret;
14325
14326        /* otherwise, try to set from custom content type */
14327        } else {
14328            if (pkcs7->contentTypeSz == 0) {
14329                WOLFSSL_MSG("CMS pkcs7->contentType must be set if "
14330                            "contentOID is not");
14331                wc_PKCS7_FreeEncodedRecipientSet(pkcs7);
14332                return BAD_FUNC_ARG;
14333            }
14334            contentTypeAttrib.value = pkcs7->contentType;
14335            contentTypeAttrib.valueSz = pkcs7->contentTypeSz;
14336        }
14337
14338        authAttribsSz += (word32)EncodeAttributes(authAttribs, 1,
14339                                                         &contentTypeAttrib, 1);
14340        authAttribsCount += 1;
14341    }
14342
14343    /* authAttribs: add in user authenticated attributes */
14344    if (pkcs7->authAttribs != NULL && pkcs7->authAttribsSz > 0) {
14345        authAttribsSz += (word32)EncodeAttributes(
14346                                 authAttribs + authAttribsCount,
14347                                 (int)(MAX_AUTH_ATTRIBS_SZ - authAttribsCount),
14348                                 pkcs7->authAttribs,
14349                                 (int)pkcs7->authAttribsSz);
14350        authAttribsCount += pkcs7->authAttribsSz;
14351    }
14352
14353    /* authAttribs: flatten authAttribs */
14354    if (authAttribsSz > 0 && authAttribsCount > 0) {
14355        flatAuthAttribs = (byte*)XMALLOC(authAttribsSz, pkcs7->heap,
14356                                         DYNAMIC_TYPE_PKCS7);
14357        if (flatAuthAttribs == NULL) {
14358            wc_PKCS7_FreeEncodedRecipientSet(pkcs7);
14359            return MEMORY_E;
14360        }
14361
14362        ret = FlattenAttributes(pkcs7, flatAuthAttribs, authAttribs,
14363                          (int)authAttribsCount);
14364        if (ret != 0) {
14365            wc_PKCS7_FreeEncodedRecipientSet(pkcs7);
14366            XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
14367            return ret;
14368        }
14369
14370        authAttribsSetSz = SetImplicit(ASN_SET, 1, authAttribsSz,
14371                                       authAttribSet, 0);
14372
14373        /* From RFC5083, "For the purpose of constructing the AAD, the
14374         * IMPLICIT [1] tag in the authAttrs field is not used for the
14375         * DER encoding: rather a universal SET OF tag is used. */
14376        authAttribsAadSetSz = SetSet(authAttribsSz, authAttribAadSet);
14377
14378        /* allocate temp buffer to hold alternate attrib encoding for aad */
14379        aadBuffer = (byte*)XMALLOC(authAttribsSz + authAttribsAadSetSz,
14380                                   pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
14381        if (aadBuffer == NULL) {
14382            wc_PKCS7_FreeEncodedRecipientSet(pkcs7);
14383            XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
14384            return MEMORY_E;
14385        }
14386
14387        /* build up alternate attrib encoding for aad */
14388        aadBufferSz = 0;
14389        XMEMCPY(aadBuffer + aadBufferSz, authAttribAadSet, authAttribsAadSetSz);
14390        aadBufferSz += authAttribsAadSetSz;
14391        XMEMCPY(aadBuffer + aadBufferSz, flatAuthAttribs, authAttribsSz);
14392        aadBufferSz += authAttribsSz;
14393    }
14394
14395    /* build up unauthenticated attributes (unauthAttrs) */
14396    if (pkcs7->unauthAttribsSz > 0) {
14397        unauthAttribsSz = (word32)EncodeAttributes(
14398                              unauthAttribs + unauthAttribsCount,
14399                              (int)(MAX_UNAUTH_ATTRIBS_SZ - unauthAttribsCount),
14400                              pkcs7->unauthAttribs,
14401                              (int)pkcs7->unauthAttribsSz);
14402        unauthAttribsCount = pkcs7->unauthAttribsSz;
14403
14404        if (unauthAttribsSz > 0) {
14405            flatUnauthAttribs = (byte*)XMALLOC(unauthAttribsSz, pkcs7->heap,
14406                                               DYNAMIC_TYPE_PKCS7);
14407            if (flatUnauthAttribs == NULL) {
14408                wc_PKCS7_FreeEncodedRecipientSet(pkcs7);
14409                XFREE(aadBuffer, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
14410                XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
14411                return MEMORY_E;
14412            }
14413
14414            FlattenAttributes(pkcs7, flatUnauthAttribs, unauthAttribs,
14415                              (int)unauthAttribsCount);
14416        }
14417
14418        unauthAttribsSetSz = SetImplicit(ASN_SET, 2, unauthAttribsSz,
14419                                         unauthAttribSet, 0);
14420    }
14421
14422    /* AES-GCM/CCM does NOT require padding for plaintext content or
14423     * AAD inputs RFC 5084 section 3.1 and 3.2, but we must alloc
14424     * full blocks to ensure crypto only gets full blocks */
14425    encryptedOutSz = (int)pkcs7->contentSz;
14426    encryptedAllocSz = (encryptedOutSz % blockSz) ?
14427                           encryptedOutSz + blockSz -
14428                           (encryptedOutSz % blockSz) :
14429                           encryptedOutSz;
14430
14431    /* Copy content to plain buffer (zero-padded) to encrypt in full,
14432     * contiguous blocks */
14433    plain = (byte*)XMALLOC((word32)encryptedAllocSz, pkcs7->heap,
14434        DYNAMIC_TYPE_PKCS7);
14435    if (plain == NULL) {
14436        wc_PKCS7_FreeEncodedRecipientSet(pkcs7);
14437        XFREE(aadBuffer, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
14438        XFREE(flatUnauthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
14439        XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
14440        return MEMORY_E;
14441    }
14442
14443    XMEMCPY(plain, pkcs7->content, pkcs7->contentSz);
14444    if ((encryptedAllocSz - encryptedOutSz) > 0) {
14445        XMEMSET(plain + encryptedOutSz, 0,
14446            (word32)(encryptedAllocSz - encryptedOutSz));
14447    }
14448
14449    encryptedContent = (byte*)XMALLOC((word32)encryptedAllocSz, pkcs7->heap,
14450                                      DYNAMIC_TYPE_PKCS7);
14451    if (encryptedContent == NULL) {
14452        ForceZero(plain, (word32)encryptedAllocSz);
14453        XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
14454        wc_PKCS7_FreeEncodedRecipientSet(pkcs7);
14455        XFREE(aadBuffer, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
14456        XFREE(flatUnauthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
14457        XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
14458        return MEMORY_E;
14459    }
14460
14461    /* encrypt content */
14462    ret = wc_PKCS7_EncryptContent(pkcs7, pkcs7->encryptOID, pkcs7->cek,
14463            (int)pkcs7->cekSz, nonce, (int)nonceSz, aadBuffer, aadBufferSz,
14464            authTag, sizeof(authTag), plain, encryptedOutSz, encryptedContent);
14465
14466    ForceZero(plain, (word32)encryptedAllocSz);
14467    XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
14468    plain = NULL;
14469
14470    XFREE(aadBuffer, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
14471    aadBuffer = NULL;
14472
14473    if (ret != 0) {
14474        wc_PKCS7_FreeEncodedRecipientSet(pkcs7);
14475        XFREE(flatUnauthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
14476        XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
14477        XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
14478        return ret;
14479    }
14480
14481    /* EncryptedContentInfo */
14482    ret = wc_SetContentType(pkcs7->contentOID, contentType,
14483                            sizeof(contentType));
14484    if (ret < 0) {
14485        wc_PKCS7_FreeEncodedRecipientSet(pkcs7);
14486        XFREE(flatUnauthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
14487        XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
14488        XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
14489        return ret;
14490    }
14491
14492    contentTypeSz = ret;
14493
14494    /* put together nonce OCTET STRING */
14495    nonceOctetStringSz = (int)SetOctetString(nonceSz, nonceOctetString);
14496
14497    /* put together aes-ICVlen INTEGER */
14498    macIntSz = (word32)SetMyVersion(sizeof(authTag), macInt, 0);
14499
14500    /* add nonce and icv len into parameters string RFC5084 */
14501    algoParamSeqSz = SetSequence((word32)nonceOctetStringSz + nonceSz +
14502            macIntSz, algoParamSeq);
14503
14504    /* build up our ContentEncryptionAlgorithmIdentifier sequence,
14505     * adding (nonceOctetStringSz + blockSz + macIntSz) for nonce OCTET STRING
14506     * and tag size */
14507    contentEncAlgoSz = (int)SetAlgoID(pkcs7->encryptOID, contentEncAlgo,
14508                                 oidBlkType, nonceOctetStringSz + (int)nonceSz +
14509                                 (int)macIntSz + (int)algoParamSeqSz);
14510
14511    if (contentEncAlgoSz == 0) {
14512        wc_PKCS7_FreeEncodedRecipientSet(pkcs7);
14513        XFREE(flatUnauthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
14514        XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
14515        XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
14516        return BAD_FUNC_ARG;
14517    }
14518
14519    encContentOctetSz = (int)SetImplicit(ASN_OCTET_STRING, 0,
14520                                (word32)encryptedOutSz, encContentOctet, 0);
14521    encContentSeqSz = (int)SetSequence((word32)contentTypeSz +
14522                               (word32)contentEncAlgoSz +
14523                               (word32)nonceOctetStringSz + nonceSz + macIntSz +
14524                               algoParamSeqSz + (word32)encContentOctetSz +
14525                               (word32)encryptedOutSz, encContentSeq);
14526
14527    macOctetStringSz = (int)SetOctetString(sizeof(authTag), macOctetString);
14528
14529    /* keep track of sizes for outer wrapper layering */
14530    totalSz = verSz + recipSetSz + recipSz + encContentSeqSz +
14531              contentTypeSz + contentEncAlgoSz + nonceOctetStringSz +
14532              (int)nonceSz + (int)macIntSz + (int)algoParamSeqSz +
14533              encContentOctetSz + encryptedOutSz + (int)authAttribsSz +
14534              (int)authAttribsSetSz + macOctetStringSz + (int)sizeof(authTag) +
14535              (int)unauthAttribsSz + (int)unauthAttribsSetSz;
14536
14537    /* EnvelopedData */
14538    envDataSeqSz = (int)SetSequence((word32)totalSz, envDataSeq);
14539    totalSz += envDataSeqSz;
14540
14541    /* outer content */
14542    outerContentSz = (int)SetExplicit(0, (word32)totalSz, outerContent, 0);
14543    totalSz += outerContentTypeSz;
14544    totalSz += outerContentSz;
14545
14546    /* ContentInfo */
14547    contentInfoSeqSz = (int)SetSequence((word32)totalSz, contentInfoSeq);
14548    totalSz += contentInfoSeqSz;
14549
14550    if (totalSz > (int)outputSz) {
14551        WOLFSSL_MSG("Pkcs7_encrypt output buffer too small");
14552        wc_PKCS7_FreeEncodedRecipientSet(pkcs7);
14553        XFREE(flatUnauthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
14554        XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
14555        XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
14556        return BUFFER_E;
14557    }
14558
14559    XMEMCPY(output + idx, contentInfoSeq, (word32)contentInfoSeqSz);
14560    idx += contentInfoSeqSz;
14561    XMEMCPY(output + idx, outerContentType, (word32)outerContentTypeSz);
14562    idx += outerContentTypeSz;
14563    XMEMCPY(output + idx, outerContent, (word32)outerContentSz);
14564    idx += outerContentSz;
14565    XMEMCPY(output + idx, envDataSeq, (word32)envDataSeqSz);
14566    idx += envDataSeqSz;
14567    XMEMCPY(output + idx, ver, (word32)verSz);
14568    idx += verSz;
14569    XMEMCPY(output + idx, recipSet, (word32)recipSetSz);
14570    idx += recipSetSz;
14571    /* copy in recipients from list */
14572    tmpRecip = pkcs7->recipList;
14573    while (tmpRecip != NULL) {
14574        XMEMCPY(output + idx, tmpRecip->recip, tmpRecip->recipSz);
14575        idx += (int)tmpRecip->recipSz;
14576        tmpRecip = tmpRecip->next;
14577    }
14578    wc_PKCS7_FreeEncodedRecipientSet(pkcs7);
14579    XMEMCPY(output + idx, encContentSeq, (word32)encContentSeqSz);
14580    idx += encContentSeqSz;
14581    XMEMCPY(output + idx, contentType, (word32)contentTypeSz);
14582    idx += contentTypeSz;
14583    XMEMCPY(output + idx, contentEncAlgo, (word32)contentEncAlgoSz);
14584    idx += contentEncAlgoSz;
14585    XMEMCPY(output + idx, algoParamSeq, algoParamSeqSz);
14586    idx += (int)algoParamSeqSz;
14587    XMEMCPY(output + idx, nonceOctetString, (word32)nonceOctetStringSz);
14588    idx += nonceOctetStringSz;
14589    XMEMCPY(output + idx, nonce, nonceSz);
14590    idx += (int)nonceSz;
14591    XMEMCPY(output + idx, macInt, macIntSz);
14592    idx += (int)macIntSz;
14593
14594
14595    XMEMCPY(output + idx, encContentOctet, (word32)encContentOctetSz);
14596    idx += encContentOctetSz;
14597    XMEMCPY(output + idx, encryptedContent, (word32)encryptedOutSz);
14598    idx += encryptedOutSz;
14599
14600    /* authenticated attributes */
14601    if (flatAuthAttribs && authAttribsSz > 0) {
14602        XMEMCPY(output + idx, authAttribSet, authAttribsSetSz);
14603        idx += (int)authAttribsSetSz;
14604        XMEMCPY(output + idx, flatAuthAttribs, authAttribsSz);
14605        idx += (int)authAttribsSz;
14606        XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
14607    }
14608
14609    XMEMCPY(output + idx, macOctetString, (word32)macOctetStringSz);
14610    idx += macOctetStringSz;
14611    XMEMCPY(output + idx, authTag, sizeof(authTag));
14612    idx += (int)sizeof(authTag);
14613
14614    /* unauthenticated attributes */
14615    if (unauthAttribsSz > 0) {
14616        XMEMCPY(output + idx, unauthAttribSet, unauthAttribsSetSz);
14617        idx += (int)unauthAttribsSetSz;
14618        XMEMCPY(output + idx, flatUnauthAttribs, unauthAttribsSz);
14619        idx += (int)unauthAttribsSz;
14620    }
14621
14622    XFREE(flatUnauthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
14623
14624    XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
14625
14626    return idx;
14627
14628#else
14629    WOLFSSL_MSG("AuthEnvelopedData requires AES-GCM or AES-CCM to be enabled");
14630    (void)pkcs7;
14631    (void)output;
14632    (void)outputSz;
14633
14634    return NOT_COMPILED_IN;
14635#endif /* HAVE_AESGCM | HAVE_AESCCM */
14636}
14637
14638
14639/* unwrap and decrypt PKCS#7 AuthEnvelopedData object, return decoded size */
14640int wc_PKCS7_DecodeAuthEnvelopedData(wc_PKCS7* pkcs7, byte* in,
14641                                                 word32 inSz, byte* output,
14642                                                 word32 outputSz)
14643{
14644#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM)
14645    int recipFound = 0;
14646    int ret = 0, length = 0;
14647    word32 idx = 0;
14648#ifndef NO_PKCS7_STREAM
14649    word32 tmpIdx = 0;
14650#endif
14651    word32 contentType = 0, encOID = 0;
14652    word32 decryptedKeySz = 0;
14653    byte* pkiMsg = in;
14654    word32 pkiMsgSz = inSz;
14655
14656    int expBlockSz = 0, blockKeySz = 0;
14657    byte authTag[WC_AES_BLOCK_SIZE];
14658    byte nonce[GCM_NONCE_MID_SZ];       /* GCM nonce is larger than CCM */
14659    int nonceSz = 0, macSz = 0;
14660    word32 authTagSz = 0;
14661    byte* decryptedKey = NULL;
14662    int encryptedContentSz = 0;
14663    int encryptedAllocSz = 0;
14664    byte* encryptedContent = NULL;
14665    int explicitOctet = 0;
14666
14667    byte* encodedAttribs = NULL;
14668    word32 encodedAttribIdx = 0, encodedAttribSz = 0;
14669    byte* authAttrib = NULL;
14670    int authAttribSz = 0;
14671    word32 localIdx;
14672    byte tag = 0;
14673
14674    if (pkcs7 == NULL)
14675        return BAD_FUNC_ARG;
14676
14677    if (pkiMsg == NULL || pkiMsgSz == 0 ||
14678        output == NULL || outputSz == 0)
14679        return BAD_FUNC_ARG;
14680#ifndef NO_PKCS7_STREAM
14681    if (pkcs7->stream == NULL) {
14682        if ((ret = wc_PKCS7_CreateStream(pkcs7)) != 0) {
14683            return ret;
14684        }
14685    }
14686#endif
14687
14688    switch (pkcs7->state) {
14689        case WC_PKCS7_START:
14690        case WC_PKCS7_INFOSET_START:
14691        case WC_PKCS7_INFOSET_STAGE1:
14692        case WC_PKCS7_INFOSET_STAGE2:
14693        case WC_PKCS7_INFOSET_END:
14694            ret = wc_PKCS7_ParseToRecipientInfoSet(pkcs7, pkiMsg, pkiMsgSz,
14695                    &idx, AUTH_ENVELOPED_DATA);
14696            if (ret < 0)
14697                break;
14698
14699        #ifndef NO_PKCS7_STREAM
14700            tmpIdx = idx;
14701        #endif
14702            wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_2);
14703            FALL_THROUGH;
14704
14705        case WC_PKCS7_AUTHENV_2:
14706        #ifndef NO_PKCS7_STREAM
14707            if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ +
14708                            MAX_VERSION_SZ + ASN_TAG_SZ, &pkiMsg, &idx)) != 0) {
14709                break;
14710            }
14711        #endif
14712            decryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap,
14713                                                            DYNAMIC_TYPE_PKCS7);
14714            if (decryptedKey == NULL) {
14715                ret = MEMORY_E;
14716                break;
14717            }
14718            else {
14719                XMEMSET(decryptedKey, 0, MAX_ENCRYPTED_KEY_SZ);
14720            #ifdef WOLFSSL_CHECK_MEM_ZERO
14721                wc_MemZero_Add("wc_PKCS7 decryptedKey", decryptedKey,
14722                                MAX_ENCRYPTED_KEY_SZ);
14723            #endif
14724            }
14725        #ifndef NO_PKCS7_STREAM
14726            pkcs7->stream->key = decryptedKey;
14727        #endif
14728            XMEMSET(decryptedKey, 0, MAX_ENCRYPTED_KEY_SZ);
14729            FALL_THROUGH;
14730
14731        case WC_PKCS7_DECRYPT_KTRI:
14732        case WC_PKCS7_DECRYPT_KTRI_2:
14733        case WC_PKCS7_DECRYPT_KTRI_3:
14734        case WC_PKCS7_DECRYPT_KARI:
14735        case WC_PKCS7_DECRYPT_KEKRI:
14736        case WC_PKCS7_DECRYPT_PWRI:
14737        case WC_PKCS7_DECRYPT_ORI:
14738
14739            decryptedKeySz = MAX_ENCRYPTED_KEY_SZ;
14740        #ifndef NO_PKCS7_STREAM
14741            decryptedKey = pkcs7->stream->key;
14742        #endif
14743
14744            ret = wc_PKCS7_DecryptRecipientInfos(pkcs7, in, inSz, &idx,
14745                                                decryptedKey, &decryptedKeySz,
14746                                                &recipFound);
14747            if (ret != 0) {
14748                break;
14749            }
14750
14751            if (recipFound == 0) {
14752                WOLFSSL_MSG(
14753                      "No recipient found in envelopedData that matches input");
14754                ret = PKCS7_RECIP_E;
14755                break;
14756            }
14757
14758        #ifndef NO_PKCS7_STREAM
14759            tmpIdx = idx;
14760            pkcs7->stream->expected = MAX_SEQ_SZ;
14761        #endif
14762            wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_3);
14763            FALL_THROUGH;
14764
14765        case WC_PKCS7_AUTHENV_3:
14766        #ifndef NO_PKCS7_STREAM
14767            if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
14768                    pkcs7->stream->expected, &pkiMsg, &idx)) != 0) {
14769                break;
14770            }
14771            pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
14772        #endif
14773
14774            /* remove EncryptedContentInfo */
14775            if (ret == 0 && GetSequence_ex(pkiMsg, &idx, &length, pkiMsgSz, 0)
14776                    < 0) {
14777                ret = ASN_PARSE_E;
14778            }
14779
14780        #ifndef NO_PKCS7_STREAM
14781            /* check that the expected size was accurate */
14782            if (ret == 0) {
14783                if (length > (int)pkcs7->stream->expected && length >
14784                        (int)pkiMsgSz) {
14785                    pkcs7->stream->expected = (word32)length + 1;
14786                    if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
14787                            pkcs7->stream->expected, &pkiMsg, &idx)) != 0) {
14788                        break;
14789                    }
14790                }
14791            }
14792        #endif
14793
14794            if (ret == 0 && wc_GetContentType(pkiMsg, &idx, &contentType,
14795                        pkiMsgSz) < 0) {
14796                ret = ASN_PARSE_E;
14797            }
14798
14799            if (ret == 0) {
14800                pkcs7->contentOID = (int)contentType;
14801            }
14802
14803            if (ret == 0 && GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType,
14804                        pkiMsgSz) < 0) {
14805                ret = ASN_PARSE_E;
14806            }
14807
14808            if (ret == 0) {
14809                blockKeySz = wc_PKCS7_GetOIDKeySize((int)encOID);
14810                if (blockKeySz < 0) {
14811                    ret = blockKeySz;
14812                }
14813            }
14814
14815            if (ret == 0) {
14816                expBlockSz = wc_PKCS7_GetOIDBlockSize((int)encOID);
14817                if (expBlockSz < 0) {
14818                    ret = expBlockSz;
14819                }
14820            }
14821
14822            /* get nonce, stored in OPTIONAL parameter of AlgoID
14823             * RFC 5084 Appendix lists GCM parameters as
14824             * seq
14825             * ---->octet string with nonce
14826             * ---->aes gcm icvlen
14827             */
14828            if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) {
14829                ret = ASN_PARSE_E;
14830            }
14831
14832
14833            if (ret == 0 && tag != (ASN_CONSTRUCTED | ASN_SEQUENCE)) {
14834                WOLFSSL_MSG("Optional parameters is not wrapped in a sequence");
14835                ret = ASN_PARSE_E;
14836            }
14837
14838            if (ret < 0)
14839                break;
14840
14841        #ifndef NO_PKCS7_STREAM
14842            if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) {
14843                break;
14844            }
14845            wc_PKCS7_StreamStoreVar(pkcs7, encOID, blockKeySz, 0);
14846        #endif
14847            wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_4);
14848            FALL_THROUGH;
14849
14850        case WC_PKCS7_AUTHENV_4:
14851
14852        #ifndef NO_PKCS7_STREAM
14853            if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ +
14854                            MAX_VERSION_SZ + ASN_TAG_SZ + MAX_LENGTH_SZ,
14855                            &pkiMsg, &idx)) != 0) {
14856                break;
14857            }
14858            pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
14859
14860            /* Restore encOID across WANT_READ re-entries so the nonce
14861             * length validation below always sees the content-cipher
14862             * algorithm parsed in AUTHENV_3. */
14863            wc_PKCS7_StreamGetVar(pkcs7, &encOID, &blockKeySz, NULL);
14864        #endif
14865            /* get length of optional parameter sequence */
14866            if (ret == 0 && GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) {
14867                ret = ASN_PARSE_E;
14868            }
14869
14870            /* get nonce from octet string */
14871            if (ret == 0 &&
14872                GetOctetString(pkiMsg, &idx, &nonceSz, pkiMsgSz) < 0) {
14873                ret = ASN_PARSE_E;
14874            }
14875
14876            if (ret == 0 && nonceSz > (int)sizeof(nonce)) {
14877                WOLFSSL_MSG("AuthEnvelopedData nonce too large for buffer");
14878                ret = ASN_PARSE_E;
14879            }
14880
14881            /* Enforce algorithm-specific nonce length bounds at the parser
14882             * layer so malformed lengths (notably zero-length, which would
14883             * catastrophically break AEAD uniqueness on HW backends that
14884             * skip their own checks) cannot reach the cipher engine.
14885             *   - AES-GCM in CMS: RFC 5084 Sec. 3.2 mandates a 12-octet IV.
14886             *   - AES-CCM: RFC 3610 Sec. 2.3 requires 7..13 octets.
14887             * Any other encOID here is a parser-state invariant violation. */
14888            if (ret == 0) {
14889                int nonceMin = 0, nonceMax = 0;
14890                switch (encOID) {
14891                #ifdef HAVE_AESGCM
14892                    case AES128GCMb:
14893                    case AES192GCMb:
14894                    case AES256GCMb:
14895                        nonceMin = GCM_NONCE_MID_SZ;
14896                        nonceMax = GCM_NONCE_MID_SZ;
14897                        break;
14898                #endif
14899                #ifdef HAVE_AESCCM
14900                    case AES128CCMb:
14901                    case AES192CCMb:
14902                    case AES256CCMb:
14903                        nonceMin = CCM_NONCE_MIN_SZ;
14904                        nonceMax = CCM_NONCE_MAX_SZ;
14905                        break;
14906                #endif
14907                    default:
14908                        WOLFSSL_MSG(
14909                            "AuthEnvelopedData unexpected content cipher");
14910                        ret = ALGO_ID_E;
14911                        break;
14912                }
14913                if (ret == 0 &&
14914                        (nonceSz < nonceMin || nonceSz > nonceMax)) {
14915                    WOLFSSL_MSG(
14916                        "AuthEnvelopedData nonce length invalid for cipher");
14917                    ret = ASN_PARSE_E;
14918                }
14919            }
14920
14921            if (ret == 0) {
14922                XMEMCPY(nonce, &pkiMsg[idx], (word32)nonceSz);
14923                idx += (word32)nonceSz;
14924            }
14925
14926            /* get mac size, also stored in OPTIONAL parameter of AlgoID */
14927            if (ret == 0 && GetMyVersion(pkiMsg, &idx, &macSz, pkiMsgSz) < 0) {
14928                ret = ASN_PARSE_E;
14929            }
14930            if (ret == 0 && (macSz <= 0 || macSz > WC_AES_BLOCK_SIZE)) {
14931                WOLFSSL_MSG("AuthEnvelopedData invalid MAC length");
14932                ret = ASN_PARSE_E;
14933            }
14934
14935            if (ret == 0) {
14936                explicitOctet = 0;
14937                localIdx = idx;
14938                if (GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) == 0 &&
14939                        tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0))
14940                    explicitOctet = 1;
14941
14942                /* read encryptedContent, cont[0] */
14943                ret = GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz);
14944            }
14945
14946            if (ret == 0 &&
14947                    tag != (ASN_CONTEXT_SPECIFIC | 0) &&
14948                    tag != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) {
14949                ret = ASN_PARSE_E;
14950            }
14951
14952            if (ret == 0 && GetLength_ex(pkiMsg, &idx, &encryptedContentSz,
14953                        pkiMsgSz, 0) <= 0) {
14954                ret = ASN_PARSE_E;
14955            }
14956
14957            if (explicitOctet) {
14958                if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) {
14959                    ret = ASN_PARSE_E;
14960                }
14961                if (ret == 0 && tag != ASN_OCTET_STRING) {
14962                    ret = ASN_PARSE_E;
14963                }
14964
14965                if (ret == 0 && GetLength(pkiMsg, &idx, &encryptedContentSz,
14966                            pkiMsgSz) <= 0) {
14967                    ret = ASN_PARSE_E;
14968                }
14969            }
14970
14971            if (ret < 0)
14972                break;
14973
14974        #ifndef NO_PKCS7_STREAM
14975            if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) {
14976                break;
14977            }
14978
14979            /* store nonce and macSz for later */
14980            pkcs7->stream->icvSz = (word32)macSz;
14981            if (nonceSz > 0) {
14982                pkcs7->stream->nonceSz = (word32)nonceSz;
14983                pkcs7->stream->nonce = (byte*)XMALLOC((word32)nonceSz,
14984                        pkcs7->heap, DYNAMIC_TYPE_PKCS7);
14985                if (pkcs7->stream->nonce == NULL) {
14986                    ret = MEMORY_E;
14987                    break;
14988                }
14989                else {
14990                    XMEMCPY(pkcs7->stream->nonce, nonce, (word32)nonceSz);
14991                }
14992            }
14993
14994            pkcs7->stream->expected = (word32)encryptedContentSz +
14995                    MAX_LENGTH_SZ + ASN_TAG_SZ + ASN_TAG_SZ;
14996            wc_PKCS7_StreamStoreVar(pkcs7, encOID, blockKeySz,
14997                    encryptedContentSz);
14998        #endif
14999
15000            wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_5);
15001            FALL_THROUGH;
15002
15003        case WC_PKCS7_AUTHENV_5:
15004        #ifndef NO_PKCS7_STREAM
15005            if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
15006                    pkcs7->stream->expected, &pkiMsg, &idx)) != 0) {
15007                break;
15008            }
15009            pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
15010
15011            wc_PKCS7_StreamGetVar(pkcs7, &encOID, &blockKeySz,
15012                &encryptedContentSz);
15013        #else
15014            pkiMsgSz = inSz;
15015        #endif
15016
15017            if (expBlockSz == 0) {
15018        #ifndef NO_PKCS7_STREAM
15019        #endif
15020                if (encOID == 0)
15021                    expBlockSz = 1;
15022                else {
15023                    expBlockSz = wc_PKCS7_GetOIDBlockSize((int)encOID);
15024                    if (expBlockSz < 0) {
15025                        ret = expBlockSz;
15026                        break;
15027                    } else if (expBlockSz == 0)
15028                        expBlockSz = 1;
15029                }
15030            }
15031
15032            /* AES-GCM/CCM does NOT require padding for plaintext content or
15033             * AAD inputs RFC 5084 section 3.1 and 3.2, but we must alloc
15034             * full blocks to ensure crypto only gets full blocks */
15035            encryptedAllocSz = (encryptedContentSz % expBlockSz) ?
15036                                   encryptedContentSz + expBlockSz -
15037                                   (encryptedContentSz % expBlockSz) :
15038                                   encryptedContentSz;
15039            encryptedContent = (byte*)XMALLOC((word32)encryptedAllocSz,
15040                                               pkcs7->heap, DYNAMIC_TYPE_PKCS7);
15041            if (ret == 0 && encryptedContent == NULL) {
15042                ret = MEMORY_E;
15043            }
15044
15045            if (ret == 0) {
15046                word32 tmpSum;
15047                if (!WC_SAFE_SUM_WORD32(idx, (word32)encryptedContentSz,
15048                                        tmpSum) ||
15049                    tmpSum > pkiMsgSz) {
15050                    ret = BUFFER_E;
15051                    break;
15052                } else {
15053                    XMEMCPY(encryptedContent, &pkiMsg[idx],
15054                                                    (word32)encryptedContentSz);
15055                    idx += (word32)encryptedContentSz;
15056                }
15057            }
15058        #ifndef NO_PKCS7_STREAM
15059            pkcs7->stream->bufferPt = encryptedContent;
15060        #endif
15061
15062            /* may have IMPLICIT [1] authenticatedAttributes */
15063            localIdx = idx;
15064            if (ret == 0 && GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) == 0 &&
15065                    tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) {
15066                encodedAttribIdx = idx;
15067                idx++;
15068
15069                if (GetLength_ex(pkiMsg, &idx, &length, pkiMsgSz, 0) <= 0) {
15070                    ret = ASN_PARSE_E;
15071                }
15072
15073            #ifdef NO_PKCS7_STREAM
15074                /* In non-streaming mode, validate authenticatedAttributes
15075                 * length is within the input buffer. The streaming path
15076                 * handles this via wc_PKCS7_AddDataToStream instead. */
15077                if (ret == 0 &&
15078                        (idx > pkiMsgSz || (word32)length > pkiMsgSz - idx)) {
15079                    ret = ASN_PARSE_E;
15080                }
15081            #else
15082                pkcs7->stream->expected = (word32)length;
15083            #endif
15084                encodedAttribSz = (word32)length + (idx - encodedAttribIdx);
15085
15086                if (ret != 0)
15087                    break;
15088
15089                if (encodedAttribSz > 0) {
15090                    encodedAttribs = (byte*)XMALLOC(encodedAttribSz,
15091                            pkcs7->heap, DYNAMIC_TYPE_PKCS7);
15092                    if (encodedAttribs == NULL) {
15093                        ret = MEMORY_E;
15094                        break;
15095                    }
15096                }
15097
15098            #ifndef NO_PKCS7_STREAM
15099                if (encodedAttribSz > 0) {
15100                    pkcs7->stream->aadSz = encodedAttribSz;
15101                    pkcs7->stream->aad   = encodedAttribs;
15102                }
15103
15104                if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) {
15105                    break;
15106                }
15107            #endif
15108                wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_ATRB);
15109            }
15110            else {
15111            #ifndef NO_PKCS7_STREAM
15112                if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) {
15113                    break;
15114                }
15115                pkcs7->stream->expected = MAX_LENGTH_SZ + ASN_TAG_SZ;
15116            #endif
15117                wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_ATRBEND);
15118                goto authenv_atrbend; /* jump over attribute cases */
15119            }
15120            FALL_THROUGH;
15121
15122        case WC_PKCS7_AUTHENV_ATRB:
15123    #ifndef NO_PKCS7_STREAM
15124            if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
15125                            pkcs7->stream->expected, &pkiMsg, &idx)) != 0) {
15126                return ret;
15127            }
15128
15129            length = (int)pkcs7->stream->expected;
15130            encodedAttribs = pkcs7->stream->aad;
15131    #endif
15132
15133            /* save pointer and length */
15134            authAttrib = &pkiMsg[idx];
15135            authAttribSz = length;
15136
15137            {
15138                word32 ofst;
15139
15140                /* From RFC5083, "For the purpose of constructing the
15141                * AAD, the IMPLICIT [1] tag in the authAttrs field is
15142                * not used for the DER encoding: rather a universal SET
15143                * OF tag is used. */
15144                ofst = SetSet((word32)length, encodedAttribs);
15145
15146                XMEMCPY(encodedAttribs + ofst, authAttrib,
15147                    (word32)authAttribSz);
15148            }
15149
15150            /* ignoring the size returned, we know it is
15151                * idx - encodedAttribIdx from parsing what's given */
15152
15153            if (ret == 0 && wc_PKCS7_ParseAttribs(pkcs7, authAttrib,
15154                    authAttribSz) < 0) {
15155                WOLFSSL_MSG("Error parsing authenticated attributes");
15156                ret = ASN_PARSE_E;
15157                break;
15158            }
15159
15160            idx += (word32)length;
15161
15162    #ifndef NO_PKCS7_STREAM
15163            if (pkcs7->stream->aadSz > 0) {
15164                XMEMCPY(pkcs7->stream->aad + (pkcs7->stream->aadSz -
15165                        (word32)length), authAttrib, (word32)authAttribSz);
15166            }
15167            if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) {
15168                break;
15169            }
15170            pkcs7->stream->expected = MAX_LENGTH_SZ + ASN_TAG_SZ;
15171    #endif
15172            wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_ATRBEND);
15173            FALL_THROUGH;
15174
15175        case WC_PKCS7_AUTHENV_ATRBEND:
15176authenv_atrbend:
15177        #ifndef NO_PKCS7_STREAM
15178            if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
15179                    pkcs7->stream->expected, &pkiMsg, &idx)) != 0) {
15180                return ret;
15181            }
15182            pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
15183
15184            if (pkcs7->stream->aadSz > 0) {
15185                encodedAttribSz = pkcs7->stream->aadSz;
15186                encodedAttribs  = pkcs7->stream->aad;
15187            }
15188            macSz = (int)pkcs7->stream->icvSz;
15189        #endif
15190
15191
15192            localIdx = idx;
15193
15194            /* Get authTag OCTET STRING */
15195            if (ret == 0 && pkiMsg[localIdx] != ASN_OCTET_STRING) {
15196                ret = ASN_PARSE_E;
15197            }
15198            localIdx++; /* move past ASN_OCTET_STRING */
15199
15200            if (ret == 0 && GetLength_ex(pkiMsg, &localIdx, &length,
15201                    pkiMsgSz, 0) < 0) {
15202                ret = ASN_PARSE_E;
15203            }
15204            authTagSz = (word32)length;
15205            if (ret == 0 && authTagSz != (word32)macSz) {
15206                WOLFSSL_MSG("AuthEnvelopedData authTag size mismatch");
15207                ret = ASN_PARSE_E;
15208            }
15209            if (ret == 0 &&
15210                    (encOID == AES128GCMb || encOID == AES192GCMb ||
15211                     encOID == AES256GCMb) &&
15212                    authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ) {
15213                WOLFSSL_MSG("AuthEnvelopedData GCM authTag too small");
15214                ret = ASN_PARSE_E;
15215            }
15216
15217        #ifndef NO_PKCS7_STREAM
15218            /* there might not be enough data for the auth tag too */
15219            if (ret == 0) {
15220                if ((authTagSz + (localIdx - idx)) > pkcs7->stream->expected &&
15221                    (authTagSz + (localIdx - idx)) > pkiMsgSz) {
15222                        pkcs7->stream->expected = authTagSz +
15223                            (localIdx - idx);
15224                        if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
15225                            pkcs7->stream->expected, &pkiMsg, &idx)) != 0) {
15226                            return ret;
15227                        }
15228                }
15229            }
15230        #endif
15231            idx = localIdx;
15232
15233            if (ret == 0 && authTagSz > (word32)sizeof(authTag)) {
15234                WOLFSSL_MSG("AuthEnvelopedData authTag too large for buffer");
15235                ret = ASN_PARSE_E;
15236            }
15237
15238            if (ret == 0) {
15239                XMEMCPY(authTag, &pkiMsg[idx], authTagSz);
15240                idx += authTagSz;
15241            }
15242
15243            if (ret < 0)
15244                break;
15245
15246        #ifndef NO_PKCS7_STREAM
15247            if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) {
15248                break;
15249            }
15250            pkcs7->stream->expected = (pkcs7->stream->maxLen -
15251                pkcs7->stream->totalRd) + pkcs7->stream->length;
15252
15253
15254            /* store tag for later */
15255            if (authTagSz > 0) {
15256                pkcs7->stream->tagSz = authTagSz;
15257                pkcs7->stream->tag = (byte*)XMALLOC(authTagSz,
15258                        pkcs7->heap, DYNAMIC_TYPE_PKCS7);
15259                if (pkcs7->stream->tag == NULL) {
15260                    ret = MEMORY_E;
15261                    break;
15262                }
15263                else {
15264                    XMEMCPY(pkcs7->stream->tag, authTag, authTagSz);
15265                }
15266            }
15267
15268        #endif
15269            wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_6);
15270            FALL_THROUGH;
15271
15272        case WC_PKCS7_AUTHENV_6:
15273        #ifndef NO_PKCS7_STREAM
15274            if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
15275                            pkcs7->stream->expected, &pkiMsg, &idx)) != 0) {
15276                break;
15277            }
15278
15279            /* restore all variables needed */
15280            if (pkcs7->stream->nonceSz > 0) {
15281                nonceSz = (int)pkcs7->stream->nonceSz;
15282                if (nonceSz > GCM_NONCE_MID_SZ) {
15283                    WOLFSSL_MSG("PKCS7 saved nonce is too large");
15284                    ret = BUFFER_E;
15285                    break;
15286                }
15287                else {
15288                    XMEMCPY(nonce, pkcs7->stream->nonce, (word32)nonceSz);
15289                }
15290            }
15291
15292            if (pkcs7->stream->tagSz > 0) {
15293                authTagSz = pkcs7->stream->tagSz;
15294                if (authTagSz > WC_AES_BLOCK_SIZE) {
15295                    WOLFSSL_MSG("PKCS7 saved tag is too large");
15296                    ret = BUFFER_E;
15297                    break;
15298                }
15299                else {
15300                    XMEMCPY(authTag, pkcs7->stream->tag, authTagSz);
15301                }
15302            }
15303
15304            if (pkcs7->stream->aadSz > 0) {
15305                encodedAttribSz = pkcs7->stream->aadSz;
15306                encodedAttribs  = pkcs7->stream->aad;
15307            }
15308
15309            wc_PKCS7_StreamGetVar(pkcs7, &encOID, &blockKeySz,
15310                                  &encryptedContentSz);
15311            encryptedContent   = pkcs7->stream->bufferPt;
15312            decryptedKey = pkcs7->stream->key;
15313        #endif
15314
15315            /* decrypt encryptedContent */
15316            ret = wc_PKCS7_DecryptContent(pkcs7, encOID, decryptedKey,
15317                    (word32)blockKeySz, nonce, nonceSz, encodedAttribs,
15318                    encodedAttribSz, authTag, authTagSz,
15319                    encryptedContent, encryptedContentSz, encryptedContent,
15320                    pkcs7->devId, pkcs7->heap);
15321            if (ret != 0) {
15322                XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
15323                return ret;
15324            }
15325
15326            if (encodedAttribs != NULL) {
15327                XFREE(encodedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
15328                encodedAttribs = NULL;
15329            #ifndef NO_PKCS7_STREAM
15330                pkcs7->stream->aad = NULL;
15331            #endif
15332            }
15333
15334            /* copy plaintext to output */
15335            if ((word32)encryptedContentSz > outputSz) {
15336                ret = BUFFER_E;
15337                break;
15338            }
15339            XMEMCPY(output, encryptedContent, (word32)encryptedContentSz);
15340
15341            /* free memory, zero out keys */
15342            ForceZero(encryptedContent, (word32)encryptedContentSz);
15343            XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
15344            encryptedContent = NULL;
15345            ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ);
15346            XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
15347            decryptedKey = NULL;
15348        #ifndef NO_PKCS7_STREAM
15349            pkcs7->stream->key = NULL;
15350        #endif
15351            ret = encryptedContentSz;
15352        #ifndef NO_PKCS7_STREAM
15353            wc_PKCS7_ResetStream(pkcs7);
15354        #endif
15355            wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START);
15356            break;
15357        default:
15358            WOLFSSL_MSG("Unknown PKCS7 state");
15359            ret = BAD_FUNC_ARG;
15360    }
15361
15362    if (ret != 0 && ret != WC_NO_ERR_TRACE(WC_PKCS7_WANT_READ_E)) {
15363        if (decryptedKey != NULL) {
15364            ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ);
15365            XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
15366            decryptedKey = NULL;
15367        #ifndef NO_PKCS7_STREAM
15368            pkcs7->stream->key = NULL;
15369        #endif
15370        }
15371
15372        if (encryptedContent != NULL) {
15373            ForceZero(encryptedContent, (word32)encryptedContentSz);
15374            XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
15375            encryptedContent = NULL;
15376        #ifndef NO_PKCS7_STREAM
15377            pkcs7->stream->bufferPt = NULL;
15378        #endif
15379        }
15380
15381        if (encodedAttribs != NULL) {
15382            XFREE(encodedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
15383            encodedAttribs = NULL;
15384        #ifndef NO_PKCS7_STREAM
15385            pkcs7->stream->aad = NULL;
15386        #endif
15387        }
15388    }
15389
15390#ifndef NO_PKCS7_STREAM
15391    if (ret != 0 && ret != WC_NO_ERR_TRACE(WC_PKCS7_WANT_READ_E)) {
15392        wc_PKCS7_ResetStream(pkcs7);
15393    }
15394#endif
15395
15396    return ret;
15397
15398#else
15399    WOLFSSL_MSG("AuthEnvelopedData requires AES-GCM or AES-CCM to be enabled");
15400    (void)pkcs7;
15401    (void)in;
15402    (void)inSz;
15403    (void)output;
15404    (void)outputSz;
15405
15406    return NOT_COMPILED_IN;
15407#endif /* HAVE_AESGCM | HAVE_AESCCM */
15408}
15409
15410
15411#ifndef NO_PKCS7_ENCRYPTED_DATA
15412
15413/* build PKCS#7 encryptedData content type, return encrypted size */
15414int wc_PKCS7_EncodeEncryptedData(wc_PKCS7* pkcs7, byte* output, word32 outputSz)
15415{
15416    int ret, idx = 0;
15417    int totalSz, padSz, encryptedOutSz;
15418
15419    int contentInfoSeqSz, outerContentTypeSz, outerContentSz;
15420    byte contentInfoSeq[MAX_SEQ_SZ];
15421    byte outerContentType[MAX_ALGO_SZ];
15422    byte outerContent[MAX_SEQ_SZ];
15423
15424    int encDataSeqSz, verSz, blockSz;
15425    byte encDataSeq[MAX_SEQ_SZ];
15426    byte ver[MAX_VERSION_SZ];
15427
15428    byte* plain = NULL;
15429    byte* encryptedContent = NULL;
15430
15431    int encContentOctetSz, encContentSeqSz, contentTypeSz;
15432    int contentEncAlgoSz, ivOctetStringSz;
15433    byte encContentSeq[MAX_SEQ_SZ];
15434    byte contentType[MAX_OID_SZ];
15435    byte contentEncAlgo[MAX_ALGO_SZ];
15436    byte tmpIv[MAX_CONTENT_IV_SIZE];
15437    byte ivOctetString[MAX_OCTET_STR_SZ];
15438    byte encContentOctet[MAX_OCTET_STR_SZ];
15439
15440    byte attribSet[MAX_SET_SZ];
15441    EncodedAttrib* attribs = NULL;
15442    word32 attribsSz;
15443    word32 attribsCount;
15444    word32 attribsSetSz;
15445
15446    byte* flatAttribs = NULL;
15447
15448    if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 ||
15449        pkcs7->encryptOID == 0 || pkcs7->encryptionKey == NULL ||
15450        pkcs7->encryptionKeySz == 0)
15451        return BAD_FUNC_ARG;
15452
15453    if (output == NULL || outputSz == 0)
15454        return BAD_FUNC_ARG;
15455
15456    if (pkcs7->version == 3) {
15457        verSz = SetMyVersion(0, ver, 0);
15458        outerContentTypeSz = 0;
15459    }
15460    else {
15461        /* outer content type */
15462        ret = wc_SetContentType(ENCRYPTED_DATA, outerContentType,
15463                                sizeof(outerContentType));
15464        if (ret < 0)
15465            return ret;
15466
15467        outerContentTypeSz = ret;
15468
15469        /* version, 2 if unprotectedAttrs present, 0 if absent */
15470        if (pkcs7->unprotectedAttribsSz > 0) {
15471            verSz = SetMyVersion(2, ver, 0);
15472        } else {
15473            verSz = SetMyVersion(0, ver, 0);
15474        }
15475    }
15476
15477    /* EncryptedContentInfo */
15478    ret = wc_SetContentType(pkcs7->contentOID, contentType,
15479                            sizeof(contentType));
15480    if (ret < 0)
15481        return ret;
15482
15483    contentTypeSz = ret;
15484
15485    /* allocate encrypted content buffer, do PKCS#7 padding */
15486    blockSz = wc_PKCS7_GetOIDBlockSize(pkcs7->encryptOID);
15487    if (blockSz < 0)
15488        return blockSz;
15489
15490    padSz = wc_PKCS7_GetPadSize(pkcs7->contentSz, (word32)blockSz);
15491    if (padSz < 0)
15492        return padSz;
15493
15494    encryptedOutSz = (int)pkcs7->contentSz + padSz;
15495
15496    plain = (byte*)XMALLOC((word32)encryptedOutSz, pkcs7->heap,
15497                           DYNAMIC_TYPE_PKCS7);
15498    if (plain == NULL)
15499        return MEMORY_E;
15500
15501    ret = wc_PKCS7_PadData(pkcs7->content, pkcs7->contentSz, plain,
15502                           (word32)encryptedOutSz, (word32)blockSz);
15503    if (ret < 0) {
15504        ForceZero(plain, (word32)encryptedOutSz);
15505        XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
15506        return ret;
15507    }
15508
15509    encryptedContent = (byte*)XMALLOC((word32)encryptedOutSz, pkcs7->heap,
15510                                      DYNAMIC_TYPE_PKCS7);
15511    if (encryptedContent == NULL) {
15512        ForceZero(plain, (word32)encryptedOutSz);
15513        XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
15514        return MEMORY_E;
15515    }
15516
15517    /* put together IV OCTET STRING */
15518    ivOctetStringSz = (int)SetOctetString((word32)blockSz, ivOctetString);
15519
15520    /* build up ContentEncryptionAlgorithmIdentifier sequence,
15521       adding (ivOctetStringSz + blockSz) for IV OCTET STRING */
15522    contentEncAlgoSz = (int)SetAlgoID(pkcs7->encryptOID, contentEncAlgo,
15523                                 oidBlkType, ivOctetStringSz + blockSz);
15524    if (contentEncAlgoSz == 0) {
15525        XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
15526        ForceZero(plain, (word32)encryptedOutSz);
15527        XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
15528        return BAD_FUNC_ARG;
15529    }
15530
15531    /* encrypt content */
15532    WOLFSSL_MSG("Encrypting the content");
15533    ret = wc_PKCS7_GenerateBlock(pkcs7, NULL, tmpIv, (word32)blockSz);
15534    if (ret != 0) {
15535        XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
15536        ForceZero(plain, (word32)encryptedOutSz);
15537        XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
15538        return ret;
15539    }
15540
15541    ret = wc_PKCS7_EncryptContent(pkcs7, pkcs7->encryptOID,
15542            pkcs7->encryptionKey, (int)pkcs7->encryptionKeySz, tmpIv, blockSz,
15543            NULL, 0, NULL, 0, plain, encryptedOutSz, encryptedContent);
15544    if (ret != 0) {
15545        XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
15546        ForceZero(plain, (word32)encryptedOutSz);
15547        XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
15548        return ret;
15549    }
15550
15551    encContentOctetSz = (int)SetImplicit(ASN_OCTET_STRING, 0,
15552                                    (word32)encryptedOutSz, encContentOctet, 0);
15553
15554    encContentSeqSz = (int)SetSequence((word32)(contentTypeSz +
15555                                  contentEncAlgoSz + ivOctetStringSz + blockSz +
15556                                  encContentOctetSz + encryptedOutSz),
15557                                  encContentSeq);
15558
15559    /* optional UnprotectedAttributes */
15560    if (pkcs7->unprotectedAttribsSz != 0) {
15561
15562        if (pkcs7->unprotectedAttribs == NULL) {
15563            XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
15564            ForceZero(plain, (word32)encryptedOutSz);
15565            XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
15566            return BAD_FUNC_ARG;
15567        }
15568
15569        attribs = (EncodedAttrib*)XMALLOC(
15570                sizeof(EncodedAttrib) * pkcs7->unprotectedAttribsSz,
15571                pkcs7->heap, DYNAMIC_TYPE_PKCS7);
15572        if (attribs == NULL) {
15573            XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
15574            ForceZero(plain, (word32)encryptedOutSz);
15575            XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
15576            return MEMORY_E;
15577        }
15578
15579        attribsCount = pkcs7->unprotectedAttribsSz;
15580        attribsSz = (word32)EncodeAttributes(attribs,
15581                                     (int)pkcs7->unprotectedAttribsSz,
15582                                     pkcs7->unprotectedAttribs,
15583                                     (int)pkcs7->unprotectedAttribsSz);
15584
15585        if (attribsSz > 0) {
15586            flatAttribs = (byte*)XMALLOC(attribsSz, pkcs7->heap,
15587                                         DYNAMIC_TYPE_PKCS7);
15588            if (flatAttribs == NULL) {
15589                XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
15590                XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
15591                ForceZero(plain, (word32)encryptedOutSz);
15592                XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
15593                return MEMORY_E;
15594            }
15595
15596            ret = FlattenAttributes(pkcs7, flatAttribs, attribs,
15597                                    (int)attribsCount);
15598            if (ret != 0) {
15599                XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
15600                XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
15601                ForceZero(plain, (word32)encryptedOutSz);
15602                XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
15603                XFREE(flatAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
15604                return ret;
15605            }
15606        }
15607
15608        attribsSetSz = SetImplicit(ASN_SET, 1, attribsSz, attribSet, 0);
15609
15610    } else {
15611        attribsSz = 0;
15612        attribsSetSz = 0;
15613    }
15614
15615    /* keep track of sizes for outer wrapper layering */
15616    totalSz = verSz + encContentSeqSz + contentTypeSz + contentEncAlgoSz +
15617              ivOctetStringSz + blockSz + encContentOctetSz + encryptedOutSz +
15618              (int)attribsSz + (int)attribsSetSz;
15619
15620    /* EncryptedData */
15621    encDataSeqSz = (int)SetSequence((word32)totalSz, encDataSeq);
15622    totalSz += encDataSeqSz;
15623
15624    if (pkcs7->version != 3) {
15625        /* outer content */
15626        outerContentSz = (int)SetExplicit(0, (word32)totalSz, outerContent, 0);
15627        totalSz += outerContentTypeSz;
15628        totalSz += outerContentSz;
15629        /* ContentInfo */
15630        contentInfoSeqSz = (int)SetSequence((word32)totalSz, contentInfoSeq);
15631        totalSz += contentInfoSeqSz;
15632    } else {
15633        contentInfoSeqSz = 0;
15634        outerContentSz = 0;
15635    }
15636
15637    if (totalSz > (int)outputSz) {
15638        WOLFSSL_MSG("PKCS#7 output buffer too small");
15639        XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
15640        XFREE(flatAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
15641        XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
15642        ForceZero(plain, (word32)encryptedOutSz);
15643        XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
15644        return BUFFER_E;
15645    }
15646
15647    XMEMCPY(output + idx, contentInfoSeq, (word32)contentInfoSeqSz);
15648    idx += contentInfoSeqSz;
15649    XMEMCPY(output + idx, outerContentType, (word32)outerContentTypeSz);
15650    idx += outerContentTypeSz;
15651    XMEMCPY(output + idx, outerContent, (word32)outerContentSz);
15652    idx += outerContentSz;
15653    XMEMCPY(output + idx, encDataSeq, (word32)encDataSeqSz);
15654    idx += encDataSeqSz;
15655    XMEMCPY(output + idx, ver, (word32)verSz);
15656    idx += verSz;
15657    XMEMCPY(output + idx, encContentSeq, (word32)encContentSeqSz);
15658    idx += encContentSeqSz;
15659    XMEMCPY(output + idx, contentType, (word32)contentTypeSz);
15660    idx += contentTypeSz;
15661    XMEMCPY(output + idx, contentEncAlgo, (word32)contentEncAlgoSz);
15662    idx += contentEncAlgoSz;
15663    XMEMCPY(output + idx, ivOctetString, (word32)ivOctetStringSz);
15664    idx += ivOctetStringSz;
15665    XMEMCPY(output + idx, tmpIv, (word32)blockSz);
15666    idx += blockSz;
15667    XMEMCPY(output + idx, encContentOctet, (word32)encContentOctetSz);
15668    idx += encContentOctetSz;
15669    XMEMCPY(output + idx, encryptedContent, (word32)encryptedOutSz);
15670    idx += encryptedOutSz;
15671
15672    if (pkcs7->unprotectedAttribsSz != 0) {
15673        XMEMCPY(output + idx, attribSet, attribsSetSz);
15674        idx += (int)attribsSetSz;
15675        if (attribsSz > 0) {
15676            XMEMCPY(output + idx, flatAttribs, attribsSz);
15677            idx += (int)attribsSz;
15678        }
15679    }
15680
15681    XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
15682    XFREE(flatAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
15683    XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
15684    ForceZero(plain, (word32)encryptedOutSz);
15685    XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
15686
15687    return idx;
15688}
15689
15690
15691/* decode and store unprotected attributes in PKCS7->decodedAttrib. Return
15692 * 0 on success, negative on error. User must call wc_PKCS7_Free(). */
15693static int wc_PKCS7_DecodeUnprotectedAttributes(wc_PKCS7* pkcs7, byte* pkiMsg,
15694                                             word32 pkiMsgSz, word32* inOutIdx)
15695{
15696    int ret, attribLen;
15697    word32 idx;
15698    byte tag;
15699
15700    if (pkcs7 == NULL || pkiMsg == NULL ||
15701        pkiMsgSz == 0 || inOutIdx == NULL)
15702        return BAD_FUNC_ARG;
15703
15704    idx = *inOutIdx;
15705
15706    if (GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0)
15707        return ASN_PARSE_E;
15708
15709    if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1))
15710        return ASN_PARSE_E;
15711
15712    if (GetLength(pkiMsg, &idx, &attribLen, pkiMsgSz) < 0)
15713        return ASN_PARSE_E;
15714
15715    /* loop through attributes */
15716    if ((ret = wc_PKCS7_ParseAttribs(pkcs7, pkiMsg + idx, attribLen)) < 0) {
15717        return ret;
15718    }
15719
15720    *inOutIdx = idx;
15721
15722    return 0;
15723}
15724
15725
15726/* unwrap and decrypt PKCS#7/CMS encrypted-data object, returned decoded size */
15727int wc_PKCS7_DecodeEncryptedData(wc_PKCS7* pkcs7, byte* in, word32 inSz,
15728                                 byte* output, word32 outputSz)
15729{
15730    int ret = 0, version = 0, length = 0, haveAttribs = 0;
15731    word32 idx = 0;
15732
15733#ifndef NO_PKCS7_STREAM
15734    word32 tmpIdx = 0;
15735#endif
15736    word32 contentType = 0, encOID = 0;
15737
15738    int expBlockSz = 0;
15739    byte tmpIvBuf[MAX_CONTENT_IV_SIZE];
15740    byte *tmpIv = tmpIvBuf;
15741
15742    int encryptedContentSz = 0;
15743    byte padLen = 0;
15744    byte* encryptedContent = NULL;
15745
15746    byte* pkiMsg = in;
15747    word32 pkiMsgSz = inSz;
15748    byte  tag = 0;
15749    byte padCheck = 0;
15750    int padIndex;
15751
15752    if (pkcs7 == NULL ||
15753            ((pkcs7->encryptionKey == NULL || pkcs7->encryptionKeySz == 0) &&
15754              pkcs7->decryptionCb == NULL))
15755        return BAD_FUNC_ARG;
15756
15757    if (pkiMsg == NULL || pkiMsgSz == 0 ||
15758        output == NULL || outputSz == 0)
15759        return BAD_FUNC_ARG;
15760
15761#ifndef NO_PKCS7_STREAM
15762    (void)tmpIv; /* help out static analysis */
15763    if (pkcs7->stream == NULL) {
15764        if ((ret = wc_PKCS7_CreateStream(pkcs7)) != 0) {
15765            return ret;
15766        }
15767    }
15768#endif
15769
15770    switch (pkcs7->state) {
15771        case WC_PKCS7_START:
15772#ifndef NO_PKCS7_STREAM
15773            if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_SEQ_SZ +
15774                            MAX_ALGO_SZ, &pkiMsg, &idx)) != 0) {
15775                return ret;
15776            }
15777
15778            if ((ret = wc_PKCS7_SetMaxStream(pkcs7, in, inSz)) != 0) {
15779                return ret;
15780            }
15781            pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
15782#endif
15783
15784            if (GetSequence_ex(pkiMsg, &idx, &length, pkiMsgSz,
15785                        NO_USER_CHECK) < 0)
15786                ret = ASN_PARSE_E;
15787
15788            if (pkcs7->version != 3) { /* ContentInfo not in firmware bundles */
15789                /* read past ContentInfo, verify type is encrypted-data */
15790                if (ret == 0 && wc_GetContentType(pkiMsg, &idx, &contentType,
15791                            pkiMsgSz) < 0)
15792                    ret = ASN_PARSE_E;
15793
15794                if (ret == 0 && contentType != ENCRYPTED_DATA) {
15795                    WOLFSSL_MSG("PKCS#7 input not of type EncryptedData");
15796                    ret = PKCS7_OID_E;
15797                }
15798            }
15799            if (ret != 0) break;
15800#ifndef NO_PKCS7_STREAM
15801            if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) {
15802                break;
15803            }
15804#endif
15805            wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_STAGE2);
15806            FALL_THROUGH;
15807            /* end of stage 1 */
15808
15809        case WC_PKCS7_STAGE2:
15810#ifndef NO_PKCS7_STREAM
15811            if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
15812                            MAX_LENGTH_SZ + MAX_SEQ_SZ + ASN_TAG_SZ, &pkiMsg,
15813                            &idx)) != 0) {
15814                return ret;
15815            }
15816            pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
15817#endif
15818            if (pkcs7->version != 3) {
15819                if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0)
15820                    ret = ASN_PARSE_E;
15821                if (ret == 0 && tag !=
15822                        (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
15823                    ret = ASN_PARSE_E;
15824
15825                if (ret == 0 && GetLength_ex(pkiMsg, &idx, &length, pkiMsgSz,
15826                            NO_USER_CHECK) < 0)
15827                    ret = ASN_PARSE_E;
15828
15829                /* remove EncryptedData and version */
15830                if (ret == 0 && GetSequence_ex(pkiMsg, &idx, &length, pkiMsgSz,
15831                            NO_USER_CHECK) < 0)
15832                    ret = ASN_PARSE_E;
15833            }
15834
15835            if (ret != 0) break;
15836#ifndef NO_PKCS7_STREAM
15837            if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) {
15838                break;
15839            }
15840#endif
15841            wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_STAGE3);
15842            FALL_THROUGH;
15843            /* end of stage 2 */
15844
15845       case WC_PKCS7_STAGE3:
15846#ifndef NO_PKCS7_STREAM
15847            if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
15848                            MAX_VERSION_SZ + MAX_SEQ_SZ + MAX_ALGO_SZ * 2,
15849                            &pkiMsg, &idx)) != 0) {
15850                return ret;
15851            }
15852            pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
15853#endif
15854            /* get version, check later */
15855            haveAttribs = 0;
15856            if (ret == 0 && GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0)
15857                ret = ASN_PARSE_E;
15858
15859            /* remove EncryptedContentInfo */
15860            if (ret == 0 && GetSequence_ex(pkiMsg, &idx, &length, pkiMsgSz,
15861                        NO_USER_CHECK) < 0)
15862                ret = ASN_PARSE_E;
15863
15864            if (ret == 0 && wc_GetContentType(pkiMsg, &idx, &contentType,
15865                        pkiMsgSz) < 0)
15866                ret = ASN_PARSE_E;
15867
15868            if (ret == 0) {
15869                pkcs7->contentOID = (int)contentType;
15870            }
15871
15872            if (ret == 0 && (ret = GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType,
15873                        pkiMsgSz)) < 0)
15874                ret = ASN_PARSE_E;
15875            if (ret == 0 && (expBlockSz =
15876                    wc_PKCS7_GetOIDBlockSize((int)encOID)) < 0)
15877                ret = expBlockSz;
15878
15879            if (ret != 0) break;
15880#ifndef NO_PKCS7_STREAM
15881            /* store expBlockSz for later */
15882            pkcs7->stream->varOne = (word32)expBlockSz;
15883            pkcs7->stream->varTwo = (int)encOID;
15884
15885            if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) {
15886                break;
15887            }
15888
15889            /* store version for later */
15890            pkcs7->stream->vers = (word32)version;
15891#endif
15892            wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_STAGE4);
15893            FALL_THROUGH;
15894            /* end of stage 3 */
15895
15896        /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */
15897       case WC_PKCS7_STAGE4:
15898#ifndef NO_PKCS7_STREAM
15899            if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
15900                            ASN_TAG_SZ + MAX_LENGTH_SZ, &pkiMsg, &idx)) != 0) {
15901                return ret;
15902            }
15903            pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
15904
15905            /* restore saved variables */
15906            expBlockSz = (int)pkcs7->stream->varOne;
15907#endif
15908            if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0)
15909                ret = ASN_PARSE_E;
15910            if (ret == 0 && tag != ASN_OCTET_STRING)
15911                ret = ASN_PARSE_E;
15912
15913            if (ret == 0 && GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
15914                ret = ASN_PARSE_E;
15915
15916            if (ret == 0 && length != expBlockSz) {
15917                WOLFSSL_MSG(
15918                      "Incorrect IV length, must be of content alg block size");
15919                ret = ASN_PARSE_E;
15920            }
15921
15922            if (ret != 0) break;
15923#ifndef NO_PKCS7_STREAM
15924            /* next chunk of data expected should have the IV */
15925            pkcs7->stream->expected = (word32)length;
15926
15927            if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) {
15928                break;
15929            }
15930#endif
15931            wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_STAGE5);
15932            FALL_THROUGH;
15933            /* end of stage 4 */
15934
15935       case WC_PKCS7_STAGE5:
15936#ifndef NO_PKCS7_STREAM
15937            if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
15938                            pkcs7->stream->expected + ASN_TAG_SZ +
15939                            MAX_LENGTH_SZ, &pkiMsg, &idx)) != 0) {
15940                return ret;
15941            }
15942            pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
15943
15944            /* use IV buffer from stream structure */
15945            tmpIv  = pkcs7->stream->tmpIv;
15946            length = (int)pkcs7->stream->expected;
15947#endif
15948            XMEMCPY(tmpIv, &pkiMsg[idx], (word32)length);
15949            idx += (word32)length;
15950            /* read encryptedContent, cont[0] */
15951            if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0)
15952                ret = ASN_PARSE_E;
15953            if (ret == 0 && tag != (ASN_CONTEXT_SPECIFIC | 0))
15954                ret = ASN_PARSE_E;
15955
15956            if (ret == 0 && GetLength_ex(pkiMsg, &idx, &encryptedContentSz,
15957                        pkiMsgSz, NO_USER_CHECK) <= 0)
15958                ret = ASN_PARSE_E;
15959
15960#ifdef NO_PKCS7_STREAM
15961            if (ret == 0 && encryptedContentSz > (int)(pkiMsgSz - idx)) {
15962                ret = BUFFER_E;
15963            }
15964#endif
15965
15966            if (ret < 0)
15967                break;
15968#ifndef NO_PKCS7_STREAM
15969            /* next chunk of data should contain encrypted content */
15970            pkcs7->stream->varThree = encryptedContentSz;
15971            if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) {
15972                break;
15973            }
15974
15975            if (pkcs7->stream->totalRd + (word32)encryptedContentSz <
15976                    pkcs7->stream->maxLen) {
15977                pkcs7->stream->flagOne = 1;
15978            }
15979
15980            pkcs7->stream->expected = (pkcs7->stream->maxLen -
15981                pkcs7->stream->totalRd) + pkcs7->stream->length;
15982
15983#endif
15984            wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_STAGE6);
15985            FALL_THROUGH;
15986            /* end of stage 5 */
15987
15988        case WC_PKCS7_STAGE6:
15989#ifndef NO_PKCS7_STREAM
15990            if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz,
15991                            pkcs7->stream->expected, &pkiMsg, &idx)) != 0) {
15992                return ret;
15993            }
15994            pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz;
15995
15996            /* restore saved variables */
15997            expBlockSz = (int)pkcs7->stream->varOne;
15998            encOID     = (word32)pkcs7->stream->varTwo;
15999            encryptedContentSz = pkcs7->stream->varThree;
16000            version    = (int)pkcs7->stream->vers;
16001            tmpIv      = pkcs7->stream->tmpIv;
16002#endif
16003            if (encryptedContentSz <= 0 ||
16004                    encryptedContentSz > (int)(pkiMsgSz - idx)) {
16005                ret = BUFFER_E;
16006                break;
16007            }
16008
16009            if (ret == 0 && (encryptedContent = (byte*)XMALLOC(
16010                                  (unsigned int)encryptedContentSz, pkcs7->heap,
16011                                  DYNAMIC_TYPE_PKCS7)) == NULL) {
16012                ret = MEMORY_E;
16013                break;
16014            }
16015
16016            if (ret == 0) {
16017                word32 tmpSum;
16018                if (!WC_SAFE_SUM_WORD32(idx, (word32)encryptedContentSz, tmpSum) ||
16019                    tmpSum > pkiMsgSz) {
16020                    ret = BUFFER_E;
16021                } else {
16022                    XMEMCPY(encryptedContent, &pkiMsg[idx],
16023                        (unsigned int)encryptedContentSz);
16024                    idx += (word32)encryptedContentSz;
16025
16026                    /* decrypt encryptedContent */
16027                    ret = wc_PKCS7_DecryptContent(pkcs7, encOID,
16028                                pkcs7->encryptionKey, pkcs7->encryptionKeySz,
16029                                tmpIv, expBlockSz, NULL, 0, NULL, 0,
16030                                encryptedContent, encryptedContentSz,
16031                                encryptedContent, pkcs7->devId, pkcs7->heap);
16032                }
16033                if (ret != 0) {
16034                    XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
16035                }
16036            }
16037
16038            if (ret == 0) {
16039                padLen = encryptedContent[encryptedContentSz-1];
16040
16041                /* Constant-time padding check */
16042                padCheck |= ctMaskEq(padLen, 0);
16043                padCheck |= ctMaskGT(padLen, expBlockSz);
16044                padCheck |= ctMaskGT(padLen, encryptedContentSz);
16045                padCheck |= ctMaskGT(expBlockSz, encryptedContentSz);
16046                for (padIndex = encryptedContentSz < expBlockSz ? 0 :
16047                         encryptedContentSz - expBlockSz;
16048                     padIndex < encryptedContentSz; padIndex++) {
16049                    byte inPad = ctMaskGTE(padIndex,
16050                                           encryptedContentSz - (int)padLen);
16051                    padCheck |= inPad & (encryptedContent[padIndex] ^ padLen);
16052                }
16053                if (padCheck != 0) {
16054                    WOLFSSL_MSG("Bad padding bytes found");
16055                    ret = BUFFER_E;
16056                    XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
16057                    break;
16058                }
16059
16060                /* copy plaintext to output */
16061                if ((word32)(encryptedContentSz - padLen) > outputSz) {
16062                    XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
16063                    ret = BUFFER_E;
16064                    break;
16065                }
16066                XMEMCPY(output, encryptedContent,
16067                    (unsigned int)(encryptedContentSz - padLen));
16068
16069                /* get implicit[1] unprotected attributes, optional */
16070                wc_PKCS7_FreeDecodedAttrib(pkcs7->decodedAttrib, pkcs7->heap);
16071                pkcs7->decodedAttrib = NULL;
16072            #ifndef NO_PKCS7_STREAM
16073                if (pkcs7->stream->flagOne)
16074            #else
16075                if (idx < pkiMsgSz)
16076            #endif
16077                {
16078                    haveAttribs = 1;
16079
16080                    ret = wc_PKCS7_DecodeUnprotectedAttributes(pkcs7, pkiMsg,
16081                                                       pkiMsgSz, &idx);
16082                    if (ret != 0) {
16083                        ForceZero(encryptedContent, (word32)encryptedContentSz);
16084                        XFREE(encryptedContent, pkcs7->heap,
16085                            DYNAMIC_TYPE_PKCS7);
16086                        ret = ASN_PARSE_E;
16087                    }
16088                }
16089            }
16090
16091            if (ret == 0) {
16092                ForceZero(encryptedContent, (word32)encryptedContentSz);
16093                XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
16094
16095                /* go back and check the version now that attribs have been
16096                 * processed */
16097                if (pkcs7->version == 3 && version != 0) {
16098                    WOLFSSL_MSG("Wrong PKCS#7 FirmwareEncryptedData version");
16099                    return ASN_VERSION_E;
16100                }
16101
16102                if (pkcs7->version != 3 &&
16103                   ((haveAttribs == 0 && version != 0) ||
16104                    (haveAttribs == 1 && version != 2))) {
16105                    WOLFSSL_MSG("Wrong PKCS#7 EncryptedData version");
16106                    return ASN_VERSION_E;
16107                }
16108                ret = encryptedContentSz - padLen;
16109            }
16110
16111            if (ret != 0) break;
16112        #ifndef NO_PKCS7_STREAM
16113            wc_PKCS7_ResetStream(pkcs7);
16114        #endif
16115            wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START);
16116            break;
16117
16118        default:
16119            WOLFSSL_MSG("Error in unknown PKCS#7 Decode Encrypted Data state");
16120            return BAD_STATE_E;
16121    }
16122
16123    if (ret != 0) {
16124    #ifndef NO_PKCS7_STREAM
16125        /* restart in error case */
16126        wc_PKCS7_ResetStream(pkcs7);
16127    #endif
16128        wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START);
16129    }
16130    return ret;
16131}
16132
16133
16134/* Function to set callback during decryption, this overrides the default
16135 * decryption function and can be used for choosing a key at run time based
16136 * on the parsed bundle so far.
16137 * returns 0 on success
16138 */
16139int wc_PKCS7_SetDecodeEncryptedCb(wc_PKCS7* pkcs7,
16140        CallbackDecryptContent decryptionCb)
16141{
16142    if (pkcs7 != NULL) {
16143        pkcs7->decryptionCb = decryptionCb;
16144    }
16145    return 0;
16146}
16147
16148
16149/* Set an optional user context that gets passed to callback
16150 * returns 0 on success
16151 */
16152int wc_PKCS7_SetDecodeEncryptedCtx(wc_PKCS7* pkcs7, void* ctx)
16153{
16154    if (pkcs7 != NULL) {
16155        pkcs7->decryptionCtx = ctx;
16156    }
16157    return 0;
16158}
16159#endif /* NO_PKCS7_ENCRYPTED_DATA */
16160
16161
16162/* Unwrap and decrypt PKCS#7/CMS EncryptedKeyPackage object, return the
16163 * decoded size. */
16164int wc_PKCS7_DecodeEncryptedKeyPackage(wc_PKCS7 * pkcs7,
16165        byte * pkiMsg, word32 pkiMsgSz, byte * output, word32 outputSz)
16166{
16167    int ret = 0;
16168    word32 pkiIndex = 0;
16169    word32 contentType = 0;
16170    int length = 0;
16171
16172    if (pkiMsg == NULL) {
16173        ret = BAD_FUNC_ARG;
16174    }
16175    /* Expect a SEQUENCE header to start the EncryptedKeyPackage
16176     * ContentInfo. */
16177    else if (GetSequence_ex(pkiMsg, &pkiIndex, &length, pkiMsgSz, 1) < 0) {
16178        ret = ASN_PARSE_E;
16179    }
16180    /* Validate the EncryptedKeyPackage OBJECT IDENTIFIER. */
16181    else if (wc_GetContentType(pkiMsg, &pkiIndex, &contentType, pkiMsgSz) < 0) {
16182        ret = ASN_PARSE_E;
16183    }
16184    else if (contentType != ENCRYPTED_KEY_PACKAGE) {
16185        WOLFSSL_MSG("PKCS#7 input not of type EncryptedKeyPackage");
16186        ret = PKCS7_OID_E;
16187    }
16188    /* Expect content [0] tag */
16189    else if (GetASNHeader(pkiMsg, ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED,
16190                &pkiIndex, &length, pkiMsgSz) < 0) {
16191        ret = ASN_PARSE_E;
16192    }
16193    /* Check for an EncryptedKeyPackage explicit CHOICE [0] tag, indicating
16194     * an EnvelopedData subtype. */
16195    else if (GetASNHeader(pkiMsg, ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED,
16196                &pkiIndex, &length, pkiMsgSz) >= 0) {
16197        /* An explicit CHOICE [0] tag was found. pkiIndex now should point
16198         * to the EnvelopedData ContentInfo object within the
16199         * EncryptedKeyPackage. */
16200        ret = wc_PKCS7_DecodeEnvelopedData(pkcs7, &pkiMsg[pkiIndex],
16201                pkiMsgSz - pkiIndex, output, outputSz);
16202    }
16203    else {
16204#ifndef NO_PKCS7_ENCRYPTED_DATA
16205        /* An explicit CHOICE [0] tag was not found. Check if we have an
16206         * EncryptedData blob. */
16207        ret = wc_PKCS7_DecodeEncryptedData(pkcs7, &pkiMsg[pkiIndex],
16208                pkiMsgSz - pkiIndex, output, outputSz);
16209#else
16210        ret = ASN_PARSE_E;
16211#endif
16212    }
16213
16214    return ret;
16215}
16216
16217
16218/* set stream mode for encoding and signing
16219 * returns 0 on success */
16220int wc_PKCS7_SetStreamMode(wc_PKCS7* pkcs7, byte flag,
16221    CallbackGetContent getContentCb,
16222    CallbackStreamOut streamOutCb, void* ctx)
16223{
16224    if (pkcs7 == NULL) {
16225        return BAD_FUNC_ARG;
16226    }
16227#ifdef ASN_BER_TO_DER
16228    pkcs7->encodeStream = (flag != 0);
16229    pkcs7->getContentCb = getContentCb;
16230    pkcs7->streamOutCb  = streamOutCb;
16231    pkcs7->streamCtx    = ctx;
16232    return 0;
16233#else
16234    (void)flag;
16235    (void)getContentCb;
16236    (void)streamOutCb;
16237    (void)ctx;
16238    return NOT_COMPILED_IN;
16239#endif
16240}
16241
16242
16243/* returns to current stream mode flag on success, negative values on fail */
16244int wc_PKCS7_GetStreamMode(wc_PKCS7* pkcs7)
16245{
16246    if (pkcs7 == NULL) {
16247        return BAD_FUNC_ARG;
16248    }
16249#ifdef ASN_BER_TO_DER
16250    return pkcs7->encodeStream;
16251#else
16252    return 0;
16253#endif
16254}
16255
16256
16257/* set option to not include certificates when creating a bundle
16258 * returns 0 on success */
16259int wc_PKCS7_SetNoCerts(wc_PKCS7* pkcs7, byte flag)
16260{
16261    if (pkcs7 == NULL) {
16262        return BAD_FUNC_ARG;
16263    }
16264    pkcs7->noCerts = (flag != 0);
16265    return 0;
16266}
16267
16268
16269/* returns the current noCerts flag value on success, negative values on fail */
16270int wc_PKCS7_GetNoCerts(wc_PKCS7* pkcs7)
16271{
16272    if (pkcs7 == NULL) {
16273        return BAD_FUNC_ARG;
16274    }
16275    return pkcs7->noCerts;
16276}
16277
16278
16279#if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA)
16280
16281/* build PKCS#7 compressedData content type, return encrypted size */
16282int wc_PKCS7_EncodeCompressedData(wc_PKCS7* pkcs7, byte* output,
16283    word32 outputSz)
16284{
16285    byte contentInfoSeq[MAX_SEQ_SZ];
16286    byte contentInfoTypeOid[MAX_OID_SZ];
16287    byte contentInfoContentSeq[MAX_SEQ_SZ]; /* EXPLICIT [0] */
16288    byte compressedDataSeq[MAX_SEQ_SZ];
16289    byte cmsVersion[MAX_VERSION_SZ];
16290    byte compressAlgId[MAX_ALGO_SZ];
16291    byte encapContentInfoSeq[MAX_SEQ_SZ];
16292    byte contentTypeOid[MAX_OID_SZ];
16293    byte contentSeq[MAX_SEQ_SZ];            /* EXPLICIT [0] */
16294    byte contentOctetStr[MAX_OCTET_STR_SZ];
16295
16296    int ret;
16297    word32 totalSz, idx;
16298    word32 contentInfoSeqSz, contentInfoContentSeqSz, contentInfoTypeOidSz;
16299    word32 compressedDataSeqSz, cmsVersionSz, compressAlgIdSz;
16300    word32 encapContentInfoSeqSz, contentTypeOidSz, contentSeqSz;
16301    word32 contentOctetStrSz;
16302
16303    byte* compressed;
16304    word32 compressedSz;
16305
16306    if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 ||
16307        output == NULL || outputSz == 0) {
16308        return BAD_FUNC_ARG;
16309    }
16310
16311    /* allocate space for compressed content. The libz code says the compressed
16312     * buffer should be srcSz + 0.1% + 12. */
16313    compressedSz = (pkcs7->contentSz + (word32)(pkcs7->contentSz * 0.001) + 12);
16314    compressed = (byte*)XMALLOC(compressedSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
16315    if (compressed == NULL) {
16316        WOLFSSL_MSG("Error allocating memory for CMS compressed content");
16317        return MEMORY_E;
16318    }
16319
16320    /* compress content */
16321    ret = wc_Compress(compressed, compressedSz, pkcs7->content,
16322                      pkcs7->contentSz, 0);
16323    if (ret < 0) {
16324        XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
16325        return ret;
16326    }
16327    compressedSz = (word32)ret;
16328
16329    /* eContent OCTET STRING, working backwards */
16330    contentOctetStrSz = SetOctetString(compressedSz, contentOctetStr);
16331    totalSz = contentOctetStrSz + compressedSz;
16332
16333    /* EXPLICIT [0] eContentType */
16334    contentSeqSz = SetExplicit(0, totalSz, contentSeq, 0);
16335    totalSz += contentSeqSz;
16336
16337    /* eContentType OBJECT IDENTIFIER */
16338    ret = wc_SetContentType(pkcs7->contentOID, contentTypeOid,
16339                            sizeof(contentTypeOid));
16340    if (ret < 0) {
16341        XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
16342        return ret;
16343    }
16344
16345    contentTypeOidSz = ret;
16346    totalSz += contentTypeOidSz;
16347
16348    /* EncapsulatedContentInfo SEQUENCE */
16349    encapContentInfoSeqSz = SetSequence(totalSz, encapContentInfoSeq);
16350    totalSz += encapContentInfoSeqSz;
16351
16352    /* compressionAlgorithm AlgorithmIdentifier */
16353    /* Only supports zlib for compression currently:
16354     * id-alg-zlibCompress (1.2.840.113549.1.9.16.3.8) */
16355    compressAlgIdSz = SetAlgoID(ZLIBc, compressAlgId, oidCompressType, 0);
16356    totalSz += compressAlgIdSz;
16357
16358    /* version */
16359    cmsVersionSz = SetMyVersion(0, cmsVersion, 0);
16360    totalSz += cmsVersionSz;
16361
16362    /* CompressedData SEQUENCE */
16363    compressedDataSeqSz = SetSequence(totalSz, compressedDataSeq);
16364    totalSz += compressedDataSeqSz;
16365
16366    if (pkcs7->version == 3) {
16367        /* RFC 4108 section 2
16368         * When the SignedData is version 3 and eContent is compressedData then
16369         * the encoding is :
16370         * CompressedData {
16371         *   version
16372         *   compressionAlgorithm
16373         *   encapContentInfo
16374         * }
16375         */
16376        contentInfoSeqSz        = 0;
16377        contentInfoTypeOidSz    = 0;
16378        contentInfoContentSeqSz = 0;
16379    }
16380    else {
16381        /* EncryptedData eContent type is encoded with:
16382         * EncryptedData {
16383         *  version
16384         *  EncryptedContentInfo {
16385         *      contentType (i.e id-ct-compressedData)
16386         *      contentEncryptionAlgorithm
16387         *      octet string of CompressedData or FirmwarePkgData
16388         *  }
16389         *  attributes
16390         * }
16391         */
16392
16393        /* ContentInfo content EXPLICIT SEQUENCE */
16394        contentInfoContentSeqSz = SetExplicit(0, totalSz, contentInfoContentSeq,
16395            0);
16396        totalSz += contentInfoContentSeqSz;
16397
16398        ret = wc_SetContentType(COMPRESSED_DATA, contentInfoTypeOid,
16399                                sizeof(contentInfoTypeOid));
16400        if (ret < 0) {
16401            XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
16402            return ret;
16403        }
16404
16405        contentInfoTypeOidSz = ret;
16406        totalSz += contentInfoTypeOidSz;
16407
16408        /* ContentInfo SEQUENCE */
16409        contentInfoSeqSz = SetSequence(totalSz, contentInfoSeq);
16410        totalSz += contentInfoSeqSz;
16411    }
16412
16413    if (outputSz < totalSz) {
16414        XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
16415        return BUFFER_E;
16416    }
16417
16418    idx = 0;
16419    if (contentInfoSeqSz > 0) {
16420        XMEMCPY(output + idx, contentInfoSeq, contentInfoSeqSz);
16421        idx += contentInfoSeqSz;
16422    }
16423    if (contentInfoTypeOidSz > 0) {
16424        XMEMCPY(output + idx, contentInfoTypeOid, contentInfoTypeOidSz);
16425        idx += contentInfoTypeOidSz;
16426    }
16427    if (contentInfoContentSeqSz > 0) {
16428        XMEMCPY(output + idx, contentInfoContentSeq, contentInfoContentSeqSz);
16429        idx += contentInfoContentSeqSz;
16430    }
16431    XMEMCPY(output + idx, compressedDataSeq, compressedDataSeqSz);
16432    idx += compressedDataSeqSz;
16433    XMEMCPY(output + idx, cmsVersion, cmsVersionSz);
16434    idx += cmsVersionSz;
16435    XMEMCPY(output + idx, compressAlgId, compressAlgIdSz);
16436    idx += compressAlgIdSz;
16437    XMEMCPY(output + idx, encapContentInfoSeq, encapContentInfoSeqSz);
16438    idx += encapContentInfoSeqSz;
16439    XMEMCPY(output + idx, contentTypeOid, contentTypeOidSz);
16440    idx += contentTypeOidSz;
16441    XMEMCPY(output + idx, contentSeq, contentSeqSz);
16442    idx += contentSeqSz;
16443    XMEMCPY(output + idx, contentOctetStr, contentOctetStrSz);
16444    idx += contentOctetStrSz;
16445    XMEMCPY(output + idx, compressed, compressedSz);
16446    idx += compressedSz;
16447
16448    XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
16449
16450    return idx;
16451}
16452
16453/* unwrap and decompress PKCS#7/CMS compressedData object,
16454 * Handles content wrapped compressed data and raw compressed data packet
16455 * returned decoded size */
16456int wc_PKCS7_DecodeCompressedData(wc_PKCS7* pkcs7, byte* pkiMsg,
16457    word32 pkiMsgSz, byte* output, word32 outputSz)
16458{
16459    int length, version, ret;
16460    word32 idx = 0, algOID, contentType;
16461    byte tag;
16462
16463    byte* decompressed;
16464    word32 decompressedSz;
16465
16466    if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0 ||
16467        output == NULL || outputSz == 0) {
16468        return BAD_FUNC_ARG;
16469    }
16470
16471    /* unwarp content surrounding if found */
16472    {
16473        word32 localIdx = idx;
16474        int err = 0;
16475
16476        /* get ContentInfo SEQUENCE */
16477        if (GetSequence(pkiMsg, &localIdx, &length, pkiMsgSz) < 0)
16478            err = ASN_PARSE_E;
16479
16480        if (err == 0 && pkcs7->version != 3) {
16481            /* get ContentInfo contentType */
16482            if (wc_GetContentType(pkiMsg, &localIdx, &contentType, pkiMsgSz)
16483                    < 0)
16484                err = ASN_PARSE_E;
16485
16486            if (err == 0 && contentType != COMPRESSED_DATA)
16487                err = ASN_PARSE_E;
16488        }
16489
16490        /* get ContentInfo content EXPLICIT SEQUENCE */
16491        if (err == 0) {
16492            if (GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) < 0)
16493                err = ASN_PARSE_E;
16494        }
16495
16496        if (err == 0) {
16497            if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
16498                err = ASN_PARSE_E;
16499        }
16500
16501        if (err == 0) {
16502            if (GetLength(pkiMsg, &localIdx, &length, pkiMsgSz) < 0)
16503                err = ASN_PARSE_E;
16504        }
16505
16506        /* successful content unwrap, update index */
16507        if (err == 0) {
16508            idx = localIdx;
16509        }
16510    }
16511
16512    /* get CompressedData SEQUENCE */
16513    if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
16514        return ASN_PARSE_E;
16515
16516    /* get version */
16517    if (GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0)
16518        return ASN_PARSE_E;
16519
16520    if (version != 0) {
16521        WOLFSSL_MSG("CMS CompressedData version MUST be 0, but is not");
16522        return ASN_PARSE_E;
16523    }
16524
16525    /* get CompressionAlgorithmIdentifier */
16526    if (GetAlgoId(pkiMsg, &idx, &algOID, oidIgnoreType, pkiMsgSz) < 0)
16527        return ASN_PARSE_E;
16528
16529    /* Only supports zlib for compression currently:
16530     * id-alg-zlibCompress (1.2.840.113549.1.9.16.3.8) */
16531    if (algOID != ZLIBc) {
16532        WOLFSSL_MSG("CMS CompressedData only supports zlib algorithm");
16533        return ASN_PARSE_E;
16534    }
16535
16536    /* get EncapsulatedContentInfo SEQUENCE */
16537    if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
16538        return ASN_PARSE_E;
16539
16540    /* get ContentType OID */
16541    if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0)
16542        return ASN_PARSE_E;
16543
16544    pkcs7->contentOID = contentType;
16545
16546    /* get eContent EXPLICIT SEQUENCE */
16547    if (GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0)
16548        return ASN_PARSE_E;
16549
16550    if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
16551        return ASN_PARSE_E;
16552
16553    if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
16554        return ASN_PARSE_E;
16555
16556    /* get content OCTET STRING */
16557    if (GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0)
16558        return ASN_PARSE_E;
16559
16560    if (tag != ASN_OCTET_STRING)
16561        return ASN_PARSE_E;
16562
16563    if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
16564        return ASN_PARSE_E;
16565
16566    /* decompress content */
16567    ret = wc_DeCompressDynamic(&decompressed, WOLFSSL_PKCS7_MAX_DECOMPRESSION,
16568            DYNAMIC_TYPE_PKCS7, &pkiMsg[idx], length, 0, pkcs7->heap);
16569    if (ret < 0) {
16570        return ret;
16571    }
16572    decompressedSz = (word32)ret;
16573
16574    /* get content */
16575    if (outputSz < decompressedSz) {
16576        WOLFSSL_MSG("CMS output buffer too small to hold decompressed data");
16577        XFREE(decompressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
16578        return BUFFER_E;
16579    }
16580
16581    XMEMCPY(output, decompressed, decompressedSz);
16582    XFREE(decompressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
16583
16584    return decompressedSz;
16585}
16586
16587#endif /* HAVE_LIBZ && !NO_PKCS7_COMPRESSED_DATA */
16588
16589static int wc_PKCS7_DecodeSymmetricKeyPackage(const byte * skp, word32 skpSz,
16590        size_t index, const byte ** out, word32 * outSz, int getKey)
16591{
16592    word32 skpIndex = 0;
16593    int length = 0;
16594    int version = 0;
16595    int ret = 0;
16596
16597    if (skp == NULL || out == NULL || outSz == NULL)
16598        ret = BAD_FUNC_ARG;
16599
16600    /* Expect a SEQUENCE header to start the SymmetricKeyPackage object. */
16601    if (ret == 0 && GetSequence(skp, &skpIndex, &length, skpSz) < 0)
16602        ret = ASN_PARSE_E;
16603
16604    /* Expect version v1 */
16605    if (ret == 0 && GetMyVersion(skp, &skpIndex, &version, skpSz) < 0)
16606        ret = ASN_PARSE_E;
16607
16608    if (ret == 0 && version != 1)
16609        ret = ASN_PARSE_E;
16610
16611    if (ret == 0 && GetASNHeader(skp, ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED,
16612            &skpIndex, &length, skpSz) >= 0) {
16613        /* sKeyPkgAttrs [0] tag found so there are attributes present. */
16614        if (getKey != 0) {
16615            /* Key was requested, not attribute, so skip the attributes. */
16616            skpIndex += (word32)length;
16617        }
16618        else {
16619            /* sKeyPkgAttrs is present at &skp[skpIndex], length in length */
16620            ret = wc_IndexSequenceOf(&skp[skpIndex], (word32)length, index,
16621                    out, outSz);
16622        }
16623    }
16624    else if (ret == 0 && getKey == 0) {
16625        /* An attribute was requested, but none are present. */
16626        ret = BAD_INDEX_E;
16627    }
16628
16629    if (ret == 0 && getKey != 0) {
16630        /* sKeys is present at &skp[skpIndex]. */
16631        ret = wc_IndexSequenceOf(&skp[skpIndex], skpSz - skpIndex, index,
16632                out, outSz);
16633    }
16634
16635    return ret;
16636}
16637
16638int wc_PKCS7_DecodeSymmetricKeyPackageAttribute(const byte * skp,
16639        word32 skpSz, size_t index, const byte ** attr, word32 * attrSz)
16640{
16641    return wc_PKCS7_DecodeSymmetricKeyPackage(skp, skpSz, index, attr, attrSz,
16642            0);
16643}
16644
16645int wc_PKCS7_DecodeSymmetricKeyPackageKey(const byte * skp,
16646        word32 skpSz, size_t index, const byte ** key, word32 * keySz)
16647{
16648    return wc_PKCS7_DecodeSymmetricKeyPackage(skp, skpSz, index, key, keySz, 1);
16649}
16650
16651int wc_PKCS7_DecodeOneSymmetricKeyAttribute(const byte * osk,
16652        word32 oskSz, size_t index, const byte ** attr, word32 * attrSz)
16653{
16654    word32 oskIndex = 0;
16655    word32 tmpIndex;
16656    int length = 0;
16657    int ret = 0;
16658
16659    if (osk == NULL || attr == NULL || attrSz == NULL)
16660        ret = BAD_FUNC_ARG;
16661
16662    /* Expect a SEQUENCE header to start the OneSymmetricKey object. */
16663    if (ret == 0 && GetSequence(osk, &oskIndex, &length, oskSz) < 0)
16664        ret = ASN_PARSE_E;
16665
16666    tmpIndex = oskIndex;
16667
16668    if (ret == 0 && GetSequence(osk, &tmpIndex, &length, oskSz) < 0) {
16669        /* sKeyAttrs is not present. */
16670        ret = BAD_INDEX_E;
16671    }
16672
16673    /* Index the sKeyAttrs SEQUENCE OF object with the given index. */
16674    if (ret == 0)
16675        ret = wc_IndexSequenceOf(&osk[oskIndex], oskSz - oskIndex, index, attr,
16676            attrSz);
16677
16678    return ret;
16679}
16680
16681int wc_PKCS7_DecodeOneSymmetricKeyKey(const byte * osk,
16682        word32 oskSz, const byte ** key, word32 * keySz)
16683{
16684    word32 oskIndex = 0;
16685    int length = 0;
16686    int ret = 0;
16687
16688    if (osk == NULL || key == NULL || keySz == NULL)
16689        ret = BAD_FUNC_ARG;
16690
16691    /* Expect a SEQUENCE header to start the OneSymmetricKey object. */
16692    if (ret == 0 && GetSequence(osk, &oskIndex, &length, oskSz) < 0)
16693        ret = ASN_PARSE_E;
16694
16695    if (ret == 0 && GetSequence(osk, &oskIndex, &length, oskSz) >= 0) {
16696        /* sKeyAttrs is present. Skip it. */
16697        oskIndex += (word32)length;
16698    }
16699
16700    if (ret == 0 && GetASNHeader(osk, ASN_OCTET_STRING, &oskIndex, &length,
16701                oskSz) < 0)
16702        ret = ASN_PARSE_E;
16703
16704    if (ret == 0) {
16705        *key = &osk[oskIndex];
16706        *keySz = (word32)length;
16707    }
16708
16709    return ret;
16710}
16711
16712#else  /* HAVE_PKCS7 */
16713
16714
16715#ifdef _MSC_VER
16716    /* 4206 warning for blank file */
16717    #pragma warning(disable: 4206)
16718#endif
16719
16720
16721#endif /* HAVE_PKCS7 */